From 441b5fe85ff3f14ce15a89181edce97588069f07 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Mon, 1 Apr 2024 18:58:55 +0200 Subject: [PATCH 01/37] Adjustment for compilation on Linux Renamed files to match class names and case sensisitive file system on Linux: * SimpleDLNA/StartupUtilities.cs * server/Http/HttpServer.cs * server/Types/Subtitle.cs * util/FFmpeg.cs Changed files to match case sensitive paths / names: * SimpleDLNA/FormMain.cs * server/Http/HttpClient.cs * server/Properties/Resources.resx * util/util.csproj --- SimpleDLNA/FormMain.cs | 2 +- ...tartUpUtilities.cs => StartupUtilities.cs} | 0 server/Http/HttpClient.cs | 2 +- server/Http/{HTTPServer.cs => HttpServer.cs} | 0 server/Properties/Resources.resx | 24 +++++++++---------- server/Types/{SubTitle.cs => Subtitle.cs} | 0 util/{Ffmpeg.cs => FFmpeg.cs} | 0 util/util.csproj | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) rename SimpleDLNA/{StartUpUtilities.cs => StartupUtilities.cs} (100%) rename server/Http/{HTTPServer.cs => HttpServer.cs} (100%) rename server/Types/{SubTitle.cs => Subtitle.cs} (100%) rename util/{Ffmpeg.cs => FFmpeg.cs} (100%) diff --git a/SimpleDLNA/FormMain.cs b/SimpleDLNA/FormMain.cs index 5c9043e2..f2a23206 100644 --- a/SimpleDLNA/FormMain.cs +++ b/SimpleDLNA/FormMain.cs @@ -37,7 +37,7 @@ public partial class FormMain : Form, IAppender #if DEBUG private readonly FileInfo logFile = - new FileInfo(Path.Combine(cacheDir, "sdlna.dbg.log")); + new FileInfo(Path.Combine(CacheDir, "sdlna.dbg.log")); #else private readonly FileInfo logFile = new FileInfo(Path.Combine(CacheDir, "sdlna.log")); diff --git a/SimpleDLNA/StartUpUtilities.cs b/SimpleDLNA/StartupUtilities.cs similarity index 100% rename from SimpleDLNA/StartUpUtilities.cs rename to SimpleDLNA/StartupUtilities.cs diff --git a/server/Http/HttpClient.cs b/server/Http/HttpClient.cs index cf1628bc..4107c0d4 100644 --- a/server/Http/HttpClient.cs +++ b/server/Http/HttpClient.cs @@ -384,7 +384,7 @@ private void SetupResponse() } catch (HttpStatusException ex) { #if DEBUG - Warn(String.Format("{0} - Got a {2}: {1}", this, path, ex.Code), ex); + Warn(String.Format("{0} - Got a {2}: {1}", this, Path, ex.Code), ex); #else InfoFormat("{0} - Got a {2}: {1}", this, Path, ex.Code); #endif diff --git a/server/Http/HTTPServer.cs b/server/Http/HttpServer.cs similarity index 100% rename from server/Http/HTTPServer.cs rename to server/Http/HttpServer.cs diff --git a/server/Properties/Resources.resx b/server/Properties/Resources.resx index d12268d3..4e2472b8 100644 --- a/server/Properties/Resources.resx +++ b/server/Properties/Resources.resx @@ -1,4 +1,4 @@ - + - \ No newline at end of file diff --git a/NMaier.Windows.Forms/NMaier.Windows.Forms.snk b/NMaier.Windows.Forms/NMaier.Windows.Forms.snk deleted file mode 100644 index 7dba39734594a725abdc23d2dd323ac326a0496e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50097h%#SWKTeb~si<3jpHfm6cDo6*0NB7yv z^GfkdMH49wVfIIg8JLOWzxt~dre&}qq5ybCvfO>j&%~%udFK;!Ealj)Bozf?F#V4@ z({p&a1(f9+AbbuWQ;L;I`fkhc;cD;{*u9V_Ei}yKw$F{l1n0nEpL_Rb_6`aaz3i{0FVambb0M#4@585K`Od zBaAFe%uWq1vJvF_1GM++oq4GctA#&e@(Jd<8Zw=dT6Q zO>w$_B8;d>Yj0}k`{5t__Cr|bH%j&GLovQ=zLm!nCNA(ZeOsH_k0$H94qGxfak?P ziRnNpi50=3WcLcr0SyvTNd)nvv>N)CRAX!_bG~LR+PoIP^WrXz-m5;LC6OW& defined = - new Dictionary(); - - public static readonly bool IsSupported = new Func(() => - { - if (!VisualStyleRenderer.IsSupported) { - return false; - } - return IsElementDefined( - "Menu", - (int)MenuParts.BarBackground, - (int)MenuBarStates.Active); - })(); - - private VisualStyleRenderer renderer; - - public ToolStripRealSystemRenderer() - : this(ToolbarTheme.Toolbar) - { - } - - public ToolStripRealSystemRenderer(ToolbarTheme theme) - { - Theme = theme; - } - - private enum MenuBarItemStates : int - { - Normal = 1, - Hover = 2, - Pushed = 3, - Disabled = 4, - DisabledHover = 5, - DisabledPushed = 6 - } - - private enum MenuBarStates : int - { - Active = 1, - Inactive = 2 - } - - private enum MenuParts : int - { - ItemTMSchema = 1, - DropDownTMSchema = 2, - BarItemTMSchema = 3, - BarDropDownTMSchema = 4, - ChevronTMSchema = 5, - SeparatorTMSchema = 6, - BarBackground = 7, - BarItem = 8, - PopupBackground = 9, - PopupBorders = 10, - PopupCheck = 11, - PopupCheckBackground = 12, - PopupGutter = 13, - PopupItem = 14, - PopupSeparator = 15, - PopupSubmenu = 16, - SystemClose = 17, - SystemMaximize = 18, - SystemMinimize = 19, - SystemRestore = 20 - } - - private enum MenuPopupCheckBackgroundStates : int - { - Disabled = 1, - Normal = 2, - Bitmap = 3 - } - - private enum MenuPopupCheckStates : int - { - CheckmarkNormal = 1, - CheckmarkDisabled = 2, - BulletNormal = 3, - BulletDisabled = 4 - } - - private enum MenuPopupItemStates : int - { - Normal = 1, - Hover = 2, - Disabled = 3, - DisabledHover = 4 - } - - private enum MenuPopupSubMenuStates : int - { - Normal = 1, - Disabled = 2 - } - - public enum ToolbarTheme - { - BrowserTabBar, - CommunicationsToolbar, - HelpBar, - MediaToolbar, - Toolbar - } - - private string MenuClass - { - get - { - return SubclassPrefix + "Menu"; - } - } - - private string RebarClass - { - get - { - return SubclassPrefix + "Rebar"; - } - } - - private string SubclassPrefix - { - get - { - switch (Theme) { - case ToolbarTheme.MediaToolbar: - return "Media::"; - case ToolbarTheme.CommunicationsToolbar: - return "Communications::"; - case ToolbarTheme.BrowserTabBar: - return "BrowserTabBar::"; - case ToolbarTheme.HelpBar: - return "Help::"; - default: - return string.Empty; - } - } - } - - public ToolbarTheme Theme - { - get; - set; - } - - private bool EnsureRenderer() - { - if (!IsSupported) { - return false; - } - if (renderer == null) { - renderer = - new VisualStyleRenderer(VisualStyleElement.Button.PushButton.Normal); - } - return true; - } - - private static Rectangle GetBackgroundRectangle(ToolStripItem item) - { - if (!item.IsOnDropDown) { - return new Rectangle(new Point(), item.Bounds.Size); - } - - var rect = item.Bounds; - rect.X = item.ContentRectangle.X + 1; - rect.Width = item.ContentRectangle.Width - 1; - rect.Y = 0; - return rect; - } - - private static int GetItemState(ToolStripItem item) - { - var selected = item.Selected; - - if (item.IsOnDropDown) { - if (item.Enabled) { - return selected ? - (int)MenuPopupItemStates.Hover : - (int)MenuPopupItemStates.Normal; - } - return selected ? - (int)MenuPopupItemStates.DisabledHover : - (int)MenuPopupItemStates.Disabled; - } - - if (item.Pressed) { - return item.Enabled ? - (int)MenuBarItemStates.Pushed : - (int)MenuBarItemStates.DisabledPushed; - } - - if (item.Enabled) { - return selected ? - (int)MenuBarItemStates.Hover : - (int)MenuBarItemStates.Normal; - } - - return selected ? - (int)MenuBarItemStates.DisabledHover : - (int)MenuBarItemStates.Disabled; - } - - private Color GetItemTextColor(ToolStripItem item) - { - var partId = item.IsOnDropDown ? - (int)MenuParts.PopupItem : - (int)MenuParts.BarItem; - renderer.SetParameters(MenuClass, partId, (int)GetItemState(item)); - return renderer.GetColor(ColorProperty.TextColor); - } - - private Padding GetThemeMargins(IDeviceContext dc, - MarginProperty marginType) - { - NativeMethods.MARGINS margins; - try { - var hDC = dc.GetHdc(); - var rv = NativeMethods.GetThemeMargins( - renderer.Handle, - hDC, - renderer.Part, - renderer.State, - (int)marginType, - IntPtr.Zero, - out margins); - if (rv == 0) { - return new Padding( - margins.cxLeftWidth, - margins.cyTopHeight, - margins.cxRightWidth, - margins.cyBottomHeight); - } - return new Padding(0); - } - catch (Exception) { - return renderer.GetMargins(dc, marginType); - } - finally { - dc.ReleaseHdc(); - } - } - - private static bool IsElementDefined(VSEInternal e) - { - var el = VisualStyleElement.CreateElement(e.cls, e.part, e.state); - return VisualStyleRenderer.IsElementDefined(el); - } - - protected override void Initialize(ToolStrip toolStrip) - { - if (toolStrip.Parent is ToolStripPanel) { - toolStrip.BackColor = Color.Transparent; - } - base.Initialize(toolStrip); - } - - protected override void InitializePanel(ToolStripPanel toolStripPanel) - { - foreach (Control control in toolStripPanel.Controls) { - if (control is ToolStrip) { - Initialize((ToolStrip)control); - } - } - base.InitializePanel(toolStripPanel); - } - - protected static bool IsElementDefined(string className, int part, - int state) - { - var el = new VSEInternal(className, part, state); - bool rv; - if (!defined.TryGetValue(el, out rv)) { - defined.Add(el, rv = IsElementDefined(el)); - } - return rv; - } - - protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e) - { - if (EnsureRenderer()) { - e.ArrowColor = GetItemTextColor(e.Item); - } - base.OnRenderArrow(e); - } - - protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) - { - if (!EnsureRenderer()) { - base.OnRenderImageMargin(e); - return; - } - if (!e.ToolStrip.IsDropDown) { - return; - } - renderer.SetParameters(MenuClass, (int)MenuParts.PopupGutter, 0); - var margins = GetThemeMargins(e.Graphics, MarginProperty.SizingMargins); - var ts = e.ToolStrip; - var extraWidth = - (ts.Width - ts.DisplayRectangle.Width - margins.Left - margins.Right - 1) - - e.AffectedBounds.Width; - var rect = e.AffectedBounds; - rect.Y += 2; - rect.Height -= 4; - var sepWidth = - renderer.GetPartSize(e.Graphics, ThemeSizeType.True).Width; - if (e.ToolStrip.RightToLeft == RightToLeft.Yes) { - rect = new Rectangle( - rect.X - extraWidth, rect.Y, sepWidth, rect.Height); - rect.X += sepWidth; - } - else { - rect = new Rectangle( - rect.Width + extraWidth - sepWidth, - rect.Y, - sepWidth, - rect.Height); - } - renderer.DrawBackground(e.Graphics, rect); - } - - protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) - { - if (!EnsureRenderer()) { - base.OnRenderItemCheck(e); - return; - } - var bgRect = GetBackgroundRectangle(e.Item); - bgRect.Width = bgRect.Height; - - if (e.Item.RightToLeft == RightToLeft.Yes) { - bgRect = new Rectangle( - e.ToolStrip.ClientSize.Width - bgRect.X - bgRect.Width, - bgRect.Y, - bgRect.Width, - bgRect.Height); - } - var state = e.Item.Enabled ? - (int)MenuPopupCheckBackgroundStates.Normal : - (int)MenuPopupCheckBackgroundStates.Disabled; - renderer.SetParameters( - MenuClass, - (int)MenuParts.PopupCheckBackground, - state); - renderer.DrawBackground(e.Graphics, bgRect); - - var checkRect = e.ImageRectangle; - checkRect.X = bgRect.X + bgRect.Width / 2 - checkRect.Width / 2; - checkRect.Y = bgRect.Y + bgRect.Height / 2 - checkRect.Height / 2; - - state = e.Item.Enabled ? - (int)MenuPopupCheckStates.CheckmarkNormal : - (int)MenuPopupCheckStates.CheckmarkDisabled; - renderer.SetParameters(MenuClass, (int)MenuParts.PopupCheck, state); - - renderer.DrawBackground(e.Graphics, checkRect); - } - - protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) - { - if (EnsureRenderer()) { - e.TextColor = GetItemTextColor(e.Item); - } - base.OnRenderItemText(e); - } - - protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) - { - if (EnsureRenderer()) { - var partID = e.Item.IsOnDropDown ? - (int)MenuParts.PopupItem : - (int)MenuParts.BarItem; - renderer.SetParameters(MenuClass, partID, GetItemState(e.Item)); - - var bgRect = GetBackgroundRectangle(e.Item); - renderer.DrawBackground(e.Graphics, bgRect, bgRect); - } - else { - base.OnRenderMenuItemBackground(e); - } - } - - protected override void OnRenderOverflowButtonBackground( - ToolStripItemRenderEventArgs e) - { - if (EnsureRenderer()) { - var rebarClass = RebarClass; - if (Theme == ToolbarTheme.BrowserTabBar) { - rebarClass = "Rebar"; - } - var state = VisualStyleElement.Rebar.Chevron.Normal.State; - if (e.Item.Pressed) { - state = VisualStyleElement.Rebar.Chevron.Pressed.State; - } - else { - if (e.Item.Selected) { - state = VisualStyleElement.Rebar.Chevron.Hot.State; - } - } - renderer.SetParameters( - rebarClass, - VisualStyleElement.Rebar.Chevron.Normal.Part, - state); - renderer.DrawBackground( - e.Graphics, new Rectangle(Point.Empty, e.Item.Size)); - } - else { - base.OnRenderOverflowButtonBackground(e); - } - } - - protected override void OnRenderSeparator( - ToolStripSeparatorRenderEventArgs e) - { - if (e.ToolStrip.IsDropDown && EnsureRenderer()) { - renderer.SetParameters(MenuClass, (int)MenuParts.PopupSeparator, 0); - var rect = new Rectangle( - e.ToolStrip.DisplayRectangle.Left, - 0, - e.ToolStrip.DisplayRectangle.Width, - e.Item.Height); - renderer.DrawBackground(e.Graphics, rect, rect); - } - else { - base.OnRenderSeparator(e); - } - } - - protected override void OnRenderSplitButtonBackground( - ToolStripItemRenderEventArgs e) - { - if (!EnsureRenderer()) { - base.OnRenderSplitButtonBackground(e); - return; - } - var sb = (ToolStripSplitButton)e.Item; - base.OnRenderSplitButtonBackground(e); - OnRenderArrow(new ToolStripArrowRenderEventArgs( - e.Graphics, - sb, - sb.DropDownButtonBounds, - Color.Red, - ArrowDirection.Down)); - } - - protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) - { - if (!EnsureRenderer()) { - base.OnRenderToolStripBackground(e); - return; - } - if (e.ToolStrip.IsDropDown) { - renderer.SetParameters(MenuClass, (int)MenuParts.PopupBackground, 0); - } - else { - if (e.ToolStrip.Parent is ToolStripPanel) { - return; - } - if (IsElementDefined(RebarClass, RebarBackground, 0)) { - renderer.SetParameters(RebarClass, RebarBackground, 0); - } - else { - renderer.SetParameters(RebarClass, 0, 0); - } - } - - if (renderer.IsBackgroundPartiallyTransparent()) { - renderer.DrawParentBackground( - e.Graphics, - e.ToolStrip.ClientRectangle, - e.ToolStrip); - } - renderer.DrawBackground( - e.Graphics, - e.ToolStrip.ClientRectangle, - e.AffectedBounds); - } - - protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) - { - if (!EnsureRenderer()) { - base.OnRenderToolStripBorder(e); - return; - } - renderer.SetParameters(MenuClass, (int)MenuParts.PopupBorders, 0); - if (e.ToolStrip.IsDropDown) { - var oldClip = e.Graphics.Clip; - var insideRect = e.ToolStrip.ClientRectangle; - insideRect.Inflate(-1, -1); - e.Graphics.ExcludeClip(insideRect); - renderer.DrawBackground( - e.Graphics, - e.ToolStrip.ClientRectangle, - e.AffectedBounds); - e.Graphics.Clip = oldClip; - } - } - - protected override void OnRenderToolStripPanelBackground( - ToolStripPanelRenderEventArgs e) - { - if (!EnsureRenderer()) { - base.OnRenderToolStripPanelBackground(e); - return; - } - if (IsElementDefined(RebarClass, RebarBackground, 0)) { - renderer.SetParameters(RebarClass, RebarBackground, 0); - } - else { - renderer.SetParameters(RebarClass, 0, 0); - } - - if (renderer.IsBackgroundPartiallyTransparent()) { - renderer.DrawParentBackground( - e.Graphics, - e.ToolStripPanel.ClientRectangle, - e.ToolStripPanel); - } - renderer.DrawBackground(e.Graphics, e.ToolStripPanel.ClientRectangle); - - e.Handled = true; - } - - private struct VSEInternal - { - public readonly string cls; - - public readonly int part; - - public readonly int state; - - public VSEInternal(string cls, int part, int state) - { - this.cls = cls; - this.part = part; - this.state = state; - } - } - - private static class NativeMethods - { - [DllImport("uxtheme.dll")] - public extern static int GetThemeMargins( - IntPtr hTheme, - IntPtr hdc, - int iPartId, - int iStateId, - int iPropId, - IntPtr rect, - out MARGINS pMargins); - - [StructLayout(LayoutKind.Sequential)] - public struct MARGINS - { - public int cxLeftWidth; - - public int cxRightWidth; - - public int cyTopHeight; - - public int cyBottomHeight; - } - } - } -} diff --git a/NgenInstaller.cs b/NgenInstaller.cs deleted file mode 100644 index fb516f89..00000000 --- a/NgenInstaller.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections; -using System.ComponentModel; -using System.Configuration.Install; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace NMaier.SimpleDlna -{ - [RunInstaller(true)] - public class NgenInstaller : Installer - { - public override void Install(IDictionary stateSaver) - { - base.Install(stateSaver); - using (var proc = new Process()) { - proc.StartInfo.FileName = Path.Combine( - RuntimeEnvironment.GetRuntimeDirectory(), - "ngen.exe" - ); - proc.StartInfo.Arguments = $"install /nologo \"{Assembly.GetExecutingAssembly().Location}\""; - proc.StartInfo.UseShellExecute = false; - proc.StartInfo.CreateNoWindow = true; - proc.Start(); - proc.WaitForExit(); - if (proc.ExitCode != 0) { - throw new Exception("Failed to run ngen"); - } - } - } - } -} diff --git a/SimpleDLNA/FormAbout.Designer.cs b/SimpleDLNA/FormAbout.Designer.cs deleted file mode 100644 index 13cba54c..00000000 --- a/SimpleDLNA/FormAbout.Designer.cs +++ /dev/null @@ -1,170 +0,0 @@ -namespace NMaier.SimpleDlna.GUI -{ - sealed partial class FormAbout - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); - this.logoPictureBox = new System.Windows.Forms.PictureBox(); - this.Product = new System.Windows.Forms.Label(); - this.Version = new System.Windows.Forms.Label(); - this.Copyright = new System.Windows.Forms.Label(); - this.License = new System.Windows.Forms.TextBox(); - this.okButton = new System.Windows.Forms.Button(); - this.tableLayoutPanel.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit(); - this.SuspendLayout(); - // - // tableLayoutPanel - // - this.tableLayoutPanel.ColumnCount = 2; - this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F)); - this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 67F)); - this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0); - this.tableLayoutPanel.Controls.Add(this.Product, 1, 0); - this.tableLayoutPanel.Controls.Add(this.Version, 1, 1); - this.tableLayoutPanel.Controls.Add(this.Copyright, 1, 2); - this.tableLayoutPanel.Controls.Add(this.License, 1, 4); - this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5); - this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel.Location = new System.Drawing.Point(10, 10); - this.tableLayoutPanel.Name = "tableLayoutPanel"; - this.tableLayoutPanel.RowCount = 6; - this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); - this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); - this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); - this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); - this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); - this.tableLayoutPanel.Size = new System.Drawing.Size(487, 307); - this.tableLayoutPanel.TabIndex = 0; - // - // logoPictureBox - // - this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.logoPictureBox.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.banner; - this.logoPictureBox.Location = new System.Drawing.Point(3, 3); - this.logoPictureBox.Name = "logoPictureBox"; - this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6); - this.logoPictureBox.Size = new System.Drawing.Size(154, 301); - this.logoPictureBox.TabIndex = 12; - this.logoPictureBox.TabStop = false; - // - // Product - // - this.Product.Dock = System.Windows.Forms.DockStyle.Fill; - this.Product.Location = new System.Drawing.Point(167, 0); - this.Product.Margin = new System.Windows.Forms.Padding(7, 0, 3, 0); - this.Product.MaximumSize = new System.Drawing.Size(0, 20); - this.Product.Name = "Product"; - this.Product.Size = new System.Drawing.Size(317, 20); - this.Product.TabIndex = 19; - this.Product.Text = "Product Name"; - this.Product.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // Version - // - this.Version.Dock = System.Windows.Forms.DockStyle.Fill; - this.Version.Location = new System.Drawing.Point(167, 30); - this.Version.Margin = new System.Windows.Forms.Padding(7, 0, 3, 0); - this.Version.MaximumSize = new System.Drawing.Size(0, 20); - this.Version.Name = "Version"; - this.Version.Size = new System.Drawing.Size(317, 20); - this.Version.TabIndex = 0; - this.Version.Text = "Version"; - this.Version.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // Copyright - // - this.Copyright.Dock = System.Windows.Forms.DockStyle.Fill; - this.Copyright.Location = new System.Drawing.Point(167, 60); - this.Copyright.Margin = new System.Windows.Forms.Padding(7, 0, 3, 0); - this.Copyright.MaximumSize = new System.Drawing.Size(0, 20); - this.Copyright.Name = "Copyright"; - this.Copyright.Size = new System.Drawing.Size(317, 20); - this.Copyright.TabIndex = 21; - this.Copyright.Text = "Copyright"; - this.Copyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // License - // - this.License.AcceptsReturn = true; - this.License.AcceptsTab = true; - this.License.Dock = System.Windows.Forms.DockStyle.Fill; - this.License.Location = new System.Drawing.Point(167, 123); - this.License.Margin = new System.Windows.Forms.Padding(7, 3, 3, 3); - this.License.Multiline = true; - this.License.Name = "License"; - this.License.ReadOnly = true; - this.License.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.License.Size = new System.Drawing.Size(317, 147); - this.License.TabIndex = 23; - this.License.TabStop = false; - this.License.Text = "Description"; - // - // okButton - // - this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.okButton.Location = new System.Drawing.Point(397, 277); - this.okButton.Name = "okButton"; - this.okButton.Size = new System.Drawing.Size(87, 27); - this.okButton.TabIndex = 24; - this.okButton.Text = "&OK"; - // - // FormAbout - // - this.AcceptButton = this.okButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(507, 327); - this.Controls.Add(this.tableLayoutPanel); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "FormAbout"; - this.Padding = new System.Windows.Forms.Padding(10, 10, 10, 10); - this.ShowIcon = false; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "FormAbout"; - this.tableLayoutPanel.ResumeLayout(false); - this.tableLayoutPanel.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit(); - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; - private System.Windows.Forms.PictureBox logoPictureBox; - private System.Windows.Forms.Label Product; - private System.Windows.Forms.Label Version; - private System.Windows.Forms.Label Copyright; - private System.Windows.Forms.TextBox License; - private System.Windows.Forms.Button okButton; - } -} diff --git a/SimpleDLNA/FormAbout.cs b/SimpleDLNA/FormAbout.cs deleted file mode 100644 index 7cf6a93c..00000000 --- a/SimpleDLNA/FormAbout.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text; -using NMaier.SimpleDlna.GUI.Properties; -using NMaier.SimpleDlna.Utilities; -using NMaier.Windows.Forms; - -namespace NMaier.SimpleDlna.GUI -{ - internal sealed partial class FormAbout : Form - { - public FormAbout() - { - InitializeComponent(); - Text = $"About {ProductInformation.Title}"; - Product.Text = ProductInformation.Title; - Product.Font = BoldFont; - Version.Text = $"Version {ProductInformation.ProductVersion}"; - Copyright.Text = ProductInformation.Copyright; - Copyright.Font = ItalicFont; - License.Text = Encoding.UTF8.GetString(Resources.LICENSE); - } - } -} diff --git a/SimpleDLNA/FormAbout.resx b/SimpleDLNA/FormAbout.resx deleted file mode 100644 index 1af7de15..00000000 --- a/SimpleDLNA/FormAbout.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/SimpleDLNA/FormMain.Designer.cs b/SimpleDLNA/FormMain.Designer.cs deleted file mode 100644 index 44da6b3e..00000000 --- a/SimpleDLNA/FormMain.Designer.cs +++ /dev/null @@ -1,527 +0,0 @@ -namespace NMaier.SimpleDlna.GUI -{ - partial class FormMain - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - if (httpServer != null) { - httpServer.Dispose(); - httpServer = null; - } - if (appenderTimer != null) - appenderTimer.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormMain)); - this.listDescriptions = new System.Windows.Forms.ListView(); - this.colName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colDirectories = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colActive = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); - this.ctxStartStop = new System.Windows.Forms.ToolStripMenuItem(); - this.ctxEdit = new System.Windows.Forms.ToolStripMenuItem(); - this.ctxRemove = new System.Windows.Forms.ToolStripMenuItem(); - this.ctxRescan = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator(); - this.ctxNewServer = new System.Windows.Forms.ToolStripMenuItem(); - this.listImages = new System.Windows.Forms.ImageList(this.components); - this.buttonNewServer = new System.Windows.Forms.Button(); - this.buttonEdit = new System.Windows.Forms.Button(); - this.buttonStartStop = new System.Windows.Forms.Button(); - this.buttonRemove = new System.Windows.Forms.Button(); - this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components); - this.notifyContext = new System.Windows.Forms.ContextMenuStrip(this.components); - this.showContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.rescanAllContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ContextSeperatorPre = new System.Windows.Forms.ToolStripSeparator(); - this.ContextSeperatorPost = new System.Windows.Forms.ToolStripSeparator(); - this.exitContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.mainMenu = new System.Windows.Forms.MenuStrip(); - this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.newServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); - this.openInBrowserToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); - this.dropCacheToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); - this.hideToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.homepageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.logger = new System.Windows.Forms.ListView(); - this.colLogTime = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colLogLogger = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colLogMessage = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.buttonRescan = new System.Windows.Forms.Button(); - this.contextMenu.SuspendLayout(); - this.notifyContext.SuspendLayout(); - this.mainMenu.SuspendLayout(); - this.SuspendLayout(); - // - // listDescriptions - // - this.listDescriptions.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.listDescriptions.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.colName, - this.colDirectories, - this.colActive}); - this.listDescriptions.ContextMenuStrip = this.contextMenu; - this.listDescriptions.FullRowSelect = true; - this.listDescriptions.HideSelection = false; - this.listDescriptions.Location = new System.Drawing.Point(14, 31); - this.listDescriptions.MultiSelect = false; - this.listDescriptions.Name = "listDescriptions"; - this.listDescriptions.Size = new System.Drawing.Size(698, 212); - this.listDescriptions.SmallImageList = this.listImages; - this.listDescriptions.TabIndex = 5; - this.listDescriptions.UseCompatibleStateImageBehavior = false; - this.listDescriptions.View = System.Windows.Forms.View.Details; - this.listDescriptions.SelectedIndexChanged += new System.EventHandler(this.ListDescriptions_SelectedIndexChanged); - this.listDescriptions.DoubleClick += new System.EventHandler(this.listDescriptions_DoubleClick); - // - // colName - // - this.colName.Text = "Name"; - // - // colDirectories - // - this.colDirectories.Text = "Directories"; - this.colDirectories.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - // - // colActive - // - this.colActive.Text = "Active"; - // - // contextMenu - // - this.contextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ctxStartStop, - this.ctxEdit, - this.ctxRemove, - this.ctxRescan, - this.toolStripMenuItem5, - this.ctxNewServer}); - this.contextMenu.Name = "contextMenu"; - this.contextMenu.Size = new System.Drawing.Size(134, 120); - // - // ctxStartStop - // - this.ctxStartStop.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.active; - this.ctxStartStop.Name = "ctxStartStop"; - this.ctxStartStop.Size = new System.Drawing.Size(133, 22); - this.ctxStartStop.Text = "Start/Stop"; - this.ctxStartStop.Click += new System.EventHandler(this.ButtonStartStop_Click); - // - // ctxEdit - // - this.ctxEdit.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.edit; - this.ctxEdit.Name = "ctxEdit"; - this.ctxEdit.Size = new System.Drawing.Size(133, 22); - this.ctxEdit.Text = "Edit"; - this.ctxEdit.Click += new System.EventHandler(this.ButtonEdit_Click); - // - // ctxRemove - // - this.ctxRemove.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.remove; - this.ctxRemove.Name = "ctxRemove"; - this.ctxRemove.Size = new System.Drawing.Size(133, 22); - this.ctxRemove.Text = "Remove"; - this.ctxRemove.Click += new System.EventHandler(this.buttonRemove_Click); - // - // ctxRescan - // - this.ctxRescan.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.refreshing; - this.ctxRescan.Name = "ctxRescan"; - this.ctxRescan.Size = new System.Drawing.Size(133, 22); - this.ctxRescan.Text = "Rescan"; - this.ctxRescan.Click += new System.EventHandler(this.buttonRescan_Click); - // - // toolStripMenuItem5 - // - this.toolStripMenuItem5.Name = "toolStripMenuItem5"; - this.toolStripMenuItem5.Size = new System.Drawing.Size(130, 6); - // - // ctxNewServer - // - this.ctxNewServer.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.add; - this.ctxNewServer.Name = "ctxNewServer"; - this.ctxNewServer.Size = new System.Drawing.Size(133, 22); - this.ctxNewServer.Text = "New Server"; - this.ctxNewServer.Click += new System.EventHandler(this.ButtonNewServer_Click); - // - // listImages - // - this.listImages.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit; - this.listImages.ImageSize = new System.Drawing.Size(16, 16); - this.listImages.TransparentColor = System.Drawing.Color.Transparent; - // - // buttonNewServer - // - this.buttonNewServer.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonNewServer.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.add; - this.buttonNewServer.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.buttonNewServer.Location = new System.Drawing.Point(625, 250); - this.buttonNewServer.Name = "buttonNewServer"; - this.buttonNewServer.Size = new System.Drawing.Size(87, 27); - this.buttonNewServer.TabIndex = 0; - this.buttonNewServer.Text = "New"; - this.buttonNewServer.UseVisualStyleBackColor = true; - this.buttonNewServer.Click += new System.EventHandler(this.ButtonNewServer_Click); - // - // buttonEdit - // - this.buttonEdit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.buttonEdit.Enabled = false; - this.buttonEdit.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.edit; - this.buttonEdit.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.buttonEdit.Location = new System.Drawing.Point(108, 250); - this.buttonEdit.Name = "buttonEdit"; - this.buttonEdit.Size = new System.Drawing.Size(87, 27); - this.buttonEdit.TabIndex = 2; - this.buttonEdit.Text = "Edit"; - this.buttonEdit.UseVisualStyleBackColor = true; - this.buttonEdit.Click += new System.EventHandler(this.ButtonEdit_Click); - // - // buttonStartStop - // - this.buttonStartStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.buttonStartStop.Enabled = false; - this.buttonStartStop.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.active; - this.buttonStartStop.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.buttonStartStop.Location = new System.Drawing.Point(14, 250); - this.buttonStartStop.Name = "buttonStartStop"; - this.buttonStartStop.Size = new System.Drawing.Size(87, 27); - this.buttonStartStop.TabIndex = 1; - this.buttonStartStop.Text = "Start"; - this.buttonStartStop.UseVisualStyleBackColor = true; - this.buttonStartStop.Click += new System.EventHandler(this.ButtonStartStop_Click); - // - // buttonRemove - // - this.buttonRemove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.buttonRemove.Enabled = false; - this.buttonRemove.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.remove; - this.buttonRemove.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.buttonRemove.Location = new System.Drawing.Point(203, 250); - this.buttonRemove.Name = "buttonRemove"; - this.buttonRemove.Size = new System.Drawing.Size(87, 27); - this.buttonRemove.TabIndex = 3; - this.buttonRemove.Text = "Remove"; - this.buttonRemove.UseVisualStyleBackColor = true; - this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click); - // - // notifyIcon - // - this.notifyIcon.ContextMenuStrip = this.notifyContext; - this.notifyIcon.DoubleClick += new System.EventHandler(this.notifyIcon_DoubleClick); - // - // notifyContext - // - this.notifyContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.showContextMenuItem, - this.rescanAllContextMenuItem, - this.ContextSeperatorPre, - this.ContextSeperatorPost, - this.exitContextMenuItem}); - this.notifyContext.Name = "notifyContext"; - this.notifyContext.Size = new System.Drawing.Size(153, 104); - this.notifyContext.Opening += new System.ComponentModel.CancelEventHandler(this.notifyContext_Opening); - // - // showContextMenuItem - // - this.showContextMenuItem.Name = "showContextMenuItem"; - this.showContextMenuItem.Size = new System.Drawing.Size(152, 22); - this.showContextMenuItem.Text = "Show"; - this.showContextMenuItem.Click += new System.EventHandler(this.notifyIcon_DoubleClick); - // - // rescanAllContextMenuItem - // - this.rescanAllContextMenuItem.Name = "rescanAllContextMenuItem"; - this.rescanAllContextMenuItem.Size = new System.Drawing.Size(152, 22); - this.rescanAllContextMenuItem.Text = "Rescan all"; - this.rescanAllContextMenuItem.Click += new System.EventHandler(this.rescanAllContextMenuItem_Click); - // - // ContextSeperatorPre - // - this.ContextSeperatorPre.Name = "ContextSeperatorPre"; - this.ContextSeperatorPre.Size = new System.Drawing.Size(149, 6); - // - // ContextSeperatorPost - // - this.ContextSeperatorPost.Name = "ContextSeperatorPost"; - this.ContextSeperatorPost.Size = new System.Drawing.Size(149, 6); - // - // exitContextMenuItem - // - this.exitContextMenuItem.Name = "exitContextMenuItem"; - this.exitContextMenuItem.Size = new System.Drawing.Size(152, 22); - this.exitContextMenuItem.Text = "Exit"; - this.exitContextMenuItem.Click += new System.EventHandler(this.exitContextMenuItem_Click); - // - // mainMenu - // - this.mainMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.fileToolStripMenuItem, - this.helpToolStripMenuItem}); - this.mainMenu.Location = new System.Drawing.Point(0, 0); - this.mainMenu.Name = "mainMenu"; - this.mainMenu.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2); - this.mainMenu.Size = new System.Drawing.Size(727, 24); - this.mainMenu.TabIndex = 6; - this.mainMenu.Text = "menuStrip1"; - // - // fileToolStripMenuItem - // - this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.newServerToolStripMenuItem, - this.settingsToolStripMenuItem, - this.toolStripMenuItem2, - this.openInBrowserToolStripMenuItem, - this.toolStripMenuItem3, - this.dropCacheToolStripMenuItem, - this.toolStripMenuItem4, - this.hideToolStripMenuItem, - this.exitToolStripMenuItem}); - this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; - this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); - this.fileToolStripMenuItem.Text = "&File"; - // - // newServerToolStripMenuItem - // - this.newServerToolStripMenuItem.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.add; - this.newServerToolStripMenuItem.Name = "newServerToolStripMenuItem"; - this.newServerToolStripMenuItem.Size = new System.Drawing.Size(161, 22); - this.newServerToolStripMenuItem.Text = "New Server"; - this.newServerToolStripMenuItem.Click += new System.EventHandler(this.ButtonNewServer_Click); - // - // settingsToolStripMenuItem - // - this.settingsToolStripMenuItem.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.preferences; - this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; - this.settingsToolStripMenuItem.Size = new System.Drawing.Size(161, 22); - this.settingsToolStripMenuItem.Text = "Settings"; - this.settingsToolStripMenuItem.Click += new System.EventHandler(this.settingsToolStripMenuItem_Click); - // - // toolStripMenuItem2 - // - this.toolStripMenuItem2.Name = "toolStripMenuItem2"; - this.toolStripMenuItem2.Size = new System.Drawing.Size(158, 6); - // - // openInBrowserToolStripMenuItem - // - this.openInBrowserToolStripMenuItem.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.go; - this.openInBrowserToolStripMenuItem.Name = "openInBrowserToolStripMenuItem"; - this.openInBrowserToolStripMenuItem.Size = new System.Drawing.Size(161, 22); - this.openInBrowserToolStripMenuItem.Text = "Open in Browser"; - this.openInBrowserToolStripMenuItem.Click += new System.EventHandler(this.openInBrowserToolStripMenuItem_Click); - // - // toolStripMenuItem3 - // - this.toolStripMenuItem3.Name = "toolStripMenuItem3"; - this.toolStripMenuItem3.Size = new System.Drawing.Size(158, 6); - // - // dropCacheToolStripMenuItem - // - this.dropCacheToolStripMenuItem.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.delete; - this.dropCacheToolStripMenuItem.Name = "dropCacheToolStripMenuItem"; - this.dropCacheToolStripMenuItem.Size = new System.Drawing.Size(161, 22); - this.dropCacheToolStripMenuItem.Text = "Drop cache"; - this.dropCacheToolStripMenuItem.Click += new System.EventHandler(this.dropCacheToolStripMenuItem_Click); - // - // toolStripMenuItem4 - // - this.toolStripMenuItem4.Name = "toolStripMenuItem4"; - this.toolStripMenuItem4.Size = new System.Drawing.Size(158, 6); - // - // hideToolStripMenuItem - // - this.hideToolStripMenuItem.Name = "hideToolStripMenuItem"; - this.hideToolStripMenuItem.Size = new System.Drawing.Size(161, 22); - this.hideToolStripMenuItem.Text = "Hide"; - this.hideToolStripMenuItem.Click += new System.EventHandler(this.hideToolStripMenuItem_Click); - // - // exitToolStripMenuItem - // - this.exitToolStripMenuItem.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.close; - this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; - this.exitToolStripMenuItem.Size = new System.Drawing.Size(161, 22); - this.exitToolStripMenuItem.Text = "&Exit"; - this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitContextMenuItem_Click); - // - // helpToolStripMenuItem - // - this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.homepageToolStripMenuItem, - this.aboutToolStripMenuItem}); - this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; - this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20); - this.helpToolStripMenuItem.Text = "Help"; - // - // homepageToolStripMenuItem - // - this.homepageToolStripMenuItem.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.homepage; - this.homepageToolStripMenuItem.Name = "homepageToolStripMenuItem"; - this.homepageToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.homepageToolStripMenuItem.Text = "Homepage"; - this.homepageToolStripMenuItem.Click += new System.EventHandler(this.homepageToolStripMenuItem_Click); - // - // aboutToolStripMenuItem - // - this.aboutToolStripMenuItem.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.about; - this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; - this.aboutToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.aboutToolStripMenuItem.Text = "About"; - this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); - // - // logger - // - this.logger.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.logger.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.colLogTime, - this.colLogLogger, - this.colLogMessage}); - this.logger.FullRowSelect = true; - this.logger.HideSelection = false; - this.logger.Location = new System.Drawing.Point(14, 284); - this.logger.MultiSelect = false; - this.logger.Name = "logger"; - this.logger.Size = new System.Drawing.Size(698, 170); - this.logger.SmallImageList = this.listImages; - this.logger.TabIndex = 7; - this.logger.UseCompatibleStateImageBehavior = false; - this.logger.View = System.Windows.Forms.View.Details; - // - // colLogTime - // - this.colLogTime.Text = "Time"; - this.colLogTime.Width = 80; - // - // colLogLogger - // - this.colLogLogger.Text = "Logger"; - // - // colLogMessage - // - this.colLogMessage.Text = "Message"; - this.colLogMessage.Width = 200; - // - // buttonRescan - // - this.buttonRescan.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.buttonRescan.Enabled = false; - this.buttonRescan.Image = global::NMaier.SimpleDlna.GUI.Properties.Resources.refreshing; - this.buttonRescan.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.buttonRescan.Location = new System.Drawing.Point(297, 250); - this.buttonRescan.Name = "buttonRescan"; - this.buttonRescan.Size = new System.Drawing.Size(87, 27); - this.buttonRescan.TabIndex = 4; - this.buttonRescan.Text = "Rescan"; - this.buttonRescan.UseVisualStyleBackColor = true; - this.buttonRescan.Click += new System.EventHandler(this.buttonRescan_Click); - // - // FormMain - // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(727, 468); - this.Controls.Add(this.buttonRescan); - this.Controls.Add(this.logger); - this.Controls.Add(this.mainMenu); - this.Controls.Add(this.buttonRemove); - this.Controls.Add(this.buttonStartStop); - this.Controls.Add(this.buttonEdit); - this.Controls.Add(this.buttonNewServer); - this.Controls.Add(this.listDescriptions); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MainMenuStrip = this.mainMenu; - this.Name = "FormMain"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "SimpleDLNA"; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormMain_FormClosing); - this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormMain_FormClosed); - this.Resize += new System.EventHandler(this.FormMain_Resize); - this.contextMenu.ResumeLayout(false); - this.notifyContext.ResumeLayout(false); - this.mainMenu.ResumeLayout(false); - this.mainMenu.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.ListView listDescriptions; - private System.Windows.Forms.Button buttonNewServer; - private System.Windows.Forms.ColumnHeader colName; - private System.Windows.Forms.ColumnHeader colDirectories; - private System.Windows.Forms.ColumnHeader colActive; - private System.Windows.Forms.Button buttonEdit; - private System.Windows.Forms.Button buttonStartStop; - private System.Windows.Forms.Button buttonRemove; - private System.Windows.Forms.NotifyIcon notifyIcon; - private System.Windows.Forms.ContextMenuStrip notifyContext; - private System.Windows.Forms.ToolStripMenuItem showContextMenuItem; - private System.Windows.Forms.ToolStripSeparator ContextSeperatorPost; - private System.Windows.Forms.ToolStripMenuItem exitContextMenuItem; - private System.Windows.Forms.MenuStrip mainMenu; - private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem hideToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; - private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem openInBrowserToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3; - private System.Windows.Forms.ListView logger; - private System.Windows.Forms.ColumnHeader colLogMessage; - private System.Windows.Forms.ColumnHeader colLogLogger; - private System.Windows.Forms.ImageList listImages; - private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem; - private System.Windows.Forms.Button buttonRescan; - private System.Windows.Forms.ColumnHeader colLogTime; - private System.Windows.Forms.ToolStripMenuItem dropCacheToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4; - private System.Windows.Forms.ToolStripMenuItem homepageToolStripMenuItem; - private System.Windows.Forms.ContextMenuStrip contextMenu; - private System.Windows.Forms.ToolStripMenuItem ctxStartStop; - private System.Windows.Forms.ToolStripMenuItem ctxEdit; - private System.Windows.Forms.ToolStripMenuItem ctxRemove; - private System.Windows.Forms.ToolStripMenuItem ctxRescan; - private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5; - private System.Windows.Forms.ToolStripMenuItem ctxNewServer; - private System.Windows.Forms.ToolStripMenuItem newServerToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator ContextSeperatorPre; - private System.Windows.Forms.ToolStripMenuItem rescanAllContextMenuItem; - } -} - diff --git a/SimpleDLNA/FormMain.cs b/SimpleDLNA/FormMain.cs deleted file mode 100644 index f2a23206..00000000 --- a/SimpleDLNA/FormMain.cs +++ /dev/null @@ -1,663 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.IO.Pipes; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Timers; -using System.Windows.Forms; -using System.Xml.Serialization; -using log4net; -using log4net.Appender; -using log4net.Config; -using log4net.Core; -using log4net.Layout; -using NMaier.SimpleDlna.GUI.Properties; -using NMaier.SimpleDlna.Server; -using Form = NMaier.Windows.Forms.Form; -using SystemInformation = NMaier.SimpleDlna.Utilities.SystemInformation; -using Timer = System.Timers.Timer; - -namespace NMaier.SimpleDlna.GUI -{ - public partial class FormMain : Form, IAppender - { - private const string DESCRIPTOR_FILE = "descriptors.xml"; - - private bool canClose; - - private static readonly Settings config = Settings.Default; - - private readonly FileInfo cacheFile = - new FileInfo(Path.Combine(CacheDir, "sdlna.cache")); - -#if DEBUG - private readonly FileInfo logFile = - new FileInfo(Path.Combine(CacheDir, "sdlna.dbg.log")); -#else - private readonly FileInfo logFile = - new FileInfo(Path.Combine(CacheDir, "sdlna.log")); -#endif - - private readonly object appenderLock = new object(); - - private readonly Timer appenderTimer = - new Timer(2000); - - private readonly ConcurrentQueue pendingLogEntries = - new ConcurrentQueue(); - - private static readonly ILog log = LogManager.GetLogger(typeof (FormMain)); - - private bool minimized = config.startminimized; - - private HttpServer httpServer; - - private bool logging; - - public FormMain() - { - HandleCreated += (o, e) => { logging = true; }; - HandleDestroyed += (o, e) => { logging = false; }; - - InitializeComponent(); - - listImages.Images.Add("idle", Resources.idle); - listImages.Images.Add("active", Resources.active); - listImages.Images.Add("inactive", Resources.inactive); - listImages.Images.Add("refreshing", Resources.refreshing); - listImages.Images.Add("loading", Resources.loading); - listImages.Images.Add("info", Resources.info); - listImages.Images.Add("warn", Resources.warn); - listImages.Images.Add("error", Resources.error); - listImages.Images.Add("server", Resources.server.ToBitmap()); - - appenderTimer.Elapsed += (s, e) => { BeginInvoke((Action)(() => { DoAppendInternal(s, e); })); }; - - SetupLogging(); - - StartPipeNotification(); - - notifyIcon.Icon = Icon; - if (!string.IsNullOrWhiteSpace(config.cache)) { - cacheFile = new FileInfo(config.cache); - } - CreateHandle(); - SetupServer(); - } - - protected sealed override void CreateHandle() - { - base.CreateHandle(); - } - - private static string CacheDir - { - get { - var rv = config.cache; - if (!string.IsNullOrWhiteSpace(rv) && Directory.Exists(rv)) { - return rv; - } - try { - try { - rv = Environment.GetFolderPath( - Environment.SpecialFolder.LocalApplicationData); - if (string.IsNullOrEmpty(rv)) { - throw new IOException("Cannot get LocalAppData"); - } - } - catch (Exception) { - rv = Environment.GetFolderPath( - Environment.SpecialFolder.ApplicationData); - if (string.IsNullOrEmpty(rv)) { - throw new IOException("Cannot get LocalAppData"); - } - } - rv = Path.Combine(rv, "SimpleDLNA"); - if (!Directory.Exists(rv)) { - Directory.CreateDirectory(rv); - } - return rv; - } - catch (Exception) { - return Path.GetTempPath(); - } - } - } - - public override string Text - { - get { return base.Text; } - set { - base.Text = value; - notifyIcon.Text = value; - } - } - - private void aboutToolStripMenuItem_Click(object sender, EventArgs e) - { - using (var about = new FormAbout()) { - about.ShowDialog(); - } - } - - private void ButtonEdit_Click(object sender, EventArgs e) - { - var item = listDescriptions.SelectedItems[0] as ServerListViewItem; - if (item == null) { - return; - } - using (var ns = new FormServer(item.Description)) { - var rv = ns.ShowDialog(); - if (rv == DialogResult.OK) { - var desc = ns.Description; - Task.Factory.StartNew(() => - { - item.UpdateInfo(desc); - BeginInvoke((Action)SaveConfig); - }); - } - } - } - - private void ButtonNewServer_Click(object sender, EventArgs e) - { - using (var ns = new FormServer()) { - var rv = ns.ShowDialog(); - if (rv == DialogResult.OK) { - var item = new ServerListViewItem( - httpServer, cacheFile, ns.Description); - listDescriptions.Items.Add(item); - item.Load(); - SaveConfig(); - } - } - } - - private void buttonRemove_Click(object sender, EventArgs e) - { - var item = listDescriptions.SelectedItems[0] as ServerListViewItem; - if (item == null) { - return; - } - var dr = MessageBox.Show( - $"Would you like to remove {item.Description.Name}?", - "Remove Server", - MessageBoxButtons.YesNo, - MessageBoxIcon.Question); - if (dr != DialogResult.Yes) { - return; - } - if (item.Description.Active) { - item.Toggle(); - } - listDescriptions.Items.Remove(item); - SaveConfig(); - } - - private void buttonRescan_Click(object sender, EventArgs e) - { - try { - var item = listDescriptions.SelectedItems[0] as ServerListViewItem; - if (item == null) { - return; - } - item.Rescan(); - } - catch (Exception ex) { - MessageBox.Show( - this, ex.Message, "Error", MessageBoxButtons.OK, - MessageBoxIcon.Error); - } - } - - private void ButtonStartStop_Click(object sender, EventArgs e) - { - var item = listDescriptions.SelectedItems[0] as ServerListViewItem; - if (item == null) { - return; - } - Task.Factory.StartNew(() => - { - item.Toggle(); - BeginInvoke((Action)(() => - { - SaveConfig(); - ctxStartStop.Text = buttonStartStop.Text = - item.Description.Active ? "Stop" : "Start"; - ctxStartStop.Image = buttonStartStop.Image = - item.Description.Active - ? Resources.inactive - : Resources.active; - })); - }); - } - - private void dropCacheToolStripMenuItem_Click(object sender, EventArgs e) - { - var res = MessageBox.Show( - this, - "Are you sure you want to drop the cache?", - "Drop cache", - MessageBoxButtons.YesNo, - MessageBoxIcon.Warning); - if (res != DialogResult.Yes) { - return; - } - var running = (from ServerListViewItem item in listDescriptions.Items - where item.Description.Active - select item).ToList(); - foreach (var item in running) { - item.Toggle(); - } - try { - if (cacheFile.Exists) { - cacheFile.Delete(); - } - } - catch (Exception ex) { - log.Error( - $"Failed to remove cache file {cacheFile.FullName}", - ex); - } - foreach (var item in running) { - item.Toggle(); - } - } - - private void exitContextMenuItem_Click(object sender, EventArgs e) - { - canClose = true; - notifyIcon_DoubleClick(sender, e); - Close(); - } - - private void FormMain_FormClosed(object sender, FormClosedEventArgs e) - { - Text = "Going down..."; - httpServer.Dispose(); - httpServer = null; - } - - private void FormMain_FormClosing(object sender, FormClosingEventArgs e) - { - e.Cancel = !canClose; - if (!canClose) { - WindowState = FormWindowState.Minimized; - } - } - - private void FormMain_Resize(object sender, EventArgs e) - { - if (WindowState == FormWindowState.Minimized) { - ShowInTaskbar = false; - minimized = true; - Hide(); - } - } - - private void hideToolStripMenuItem_Click(object sender, EventArgs e) - { - WindowState = FormWindowState.Minimized; - } - - private void homepageToolStripMenuItem_Click(object sender, EventArgs e) - { - Process.Start("http://nmaier.github.io/simpleDLNA/"); - } - - private void listDescriptions_DoubleClick(object sender, EventArgs e) - { - if (buttonEdit.Enabled) { - ButtonEdit_Click(sender, e); - } - else { - ButtonNewServer_Click(sender, e); - } - } - - private void ListDescriptions_SelectedIndexChanged(object sender, - EventArgs e) - { - var enable = listDescriptions.SelectedItems.Count != 0; - ctxStartStop.Enabled = ctxRemove.Enabled = ctxEdit.Enabled = - buttonStartStop.Enabled = buttonRemove.Enabled = buttonEdit.Enabled = - enable; - if (enable) { - var item = (ServerListViewItem)listDescriptions.SelectedItems[0]; - ctxStartStop.Text = buttonStartStop.Text = - item.Description.Active ? "Stop" : "Start"; - ctxStartStop.Image = buttonStartStop.Image = - item.Description.Active - ? Resources.inactive - : Resources.active; - ctxRescan.Enabled = buttonRescan.Enabled = item.Description.Active; - } - else { - ctxRescan.Enabled = buttonRescan.Enabled = false; - } - } - - private void LoadConfig() - { - var descs = LoadDescriptors(); - if (descs == null) { - throw new ArgumentException("Failed to load config"); - } - var items = new List(); - items.AddRange(descs.ToArray()); - listDescriptions.Items.AddRange(items.ToArray()); - - Task.Factory.StartNew(() => - { - var po = new ParallelOptions - { - MaxDegreeOfParallelism = Math.Min(2, Environment.ProcessorCount) - }; - Parallel.ForEach(descs, po, i => { i.Load(); }); - BeginInvoke((Action)(() => - { - config.Descriptors.Clear(); - SaveConfig(); - })); - }); - } - - private ServerListViewItem[] LoadDescriptors() - { - List rv; - try { - var serializer = new XmlSerializer(typeof (List)); - using (var reader = new StreamReader( - Path.Combine(CacheDir, DESCRIPTOR_FILE))) { - rv = serializer.Deserialize(reader) as List; - } - } - catch (Exception) { - rv = config.Descriptors; - } - return (from d in rv - let i = new ServerListViewItem(httpServer, cacheFile, d) - select i).ToArray(); - } - - private void notifyContext_Opening(object sender, - CancelEventArgs e) - { - var items = (from ToolStripItem i in notifyContext.Items - where i.Tag != null - select i).ToList(); - foreach (var i in items) { - notifyContext.Items.Remove(i); - } - items.Clear(); - if (listDescriptions.Items.Count == 0) { - ContextSeperatorPre.Visible = false; - return; - } - ContextSeperatorPre.Visible = true; - foreach (ServerListViewItem item in listDescriptions.Items) { - if (!item.Description.Active) { - continue; - } - var innerItem = item; - var menuItem = - new ToolStripMenuItem($"Rescan {item.Text}") - { - Tag = innerItem, - Image = Resources.refreshing - }; - menuItem.Click += (s, a) => - { - try { - innerItem.Rescan(); - } - catch (Exception) { - // no op - } - }; - items.Add(menuItem); - } - items.Reverse(); - var idx = notifyContext.Items.IndexOf(ContextSeperatorPre) + 1; - foreach (var i in items) { - notifyContext.Items.Insert(idx, i); - } - } - - private void notifyIcon_DoubleClick(object sender, EventArgs e) - { - minimized = false; - Show(); - WindowState = FormWindowState.Normal; - ShowInTaskbar = true; - if (logger != null && logger.Items.Count > 0) { - logger.EnsureVisible(logger.Items.Count - 1); - } - } - - private void openInBrowserToolStripMenuItem_Click(object sender, - EventArgs e) - { - Process.Start($"http://localhost:{httpServer.RealPort}/"); - } - - private void rescanAllContextMenuItem_Click(object sender, EventArgs e) - { - foreach (ServerListViewItem l in listDescriptions.Items) { - try { - l.Rescan(); - } - catch (Exception) { - // no op - } - } - } - - private void SaveConfig() - { - try { - var descs = (from ServerListViewItem item in listDescriptions.Items - select item.Description).ToArray(); - var serializer = new XmlSerializer(descs.GetType()); - var file = new FileInfo( - Path.Combine(CacheDir, DESCRIPTOR_FILE + ".tmp")); - using (var writer = new StreamWriter(file.FullName)) { - serializer.Serialize(writer, descs); - } - var outfile = Path.Combine(CacheDir, DESCRIPTOR_FILE); - File.Copy(file.FullName, outfile, true); - file.Delete(); - } - catch (Exception ex) { - log.Error("Failed to write descriptors", ex); - } - config.Save(); - } - - private void settingsToolStripMenuItem_Click(object sender, EventArgs e) - { - using (var settings = new FormSettings()) { - settings.ShowDialog(); - config.Save(); - SetupLogging(); - } - } - - private void SetupLogging() - { - if (!config.filelogging) { - BasicConfigurator.Configure(this); - return; - } - - var layout = new PatternLayout - { - ConversionPattern = "%date %6level [%3thread] %-30.30logger{1} - %message%newline%exception" - }; - layout.ActivateOptions(); - var fileAppender = new RollingFileAppender - { - File = logFile.FullName, - Layout = layout, - MaximumFileSize = "10MB", - MaxSizeRollBackups = 3, - RollingStyle = RollingFileAppender.RollingMode.Size, - ImmediateFlush = false, - Threshold = Level.Info - }; - fileAppender.ActivateOptions(); - - BasicConfigurator.Configure(this, fileAppender); - } - - private void SetupServer() - { - httpServer = new HttpServer((int)config.port); - LoadConfig(); - Text = $"{Text} - Port {httpServer.RealPort}"; - } - - private void StartPipeNotification() - { -#if DEBUG - log.Info("Debug mode / Skipping one-instance-only stuff"); -#else - if (SystemInformation.IsRunningOnMono()) { - // XXX Mono sometimes stack overflows for whatever reason. - return; - } - new Thread(() => - { - for (;;) { - try { - using (var pipe = new NamedPipeServerStream( - "simpledlnagui", PipeDirection.InOut)) { - pipe.WaitForConnection(); - pipe.ReadByte(); - BeginInvoke((Action)(() => - { - notifyIcon_DoubleClick(null, null); - BringToFront(); - })); - } - } - catch (Exception) { - // ignored - } - } - // ReSharper disable once FunctionNeverReturns - }) {IsBackground = true}.Start(); -#endif - } - - protected override void SetVisibleCore(bool value) - { - if (minimized) { - value = false; - if (!IsHandleCreated) { - CreateHandle(); - } - } - notifyIcon.Visible = !value; - base.SetVisibleCore(value); - } - - public void DoAppend(LoggingEvent loggingEvent) - { - if (!logging) { - return; - } - if (loggingEvent == null) { - return; - } - if (loggingEvent.Level < Level.Notice) { - return; - } - var cls = loggingEvent.LoggerName; - cls = cls.Substring(cls.LastIndexOf('.') + 1); - var key = "info"; - if (loggingEvent.Level >= Level.Error) { - key = "error"; - } - else { - if (loggingEvent.Level >= Level.Warn) { - key = "warn"; - } - } - pendingLogEntries.Enqueue(new LogEntry - { - Class = cls, - Exception = loggingEvent.GetExceptionString(), - Key = key, - Message = loggingEvent.RenderedMessage, - Time = loggingEvent.TimeStamp.ToString("T") - }); - lock (appenderLock) { - appenderTimer.Enabled = true; - } - } - - public void DoAppendInternal(object sender, - ElapsedEventArgs e) - { - lock (appenderLock) { - appenderTimer.Enabled = false; - } - if (!logging) { - return; - } - ListViewItem last = null; - logger.BeginUpdate(); - try { - LogEntry entry; - while (pendingLogEntries.TryDequeue(out entry)) { - if (logger.Items.Count >= 300) { - logger.Items.RemoveAt(0); - } - last = logger.Items.Add( - new ListViewItem(new[] - { - entry.Time, entry.Class, entry.Message - })); - last.ImageKey = entry.Key; - if (!string.IsNullOrWhiteSpace(entry.Exception)) { - last = logger.Items.Add( - new ListViewItem(new[] - { - string.Empty, entry.Class, entry.Exception - })); - last.ImageKey = entry.Key; - last.IndentCount = 1; - } - } - } - finally { - logger.EndUpdate(); - } - if (last != null) { - logger.EnsureVisible(last.Index); - colLogTime.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent); - colLogLogger.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent); - colLogMessage.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent); - } - } - - private struct LogEntry - { - public string Class; - - public string Exception; - - public string Key; - - public string Message; - - public string Time; - } - } -} diff --git a/SimpleDLNA/FormMain.resx b/SimpleDLNA/FormMain.resx deleted file mode 100644 index 72d0b33b..00000000 --- a/SimpleDLNA/FormMain.resx +++ /dev/null @@ -1,2441 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 464, 17 - - - 358, 17 - - - 17, 17 - - - 123, 17 - - - 248, 17 - - - - - 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 - J/+cWhf/l1MQ/5dYF/+eZCr/n2kz/5xnMv+XYSz/j1cg/4dOFv+CShL/RykL/10yBv+pYx3/LyEU/xMP - DP8yJhn/j14t/6FbFv+nZyj/EQ0K/xoVEP8gGRL/KB4V/25OL/+cYCb/kFES/00rCf9gMwX/rWMZ/2lH - Jv+IYj3/IBoT/0g0If+pYx3/r28v/x0YEv9CMiL/g2A8/zcqHP8ZFA//e1Yw/59cGP9TLQf/ZDQF/7Fi - Ff+xdDj/UTsl/x0YEv9hQyf/rmMZ/7RxLv8dFxL/MiUa/7V3OP+tdT3/Jx8W/0AwH/+qZyX/Vy4G/2Y1 - A/+5ax7/NCYY/yAZE/9mSSz/unMs/69eDv+4cy3/HRgS/zImGf+0byr/tHAr/zElGf8bFhH/sm8t/1kv - Bf9pNgP/vm8f/ywgFf9DMSD/gFo1/6ZlI/+0YA3/vXQs/x0YEv8yJhn/uXEo/7hxKv8yJhn/HBYR/7Zx - LP9cMQX/bDcC/79pE/+KWin/HxgQ/xsUDf96Sx7/umQO/8F2K/8dFxL/MyYa/8F7NP+2dzj/KB8W/zor - G/+4biP/XzIE/244Av/AYwb/wmoS/8Z0Iv/FcyP/wGsV/7xiCP/Edij/HBcR/0QyIf+PZDn/Ujoj/xoV - EP9xTSn/uWgX/2IzA/9wOQH/w2MC/8JiAv/CYgP/wWID/8BiA/+/YQP/xnEd/ygdEv8aFRD/FREN/zcn - GP9zTSf/wXAf/7piCv9kNAP/czoB/8ZkAf/GZAL/xWMC/8VjAv/EYwL/w2MC/8VnCv/Ich3/ynko/8l5 - KP/HcyD/w2wU/79kCP+9YQT/aTUC/3A4Af/JZQH/yWUB/8hlAf/IZAH/x2QB/8dkAf/GZAH/xWQC/8Vj - Av/EYwL/w2MC/8NjAv/CYgL/wWID/2QzAv8qFQD/oFAA/8tmAP/LZgD/y2UA/8plAP/KZQH/yWUB/8ll - Af/IZAH/x2QB/8dkAf/GZAH/xmQC/5ZLAv8jEQD/AAAAXykUAP9qNQD/cjkA/3A4AP9wOAD/cDgA/3A4 - AP9vOAD/bzgA/283AP9vNwH/cDgB/2c0Af8kEgD/AAAAWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAGAAAADAAAAABAAgAAAAAAKAC - AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAABVIgAAZjMAADMRAACZVQAA3WYAAMxmAAC7VQAAIhEAAHcz - AAC7ZgAARCIAADMiAAC7ZhEAqmYiAKpmEQBEMxEAERERAEQzIgCZVSIAzGYRACIiEQCqZjMAiFUiAKpV - AABVMyIAMyIRAGZEEQDMdyIAd0QiACIREQCIVTMAZkQiAFUzEQC7ZiIAu3ciAHdVIgCqVREAiFURAJlm - MwCZZiIAMyIiAEQiEQBVMwAAmVURAIhEAACIRBEAd0QRAGYzEQARAAAAMzMzADQ0NAA1NTUANjY2ADc3 - NwA4ODgAOTk5ADo6OgA7OzsAPDw8AD09PQA+Pj4APz8/AEBAQABBQUEAQkJCAENDQwBEREQARUVFAEZG - RgBHR0cASEhIAElJSQBKSkoAS0tLAExMTABNTU0ATk5OAE9PTwBQUFAAUVFRAFJSUgBTU1MAVFRUAFVV - VQBWVlYAV1dXAFhYWABZWVkAWlpaAFtbWwBcXFwAXV1dAF5eXgBfX18AYGBgAGFhYQBiYmIAY2NjAGRk - ZABlZWUAZmZmAGdnZwBoaGgAaWlpAGpqagBra2sAbGxsAG1tbQBubm4Ab29vAHBwcABxcXEAcnJyAHNz - cwB0dHQAdXV1AHZ2dgB3d3cAeHh4AHl5eQB6enoAe3t7AHx8fAB9fX0Afn5+AH9/fwCAgIAAgYGBAIKC - ggCDg4MAhISEAIWFhQCGhoYAh4eHAIiIiACJiYkAioqKAIuLiwCMjIwAjY2NAI6OjgCPj48AkJCQAJGR - kQCSkpIAk5OTAJSUlACVlZUAlpaWAJeXlwCYmJgAmZmZAJqamgCbm5sAnJycAJ2dnQCenp4An5+fAKCg - oAChoaEAoqKiAKOjowCkpKQApaWlAKampgCnp6cAqKioAKmpqQCqqqoAq6urAKysrACtra0Arq6uAK+v - rwCwsLAAsbGxALKysgCzs7MAtLS0ALW1tQC2trYAt7e3ALi4uAC5ubkAurq6ALu7uwC8vLwAvb29AL6+ - vgC/v78AwMDAAMHBwQDCwsIAw8PDAMTExADFxcUAxsbGAMfHxwDIyMgAycnJAMrKygDLy8sAzMzMAM3N - zQDOzs4Az8/PANDQ0ADR0dEA0tLSANPT0wDU1NQA1dXVANbW1gDX19cA2NjYANnZ2QDa2toA29vbANzc - 3ADd3d0A3t7eAN/f3wDg4OAA4eHhAOLi4gDj4+MA5OTkAOXl5QDm5uYA5+fnAOjo6ADp6ekA6urqAOvr - 6wDs7OwA7e3tAO7u7gDv7+8A8PDwAPHx8QDy8vIA8/PzAPT09AD19fUA9vb2APf39wD4+PgA+fn5APr6 - +gD7+/sA/Pz8AP39/QD+/v4A////AAEBATIJCQkJCQkJCQkJCQkJCQkJCQEBAQEBDDAwMDAwMDAwMDAc - HBwcHBwcMSIJAQEJLS8vLy8vLzAwMDAwMDAwMBwcHBwxAQECBQUFLi8vLy8vLy8wMDAwMDAwMDAcCQEs - BQUFBQUFBS4vLy8vLy8vMDAwMDAwCQEsGQUFBQUFBQUFBQUuLi8vLy8vLy8wCQEsGRkZGRkZGQUFBQUF - BQUFBS8vLy8vCQEsGRkZGSYUFBAZJi0UFBQtLQUFBQUuCQEDGRkZEBESHyEQECsSEh8TGCYFBQUFBAED - CBkZECcoGhIpDxMWKCUSKikZBQUFBAEDCAgZCCMhHxsQDxMWJA4lEiUmGRkFBAEDCwgIDiISIQ8LEBMW - IxkPEiEQGRkZBAEDCwgIDhEfIBgLDhMWDggPEiEOGRkZBAEDBwgICw8aGxwODhMWHRUYEh4OGRkZBAED - BwsLCwsVFQ4LDhMWFxgWFg8LCAgZBAEDBwsLCwsLCAgLDhESEhITFA4ICAgIBAEKBwcHBwcHBwsLCw4P - DxAOBwgICAgIBAEKBwcHBwcHBwcHBwcHBwcLCwgICAsIBAEKBwcHBwcHBwcHBwcHBwcHCwsLCwsIDQEK - BwcHBwcHBwcHBwcHBwcHBwcHBwcLDAECBgcHBwcHBwcHBwcHBwcHBwcHBwcICQEBBQYGBgYGBgYHBwcH - BwcHBwcHBwcDAQEBAQIDAwMDAwMDAwMDAwMDAwMDAwQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAeAA - A//AAAH/gAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA - AP8AAAD/AAAA/wAAAP8AAAD/gAAA/4AAAf/AAAP/8AAH/ygAAAAYAAAAMAAAAAEAIAAAAAAAYAkAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG0VDAO3KRgI1SkYCNUoFwfVKBcH1ScXB9UmFwjVJhcI1SUX - CNUlFwjVJBcI1SQWCNUjFgnVIxYJ1SMWCdUjFgnVIxYJ1iAUCNAKBgKrAAAASwAAAAAAAAAAAQEAfkoq - Cv98RxL/fkgT/3xIFP96RhT/eEYV/3ZFFf90RRb/c0QW/3JEFv9wQxf/bkMX/21CF/9rQRj/akEY/2lA - GP9oQBn/Z0AZ/2U/Gf9dOhf/JBYJ9QAAAEwAAABCLRkF45FREf+MTxH/iU0S/4dMEf+FSxP/g0sT/4FK - FP9/SRT/fUgV/3tIFf95Rxb/d0YW/3ZGFv90RRf/c0QX/3FEF/9vQxj/bkMY/21CGP9vRBr/YDwX/wwI - A7IAAACcVC0H7plUDv+TUA//kVAP/45PD/+MThD/ik0R/4hNEf+GSxL/hEsS/4JKEv+ASRP/fkkT/3xI - FP96RxT/eEYV/3dGFf91RRb/c0UW/3JEFv9xRBf/bUIX/yMVCNIAAACjWjAH759WDP+aUw3/mVMN/5dT - Df+VUQ7/k1EO/5FQD/+PTw//jU4Q/4tOEP+JTRH/hkwR/4RLEv+CShL/gEoT/39JE/99SBT/e0gU/3lH - Ff95RxX/dEUW/ygXB9UAAAChWzAG76NXDP+eVAz/nVQM/5xUDP+bUwz/mlMN/5pTDf+YUg3/llIO/5RR - Dv+SUA//j08P/41PD/+LThD/iU0R/4dNEf+FSxL/g0sS/4FKE/+BShP/fEgU/yoYB9QAAAChXTEF76dZ - Cv+hVgr/oVYL/6BVC/+hVQv/olcL/6FWC/+dVAv/m1MM/5tUDP+bVAz/nFQN/5pUDf+YUg3/lFEO/5BQ - Dv+OThD/jE4Q/4pNEf+JTRH/hEoS/ywZBtQAAAChXzIF76paCv+lVwr/pVcK/6VZD/+gXx3/l14l/5le - Iv+nYBn/oVYM/6FYEP+YXB//ll4o/5NcJv+XXiT/n14e/59aE/+WUgz/lVEO/5NRDv+SUQ//jU4P/y8a - BdQAAAChYjMF769bCf+pWQn/qlkI/6piGv9EMBz/ExIR/yAbFv9qSCb/qmAX/6ZiHv9ALx7/GBYU/x4Z - Ff8iHRf/TDgl/45aJv+kXBT/m1ML/5tTDf+bVA3/lVEN/zMbBdQAAAChZDQE77JdCP+sWwj/rVoH/61g - Ev+JUx//k2Y3/1U+Kf8VExL/n2Ag/6pmIf9GNSP/LiQc/5ZlNf93USv/HxoV/z0uIP+cYCP/o1cL/55V - C/+fVgz/m1MM/zQcBNQAAAChZTUE77ZfB/+wWwf/r1sG/7NeCv+0bCX/aUoq/yMdF/82KRv/qWMb/61n - If9FNCP/LiQY/7xwJf+1Zxn/clAt/xgWFf99Uib/rl8R/6FVCf+jVwv/nlUL/zYcA9QAAAChZzUE77lg - Bv+0XAb/tFwF/7loFv9XOx7/HhsX/2FFKf+paSn/uGMP/61lH/9GNCL/LSMX/7ZrIP+tWgb/oWYq/xUU - E/9pSCf/rWIX/6ZXCf+nWAr/olYK/zYdA9QAAAChaTYD771iBf+3XgX/t14E/7tpGP9JMxz/JR8a/4Zd - N/+GVCL/s2AP/7FnHv9GNSL/LSMX/7psH/+xWwT/qGkp/xYVE/9lRyj/sGQX/6pZB/+qWgn/pVgJ/zge - A9QAAAChazcD78BiBP+6XwX/uV8E/75kCv+nZCH/Vjsh/zIkFv9iQB7/tmMS/7VpHv9HNSL/LiQY/8Z0 - Iv/AahT/glct/xQUFP95TyX/uWUS/61ZB/+uWwj/qVkI/zkeA9QAAAChbDcD78NjBP+9YAT/vWAE/7tg - BP+/Ywj/w2sU/8JuGf+/aBL/vGEH/7VpHv9HNSH/LiQb/6BpMf+EVin/KyIZ/y8mHP+jYiL/uGEJ/7Fb - Bv+xXAf/rVoI/zoeA9QAAAChbjgC78VlA/+/YgP/v2ED/75hA/+9YAP/vWAC/7xfAf+7XwL/vmAD/7pq - GP9NNh7/FxYU/x4aFv8eGRX/RjQi/5JbJP+7ZhH/tV0F/7RdBv+1Xgb/sFwG/zwfAtQAAAChcDgB78hm - Av/CYgL/wmID/8JiA//BYgP/wGID/8BhA/+/YQP/vmED/79jCP+1Zhj/rmcg/6tmIP+vZx//umka/8Bn - Df+5XwT/uF4F/7deBf+4XwX/s10G/zwfAtQAAAChcTkB78tmAv/FYwL/xWMC/8RjAv/DYgL/w2IC/8Ni - A//CYgP/wWID/8FhA//CYgL/w2MD/8NjA//BYgP/v2ED/71gA/+8XwT/u18E/7tfBf+7YAX/t10F/z4f - AtQAAACicjkB781oAf/HZAH/x2QB/8ZkAf/FZAH/xWQC/8VkAv/EYwL/w2MC/8NjAv/CYwL/wWIC/8Fi - A//AYgP/wGID/79iA/++YQP/vmED/71hA/++YQT/ul8E/z8gAdQAAACldToA8M9oAf/JZQH/yWUB/8ll - Af/IZAH/x2QB/8dkAf/GZAH/xmQC/8ZkAv/FYwL/xGMC/8RjAv/DYwL/w2IC/8JiAv/BYgP/wWID/8Bi - A//BYgP/vmED/0EhAdUAAABiVCoA6tZrAP/LZQD/y2UA/8plAf/KZQH/yWUB/8llAf/IZAH/yGQB/8hk - Af/HZAH/x2QB/8ZkAv/GYwL/xWMC/8VjAv/EYwL/w2IC/8NiAv/GZAP/u18D/yMSAb8AAAAEDgcApJ9Q - AP/WawD/0mkA/9FpAP/RaQD/0WgA/9BoAP/QaAD/z2gA/89oAP/PaAH/zmcB/85nAf/NZwH/zWcB/8xn - Af/MZgH/y2YB/8tmAv/MZwL/bTcB/wAAAGwAAAAAAAAAEQ8IAKRQKADibjcA7W43AO1tNwDsbTcA7G03 - AOxtNwDsbTcA7G03AOxtNwDsbTcA7Gw3AOxsNwHsbDYB7Gw2AexrNgHsbTYB7Wk0Aes6HQDcAwEAfgAA - AAQAAAAAAAAAAAAAAAAAAABaAAAAlwAAAJYAAACVAAAAlQAAAJUAAACVAAAAlQAAAJUAAACVAAAAlQAA - AJUAAACVAAAAlQAAAJUAAACVAAAAlwAAAJAAAAA3AAAAAAAAAADAAAEAgAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AACAAAAAgAABAOAAAwAoAAAAIAAAAEAAAAABAAgAAAAAAIAEAAAAAAAAAAAAAAAAAAAAAAAA////AAAA - AAAiEQAAZjMAAHczAABVIgAAEQAAAMxmAAC7ZgAARCIAALtVAACIRAAAd0QAAMxmEQDMdyIAu2YRAKpm - IgAiIhEAERERADMiEQBmRCIAmWYiACIREQBEMyIAmWYzAMyIRAC7dyIAqnczALtmIgCqVQAAEREAAGZE - EQCIVTMAd0QiALt3MwCIVSIAqlURAJlVIgCqd0QAzHczAIhmMwCqZhEAu1URAFUzAABVRCIARCIRAHdV - MwC7iEQAu3dEAJlVAACqZjMAmVURAJlEAACIRBEAd0QRADMRAABmMxEAMyIAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAACAAAAAQAAAAFAAAABQAAAAYAAAAGAAAABgAAAAgAAAAIAAAABwAAAAYAAAAGAAAABgAAAAgA - AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAACAAAAAwAAAAQAAAAFAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAFAAAAAAAAAHSXbgAAAAAAAAAAAAgAAAAJAAAACgAAAAsAAAAMAAAAEgAAAA4A - AAAPAAAAEAAAABQAAAAZAAAAAgEAAAMBAAABAAAAAgAAAAMAAAAHAAAAEQAAABMAAAAVAAAAFgAAAAEB - AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBATcJCQkJCQkJCQkJCQkJCTk5OTk5OTk5AgEB - AQEBAQI2NTY2NjY2NjY2NjY2Nh8fHx8fHx8fHx8fOB4BAQEGNTU1NTU1NTY2NjY2NjY2NjY2NjYfHx8f - Hx8fOAEBAQkxCzU1NTU1NTU1NTU2NjY2NjY2NjY2NjYfHx8fNwEBAzExMTExCzU1NTU1NTU1NTU2NjY2 - NjY2NjY2NjYJAQEDMTExMTExMTExNAs1NTU1NTU1NTU2NjY2NjY2NgkBAQMxMTExMTExMTExMTExMQs1 - NTU1NTU1NTU2NjY2CQEBAx0dHTExMTExMTExMTExMTExMQs1NTU1NTU1NTUJAQEDHR0dHR0dHTExMTEx - MTExMTExMTExMTQLNTU1NQkBAQMdHR0dHSQQEBAQJDEdJBAyMhAQJDMxMTExMTELBQEBAx0dHR0dJRMS - EhcQJCQjHhISEhcUECQxMTExMTErAQEEHR0dHR0lHhcTFhMQJCAWERcXEhYTECQxMTExMSsBAQQdHR0d - HQ8QLygREhwkKBYWMBwYERYsKR0xMTExKwEBBAoKCh0dDxAsFhYtDykoFhYaHSkuFhYcHR0dHR0rAQEE - CgoKCgoaExYWFxAqKRgWFhodHRsWFhUkHR0dHSsBAQQKCgoKCCUWESYnDwoPGBYWGh0dGhYWKCkdHR0d - AwEBBAoKCgoIHBYWFBchDw8YFhYaHR0iFhYjJB0dHR0DAQEECAoKCggPEBceEx8PDxgWFhoKDyAWEhod - HR0dHQMBAQQICAgICAgIDQ4ODwgIGBYWGRobExYXHAoKHR0dAwEBBAgICAgICAgICAgKCggVFhEXFxIW - FhUPCgoKCgoDAQEEBwcHBwgICAgICAgICBAREhISExQQDwoKCgoKCgMBAQwHBwcHBwcHBwcICAgIDQ4O - Dg4ODwgICgoKCgoKAwEBCwcHBwcHBwcHBwcHBwcICAgICAgICAgKCgoKCgoDAQELBwcHBwcHBwcHBwcH - BwcHBwcICAgICAgICAgICgMBAQsHBwcHBwcHBwcHBwcHBwcHBwcHBwcHCAgICAgIAwEBCwcHBwcHBwcH - BwcHBwcHBwcHBwcHBwcHBwcHCAgEAQEDBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwUBAQIHBwcH - BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcKBgEBAQUHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHCAkBAQEB - AQIDBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAUGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB - AQH4AAAfwAAAA4AAAAGAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAA - AAHAAAAD+AAAHygAAAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAeAAAAbAAAAJkAAACZAAAAmQAAAJkAAACZAAAAmQAAAJkAAACZAAAAmQAAAJkAAACZAAAAmQAA - AJkAAACZAAAAmQAAAJkAAACZAAAAmQAAAJkAAACZAAAAmQAAAJkAAABpAAAAGAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAig8IAv80Hgj/SSsN/0gqDf9HKg3/RikN/0YpDf9EKQ3/RCkO/0MpDv9DKA7/QigO/0Eo - Dv9BKA7/QCgO/0AnDv8/Jw//PicP/z4mD/8+Jg//PSYP/z0mD/89Jg//PSYP/yoaCv8KBgL/AAAAhwAA - AAAAAAAAAAAAAAAAAJAuGgb/fEcS/4BKE/9/SRP/fUkU/3xIFP97RxT/eUcV/3hGFf93RhX/dUUW/3RF - Fv9zRRb/ckQX/3FEF/9vQxf/bkMX/21CGP9sQhj/a0IY/2pBGP9pQRn/aUEZ/2hAGf9nQBn/ZkAZ/2A8 - GP8eEwf/AAAAigAAAAAAAAAqFw0D/4dLEf+ITRH/h0wR/4VLEv+ESxL/gkoS/4FKE/9/SRP/fkkU/3xI - FP97SBT/ekcV/3hHFf93RhX/dkYW/3RFFv9zRRb/ckQX/3FEF/9wQxf/b0MX/25DGP9tQhj/bEIY/2tB - GP9qQRn/aUEZ/2M+GP8LBwP/AAAAGwAAAIRMKQf/kVAP/49PD/+NTxD/jE4Q/4pNEP+JTRH/h0wR/4ZM - Ev+ESxL/g0oS/4FKE/+ASRP/fkkT/31IFP97SBT/ekcU/3lHFf93RhX/dkYV/3VFFv90RRb/ckQW/3FE - F/9wRBf/b0MX/25DGP9tQhj/bEIY/zEeC/8AAAB1AAAApWM2CP+YUg3/llIO/5RRDv+TUQ7/kVAP/49P - D/+OTxD/jE4Q/4tOEP+JTRH/iEwR/4ZMEf+FSxL/g0sS/4JKE/+AShP/f0kT/31IFP98SBT/ekcU/3lH - Ff94RhX/dkYV/3VFFv90RRb/c0UW/3FEF/9wRBf/QScO/wAAAJYAAAClZTYI/5tUDP+bUwz/mlMN/5lT - Df+YUw3/llIN/5VRDv+TUQ7/klAP/5BPD/+OTw//jU4Q/4tOEP+KTRH/iE0R/4ZMEf+FSxL/g0sS/4JK - Ev+AShP/f0kT/35JFP98SBT/e0gU/3lHFf94RxX/d0YV/3VGFv9EKQ3/AAAAlgAAAKVnNwf/nlUL/51V - DP+dVAz/nFQM/5tUDP+bVAz/mlMM/5lTDf+YUw3/l1IN/5VRDv+UUQ7/klAO/5BQD/+PTw//jU4Q/4xO - EP+KTRD/iE0R/4dMEf+FTBL/hEsS/4JKEv+BShP/f0kT/35JE/99SBT/e0gU/0gqDP8AAACWAAAApWk4 - B/+hVgv/oFYL/6BVC/+fVQv/nlUL/55VDP+dVAz/nFQM/5xUDP+bVAz/mlMM/5pTDf+ZUw3/l1IN/5ZS - Dv+UUQ7/klAO/5FQD/+PTw//jk8Q/4xOEP+LTRD/iU0R/4dMEf+GTBL/hEsS/4NLEv+BShP/SysL/wAA - AJYAAAClajgG/6RXCv+jVwr/olYK/6JWC/+hVgv/oFYL/6BVC/+fVQv/nlUL/55VDP+dVAz/nFQM/5xU - DP+bVAz/mlMM/5pTDf+ZUw3/mFIN/5ZSDf+VUQ7/k1EO/5FQD/+QTw//jk8P/41OEP+LThD/iU0R/4hM - Ef9PLQr/AAAAlgAAAKVsOQb/plgJ/6ZYCv+lVwr/pVcK/6VYDP+nXhX/rWgk/69vLv+ubSz/qWUh/6Na - E/+fVgz/oFYN/6NeF/+paSr/rG0w/6ttMP+pbC7/pmcn/6FeHP+bVxP/mFQO/5dSDf+VUQ7/k1EO/5JQ - D/+QUA//j08P/1MuCf8AAACWAAAApW46Bv+pWQn/qVkJ/6hYCf+nWAn/qVwP/5JcJf8yJRj/GxUQ/xoV - EP9KNiL/pmos/6VbEv+jWhH/j10q/xURDf8fGRP/HBcR/xoVEP9BMSD/aEsu/6BmLP+gWxb/m1UN/5pT - DP+aUw3/mVMN/5dSDf+VUg7/VzAI/wAAAJYAAAClcDoF/6xaCP+rWgj/q1oI/6pZCP+rXQ//lF0m/xsU - Dv9HNCL/Nioc/yQdFv8/Lh7/rWch/6heFP+LXjP/JR4W/ywjG/9INST/RDIi/x8ZE/8iGxX/Nigb/6Fn - LP+gWRL/nVQM/5xUDP+cVAz/m1QM/5pTDP9bMQj/AAAAlgAAAKVxOwX/r1sH/65bCP+tWwj/rVoI/61b - Cv+wZBf/rGsq/76BQ/+LYzz/KSEZ/xsWEP+zbin/ql8T/41gM/8lHhb/IxwW/7l+Q/+wbSv/l2o7/yog - F/8kHRb/X0Ur/6hjHv+gVQv/n1UL/59VC/+eVQz/nVQM/1wxB/8AAACWAAAApXM8Bf+xXAf/sVwH/7Bb - B/+vWwf/r1sH/7FhEf+vbiz/WUAn/yMcFf8mHhf/QC8d/7JpH/+tYBP/jmAz/yUeFv8gGhP/tHEu/6hZ - C/+tZh7/eFY0/yYeF/8mHhX/sG8u/6RXDP+iVgr/oVYL/6FWC/+gVgv/XjIG/wAAAJYAAACldDwE/7Rd - Bv+zXQb/s1wG/7JcB/+yXQn/unAl/zcoGf8lHhb/IhsU/004Iv+ubSv/sF8Q/69gEv+QYTL/JR4W/yAa - E/+3ci7/qVkJ/6tcDv+ucjX/IhsV/yMcFf+VYy//p1wQ/6VXCv+kVwr/pFcK/6NXCv9fMwb/AAAAlgAA - AKV2PQP/tl4F/7ZeBv+1XQb/tF0G/7ZhDP+RXSj/IBoU/yggGP+ldET/wHs3/7dqHP+yXgz/smER/5Jh - Mf8lHhb/IBoT/7lzLf+sWgj/q1sJ/7h0L/8gGhT/JR4W/45gMv+rYBP/qFgJ/6dYCf+mWAn/plgK/2Ez - Bv8AAACWAAAApXg9A/+5XwX/uF8F/7heBf+3XgX/t2EJ/7VuKP8jGxL/IxwV/2xMLv9MNiD/eE0h/7Zk - Ev+1YhH/kmIx/yUeFv8gGhP/u3Ms/69bB/+vXQr/u3g0/yIbFP8kHRb/j18v/65fEP+qWQj/qlkJ/6lZ - Cf+oWQn/YzQF/wAAAJYAAACleT4D/7tgBP+6XwT/ul8F/7lfBf+5YAb/vGgT/6FmLP9OOCH/FREN/zUm - F/9uRx//uWUT/7djEP+UYjH/JR4W/yAaE/+9dCz/sV0I/7ZnGP+IXTP/JR4X/x8ZE/+wcC7/r14M/61a - CP+sWgj/rFoI/6taCP9kNAX/AAAAlgAAAKV7PwP/vWAE/71gBP+8YAT/vGAE/7tgBP+8YAb/vWUO/8Bu - Hf/CdCX/wHEh/71pFv+4YQr/umQP/5VjMP8lHhb/IxwW/8WCQP++cib/rHI5/z4uHv8mHxf/Tzgj/7lt - IP+wXQj/sFsH/69bB/+uWwf/rlsI/2Y1Bf8AAACWAAAApXw/Av+/YQP/v2ED/75hA/++YQT/vWEE/71g - BP+8YAT/vGAE/7tgBP+7YAT/ul8E/7pfBf+8ZQ//lmIu/yMcFv8rIxr/TDcj/0g0IP8eGBL/IxwV/yQc - E/+eZS3/tmMQ/7NdBv+yXAb/slwH/7FcB/+wXAf/aDYE/wAAAJYAAAClfj8C/8FiA//BYgP/wGID/8Bh - A/+/YQP/v2ED/75hA/++YQT/vWEE/71gBP+8YAT/vGAE/71kCv+gYiP/KyAU/x0YEv8cFxH/GhUQ/zsr - G/9nSCr/rGss/7pnFP+3Xwj/tV0G/7VdBv+0XQb/tF0G/7NdBv9pNgT/AAAAlgAAAKV/QAH/w2MC/8Nj - Av/CYgL/wmID/8JiA//BYgP/wWID/8BiA//AYQP/v2ED/79hA/++YQP/v2IG/8BnEP/EcSD/xnco/8Z4 - Kf/Fdyj/wnIi/79rGP+7ZA3/uWAG/7hfBf+4XgX/t14F/7deBf+2XgX/tV4G/2o3BP8AAACWAAAApYBB - Af/FYwL/xWMC/8RjAv/EYwL/w2MC/8NjAv/DYgL/wmIC/8JiA//BYgP/wWID/8BiA//AYQP/v2ED/79h - A/++YQP/vmEE/71gBP+9YAT/vGAE/7xgBP+7YAT/u18E/7pfBP+6XwX/uV8F/7hfBf+4XgX/bDcD/wAA - AJYAAAClgUEB/8dkAf/GZAH/xmQB/8ZkAv/FYwL/xWMC/8RjAv/EYwL/xGMC/8NjAv/DYwL/wmIC/8Ji - A//BYgP/wWID/8BiA//AYQP/v2ED/79hA/++YQP/vmEE/71hBP+9YAT/vGAE/7xgBP+7YAT/u2AE/7pf - BP9tOAP/AAAAlgAAAKWCQQH/yGUB/8hlAf/IZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAv/FZAL/xWMC/8Vj - Av/EYwL/xGMC/8NjAv/DYwL/wmIC/8JiA//BYgP/wWID/8FiA//AYgP/wGED/79hA/+/YQP/vmED/75h - BP+9YAT/vWAE/284Av8AAACWAAAApYNBAP/KZQH/ymUB/8llAf/JZQH/yWUB/8hlAf/IZAH/x2QB/8dk - Af/HZAH/xmQB/8ZkAv/GZAL/xWMC/8VjAv/EYwL/xGMC/8NjAv/DYwL/w2IC/8JiAv/CYgP/wWID/8Fi - A//AYgP/wGED/79hA/+/YQP/cDkC/wAAAJYAAACKbjcA/8tmAP/LZgD/y2UA/8plAP/KZQH/ymUB/8ll - Af/JZQH/yWUB/8hlAf/IZAH/yGQB/8dkAf/HZAH/xmQB/8ZkAf/GZAL/xWMC/8VjAv/EYwL/xGMC/8Rj - Av/DYwL/w2IC/8JiAv/CYgP/wWID/8FiA/9YLQH/AAAAdQAAACoiEQD/x2QA/8xmAP/MZgD/zGYA/8tm - AP/LZgD/y2YA/8plAP/KZQD/ymUB/8llAf/JZQH/yWUB/8hlAf/IZQH/yGQB/8dkAf/HZAH/x2QB/8Zk - Af/GZAL/xWQC/8VjAv/EYwL/xGMC/8RjAv/DYwL/ul4C/xcMAP8AAAAeAAAAAAAAAJBSKQD/x2QA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8tmAP/LZgD/y2YA/8plAP/KZQD/ymUB/8plAf/JZQH/yWUB/8ll - Af/IZQH/yGQB/8dkAf/HZAH/x2QB/8ZkAf/GZAL/xWQC/75gAv9DIgH/AAAAigAAAAAAAAAAAAAAAAAA - AJAkEgD/YjEA/3o9AP96PQD/ej0A/3o9AP96PQD/ej0A/3o9AP96PQD/ej0A/3o9AP96PQD/ej0A/3o9 - AP95PQD/eT0B/3k9Af95PQH/eT0B/3k9Af94PQH/eDwB/3g8Af9eLwD/Gg0A/wAAAI0AAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAC0AAAB7AAAAmQAAAJkAAACZAAAAmQAAAJkAAACZAAAAmQAAAJkAAACZAAAAmQAA - AJkAAACZAAAAmQAAAJkAAACZAAAAmQAAAJkAAACZAAAAmQAAAJkAAACZAAAAmQAAAHgAAAAhAAAAAAAA - AAAAAAAA4AAAB8AAAAOAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AACAAAABwAAAA+AAAAcoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAABAAAABwAAABQAAAAhgAAAKgAAAC3AAAAvwAAAMIAAADCAAAAwgAAAMIAAADCAAAAwgAA - AMIAAADCAAAAwgAAAMIAAADCAAAAwgAAAMIAAADCAAAAwgAAAMIAAADCAAAAwgAAAMIAAADCAAAAwgAA - AMIAAADCAAAAwgAAAMIAAADCAAAAwgAAAMIAAADCAAAAwgAAAMIAAADCAAAAvwAAALgAAACqAAAAigAA - AFQAAAAfAAAAAAAAAAAAAAABAAAAFRAJA1k9JAu/Ty4O5WM6EfRjOhH1YjoR9WE5EvVgORL1YDkS9WA5 - EvVfORP1XjkT9V05E/VdOBP1XDgT9Vs4E/VbOBT1WzcU9Vo3FPVZNxT1WTcU9Vg2FPVYNhX1VzYV9Vc2 - FfVWNRX1VjUV9VY1FfVWNRX1VTUV9VU1FfVVNRX1VTUV9VU1FfVVNRX1VTUV9VU1FfVCKhDrLh0L4AkG - AtAAAADLAAAAwgAAAJ0AAABYAAAAAAAAAAAAAAAGVDANbXZEEvF9SRT/fEgU/3xIFP97RxT/ekcV/3lH - Ff94RhX/d0YV/3ZGFf91RRb/dEUW/3RFFv9zRRb/ckQW/3FEF/9xRBf/cEMX/29DF/9uQxf/bkMY/21C - GP9sQhj/bEIY/2tCGP9qQRj/akEZ/2lBGf9pQRn/aEEZ/2hAGf9nQBn/Z0AZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/188F/smGAncAAAAzAAAAMMAAACQAAAAAAAAAAByQRBag0sS/4JKEv+BShP/gEoT/4BJ - E/9/SRP/fkkU/31IFP98SBT/e0gU/3pHFf95RxX/eEcV/3dGFf92RhX/dUYW/3VFFv90RRb/c0UW/3JE - Fv9xRBf/cUQX/3BDF/9vQxf/bkMX/25DGP9tQhj/bEIY/2xCGP9rQhj/akEY/2pBGf9pQRn/aUEZ/2hB - Gf9oQBn/Z0AZ/2dAGf9mQBn/ZkAZ/2ZAGf9mQBn/Lh0L4AAAAMsAAACuAAAAAIpNEQyHTBHqiEwR/4dM - Ef+GTBL/hUsS/4RLEv+DShL/gkoT/4FKE/+ASRP/f0kT/35JFP99SBT/fEgU/3tIFP96RxT/eUcV/3hH - Ff93RhX/dkYV/3ZGFv91RRb/dEUW/3NFFv9yRBb/ckQX/3FEF/9wRBf/b0MX/29DF/9uQxj/bUIY/2xC - GP9sQhj/a0IY/2tBGP9qQRj/aUEZ/2lBGf9oQRn/aEAZ/2dAGf9nQBn/Yj0Y/Q0IA9EAAAC6AAAAAI5P - D1qNThD/jE4Q/4tOEP+KTRD/iU0R/4hMEf+HTBH/hkwS/4VLEv+ESxL/g0sS/4JKE/+BShP/gEkT/39J - E/9+SRT/fUgU/3xIFP97SBT/ekcU/3lHFf94RxX/eEYV/3dGFf92Rhb/dUUW/3RFFv9zRRb/ckQW/3JE - F/9xRBf/cEQX/29DF/9vQxf/bkMY/21CGP9tQhj/bEIY/2tCGP9rQhj/akEY/2lBGf9pQRn/aEEZ/zci - DeQAAAC/AAAAAJNQDpaSUA//kFAP/49PD/+OTw//jU4Q/4xOEP+LThD/ik0Q/4lNEf+ITRH/h0wR/4ZM - Ef+FSxL/hEsS/4NLEv+CShL/gUoT/4BKE/9/SRP/fkkT/31IFP98SBT/e0gU/3pHFP95RxX/eUcV/3hG - Ff93RhX/dkYW/3VFFv90RRb/c0UW/3NEFv9yRBf/cUQX/3BEF/9wQxf/b0MX/25DF/9tQxj/bUIY/2xC - GP9rQhj/a0IY/00vEu8AAADAAAAAAJdSDaWWUg3/lVEO/5RRDv+TUQ7/klAP/5FQD/+QTw//j08P/41P - EP+MThD/i04Q/4pNEP+JTRH/iE0R/4dMEf+GTBH/hUsS/4RLEv+DSxL/gkoS/4FKE/+AShP/f0kT/35J - E/99SBT/fEgU/3tIFP97RxT/ekcV/3lHFf94RhX/d0YV/3ZGFf91RRb/dEUW/3RFFv9zRRb/ckQX/3FE - F/9wRBf/cEMX/29DF/9uQxf/bkMY/1g1E/MAAADAAAAAAJpTDKWaUw3/mVMN/5hTDf+XUg3/llIN/5VR - Dv+UUQ7/k1EO/5JQDv+RUA//kE8P/49PD/+OTxD/jU4Q/4xOEP+LTRD/iU0R/4hNEf+HTBH/hkwR/4VM - Ev+ESxL/g0sS/4JKEv+BShP/gEoT/39JE/9+SRP/fkkU/31IFP98SBT/e0gU/3pHFf95RxX/eEYV/3dG - Ff92RhX/dUYW/3VFFv90RRb/c0UW/3JEFv9xRBf/cUQX/1o2EvMAAADAAAAAAJxUDKWbVAz/m1QM/5tT - DP+aUwz/mlMN/5lTDf+ZUw3/mFIN/5ZSDf+VUg7/lFEO/5NRDv+SUA7/kVAP/5BQD/+PTw//jk8Q/41O - EP+MThD/i04Q/4pNEf+JTRH/iEwR/4dMEf+GTBL/hUsS/4RLEv+DShL/gkoT/4FKE/+ASRP/f0kT/35J - FP99SBT/fEgU/3tIFP96RxX/eUcV/3hHFf93RhX/dkYV/3ZGFv91RRb/dEUW/1w3EvMAAADAAAAAAJ5V - DKWdVQz/nVQM/5xUDP+cVAz/nFQM/5tUDP+bVAz/mlMM/5pTDf+ZUw3/mVMN/5hSDf+XUg3/llIO/5RR - Dv+TUQ7/klAO/5FQD/+QUA//j08P/45PD/+NThD/jE4Q/4tOEP+KTRH/iU0R/4hMEf+HTBH/hkwS/4VL - Ev+ESxL/g0sS/4JKE/+BShP/gEkT/39JE/9+SRT/fUgU/3xIFP97SBT/ekcU/3lHFf94RxX/d0YV/2A4 - EfMAAADAAAAAAKBVC6WfVQv/n1UL/55VC/+eVQz/nVUM/51UDP+dVAz/nFQM/5xUDP+bVAz/m1QM/5pT - DP+aUw3/mVMN/5lTDf+YUg3/l1IN/5ZSDv+VUQ7/lFEO/5NQDv+RUA//kFAP/49PD/+OTw//jU4Q/4xO - EP+LThD/ik0Q/4lNEf+ITBH/h0wR/4ZMEv+FSxL/hEsS/4NLEv+CShP/gUoT/4BJE/9/SRP/fkkT/31I - FP98SBT/e0gU/2I5EPMAAADAAAAAAKFWC6WiWQ//p2Ea/6tqKP+ubi7/rW4v/6xsLP+paCf/pmQh/6Jd - F/+eVg//nVQM/5xUDP+gWxb/pmco/6ptMP+pbTD/qW0x/6ltMf+obTH/pGcp/5xaGP+cXBv/omYr/6Bl - Kf+XWBf/klAP/5FQD/+TVRf/mmEn/55pM/+ZYiv/k1og/5VeJ/+ZZTH/k14n/4pRGP+GTBH/hUsS/4dP - GP+NWib/k2Iy/49fLv+FUh3/gEoU/2U7D/MAAADAAAAAAKNXCqWnXxb/cUsm/ywhF/8dGBL/GxYR/yMc - FP9CMSD/VT4n/35XMf+rair/oVsU/55WDP+paCj/Eg4L/yAaE/8gGhP/IBoT/yAaE/8gGhP/Eg4L/6ls - L/+BVir/FREN/xIOC/+jZin/llIN/5dUE/+jaS//Jx4V/x8ZE/8SDgv/pXE9/y0hF/8ZFA//OCod/5Zf - J/+KThH/iU0R/5JcJf9LOCb/GxYQ/xANCv+JWSv/g0wT/2k7DvMAAADAAAAAAKVXCqWrYhr/a0wu/ycg - GP8rIxr/SDYk/0QyIf8cFhH/IhsV/yIbFf81Jxv/pGkt/6NaEv+tbi//IBoT/zAnHf8pIRn/IhsV/yAa - E/8gGhP/Eg4L/6tuMf+GXjT/JR4W/yAaE/+pbTD/mlQO/6FhIf9oTDD/KCAY/zIpH/8gGhP/rXlG/1tE - Lf8pIRn/IBkT/5pnNv+RUhT/j1AS/55oM/8mHRb/LCMb/zUpHf+XYy7/iE0S/2w9DvMAAADAAAAAAKdY - CaWsZBr/bE0u/ykhGf8jHBb/un5D/69sKf+qcDb/Ykgt/yYeF/8nIBj/VT4n/6plIf+vcDD/IBoT/ysj - Gv9vUDP/s3g9/61uL/+tbi//qWgn/6ZiH/+HXjT/JR4W/yAaE/+rbTD/n1oV/5loNf8nHhb/LSQc/zIo - Hv8gGhP/rXQ8/4RbNP8kHRb/KCAY/31dPf+mcDn/pG02/5BrRv8mHxf/KSEZ/2NLMv+VWiH/jE4Q/3A/ - DfMAAADAAAAAAKlZCaWuZRr/bU0u/ykhGf8gGhP/tHEu/6ZZCv+oXBD/sm8t/045Jf8qIhr/HhgS/6hs - L/+yczL/IBoT/ykhGf9rTS//qGIc/6FWC/+gVgv/oFYL/6RcFf+IXjP/JR4W/yAaE/+ucDP/qGgo/0o3 - JP8mHxf/UDwp/y4lHP8gGhP/q28z/6ltMf8nHhf/LSQc/yYfF/8dGBL/HRcS/yUeFv8uJRz/IxwV/4pg - Nv+UVRf/kFAP/3NADPMAAADAAAAAAKpZCKWwZRn/bk4u/ykhGf8gGhP/tXIu/6hYCf+nWAn/q18U/41h - NP8mHhf/JR4W/4xfM/+2dzn/IBoT/ykhGf9rTS//qWMb/6NXCv+iVgr/olYL/6VdFf+KXjP/JR4W/yAa - E/+zdzz/iV81/yIbFf8lHhb/clQ2/ykhGf8gGhP/rG0w/6ZlJf9LNyT/LCMb/zQpHv9GNSP/RjUj/zMp - Hf8vJhz/MCQZ/6ZqL/+XUxD/lVEO/3dBC/MAAADAAAAAAKxaCKWyZhn/bk4u/ykhGf8gGhP/t3It/6pZ - Cf+pWQn/qloL/7d1Mv8hGxT/KCAY/2xMLf+6ez3/IBoT/ykhGf9sTS//q2Mb/6VXCv+kVwr/pFcK/6de - FP+KXzP/JR4W/yIbFf+8hlH/OCsc/yggGP9FNCL/kGhC/yYfF/8gGhP/rG4v/6RfGv90UzL/JyAY/yQd - Fv+2gEv/tX9J/y0jGf8qIhr/VD4o/6NjIv+aUw3/mVMN/3pDCvMAAADAAAAAAK5bCKW0Zxn/b04u/ykh - Gf8gGhP/uHMt/6taCP+rWgj/q1oJ/7h0MP8hGhT/KSEZ/25OLv+7fT//IBoT/ykhGf9tTS7/rWQa/6ZY - Cf+mWAr/pVgK/6leFP+MXzP/JR4W/yggGP9+XDn/JR4W/yMcFf+NYzv/jWQ8/yUeFv8gGhP/rm8v/6JZ - Ef+caDT/IhsV/yQdFv+KYTj/lGg8/yMcFv8mHxf/fVgz/6FdGP+bVAz/m1QM/31DCvMAAADAAAAAALBb - B6W1Zxn/cE8u/ykhGf8gGhP/unMt/61aCP+tWgj/rl8P/6ZtNP8jHBb/KCAY/25NLP+8fDz/IBoT/ykh - Gf9uTi7/r2Ua/6hZCf+oWAn/p1gJ/6pfE/+NYDP/JR4W/y8mHP8/MCL/KSEZ/0IxIP+zczL/i2A1/yUe - Fv8gGhP/sG8v/6JXDP+ubSz/MCQZ/yUeF/9uUDP/bVAz/ycfGP8gGRP/pGwz/6BYEf+dVAz/nVQM/31E - CvMAAADAAAAAALFcB6W3aBn/cU8u/ykhGf8gGhP/u3Ms/69bB/+wXgz/t24j/3FRMf8pIRn/IhsV/5pl - Mf+7eDb/IBoT/ykhGf9uTi7/sGUZ/6pZCf+pWQn/qVkJ/6xgE/+NYDP/JR4W/zIpH/8xJx7/IxwW/41h - NP+uZh//jF8z/yUeFv8gGhP/snAv/6NXCv+rZR//YUYs/yQdFv9UPin/XkUt/ycfGP9DMiD/q2gn/6BW - DP+fVQv/n1UL/39ECfMAAADAAAAAALNdBqW4aBj/cU8t/ykhGf8jHBb/w4JA/7pvJP+9dzH/cVAw/yQd - Fv8qIhr/OSob/7hvJf+7dS//IBoT/ykhGf9vTi7/smYZ/6xaCP+rWgj/q1oI/61gEv+PYDP/JR4W/zMp - H/8uJRz/Oisc/7RuKv+rYRb/jWAz/yUeFv8gGhP/s3Ev/6VXCv+pXhX/gFgx/yIbFf9HNiX/PS8h/yYe - F/9rTS//qWIc/6FWC/+hVgv/oFYL/4FFCfMAAADAAAAAALVdBqW5aBf/cU4r/yYfF/8qIhr/SzYj/0Yz - IP8nHhX/IxwV/yUeFv8lHBP/nGYv/7NiEv+7cyz/IBoT/ykhGf9wTy7/tGcZ/61bCP+tWgj/rVoI/69g - Ev+QYTL/JR4W/zIpH/8mHxf/eVQw/69jF/+sYBP/jmAz/yUeFv8gGhP/tXEu/6dYCf+oWgz/tXQy/x0Y - Ev8vJhz/MCcd/yIbFf+VZDP/p1wS/6NXCv+jVwr/olYK/4JFCfMAAADAAAAAALZeBaW5ZhL/ek4j/0Qx - Hv8cFxH/HBcR/xoVEP88LBv/RTIe/3FOLP+ybyv/tmUV/7NdCf+6byP/Eg4L/xgUD/9tSCT/tGMU/69b - B/+vWwf/rlsH/7FgEP+NWij/FREN/x8ZE/8pHxT/t3Ap/6xdDP+uXxD/i1ko/xURDf8SDgv/s2wl/6lZ - Cf+oWQn/sGYe/0k0IP8dFxL/HxkT/ygeFP+wbCf/plkM/6VXCv+lVwr/pFcK/4RGCPMAAADAAAAAALhe - BaW4YQn/u2cU/79vH//AdSj/wXYr/8F1Kv++cSX/vW4f/7loF/+2YQz/tF4H/7NdBv+2YxD/u28i/7xx - Jv+3aBn/s18M/7FcB/+wXAf/sFwH/7FcCf+0ZRb/uW8l/7pzK/+2bCH/sWAQ/61aCP+uWwr/sWQX/7Zu - Jv+1bST/rmAS/6tZCP+qWQj/rF0P/7BnHv+1cCv/tXEt/7FqIv+rXRH/p1gJ/6dYCf+mWAn/plgK/4VH - CPMAAADAAAAAALlfBaW5XwX/uV8F/7hfBf+4XgX/t14F/7deBf+3XgX/tl4F/7ZeBv+2Xgb/tV0G/7Vd - Bv+0XQb/tF0G/7RdBv+zXQb/s10G/7JcBv+yXAb/slwH/7FcB/+xXAf/sFwH/7BcB/+wWwf/r1sH/69b - B/+uWwf/rlsH/65bCP+tWgj/rVoI/6xaCP+sWgj/rFoI/6taCP+rWgj/qlkI/6pZCf+pWQn/qVkJ/6lZ - Cf+oWQn/qFgJ/4ZHB/MAAADAAAAAALtgBKW6XwT/ul8E/7pfBf+5XwX/uV8F/7lfBf+4XwX/uF4F/7he - Bf+3XgX/t14F/7ZeBf+2XgX/tl4G/7VdBv+1XQb/tV0G/7RdBv+0XQb/s10G/7NdBv+0Xgn/t2YW/7lq - HP+0YhH/sVwH/7FcB/+wXAf/sFsH/69bB/+vWwf/r1sH/65bB/+uWwj/rVoI/61aCP+sWgj/rFoI/6xa - CP+rWgj/q1oI/6pZCP+qWQn/qlkJ/4hIB/MAAADAAAAAALxgBKW8YAT/vGAE/7tgBP+7YAT/u18E/7pf - BP+6XwX/uV8F/7lfBf+5XwX/uF8F/7hfBf+4XgX/t14F/7deBf+2XgX/tl4F/7ZeBv+1Xgb/tV0G/7Vd - Bv+3YxD/hlYn/w0KCP+8byL/s1wG/7JcBv+yXAf/sVwH/7FcB/+xXAf/sFwH/7BbB/+vWwf/r1sH/69b - B/+uWwf/rlsI/61bCP+tWgj/rVoI/6xaCP+sWgj/q1oI/4lIBvMAAADAAAAAAL5hBKW9YQT/vWAE/71g - BP+8YAT/vGAE/7xgBP+7YAT/u2AE/71kDP/Bbx7/w3Qm/8BuHf++ahf/v20c/79vHv+/bx7/vGgV/7tm - Ev+9bBv/vGoY/7tqGP/BdSr/f1o0/xgUD//IhkX/vXEl/7loGP+3ZhT/umsb/7hoGP+3Zxf/u28j/7xy - Kf+5bB//s2EP/7BcB/+wWwf/r1sH/69bB/+vWwf/rlsH/65bCP+tWwj/rVoI/4tIBvMAAADAAAAAAL9h - A6W/YQP/vmED/75hA/++YQT/vWEE/71gBP+9YAT/vGAE/8FrFv8mGg//EQ4L/0AtGv++fjz/DQoI/49j - OP8OCwj/iFcm/8R3K/8NCgj/ilst/4pbLf8QDQr/hF02/x4YEv8wJBj/EA0K/3BMJ//EfTj/DQoI/4lc - MP+UYjH/JhwS/w4LCf8xIRL/t2cX/7JcB/+yXAf/sVwH/7FcB/+wXAf/sFsH/7BbB/+vWwf/r1sH/4xJ - BvMAAADAAAAAAMBiA6XAYgP/wGED/8BhA/+/YQP/v2ED/79hA/++YQP/vmEE/8JsFf+mbDL/oG8//xgU - D/+RZTn/GBMP/4hfN/8bFhH/gFcu/8iAOP8UEAz/g1s0/4JbNP8cFhH/h183/xsWEf+abD3/jWM4/xQQ - DP+odUL/GBMP/4RdNv8xJBj/bk4v/7N9SP+udTz/u20e/7VeCP+zXQb/s10G/7JcBv+yXAb/slwH/7Fc - B/+xXAf/sFwH/41KBvMAAADAAAAAAMJiA6XBYgP/wWID/8FiA//BYgP/wGID/8BhA//AYQP/v2ED/8Ru - GP91Tyn/GBMP/zcnGP/EhUf/FxIO/4lgN/8dFxL/gloy/8yGQP8WEg7/hFw0/4RcNP8cFxH/h183/xcT - Dv/Igjv/yII8/xYSDf+FXjb/GhUQ/4ZeNv8gGRP/IBkT/xoVEP8SDwv/klsl/7dhDP+1XQb/tF0G/7Rd - Bv+0XQb/s10G/7NdBv+zXAb/slwG/49KBvMAAADAAAAAAMNjAqXDYwL/wmIC/8JiAv/CYgP/wmID/8Fi - A//BYgP/wWID/8dzH/8QDQr/fVcy/7Z6Pf/Ohj7/FREN/4lgNv8fGRP/YkUo/55uPv8dFxH/b04t/25N - Lf8lHBP/hl42/xoVEP+cbT3/j2M4/xQQDP+pdUL/GBQP/4RdNf87Kxr/eVYy/7V/R/8VEQ3/t3Er/7hh - Cf+2XgX/tl4F/7ZeBv+1XQb/tV0G/7VdBv+0XQb/tF0G/5BLBfMAAADAAAAAAMRjAqXEYwL/xGMC/8Nj - Av/DYwL/w2MC/8NiAv/CYgL/wmID/8ZtFf90TCT/HRYP/xoSDP/Cfjn/Ew8M/5RmOf8UEAz/RzIe/xMP - C/85KRn/UToh/xANCv+BVy7/jl8w/x0WD/83KBn/EA0K/2dFJP/Mh0H/FREN/4JaNP+wczX/JxsR/w8M - Cf9xSyX/vmwZ/7hgBv+4XwX/uF4F/7deBf+3XgX/t14F/7ZeBf+2Xgb/tV4G/5JLBfMAAADAAAAAAMVk - AqXFYwL/xWMC/8VjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8RmB//HbRT/yXUh/8hzHv/Meyv/JxsR/45d - K//KeSj/yHYk/8h3Jf/IdCL/x3Qh/8ZzIP/Ebhj/w20W/8VzIP/HdiX/xXUj/8JsGP/Iey7/FBAM/4FX - Lv/DcB7/wnEf/8R0I//Aahb/u2IJ/7pfBf+6XwX/uV8F/7lfBf+4XwX/uF8F/7heBf+3XgX/t14F/5NM - BPMAAADAAAAAAMdkAaXGZAH/xmQB/8ZkAv/FZAL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8Nj - Av/HbBH/jFMb/7xqGf/DZQf/wmID/8FiA//BYgP/wWID/8BiA//AYgP/wGED/79hA/+/YQP/v2ED/79h - A//FcyD/DQoI/4tYJf/AZg7/vWAE/7xgBP+8YAT/vGAE/7tgBP+7YAT/u2AE/7pfBP+6XwX/ul8F/7lf - Bf+5XwX/uV8F/5RMBPMAAADAAAAAAMhkAaXHZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAf/GZAL/xmQC/8Vj - Av/FYwL/xWMC/8RjAv/FZQX/xmcJ/8VmB//DZAP/w2MC/8NjAv/CYgL/wmIC/8JiA//BYgP/wWID/8Fi - A//BYgP/wGID/8BhA//CZw3/xW8Z/8NrE//AYwb/vmED/75hBP++YQT/vWAE/71gBP+9YAT/vGAE/7xg - BP+7YAT/u2AE/7tgBP+6XwT/ul8E/5ZMBPMAAADAAAAAAMllAaXIZQH/yGUB/8hkAf/IZAH/x2QB/8dk - Af/HZAH/x2QB/8ZkAf/GZAH/xmQC/8ZkAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8Nj - Av/DYwL/wmIC/8JiAv/CYgP/wmID/8FiA//BYgP/wWID/8BiA//AYQP/wGED/79hA/+/YQP/v2ED/75h - A/++YQT/vmEE/71gBP+9YAT/vWAE/7xgBP+8YAT/vGAE/5ZNA/MAAAC/AAAAAMplAaXJZQH/yWUB/8ll - Af/JZQH/yGUB/8hlAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAv/GZAL/xWQC/8Vj - Av/FYwL/xWMC/8RjAv/EYwL/xGMC/8NjAv/DYwL/w2MC/8JiAv/CYgL/wmID/8JiA//BYgP/wWID/8Fi - A//AYgP/wGED/8BhA/+/YQP/v2ED/79hA/++YQP/vmED/75hBP+9YQT/vWAE/5hNA/MAAAC6AAAAAMpl - AKXKZQD/ymUA/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8hlAf/IZQH/yGQB/8hkAf/HZAH/x2QB/8dk - Af/HZAH/xmQB/8ZkAf/GZAL/xmQC/8VkAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8Nj - Av/DYgL/wmIC/8JiA//CYgP/wWID/8FiA//BYgP/wGID/8BiA//AYQP/v2ED/79hA/+/YQP/vmED/5lO - AvMAAACtAAAAAMtmAJDLZgD/y2YA/8tmAP/KZQD/ymUA/8plAP/KZQH/ymUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yGUB/8hlAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAv/FZAL/xWMC/8Vj - Av/FYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2IC/8JiAv/CYgP/wmID/8FiA//BYgP/wWID/8Bi - A//AYgP/wGED/41IAuwAAACMAAAAAMxmAFrMZgD/zGYA/8xmAP/LZgD/y2YA/8tmAP/LZgD/y2UA/8pl - AP/KZQD/ymUB/8plAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hlAf/IZQH/yGQB/8hkAf/HZAH/x2QB/8dk - Af/HZAH/xmQB/8ZkAf/GZAL/xmQC/8VjAv/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8Ni - Av/CYgL/wmIC/8JiA//BYgP/wWID/3E5AsgAAABTAAAAAAAAAAbMZgDhzGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/y2YA/8tmAP/LZgD/y2YA/8tlAP/KZQD/ymUA/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/IZQH/yGUB/8hkAf/IZAH/x2QB/8dkAf/HZAH/x2QB/8ZkAf/GZAH/xmQC/8ZkAv/FYwL/xWMC/8Vj - Av/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/ul4C9yUTAF4AAAAdAAAAAAAAAADMZgA/zGYA+cxm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8tmAP/LZgD/y2YA/8tmAP/LZQD/ymUA/8pl - AP/KZQH/ymUB/8plAf/JZQH/yWUB/8llAf/JZQH/yGUB/8hlAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dk - Af/GZAH/xmQB/8ZkAv/GZAL/xWQC/8VjAv/FYwL/xGMC/8RjAv/EYwL/iUUBdAAAABUAAAAEAAAAAAAA - AAAAAAAAzGYAP8xmAOHMZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/LZgD/y2YA/8tmAP/LZgD/y2UA/8plAP/KZQD/ymUA/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8hl - Af/IZQH/yGQB/8hkAf/HZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAf/GZAL/xmQC/8NjAuyrVgJaAAAABgAA - AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbMZgBRzGYAlsxmAJnMZgCZzGYAmcxmAJnMZgCZzGYAmcxm - AJnMZgCZzGYAmcxmAJnMZgCZzGYAmcxmAJnMZgCZy2YAmctmAJnLZgCZy2YAmctmAJnKZQCZymUAmcpl - AJnKZQGZymUBmcllAZnJZQGZyWUBmcllAZnIZQGZyGUBmchlAZnIZAGZyGQBmcdkAZnHZAGZx2QBWsZk - AQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAADgAAAAAAAAAOAAAAAAAAAAwAAAAAAA - AACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAA - AAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAA - AACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAA - AAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAA - AACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAA - AAAAAAAAgAAAAAAAAADAAAAAAAAAAMAAAAAAAQAA4AAAAAAHAAD4AAAAAA8AAP///////wAAKAAAAEAA - AACAAAAAAQAgAAAAAAAAQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAA - ABwAAAA7AAAAYAAAAIIAAACaAAAAqgAAALEAAAC0AAAAtgAAALYAAAC2AAAAtgAAALYAAAC2AAAAtgAA - ALYAAAC2AAAAtgAAALYAAAC2AAAAtgAAALYAAAC2AAAAtgAAALYAAAC2AAAAtgAAALYAAAC2AAAAtgAA - ALYAAAC2AAAAtgAAALYAAAC2AAAAtgAAALYAAAC2AAAAtgAAALYAAAC2AAAAtgAAALYAAAC2AAAAtgAA - ALYAAAC2AAAAtgAAALYAAAC1AAAAtAAAAK8AAACmAAAAlAAAAHkAAABVAAAAMgAAABYAAAAAAAAAAAAA - AAAAAAABAAAABgAAABoAAAA9AAAAagAAAJIAAACuAAAAvgAAAMYAAADKAAAAywAAAMwAAADMAAAAzAAA - AMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAA - AMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAA - AMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMsAAADJAAAAxAAAALoAAACnAAAAhwAA - AF0AAAAyAAAAAAAAAAAAAAAAAAAAAgAAABEAAAAyJhYHe1EwDs9lPBLxdUYW/3VFFv90RRb/dEUW/3NF - Fv9zRBb/ckQW/3FEF/9xRBf/cEQX/3BDF/9vQxf/b0MX/25DF/9uQxj/bUMY/21CGP9sQhj/bEIY/2xC - GP9rQhj/a0EY/2pBGP9qQRn/aUEZ/2lBGf9pQRn/aEEZ/2hAGf9oQBn/Z0AZ/2dAGf9nQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/Yj0Y/VEzFPI2Ig3kBgQBzgAA - AMwAAADKAAAAwgAAAK4AAACHAAAAVQAAAAAAAAAAAAAAAAAAAAYAAAAeWTQPnXhGFPt6RxX/eUcV/3hH - Ff94RhX/d0YV/3ZGFf92Rhb/dUUW/3VFFv90RRb/dEUW/3NFFv9yRBb/ckQX/3FEF/9xRBf/cEQX/3BD - F/9vQxf/b0MX/25DF/9uQxj/bUIY/21CGP9sQhj/bEIY/2tCGP9rQhj/akEY/2pBGP9qQRn/aUEZ/2lB - Gf9oQRn/aEEZ/2hAGf9nQBn/Z0AZ/2dAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/1s5FvgeEwfZAAAAzAAAAMoAAADCAAAApgAAAHYAAAAAAAAAAAAAAAAqGAYSd0QSxH5J - FP99SBT/fUgU/3xIFP97SBT/e0cU/3pHFf95RxX/eUcV/3hHFf93RhX/d0YV/3ZGFf92Rhb/dUUW/3RF - Fv90RRb/c0UW/3NFFv9yRBb/ckQX/3FEF/9xRBf/cEQX/3BDF/9vQxf/bkMX/25DGP9tQxj/bUIY/21C - GP9sQhj/bEIY/2tCGP9rQhj/akEY/2pBGf9pQRn/aUEZ/2lBGf9oQRn/aEAZ/2hAGf9nQBn/Z0AZ/2dA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/zQhDeMAAADMAAAAygAAALcAAACOAAAAAAAA - AAAAAAAAe0YRm4JKE/+BShP/gEoT/4BJE/9/SRP/fkkT/35JFP99SBT/fEgU/3xIFP97SBT/ekcU/3pH - Ff95RxX/eEcV/3hGFf93RhX/d0YV/3ZGFf91Rhb/dUUW/3RFFv90RRb/c0UW/3NEFv9yRBf/cUQX/3FE - F/9wRBf/cEMX/29DF/9vQxf/bkMX/25DGP9tQhj/bUIY/2xCGP9sQhj/a0IY/2tCGP9rQRj/akEY/2pB - Gf9pQRn/aUEZ/2lBGf9oQRn/aEAZ/2dAGf9nQBn/Z0AZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/JBcJ3AAA - AMwAAAC/AAAAnQAAAAAAAAAAhkwRLYZMEvyFSxL/hEsS/4RLEv+DSxL/gkoS/4FKE/+BShP/gEoT/39J - E/9/SRP/fkkT/31JFP99SBT/fEgU/3tIFP97SBT/ekcU/3lHFf95RxX/eEcV/3hGFf93RhX/dkYV/3ZG - Fv91RRb/dUUW/3RFFv9zRRb/c0UW/3JEFv9yRBf/cUQX/3FEF/9wRBf/cEMX/29DF/9vQxf/bkMX/25D - GP9tQhj/bUIY/2xCGP9sQhj/a0IY/2tCGP9qQRj/akEY/2pBGf9pQRn/aUEZ/2hBGf9oQRn/aEAZ/2dA - Gf9nQBn/Z0AZ/1o4FvgDAgHNAAAAwwAAAKQAAAAAAAAAAIpNEZOJTRH/iE0R/4hMEf+HTBH/hkwR/4VM - Ev+FSxL/hEsS/4NLEv+DShL/gkoT/4FKE/+AShP/gEkT/39JE/9+SRP/fkkU/31IFP98SBT/fEgU/3tI - FP96RxT/ekcV/3lHFf95RxX/eEYV/3dGFf93RhX/dkYV/3ZGFv91RRb/dEUW/3RFFv9zRRb/c0QW/3JE - Fv9yRBf/cUQX/3BEF/9wQxf/b0MX/29DF/9uQxf/bkMY/21DGP9tQhj/bEIY/2xCGP9sQhj/a0IY/2tC - GP9qQRj/akEZ/2lBGf9pQRn/aUEZ/2hBGf9oQBn/IxYJ2wAAAMUAAACnAAAAAAAAAACNThDbjE4Q/4xO - EP+LThD/ik0Q/4lNEf+JTRH/iEwR/4dMEf+HTBH/hkwS/4VLEv+ESxL/hEsS/4NLEv+CShL/gkoT/4FK - E/+AShP/gEkT/39JE/9+SRP/fkkU/31IFP98SBT/fEgU/3tIFP96RxT/ekcV/3lHFf94RxX/eEYV/3dG - Ff93RhX/dkYW/3VFFv91RRb/dEUW/3RFFv9zRRb/ckQW/3JEF/9xRBf/cUQX/3BEF/9wQxf/b0MX/29D - F/9uQxf/bkMY/21CGP9tQhj/bEIY/2xCGP9rQhj/a0IY/2tBGP9qQRj/akEZ/0AoD+gAAADGAAAAqAAA - AAAAAAAAkVAP+ZBPD/+PTw//jk8P/45PEP+NThD/jE4Q/4tOEP+LTRD/ik0R/4lNEf+ITRH/iEwR/4dM - Ef+GTBH/hkwS/4VLEv+ESxL/g0sS/4NLEv+CShL/gUoT/4FKE/+ASRP/f0kT/39JE/9+SRT/fUgU/31I - FP98SBT/e0gU/3tHFP96RxT/eUcV/3lHFf94RxX/eEYV/3dGFf92RhX/dkYW/3VFFv90RRb/dEUW/3NF - Fv9zRRb/ckQW/3JEF/9xRBf/cUQX/3BEF/9wQxf/b0MX/29DF/9uQxf/bkMY/21CGP9tQhj/bEIY/2xC - GP9NLxHuAAAAxgAAAKgAAAAAAAAAAJRRDv+TUQ7/k1AO/5JQD/+RUA//kFAP/5BPD/+PTw//jk8P/41O - EP+NThD/jE4Q/4tOEP+KTRD/ik0R/4lNEf+ITRH/h0wR/4dMEf+GTBH/hUsS/4VLEv+ESxL/g0sS/4JK - Ev+CShP/gUoT/4BKE/+ASRP/f0kT/35JE/9+SRT/fUgU/3xIFP98SBT/e0gU/3pHFP96RxX/eUcV/3hH - Ff94RhX/d0YV/3dGFf92RhX/dUYW/3VFFv90RRb/dEUW/3NFFv9zRBb/ckQW/3FEF/9xRBf/cEQX/3BD - F/9vQxf/b0MX/25DF/9uQxj/UjIS8AAAAMYAAACoAAAAAAAAAACYUg3/l1IN/5ZSDf+VUQ7/lFEO/5RR - Dv+TUQ7/klAO/5JQD/+RUA//kE8P/49PD/+OTw//jk8Q/41OEP+MThD/jE4Q/4tOEP+KTRD/iU0R/4lN - Ef+ITBH/h0wR/4ZMEf+GTBL/hUsS/4RLEv+ESxL/g0sS/4JKEv+BShP/gUoT/4BKE/9/SRP/f0kT/35J - E/99SRT/fUgU/3xIFP97SBT/e0gU/3pHFP95RxX/eUcV/3hHFf94RhX/d0YV/3ZGFf92Rhb/dUUW/3VF - Fv90RRb/c0UW/3NFFv9yRBb/ckQX/3FEF/9xRBf/cEQX/1QyEfAAAADGAAAAqAAAAAAAAAAAmlMN/5pT - Df+ZUw3/mVMN/5hSDf+XUg3/llIN/5ZSDv+VUQ7/lFEO/5NRDv+TUQ7/klAP/5FQD/+QUA//kE8P/49P - D/+OTw//jU8Q/41OEP+MThD/i04Q/4tNEP+KTRH/iU0R/4hNEf+ITBH/h0wR/4ZMEf+FTBL/hUsS/4RL - Ev+DSxL/g0oS/4JKE/+BShP/gUoT/4BJE/9/SRP/fkkT/35JFP99SBT/fEgU/3xIFP97SBT/e0cU/3pH - Ff95RxX/eUcV/3hHFf93RhX/d0YV/3ZGFf92Rhb/dUUW/3RFFv90RRb/c0UW/3NFFv9VMxDwAAAAxgAA - AKgAAAAAAAAAAJtUDP+bVAz/m1MM/5pTDP+aUwz/mlMN/5lTDf+ZUw3/mFMN/5hSDf+XUg3/llIN/5VS - Dv+VUQ7/lFEO/5NRDv+SUA7/klAP/5FQD/+QUA//j08P/49PD/+OTxD/jU4Q/4xOEP+MThD/i04Q/4pN - EP+JTRH/iU0R/4hNEf+HTBH/h0wR/4ZMEv+FSxL/hEsS/4RLEv+DSxL/gkoS/4JKE/+BShP/gEoT/4BJ - E/9/SRP/fkkT/35JFP99SBT/fEgU/3xIFP97SBT/ekcU/3pHFf95RxX/eEcV/3hGFf93RhX/d0YV/3ZG - Fv91Rhb/WDQQ8AAAAMYAAACoAAAAAAAAAACdVAz/nFQM/5xUDP+cVAz/m1QM/5tUDP+bVAz/m1MM/5pT - DP+aUw3/mlMN/5lTDf+ZUw3/mFMN/5dSDf+XUg3/llIO/5VRDv+UUQ7/lFEO/5NRDv+SUA7/kVAP/5FQ - D/+QTw//j08P/45PD/+OTxD/jU4Q/4xOEP+LThD/i00Q/4pNEf+JTRH/iE0R/4hMEf+HTBH/hkwR/4ZM - Ev+FSxL/hEsS/4NLEv+DSxL/gkoS/4FKE/+BShP/gEkT/39JE/9/SRP/fkkU/31IFP99SBT/fEgU/3tI - FP97SBT/ekcU/3lHFf95RxX/eEcV/1o0EPAAAADGAAAAqAAAAAAAAAAAnlUL/55VDP+dVQz/nVQM/51U - DP+dVAz/nFQM/5xUDP+cVAz/m1QM/5tUDP+bVAz/mlMM/5pTDP+aUw3/mVMN/5lTDf+ZUw3/mFIN/5dS - Df+WUg3/llIO/5VRDv+UUQ7/k1EO/5NQDv+SUA//kVAP/5BQD/+QTw//j08P/45PD/+NThD/jU4Q/4xO - EP+LThD/ik0Q/4pNEf+JTRH/iE0R/4dMEf+HTBH/hkwR/4VLEv+FSxL/hEsS/4NLEv+CShL/gkoT/4FK - E/+AShP/gEkT/39JE/9+SRP/fkkU/31IFP98SBT/fEgU/3tIFP9bNQ/wAAAAxgAAAKgAAAAAAAAAAKBV - C/+fVQv/n1UL/59VC/+eVQv/nlUL/55VDP+dVQz/nVQM/51UDP+cVAz/nFQM/5xUDP+cVAz/m1QM/5tU - DP+bUwz/mlMM/5pTDf+aUw3/mVMN/5lTDf+YUw3/mFIN/5dSDf+WUg3/lVEO/5VRDv+UUQ7/k1EO/5JQ - Dv+SUA//kVAP/5BQD/+PTw//j08P/45PEP+NThD/jE4Q/4xOEP+LThD/ik0Q/4lNEf+JTRH/iEwR/4dM - Ef+GTBH/hkwS/4VLEv+ESxL/hEsS/4NLEv+CShL/gkoT/4FKE/+AShP/gEkT/39JE/9+SRP/XjcP8AAA - AMYAAACoAAAAAAAAAAChVgv/oVYL/6NbE/+pZyP/rm4u/61uL/+tbi//rW4v/6xtLf+paCf/pmMg/6Jc - Fv+eVg//nVQM/51UDP+cVAz/nFQM/6BbFv+mZyj/qm0w/6ptMP+pbTD/qW0w/6ltMf+pbTH/qG0x/6Vo - Kv+eXRv/nFoY/6NmKf+mbDL/oWUp/5hYF/+UUQ7/k1EO/5JQDv+RUA//k1UX/5tgJ/+faTL/n2kz/5tj - K/+TVxz/lFog/5plL/+caDT/l2Es/45VG/+IThL/iEwR/4dMEf+GTBH/iFEZ/5BcKP+VZDP/lWU0/49d - Kf+GUBn/gUoT/2E3DvAAAADGAAAAqAAAAAAAAAAAolYK/6JWCv+rZyP/MSQX/x4YEv8gGhP/IBoT/yAa - E/8dGBL/QzEh/19FLP9+VzD/rGws/6NeF/+fVg3/nlUM/51VDP+oZyj/Eg4L/yAaE/8gGhP/IBoT/yAa - E/8gGhP/IBoT/yAaE/8VEQ3/gVYq/6lsMP8SDgv/IBoT/xIOC/+kZin/l1IN/5ZSDf+WUg7/l1QT/6Jo - Lv8xJRn/HhgS/yAaE/8SDgv/oGky/2dGJf8WEg3/IBoT/xQQDP+UYzL/jlEV/4tOEP+KTRD/ik4S/5Ve - KP83Kh7/HRgS/xwWEf8sIRf/j1om/4VLEv9jOA3wAAAAxgAAAKgAAAAAAAAAAKRXCv+jVwr/sG8u/x4Y - Ev8yKB//MSce/y0kG/8pIRn/KSEZ/yoiGf8pIRn/JB0W/y4jGP+JXjP/p2Ie/6BWDf+fVQv/rW4v/yAa - E/8zKR//Migf/zAmHf8uJRz/LiUc/y4lHP8uJRz/IRoU/4VbMf+udDr/IBoT/zMpH/8gGhP/qW0x/5pT - Df+ZUw3/mVQO/6BhIf9nSy//Jx8Y/zIoH/8zKR//IBoT/6ZuN/+caTb/IBoT/zIoHv8nHxj/bU8x/5VZ - HP+OTw//jk8Q/49RFf+WZjf/IBkT/zIoHv8qIhn/WEMu/5JbJP+ITBH/ZTkN8AAAAMYAAACoAAAAAAAA - AAClVwr/pVcK/7JwL/8gGhP/Mykf/ywjG/9dRCv/bE8x/21PMf85Kx3/JR4W/y4lHP8uJRz/HxkT/4pf - NP+nYBn/oFcM/65uL/8gGhP/Mykf/y4lHP9AMCH/QzIh/0IxIP9CMSD/QjEg/zssHf+LWSf/rnI3/yAa - E/8zKR//IBoT/6ptMP+bVAz/m1QM/55aFv+ZZzb/KB8X/zAmHf8zKR//Mykf/yAaE/+nbDL/omYp/0Ex - If8uJRz/LCMb/1I+Kf+dYCX/klAP/5FQD/+WWRv/d1U1/yYfF/8zKR//JB0W/4dgOP+QVBj/i04Q/2c6 - DPAAAADGAAAAqAAAAAAAAAAAp1gJ/6ZYCf+zcS//IBoT/zMpH/8nHxf/j2Q7/65pJP+rZR7/sG0r/41j - Of8rIRf/LyYd/y8mHP8lHRX/pmot/6RZEP+vby//IBoT/zMpH/8oIBj/jWZA/65uLv+qaCb/qmgm/6po - Jv+oZCH/olwW/61wMf8gGhP/Mykf/yAaE/+sbTD/nFQM/51WD/+oaSr/QDAf/ywjG/8yKB//Mige/zIp - H/8gGhP/qW0x/6BeHf9nSy//KSEZ/zAmHf8yJxv/r3tH/6VsMv+lazL/qnVA/1ZAK/8sIxv/MCcd/yYd - Fv+gaTL/kFAR/49PD/9qOwzwAAAAxgAAAKgAAAAAAAAAAKhYCf+oWAn/tHEu/yAaE/8zKR//JR4W/41g - M/+pXxT/plgK/6ZYDP+sZR7/g1w2/yYeF/8yKB7/Jx8X/3VTMP+oYRj/sXAv/yAaE/8zKR//JR4W/4pe - M/+lXRX/oVYL/6FWC/+gVgv/oFYL/6BVC/+tbi//IBoT/zMpH/8gGhP/rG4v/55WDf+kYBz/flk1/yUe - Fv8wJh3/LSQb/z8wI/8wJx3/IBoT/6ptMP+eWRP/mWc2/yIbFf8yKB7/LSQb/yQdFv8gGhP/IBoT/yMc - Ff8qIhr/MSce/ywjG/9SPin/nmEl/5NRDv+SUA7/bTwL8AAAAMYAAACoAAAAAAAAAACpWQn/qVkJ/7Zy - Lv8gGhP/Mykf/yUeFv+NYDP/ql8T/6dYCf+nWAn/p1oM/7NwLf87LB3/LyYc/y0kG/9NOCT/rmgj/7Jw - L/8gGhP/Mykf/yUeFv+KXzP/p14U/6JWCv+iVgr/olYL/6FWC/+hVgv/r28v/yAaE/8zKR//IBoT/65u - L/+hWRH/pGsx/yYeFv8vJh3/KyMa/11FLf9MOSf/LyYd/yAaE/+sbTD/nFUN/6lrLP8vJBn/MCYd/zIo - Hv8uJRz/KiIa/ykhGf8tJBv/MSce/zMpH/8mHxf/elcz/5xaGP+WUg3/llIO/3A9CvAAAADGAAAAqAAA - AAAAAAAAq1oI/6pZCP+3ci3/IBoT/zMpH/8lHhb/jmAz/6xgE/+oWQn/qFkJ/6hYCf+vZh7/Y0cs/ysj - Gv8xJx7/Jh4V/7JuK/+zcS//IBoT/zMpH/8lHhb/i18z/6heFP+kVwr/o1cK/6NXCv+jVwr/o1YK/7Bv - L/8gGhP/Mykf/yAaE/+wcTL/q2ck/2BGLP8pIRn/MSce/yAaFP+leEv/NCgc/zAnHf8gGhP/rG4w/55V - DP+lYyD/X0Ys/yoiGv8wJh3/Szgm/2xPMv9qTjL/W0Qt/y0kG/8xKB7/HhgS/6tvNf+bVRD/mVMN/5lT - Df9yPgrwAAAAxgAAAKgAAAAAAAAAAKxaCP+sWgj/uHMt/yAaE/8zKR//JR4W/49gMv+tYBL/qlkJ/6lZ - Cf+pWQn/r2Ua/25OL/8pIRn/Mykf/x8ZE/+0cS7/tHEu/yAaE/8zKR//JR4W/41gM/+pXxT/pVcK/6VX - Cv+lVwr/pFcK/6RXCv+ycC//IBoT/zMpH/8gGhP/tHc6/4peM/8iGxT/MCcd/yoiGv9VPyj/uH9G/x8Z - E/8yKR//IBoT/61uL/+fVQv/o1wV/4deM/8kHRb/MCYd/zwuH/+vdDn/rG0w/2JILv8sIxv/LSQb/0s4 - JP+lZSX/m1QM/5tUDP+aUwz/cz4J8AAAAMYAAACoAAAAAAAAAACtWwj/rVoI/7lzLf8gGhP/Mykf/yUe - Fv+QYTL/rmAS/6taCP+rWgj/qlkI/7FnHP9vTzD/KiIa/zIoH/8eGBL/tXEt/7VyLv8gGhP/Mykf/yUe - Fv+NYDP/ql8T/6dYCf+mWAn/plgJ/6ZYCv+lWAr/snAv/yAaE/8zKR//IhsV/76GT/9DMiD/LSQb/zAm - Hf8pIBb/nmgy/7N1N/8gGhP/Mykf/yAaE/+vby//oFYL/6FXDf+ubi//Jx8W/zAmHf8gGhT/pm01/6xu - Lv85Kx3/LyYc/ycgGP9zUjH/o14a/51UDP+cVAz/nFQM/3U/CfAAAADGAAAAqAAAAAAAAAAAr1sH/65b - B/+6cyz/IBoT/zMpH/8lHhb/kGEy/7BgEv+sWgj/rFoI/61bCv+2byf/RTMg/y4lHP8vJh3/Oiwd/7Rt - Jv+3ci7/IBoT/zMpH/8lHhb/jmAz/6tgE/+oWAn/qFgJ/6dYCf+nWAn/p1gJ/7NxLv8gGhP/Mige/yUe - F/9+Wzn/JR4X/zEnHv8nHxj/a00u/6tlHv+xcTD/IBoT/zMpH/8gGhP/sG8v/6JWC/+iVgv/qmYi/1Y/ - Kf8sIxv/Jh8X/4BbNv+gbz3/IRsU/zEnHv8hGhT/pm01/6BYEP+eVQz/nlUM/51UDP92PwnwAAAAxgAA - AKgAAAAAAAAAALBcB/+wWwf/u3Ms/yAaE/8zKR//JR4W/5FhMf+xYRH/rlsI/65cCv+yZBf/nWk3/yMc - Ff8yKB7/KiIa/1c/J/+yaBz/uHMt/yAaE/8zKR//JR4W/49gM/+tYBP/qVkJ/6lZCf+pWQn/qFkJ/6hZ - Cf+1cS7/IBoT/zAnHf9TPij/PS4g/y8mHP8tJBz/OSoc/7JwLf+nWg//snAv/yAaE/8zKR//IBoT/7Jw - L/+jVwr/o1cK/6hgF/91Ui//Jx8Y/yoiGv9kSi//eVk4/yggGP8vJRz/OCsc/6xqKf+gVgz/n1UL/59V - C/+fVQv/dkAI8AAAAMYAAACoAAAAAAAAAACxXAf/sVwH/710LP8gGhP/Mykf/ycfF/+VZjn/t2wh/7Vo - Gv+5byX/nmo2/z0uHv8tJBz/MSce/yAZE/+mazL/sF8Q/7hzLf8gGhP/Mykf/yUeFv+PYTL/rmAS/6ta - CP+qWQj/qlkI/6pZCf+qWQn/tnIu/yAaE/8yKB7/MCYd/zAnHf8wJh3/IRoU/5dmNP+rXxT/p1gJ/7Nx - Lv8gGhP/Mykf/yAaE/+ycC//pVcK/6RXCv+mWg//qW4z/yAaE/8uJRz/QzMi/1ZAKf8sJBv/KSEZ/2tN - L/+oYhz/oVYL/6FWC/+gVgv/oFYL/3hACPAAAADGAAAAqAAAAAAAAAAAs1wG/7JcBv+9dCv/IBoT/zMp - H/8sIxv/YUUq/3JQMP9xUC//UTok/yMcFf8tJBv/LyYc/yQdFv9jRin/tWkc/65cCP+6cy3/IBoT/zMp - H/8lHhb/kGEy/69gEv+sWgj/rFoI/6taCP+rWgj/q1oI/7hyLf8gGhP/Mykf/zMpH/8yKR//KCAY/25P - MP+xaB//qVoL/6hYCf+1cS7/IBoT/zMpH/8gGhP/s3Eu/6ZYCf+mWAr/plkL/69qJv9DMiD/LSQb/y4l - HP9AMiP/MCYd/yIbFf+fajT/plwR/6JWCv+iVgr/olYL/6JWC/95QAjwAAAAxgAAAKgAAAAAAAAAALRd - Bv+0XQb/vnQp/x0XEf8wJh3/MCcd/y0kG/8pIRn/KSEZ/ysiGv8sIxv/KCAY/ygfFv9wTiz/uW8j/7Je - DP+vWwf/u3Ms/yAaE/8zKR//JR4W/5FhMf+xYRL/rVsI/61aCP+tWgj/rVoI/6xaCP+4cy3/IBoT/zMp - H/8zKR//LiUc/zAkGP+sbCz/rF0P/6pZCf+pWQn/tnIu/yAaE/8zKR//IBoT/7VxLv+oWAn/p1gJ/6dY - Cf+tYxn/bE0u/ykhGf8yKR//Mige/y8mHP8wJRn/sG0r/6RYC/+kVwr/pFcK/6NXCv+jVwr/ekAH8AAA - AMYAAACoAAAAAAAAAAC1XQb/tV0G/7xsHf8/LBr/PS0d/x4YEv8gGhP/IBoT/x8ZE/8yJhn/RTIf/3FO - LP+oai7/uGkb/7NfDP+xXAf/sVwH/7lvI/8SDgv/IBoT/xURDf+OWif/smAP/69bB/+uWwf/rlsH/65b - CP+uWwj/tm0k/xIOC/8gGhP/IBoT/xgUD/+PXzD/sWQX/6tbCf+rWgj/q1oI/7RsJP8SDgv/IBoT/xIO - C/+zbCX/qVkJ/6lZCf+oWQn/ql0Q/6BmLP8VEQ3/IBoT/yAaE/8bFhD/X0Im/6xkG/+mWAr/pVcK/6VX - Cv+lVwr/pFcK/3tBB/AAAADGAAAAqAAAAAAAAAAAtl4F/7ZeBf+4Yg3/vGwb/75yJf/AdSr/wHUr/8B1 - K/+/dSr/vnIm/7xuIP+4aBf/tWEN/7NeB/+zXAb/slwG/7JcBv+1YhH/um8j/710LP+6cCX/tmYW/7Fd - Cf+wXAf/sFsH/69bB/+vWwf/r1sH/7JhEf+3biP/unMs/7pzLf+3byb/smQX/65bCv+tWgj/rFoI/6xa - CP+vYBL/tW0k/7hzLf+1bST/rmAS/6pZCP+qWQn/qlkJ/6laCv+tYRX/s20m/7VyLv+1ci7/tG4q/69l - HP+pWw7/p1gJ/6dYCf+mWAn/plgJ/6ZYCv98QgfwAAAAxgAAAKgAAAAAAAAAALheBf+3XgX/t14F/7de - Bf+3XgX/tl4F/7ZeBf+2Xgb/tV4G/7VdBv+1XQb/tV0G/7RdBv+0XQb/tF0G/7RdBv+zXQb/s10G/7Nd - Bv+yXAb/slwG/7JcB/+yXAf/sVwH/7FcB/+xXAf/sVwH/7BcB/+wWwf/sFsH/69bB/+vWwf/r1sH/69b - B/+uWwf/rlsI/65bCP+tWwj/rVoI/61aCP+sWgj/rFoI/6xaCP+sWgj/q1oI/6taCP+rWgj/qlkI/6pZ - CP+qWQn/qlkJ/6lZCf+pWQn/qVkJ/6hZCf+oWQn/qFgJ/6dYCf+nWAn/fUIH8AAAAMYAAACoAAAAAAAA - AAC5XwX/uV8F/7hfBf+4XwX/uF4F/7heBf+3XgX/t14F/7deBf+2XgX/tl4F/7ZeBv+2Xgb/tV4G/7Vd - Bv+1XQb/tV0G/7RdBv+0XQb/tF0G/7NdBv+zXQb/s10G/7NcBv+yXAb/slwG/7JcB/+yXAf/sVwH/7Fc - B/+xXAf/sFwH/7BcB/+wWwf/sFsH/69bB/+vWwf/r1sH/65bB/+uWwf/rlsI/65bCP+tWgj/rVoI/61a - CP+sWgj/rFoI/6xaCP+rWgj/q1oI/6taCP+rWQj/qlkI/6pZCP+qWQn/qVkJ/6lZCf+pWQn/qVkJ/35D - B/AAAADGAAAAqAAAAAAAAAAAul8E/7pfBf+5XwX/uV8F/7lfBf+5XwX/uF8F/7hfBf+4XgX/uF4F/7de - Bf+3XgX/t14F/7deBf+2XgX/tl4F/7ZeBv+2Xgb/tV0G/7VdBv+1XQb/tF0G/7RdBv+0XQb/tF0G/7Nd - Bv+zXQb/s10G/7NcBv+yXAb/tGEO/7psH/+5bSD/tGMS/7FdCP+xXAf/sFwH/7BcB/+wWwf/r1sH/69b - B/+vWwf/r1sH/65bB/+uWwf/rlsI/61bCP+tWgj/rVoI/61aCP+sWgj/rFoI/6xaCP+rWgj/q1oI/6ta - CP+rWQj/qlkI/6pZCf9/QwfwAAAAxgAAAKgAAAAAAAAAALtgBP+7YAT/u18E/7pfBP+6XwT/ul8F/7pf - Bf+5XwX/uV8F/7lfBf+5XwX/uF8F/7hfBf+4XgX/uF4F/7deBf+3XgX/t14F/7deBf+2XgX/tl4G/7Ze - Bv+1Xgb/tV0G/7VdBv+1XQb/tF0G/7RdBv+0XQb/tF0G/7ptHv8mGxL/KB0T/6VkI/+zXwr/slwH/7Jc - B/+xXAf/sVwH/7FcB/+wXAf/sFwH/7BbB/+wWwf/r1sH/69bB/+vWwf/rlsH/65bB/+uWwj/rlsI/61a - CP+tWgj/rVoI/6xaCP+sWgj/rFoI/6xaCP+rWgj/gEMG8AAAAMYAAACoAAAAAAAAAAC8YAT/vGAE/7xg - BP+8YAT/u2AE/7tgBP+7YAT/u18E/7pfBP+6XwT/umAG/7xkDf+/bRv/wnQl/8J0Jf/Abh3/u2cR/7xn - Ev+/bh7/vm4e/7xpFv++bh7/vm4e/7tpFv+9bh7/vW4e/7hjDv+3Yw7/vG0e/7xtHv/BeC//MiUZ/yIb - FP+vdz//vXMo/7prG/+1Yg7/tmIP/7psHv+6bR//tWMS/7NgDf+3aBn/um8k/7txJ/+5biL/tWYW/7Fd - Cv+wWwf/r1sH/69bB/+vWwf/rlsH/65bB/+uWwj/rlsI/61aCP+tWgj/rVoI/4FDBvAAAADGAAAAqAAA - AAAAAAAAvWEE/71gBP+9YAT/vWAE/7xgBP+8YAT/vGAE/7xgBP+7YAT/u2AE/7thBf+1Zhj/TDMb/x4W - D/8sIBT/Qi8c/6JoLv+tbSz/KB0S/yccEv/Gfjb/JxwR/ycbEf/Gfjb/JhsR/yYbEf++bh7/vm4e/yYb - Ef8mGxH/x4M//zMmGf8pIRn/Szci/yIaEv9MNyD/s24p/75yJv8mGxL/KB0T/6doKP+9cyj/ZEUm/ysg - Ff8rIBX/JhsS/4JSIf+0YhD/sVwH/7FcB/+wXAf/sFsH/7BbB/+vWwf/r1sH/69bB/+vWwf/rlsH/65b - CP+CRAbwAAAAxgAAAKgAAAAAAAAAAL9hA/++YQP/vmED/75hBP++YQT/vWAE/71gBP+9YAT/vWAE/7xg - BP+8YQX/wWwY/1k8Hv94VDD/fFgz/yQdFv8uIhb/tHxD/x8ZE/8yJRn/zIhG/zAkGP8wJBj/y4hG/zAk - GP8wJBj/wXQl/8FzJf8wJBj/MCQY/8qIRv8zJhn/KCAY/0o2If9JNiH/IBoT/044If/Ggj//MiUZ/x8Z - E/+vdz//WkAm/yIbFf9QOib/b1Aw/19FKf+UYzP/t2cX/7JcBv+yXAf/slwH/7FcB/+xXAf/sVwH/7Bc - B/+wXAf/sFsH/7BbB/+vWwf/g0QF8AAAAMYAAACoAAAAAAAAAADAYQP/v2ED/79hA/+/YQP/v2ED/75h - A/++YQP/vmEE/75hBP+9YQT/vWAE/8FpEv++eTX/bEws/0MyH/8jHBX/OSkZ/7V8Q/8gGhP/MyYZ/82J - Rf8xJBj/MSQY/8yKR/8xJBj/MSQY/8J0Jv/DdSf/MSQY/zEkGP/KiEb/MyYZ/yIbFf+8fkD/yIVB/ywi - GP8dFxL/voJH/zMmGf8gGhP/s35H/yceFf8qIhr/OSsd/zYpG/84Khz/Kx8U/7xuIP+zXQb/s10G/7Nd - Bv+zXAb/slwG/7JcBv+yXAf/sVwH/7FcB/+xXAf/sVwH/4RFBfAAAADGAAAAqAAAAAAAAAAAwWID/8Bi - A//AYgP/wGED/8BhA/+/YQP/v2ED/79hA/+/YQP/v2ED/75hA//Ebxn/Qi8b/yIbFf84Khz/YEQo/756 - N/+zdTn/IBoT/zMmGf/NiUX/MiUZ/yshF//QkFD/LCIX/ywiF//KhT//vn08/yshF/8wJBj/y4hF/zMm - Gf8iGxX/voBB/7x+Pv8sIhj/HRgS/7+DSP80Jhn/IBoT/7N9Rv88LRz/Jh8X/3pXM/95VzP/Jh4X/y8j - F/++cCP/tV0G/7RdBv+0XQb/tF0G/7RdBv+zXQb/s10G/7NdBv+yXAb/slwG/7JcB/+FRQXwAAAAxgAA - AKgAAAAAAAAAAMJiA//BYgP/wWID/8FiA//BYgP/wWID/8BiA//AYgP/wGED/8BhA/+/YQP/xXAb/zgn - GP8jHBb/flkz/3dTL/+MWSb/s3U2/x8ZE/8yJRn/zolF/zIlGP8lHhf/RDIg/yUeF/8iGxX/PSwc/0Av - Hv8jHBX/RDAd/8qDPf8yJRn/Jh4X/0o1IP9KNSD/IhsU/0MwHf/JhD//MyYZ/yAaE/+xdjz/f1cv/xsW - Ef9iRir/bk4u/x4YEv9mRij/u2kX/7ZeBv+2Xgb/tV4G/7VdBv+1XQb/tV0G/7RdBv+0XQb/tF0G/7Nd - Bv+zXQb/hkYE8AAAAMYAAACoAAAAAAAAAADDYgL/wmIC/8JiAv/CYgP/wmID/8JiA//BYgP/wWID/8Fi - A//BYgP/wGID/8NpDv+mZyn/Qy8c/yAYEP8nHBH/f1Ah/7NxMP8yJRj/LyMX/8yEOv8nHBH/RzMf/0cz - H/8sIBX/nWw8/1A4If8jGhL/OCgZ/6NmKv/Fdif/JxwR/zoqGv9dQif/LCAV/0IvHP+tayn/xnov/zMm - Gf8gGhP/r3Ay/8JyI/9yTSf/Kx8U/x8YEf9ZPSL/wXIj/7hhCv+3XgX/t14F/7deBf+2XgX/tl4F/7Ze - Bv+2Xgb/tV0G/7VdBv+1XQb/tF0G/4dGBPAAAADGAAAAqAAAAAAAAAAAxGMC/8NjAv/DYwL/w2MC/8Nj - Av/DYgL/wmIC/8JiAv/CYgP/wmID/8FiA//BYwX/xGkO/8dxHP/JdiT/x3Qg/8RtFf/JeSn/RzIe/1I6 - Iv/IeCj/xXAb/8ZzIP/GcyD/xXEd/8NtF//EcBz/xnUj/8RxHv/AZw//wGYO/8NvHP/EciH/w3Ef/8Ry - If/Cbxz/vmYO/8R1Jf8zJhn/IBoT/65vLv+9ZQ7/v2oW/8JyIv/CcyT/v2wa/7tjC/+5XwX/uF8F/7hf - Bf+4XgX/uF4F/7deBf+3XgX/t14F/7deBf+2XgX/tl4G/7ZeBv+IRgTwAAAAxgAAAKgAAAAAAAAAAMRj - Av/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NiAv/CYgL/wmIC/8JiAv/CYgP/wmID/8Fi - A//BYwT/u2sc/ycbEP9BLBj/xW8Y/8BiA//AYQP/wGED/79hA/+/YQP/v2ED/79hA/++YQP/vmED/75h - BP++YQT/vWEE/71gBP+9YAT/vWAE/71gBP/FdST/MiUZ/x8ZE/+vbiz/vGMJ/7tgBP+7YAT/u18E/7pf - BP+6XwT/ul8F/7pfBf+5XwX/uV8F/7lfBf+4XwX/uF8F/7heBf+4XgX/t14F/7deBf+3XgX/iUYE8AAA - AMYAAACoAAAAAAAAAADFZAL/xWMC/8VjAv/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8Nj - Av/DYwL/w2MC/8NiAv/CYgL/wmMD/8RoDf/IcRv/x3AZ/8NmCv/BYgP/wWID/8FiA//AYgP/wGID/8Bh - A//AYQP/v2ED/79hA/+/YQP/v2ED/79hA/++YQP/vmED/75hBP++YQT/w3Ad/yccEf8pHhL/rWch/71i - CP+8YAT/vGAE/7xgBP+7YAT/u2AE/7tgBP+7YAT/ul8E/7pfBP+6XwX/ul8F/7lfBf+5XwX/uV8F/7lf - Bf+4XwX/uF8F/4pGBPAAAADGAAAAqAAAAAAAAAAAxmQB/8ZkAf/GZAL/xmQC/8ZkAv/FYwL/xWMC/8Vj - Av/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8JiAv/CYgL/wmIC/8Ji - A//CYgP/wWID/8FiA//BYgP/wWID/8FiA//AYgP/wGID/8BhA//AYQP/v2ED/79hA/+/YQP/v2ED/8Bm - C//EcBz/xXEd/8FoD/++YgX/vWAE/71gBP+9YAT/vWAE/7xgBP+8YAT/vGAE/7xgBP+7YAT/u2AE/7tg - BP+7XwT/ul8E/7pfBP+6XwX/ul8F/7lfBf+LRwTwAAAAxgAAAKgAAAAAAAAAAMdkAf/HZAH/x2QB/8dk - Af/GZAH/xmQB/8ZkAf/GZAL/xmQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8Rj - Av/DYwL/w2MC/8NjAv/DYwL/w2IC/8JiAv/CYgL/wmID/8JiA//CYgP/wWID/8FiA//BYgP/wWID/8Bi - A//AYgP/wGED/8BhA//AYQP/v2ED/79hA/+/YQP/v2ED/75hA/++YQP/vmEE/75hBP+9YQT/vWAE/71g - BP+9YAT/vGAE/7xgBP+8YAT/vGAE/7xgBP+7YAT/u2AE/7tgBP+7XwT/i0cD8AAAAMYAAACoAAAAAAAA - AADIZAH/yGQB/8hkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8ZkAf/GZAH/xmQB/8ZkAv/GZAL/xmQC/8Vk - Av/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8NjAv/DYwL/w2IC/8Ji - Av/CYgL/wmID/8JiA//BYgP/wWID/8FiA//BYgP/wWID/8BiA//AYgP/wGED/8BhA/+/YQP/v2ED/79h - A/+/YQP/v2ED/75hA/++YQP/vmEE/75hBP+9YQT/vWAE/71gBP+9YAT/vGAE/7xgBP+8YAT/vGAE/4xI - A/AAAADFAAAApgAAAAAAAAAAyWUB/8llAf/IZQH/yGUB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8ZkAf/GZAH/xmQB/8ZkAv/GZAL/xWQC/8VjAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8NjAv/DYwL/w2MC/8NjAv/DYwL/wmIC/8JiAv/CYgL/wmID/8JiA//BYgP/wWID/8Fi - A//BYgP/wWID/8BiA//AYgP/wGED/8BhA/+/YQP/v2ED/79hA/+/YQP/vmED/75hA/++YQT/vmEE/75h - BP+9YAT/vWAE/71gBP+OSAPwAAAAwgAAAKIAAAAAAAAAAMllAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hl - Af/IZQH/yGUB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8ZkAf/GZAH/xmQC/8Zk - Av/GZAL/xWQC/8VjAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8NjAv/DYwL/w2MC/8Nj - Av/DYgL/wmIC/8JiAv/CYgP/wmID/8JiA//BYgP/wWID/8FiA//BYgP/wGID/8BiA//AYQP/wGED/8Bh - A/+/YQP/v2ED/79hA/+/YQP/vmED/75hA/++YQT/jkkD8AAAAL4AAACaAAAAAAAAAADKZQD/ymUB/8pl - Af/KZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hlAf/IZQH/yGUB/8hkAf/IZAH/yGQB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAf/GZAH/xmQC/8ZkAv/GZAL/xWMC/8VjAv/FYwL/xWMC/8Vj - Av/EYwL/xGMC/8RjAv/EYwL/xGMC/8NjAv/DYwL/w2MC/8NjAv/DYgL/wmIC/8JiAv/CYgP/wmID/8Fi - A//BYgP/wWID/8FiA//BYgP/wGID/8BiA//AYQP/wGED/79hA/+/YQP/v2ED/5BJAu8AAACzAAAAiAAA - AAAAAAAAy2YA8MtlAP/KZQD/ymUA/8plAP/KZQD/ymUB/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yGUB/8hlAf/IZQH/yGQB/8hkAf/IZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/xmQB/8Zk - Af/GZAH/xmQC/8ZkAv/FZAL/xWMC/8VjAv/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8Nj - Av/DYwL/w2MC/8NiAv/CYgL/wmIC/8JiA//CYgP/wmID/8FiA//BYgP/wWID/8FiA//AYgP/wGID/8Bi - A/+PSALqAAAAngAAAG0AAAAAAAAAAMtmAMPLZgD/y2YA/8tmAP/LZgD/y2YA/8tlAP/KZQD/ymUA/8pl - AP/KZQH/ymUB/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yGUB/8hlAf/IZQH/yGQB/8hk - Af/IZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAf/GZAL/xmQC/8ZkAv/FZAL/xWMC/8Vj - Av/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NiAv/CYgL/wmIC/8Ji - A//CYgP/wWID/8FiA//BYgP/cjoC0QAAAH0AAABKAAAAAAAAAADMZgB4zGYA/8xmAP/MZgD/y2YA/8tm - AP/LZgD/y2YA/8tmAP/LZgD/y2UA/8tlAP/KZQD/ymUA/8plAP/KZQH/ymUB/8plAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yGUB/8hlAf/IZQH/yGQB/8hkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/GZAH/xmQB/8ZkAf/GZAL/xmQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8RjAv/EYwL/xGMC/8Rj - Av/EYwL/w2MC/8NjAv/DYwL/w2MC/8JiAv/CYgL/wmIC/zseAZQAAABSAAAAKgAAAAAAAAAAzGYAEsxm - AO3MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2UA/8pl - AP/KZQD/ymUA/8plAP/KZQH/ymUB/8plAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/IZQH/yGUB/8hl - Af/IZAH/yGQB/8hkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAv/GZAL/xmQC/8Vk - Av/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/6dVAtYAAABKAAAAKQAA - ABEAAAAAAAAAAAAAAADMZgBgzGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2UA/8plAP/KZQD/ymUA/8plAf/KZQH/ymUB/8pl - Af/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/IZQH/yGUB/8hlAf/IZAH/yGQB/8hkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8ZkAf/GZAH/xmQB/8ZkAv/GZAL/xmQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xGMC/8Bh - AvVaLQFVAAAAHwAAAA4AAAAEAAAAAAAAAAAAAAAAAAAAAMxmAHXMZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tm - AP/LZQD/ymUA/8plAP/KZQD/ymUA/8plAf/KZQH/ymUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hl - Af/IZQH/yGUB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8ZkAf/GZAH/xmQB/8Zk - Av/GZAL/xWQC/8NiAvCQSQFWAAAAEgAAAAgAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzGYAS8xm - ANvMZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZQD/ymUA/8plAP/KZQD/ymUA/8pl - Af/KZQH/ymUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hlAf/IZQH/yGUB/8hkAf/IZAH/yGQB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8JiAbueUAEtAAAABgAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAADzGYASMxmAI3MZgCizGYAzMxmAMzMZgDMzGYAzMxmAMzMZgDMzGYAzMxm - AMzMZgDMzGYAzMxmAMzMZgDMzGYAzMxmAMzMZgDMzGYAzMxmAMzMZgDMzGYAzMtmAMzLZgDMy2YAzMtm - AMzLZgDMy2YAzMtmAMzLZQDMymUAzMplAMzKZQDMymUBzMplAczKZQHMyWUBzMllAczJZQHMyWUBzMll - AczJZQHMyWUBzMhlAczIZQHMyGUBzMhkAcbIZAGZyGQBgcdkAS0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAPgAAAAAAAAA8AAAAAAA - AADwAAAAAAAAAOAAAAAAAAAA4AAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAA - AAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAA - AADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAA - AAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAA - AADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAA - AAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAA - AADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAA - AAAAAAAAwAAAAAAAAADAAAAAAAAAAOAAAAAAAAAB8AAAAAAAAAf4AAAAAAAAH/4AAAAAAAB///////// - /////////////ygAAACAAAAAAAEAAAEAIAAAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABQAAABAAAAAjAAAAOgAAAFAAAABjAAAAbgAA - AHMAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAA - AHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAA - AHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAA - AHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAA - AHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAA - AHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAA - AHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAABxAAAAagAAAFoAAABFAAAALgAA - ABgAAAAJAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA - AAgAAAAbAAAAOwAAAGAAAACBAAAAmQAAAKgAAACwAAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAA - ALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAA - ALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAA - ALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAA - ALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAA - ALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAA - ALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAA - ALQAAAC0AAAAtAAAALMAAACtAAAAoQAAAI4AAAByAAAATgAAACoAAAAPAAAAAwAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAAAAIAAAAEoAAAB5AAAAnwAAALYAAADCAAAAyAAA - AMoAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAA - AMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAA - AMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAA - AMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAA - AMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAA - AMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAA - AMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAywAAAMkAAADFAAAAvQAA - AKwAAACOAAAAYgAAADMAAAARAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAA - AB0AAABLAAAAfwAAAKoAAADAAAAAyAAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAA - AMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAA - AMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAA - AMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAA - AMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAA - AMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAA - AMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAAAMoAAADKAAAAygAA - AMoAAADKAAAAygAAAMoAAADMAAAAzQAAAM0AAADMAAAAyAAAALoAAACZAAAAZgAAADIAAAAPAAAAAQAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAVAAAAPQAAAHwWDQS6NB8K3E8vDu5YNRDzWDQR8lg0 - EfJXNBHyVzQR8lc0EfJXNBHyVjQR8lY0EfJWNBHyVjMR8lYzEfJWMxHyVTMR8lUzEfJVMxHyVTMR8lUz - EfJUMxHyVDMR8lQzEfJTMxHyUzIR8lMyEfJTMhHyUzIR8lMyEfJSMhLyUjIS8lIyEvJSMhLyUjIS8lIx - EvJRMRLyUTES8lExEvJRMRLyUTIS8lAyEvJQMhLyUDIS8lAxEvJQMRLyUDES8k8xEvJPMRPyTzET8k8x - E/JPMRPyTzET8k8xE/JPMRPyTjET8k4xE/JOMRPyTjAT8k4wE/JNMBPyTTAT8k4wE/JNMBPyTTAT8k0w - E/JNMBPyTTAT8kwwE/JMMBPyTDAT8kwwE/JMMBPyTTAT8k0wE/JNMBPyTTAT8k0wE/JNMBPyTTAT8k0w - E/JNMBPyTTAT8k0wE/JNMBPyTTAT8k0wE/JNMBPyTTAT8k0wE/JNMBPyTTAT8k0wE/JNMBPyTTAT8k0w - E/JNMBPyTTAT8k0wE/JNMBPyTTAT8k0wE/JNMBPyTTET8ksvEvE6JQ7oHhMH2wcFAs8AAADJAAAAywAA - AMwAAADMAAAAygAAAL0AAACZAAAAXwAAACgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAA - ACYcEQWCVTIP3XdGFf5+Shb/fEkW/3xJFv98SRb/e0kW/3tJF/97SRf/e0gX/3pIF/96SBf/ekgX/3lI - F/95SBf/eUgX/3lIF/94SBf/eEcX/3hHF/93Rxf/d0cY/3dHGP93Rxj/dkcY/3ZHGP91Rxj/dUcY/3VG - GP91Rhj/dEYY/3RGGP90Rhj/dEYY/3NGGP9zRhj/c0YZ/3NGGf9yRRn/ckUZ/3JFGf9yRRn/cUUZ/3FF - Gf9xRRn/cUUZ/3BFGf9wRRn/cEUZ/3BFGf9wRBn/b0QZ/29EGf9vRBr/b0Qa/25EGv9uRBr/bkQa/25E - Gv9uRBr/bUQa/21EGv9tRBr/bUMa/21DGv9tQxr/bEMa/2xDGv9sQxr/a0Ma/2tDGv9rQxr/a0Ma/2tD - Gv9rQxr/a0Ma/2tDGv9rQxr/a0Ma/2tDGv9rQxr/a0Ma/2tDGv9rQxr/a0Ma/2tDGv9rQxr/a0Ma/2tD - Gv9rQxr/a0Ma/2tDGv9rQxr/a0Ma/2tDGv9rQxr/a0Ma/2tDGv9rQxr/a0Ma/2tDGv9rQxr/a0Ma/2tD - Gv9rQxr/a0Ma/2tDGv9qQhr/WTgW+C0cC+EEAgHMAAAAygAAAMwAAADMAAAAygAAALgAAACKAAAASgAA - ABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQAPQiYLj3pIFfl/Sxb/ekgV/3lHFf95RxX/eEcV/3hG - Ff94RhX/d0YV/3dGFf93RhX/dkYV/3ZGFf92Rhb/dUYW/3VFFv91RRb/dUUW/3RFFv90RRb/dEUW/3NF - Fv9zRRb/c0UW/3JEFv9yRBb/ckQX/3JEF/9xRBf/cUQX/3FEF/9xRBf/cEQX/3BEF/9wQxf/b0MX/29D - F/9vQxf/b0MX/25DF/9uQxf/bkMY/25DGP9tQxj/bUIY/21CGP9tQhj/bEIY/2xCGP9sQhj/bEIY/2xC - GP9rQhj/a0IY/2tCGP9rQRj/akEY/2pBGP9qQRj/akEZ/2pBGf9pQRn/aUEZ/2lBGf9pQRn/aUEZ/2hB - Gf9oQRn/aEEZ/2hAGf9oQBn/Z0AZ/2dAGf9nQBn/Z0AZ/2dAGf9nQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9pQhr/bEQb/08x - E/INCAPRAAAAygAAAMwAAADMAAAAxwAAAKkAAABsAAAAKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE4t - DYOETBX/fUkU/3tIFP97RxT/ekcU/3pHFf96RxX/eUcV/3lHFf95RxX/eEcV/3hHFf94RhX/d0YV/3dG - Ff93RhX/dkYV/3ZGFf92Rhb/dkYW/3VFFv91RRb/dUUW/3RFFv90RRb/dEUW/3RFFv9zRRb/c0UW/3NE - Fv9yRBb/ckQW/3JEF/9xRBf/cUQX/3FEF/9xRBf/cEQX/3BEF/9wQxf/cEMX/29DF/9vQxf/b0MX/29D - F/9uQxf/bkMX/25DGP9uQxj/bUIY/21CGP9tQhj/bUIY/2xCGP9sQhj/bEIY/2xCGP9rQhj/a0IY/2tC - GP9rQhj/a0EY/2pBGP9qQRj/akEZ/2pBGf9pQRn/aUEZ/2lBGf9pQRn/aUEZ/2hBGf9oQRn/aEEZ/2hA - Gf9oQBn/aEAZ/2dAGf9nQBn/Z0AZ/2dAGf9nQBn/Z0AZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/bEQb/1Y3FfYMCAPRAAAAywAAAMwAAADMAAAAugAA - AIcAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAABDJwtLhk4V/X1JFP99SBT/fEgU/3xIFP98SBT/e0gU/3tI - FP97SBT/ekcU/3pHFP96RxX/eUcV/3lHFf95RxX/eUcV/3hHFf94RhX/eEYV/3dGFf93RhX/d0YV/3ZG - Ff92RhX/dkYW/3VGFv91RRb/dUUW/3VFFv90RRb/dEUW/3RFFv9zRRb/c0UW/3NFFv9zRBb/ckQW/3JE - F/9yRBf/cUQX/3FEF/9xRBf/cUQX/3BEF/9wRBf/cEMX/3BDF/9vQxf/b0MX/29DF/9uQxf/bkMX/25D - GP9uQxj/bUMY/21CGP9tQhj/bUIY/2xCGP9sQhj/bEIY/2xCGP9sQhj/a0IY/2tCGP9rQhj/a0IY/2pB - GP9qQRj/akEY/2pBGf9qQRn/aUEZ/2lBGf9pQRn/aUEZ/2lBGf9oQRn/aEEZ/2hBGf9oQBn/aEAZ/2dA - Gf9nQBn/Z0AZ/2dAGf9nQBn/Z0AZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/bEQa/0svEvECAQDMAAAAzAAAAM0AAADDAAAAmgAAAFIAAAAAAAAAAAAAAAAAAAAACwMACn5J - E9KBShP/f0kT/35JE/9+SRT/fkkU/31IFP99SBT/fUgU/3xIFP98SBT/fEgU/3tIFP97SBT/e0cU/3pH - FP96RxT/ekcV/3lHFf95RxX/eUcV/3hHFf94RxX/eEYV/3dGFf93RhX/d0YV/3dGFf92RhX/dkYW/3ZG - Fv91RRb/dUUW/3VFFv90RRb/dEUW/3RFFv90RRb/c0UW/3NFFv9zRBb/ckQW/3JEFv9yRBf/ckQX/3FE - F/9xRBf/cUQX/3BEF/9wRBf/cEMX/3BDF/9vQxf/b0MX/29DF/9vQxf/bkMX/25DF/9uQxj/bkMY/21D - GP9tQhj/bUIY/21CGP9sQhj/bEIY/2xCGP9sQhj/a0IY/2tCGP9rQhj/a0IY/2tBGP9qQRj/akEY/2pB - Gf9qQRn/aUEZ/2lBGf9pQRn/aUEZ/2lBGf9pQRn/aEEZ/2hBGf9oQBn/aEAZ/2hAGf9nQBn/Z0AZ/2dA - Gf9nQBn/Z0AZ/2dAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/bEMa/ygZCt8AAADKAAAAzQAA - AMcAAAClAAAAXgAAAAAAAAAAAAAAAAAAAABEIgFXiU4U/4BKE/+AShP/gEkT/4BJE/9/SRP/f0kT/35J - E/9+SRP/fkkU/35JFP99SBT/fUgU/3xIFP98SBT/fEgU/3tIFP97SBT/e0gU/3pHFP96RxT/ekcV/3lH - Ff95RxX/eUcV/3lHFf94RxX/eEYV/3hGFf93RhX/d0YV/3dGFf92RhX/dkYV/3ZGFv91Rhb/dUUW/3VF - Fv91RRb/dEUW/3RFFv90RRb/c0UW/3NFFv9zRRb/c0QW/3JEFv9yRBf/ckQX/3FEF/9xRBf/cUQX/3FE - F/9wRBf/cEQX/3BDF/9wQxf/b0MX/29DF/9vQxf/bkMX/25DF/9uQxj/bkMY/21DGP9tQhj/bUIY/21C - GP9tQhj/bEIY/2xCGP9sQhj/bEIY/2tCGP9rQhj/a0IY/2tCGP9qQRj/akEY/2pBGP9qQRn/akEZ/2lB - Gf9pQRn/aUEZ/2lBGf9pQRn/aEEZ/2hBGf9oQRn/aEAZ/2hAGf9nQBn/Z0AZ/2dAGf9nQBn/Z0AZ/2dA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9qQhr/VDQV9QQCAc0AAADMAAAAyQAAAKoAAABlAAAAAAAAAAAAAAAAAAAAAGMz - A66HTRP/gkoS/4JKE/+BShP/gUoT/4FKE/+AShP/gEoT/4BJE/9/SRP/f0kT/39JE/9+SRP/fkkT/35J - FP99SBT/fUgU/31IFP98SBT/fEgU/3xIFP97SBT/e0gU/3tIFP96RxT/ekcU/3pHFf95RxX/eUcV/3lH - Ff94RxX/eEcV/3hGFf93RhX/d0YV/3dGFf93RhX/dkYV/3ZGFv92Rhb/dUUW/3VFFv91RRb/dEUW/3RF - Fv90RRb/dEUW/3NFFv9zRRb/c0UW/3JEFv9yRBb/ckQX/3JEF/9xRBf/cUQX/3FEF/9wRBf/cEQX/3BD - F/9wQxf/b0MX/29DF/9vQxf/b0MX/25DF/9uQxf/bkMY/25DGP9tQxj/bUIY/21CGP9tQhj/bEIY/2xC - GP9sQhj/bEIY/2tCGP9rQhj/a0IY/2tCGP9rQRj/akEY/2pBGP9qQRn/akEZ/2pBGf9pQRn/aUEZ/2lB - Gf9pQRn/aUEZ/2hBGf9oQRn/aEAZ/2hAGf9oQBn/Z0AZ/2dAGf9nQBn/Z0AZ/2dAGf9nQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZAGf9oQRr/Fw4G1wAA - AMsAAADJAAAAqwAAAGcAAAAAAAAAAAAAAABjVEQNgUQH2oRLEv+ESxL/g0sS/4NLEv+DSxL/gkoS/4JK - Ev+CShP/gUoT/4FKE/+BShP/gEoT/4BJE/+ASRP/f0kT/39JE/9/SRP/fkkT/35JFP9+SRT/fUgU/31I - FP98SBT/fEgU/3xIFP97SBT/e0gU/3tIFP96RxT/ekcU/3pHFf96RxX/eUcV/3lHFf95RxX/eEcV/3hG - Ff94RhX/d0YV/3dGFf93RhX/dkYV/3ZGFf92Rhb/dUYW/3VFFv91RRb/dUUW/3RFFv90RRb/dEUW/3NF - Fv9zRRb/c0UW/3NEFv9yRBb/ckQX/3JEF/9xRBf/cUQX/3FEF/9xRBf/cEQX/3BEF/9wQxf/cEMX/29D - F/9vQxf/b0MX/25DF/9uQxf/bkMY/25DGP9tQxj/bUIY/21CGP9tQhj/bUIY/2xCGP9sQhj/bEIY/2xC - GP9rQhj/a0IY/2tCGP9rQhj/akEY/2pBGP9qQRj/akEZ/2pBGf9pQRn/aUEZ/2lBGf9pQRn/aUEZ/2hB - Gf9oQRn/aEEZ/2hAGf9oQBn/aEAZ/2dAGf9nQBn/Z0AZ/2dAGf9nQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2ZA - Gf9mQBn/ZkAZ/2ZAGf9mQBn/ZkAZ/2xDGv8tHAvhAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGFT - RCGARAbshkwS/4VMEv+FSxL/hUsS/4RLEv+ESxL/hEsS/4NLEv+DSxL/g0oS/4JKEv+CShP/gUoT/4FK - E/+BShP/gEoT/4BKE/+ASRP/f0kT/39JE/9/SRP/fkkT/35JE/9+SRT/fUkU/31IFP99SBT/fEgU/3xI - FP98SBT/e0gU/3tIFP97SBT/ekcU/3pHFP96RxX/eUcV/3lHFf95RxX/eEcV/3hHFf94RhX/d0YV/3dG - Ff93RhX/d0YV/3ZGFf92Rhb/dkYW/3VFFv91RRb/dUUW/3RFFv90RRb/dEUW/3RFFv9zRRb/c0UW/3NF - Fv9yRBb/ckQW/3JEF/9yRBf/cUQX/3FEF/9xRBf/cEQX/3BEF/9wQxf/cEMX/29DF/9vQxf/b0MX/29D - F/9uQxf/bkMX/25DGP9uQxj/bUMY/21CGP9tQhj/bUIY/2xCGP9sQhj/bEIY/2xCGP9rQhj/a0IY/2tC - GP9rQhj/a0EY/2pBGP9qQRj/akEZ/2pBGf9qQRn/aUEZ/2lBGf9pQRn/aUEZ/2lBGf9oQRn/aEEZ/2hA - Gf9oQBn/aEAZ/2dAGf9nQBn/Z0AZ/2dAGf9nQBn/Z0AZ/2ZAGf9mQBn/ZkAZ/2ZAGf9mQBn/a0Ma/zol - DugAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAYlNEJYJEBvCHTBH/h0wR/4dMEf+GTBH/hkwR/4ZM - Ev+FSxL/hUsS/4VLEv+ESxL/hEsS/4NLEv+DSxL/g0sS/4JKEv+CShL/gkoT/4FKE/+BShP/gUoT/4BK - E/+ASRP/gEkT/39JE/9/SRP/f0kT/35JE/9+SRT/fkkU/31IFP99SBT/fUgU/3xIFP98SBT/e0gU/3tI - FP97SBT/e0cU/3pHFP96RxX/ekcV/3lHFf95RxX/eUcV/3hHFf94RhX/eEYV/3dGFf93RhX/d0YV/3ZG - Ff92RhX/dkYW/3VGFv91RRb/dUUW/3VFFv90RRb/dEUW/3RFFv9zRRb/c0UW/3NFFv9zRBb/ckQW/3JE - F/9yRBf/cUQX/3FEF/9xRBf/cUQX/3BEF/9wRBf/cEMX/3BDF/9vQxf/b0MX/29DF/9uQxf/bkMX/25D - F/9uQxj/bUMY/21CGP9tQhj/bUIY/21CGP9sQhj/bEIY/2xCGP9sQhj/a0IY/2tCGP9rQhj/a0IY/2pB - GP9qQRj/akEY/2pBGf9qQRn/aUEZ/2lBGf9pQRn/aUEZ/2lBGf9oQRn/aEEZ/2hBGf9oQBn/aEAZ/2hA - Gf9nQBn/Z0AZ/2dAGf9nQBn/Z0AZ/2ZAGf9rQxr/PicP6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAA - AABiU0QlhEUG8IlNEf+JTRH/iE0R/4hNEf+ITBH/h0wR/4dMEf+HTBH/hkwR/4ZMEv+FTBL/hUsS/4VL - Ev+ESxL/hEsS/4RLEv+DSxL/g0sS/4NKEv+CShL/gkoT/4FKE/+BShP/gUoT/4BKE/+AShP/gEkT/39J - E/9/SRP/f0kT/35JE/9+SRP/fkkU/31JFP99SBT/fUgU/3xIFP98SBT/fEgU/3tIFP97SBT/e0gU/3pH - FP96RxT/ekcV/3lHFf95RxX/eUcV/3hHFf94RxX/eEYV/3hGFf93RhX/d0YV/3dGFf92RhX/dkYW/3ZG - Fv91RRb/dUUW/3VFFv90RRb/dEUW/3RFFv90RRb/c0UW/3NFFv9zRRb/ckQW/3JEFv9yRBf/ckQX/3FE - F/9xRBf/cUQX/3BEF/9wRBf/cEMX/3BDF/9vQxf/b0MX/29DF/9vQxf/bkMX/25DF/9uQxj/bkMY/21D - GP9tQhj/bUIY/21CGP9sQhj/bEIY/2xCGP9sQhj/a0IY/2tCGP9rQhj/a0IY/2tBGP9qQRj/akEY/2pB - Gf9qQRn/akEZ/2lBGf9pQRn/aUEZ/2lBGf9pQRn/aEEZ/2hBGf9oQBn/aEAZ/2hAGf9nQBn/Z0AZ/2xD - Gv8+Jw/pAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGNTRCWGRgXwi04Q/4pNEP+KTRD/ik0R/4lN - Ef+JTRH/iU0R/4hNEf+ITBH/h0wR/4dMEf+HTBH/hkwR/4ZMEf+GTBL/hUsS/4VLEv+FSxL/hEsS/4RL - Ev+DSxL/g0sS/4NLEv+CShL/gkoS/4JKE/+BShP/gUoT/4FKE/+AShP/gEkT/4BJE/9/SRP/f0kT/39J - E/9+SRP/fkkU/35JFP99SBT/fUgU/31IFP98SBT/fEgU/3xIFP97SBT/e0gU/3tHFP96RxT/ekcV/3pH - Ff95RxX/eUcV/3lHFf94RxX/eEYV/3hGFf93RhX/d0YV/3dGFf92RhX/dkYV/3ZGFv91Rhb/dUUW/3VF - Fv91RRb/dEUW/3RFFv90RRb/c0UW/3NFFv9zRRb/c0QW/3JEFv9yRBb/ckQX/3FEF/9xRBf/cUQX/3FE - F/9wRBf/cEQX/3BDF/9wQxf/b0MX/29DF/9vQxf/bkMX/25DF/9uQxf/bkMY/25DGP9tQhj/bUIY/21C - GP9tQhj/bEIY/2xCGP9sQhj/bEIY/2tCGP9rQhj/a0IY/2tCGP9qQRj/akEY/2pBGP9qQRn/akEZ/2lB - Gf9pQRn/aUEZ/2lBGf9pQRn/aEEZ/2hBGf9oQRn/bUMa/z8nD+kAAADKAAAAyQAAAKwAAABnAAAAAAAA - AAAAAAAAY1NEJYhGBfCMThD/jE4Q/4xOEP+LThD/i04Q/4tNEP+KTRD/ik0R/4pNEf+JTRH/iU0R/4hN - Ef+ITRH/iEwR/4dMEf+HTBH/h0wR/4ZMEf+GTBL/hUwS/4VLEv+FSxL/hEsS/4RLEv+ESxL/g0sS/4NL - Ev+DShL/gkoS/4JKE/+CShP/gUoT/4FKE/+AShP/gEoT/4BJE/9/SRP/f0kT/39JE/9+SRP/fkkT/35J - FP99SRT/fUgU/31IFP98SBT/fEgU/3xIFP97SBT/e0gU/3tIFP96RxT/ekcU/3pHFf95RxX/eUcV/3lH - Ff94RxX/eEcV/3hGFf94RhX/d0YV/3dGFf93RhX/dkYV/3ZGFv92Rhb/dUYW/3VFFv91RRb/dEUW/3RF - Fv90RRb/dEUW/3NFFv9zRRb/c0UW/3JEFv9yRBb/ckQX/3JEF/9xRBf/cUQX/3FEF/9xRBf/cEQX/3BD - F/9wQxf/b0MX/29DF/9vQxf/b0MX/25DF/9uQxf/bkMY/25DGP9tQxj/bUIY/21CGP9tQhj/bEIY/2xC - GP9sQhj/bEIY/2xCGP9rQhj/a0IY/2tCGP9rQRj/akEY/2pBGP9qQRn/akEZ/2pBGf9pQRn/aUEZ/2lB - Gf9uRBr/PycP6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABkVEQlikcE8I5PD/+OTxD/jU8Q/41O - EP+NThD/jE4Q/4xOEP+MThD/i04Q/4tOEP+KTRD/ik0Q/4pNEf+JTRH/iU0R/4lNEf+ITRH/iEwR/4dM - Ef+HTBH/h0wR/4ZMEf+GTBH/hkwS/4VLEv+FSxL/hUsS/4RLEv+ESxL/g0sS/4NLEv+DSxL/gkoS/4JK - Ev+CShP/gUoT/4FKE/+BShP/gEoT/4BJE/+ASRP/f0kT/39JE/9/SRP/fkkT/35JFP9+SRT/fUgU/31I - FP99SBT/fEgU/3xIFP98SBT/e0gU/3tIFP97RxT/ekcU/3pHFf96RxX/eUcV/3lHFf95RxX/eEcV/3hG - Ff94RhX/d0YV/3dGFf93RhX/dkYV/3ZGFf92Rhb/dkYW/3VFFv91RRb/dUUW/3RFFv90RRb/dEUW/3NF - Fv9zRRb/c0UW/3NEFv9yRBb/ckQW/3JEF/9xRBf/cUQX/3FEF/9xRBf/cEQX/3BEF/9wQxf/cEMX/29D - F/9vQxf/b0MX/29DF/9uQxf/bkMX/25DGP9uQxj/bUIY/21CGP9tQhj/bUIY/2xCGP9sQhj/bEIY/2xC - GP9rQhj/a0IY/2tCGP9rQhj/a0EY/2pBGP9qQRj/akEZ/29EGv8/Jw/pAAAAygAAAMkAAACsAAAAZwAA - AAAAAAAAAAAAAGRURCWLSATwkE8P/5BPD/+PTw//j08P/45PD/+OTw//jk8Q/41OEP+NThD/jU4Q/4xO - EP+MThD/i04Q/4tOEP+LTRD/ik0Q/4pNEf+KTRH/iU0R/4lNEf+ITRH/iE0R/4hMEf+HTBH/h0wR/4dM - Ef+GTBH/hkwS/4VMEv+FSxL/hUsS/4RLEv+ESxL/hEsS/4NLEv+DSxL/g0oS/4JKEv+CShP/gkoT/4FK - E/+BShP/gEoT/4BKE/+ASRP/f0kT/39JE/9/SRP/fkkT/35JE/9+SRT/fUkU/31IFP99SBT/fEgU/3xI - FP98SBT/e0gU/3tIFP97SBT/ekcU/3pHFP96RxX/eUcV/3lHFf95RxX/eEcV/3hHFf94RhX/eEYV/3dG - Ff93RhX/d0YV/3ZGFf92Rhb/dkYW/3VGFv91RRb/dUUW/3RFFv90RRb/dEUW/3RFFv9zRRb/c0UW/3NF - Fv9yRBb/ckQW/3JEF/9yRBf/cUQX/3FEF/9xRBf/cUQX/3BEF/9wQxf/cEMX/29DF/9vQxf/b0MX/29D - F/9uQxf/bkMX/25DGP9uQxj/bUMY/21CGP9tQhj/bUIY/2xCGP9sQhj/bEIY/2xCGP9sQhj/a0IY/2tC - GP9rQhj/cEQZ/0AnD+kAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAZFRDJY1IA/CSUA//kVAP/5FQ - D/+QUA//kFAP/5BPD/+PTw//j08P/49PD/+OTw//jk8Q/41PEP+NThD/jU4Q/4xOEP+MThD/jE4Q/4tO - EP+LThD/ik0Q/4pNEP+KTRH/iU0R/4lNEf+JTRH/iE0R/4hMEf+ITBH/h0wR/4dMEf+GTBH/hkwR/4ZM - Ev+FSxL/hUsS/4VLEv+ESxL/hEsS/4RLEv+DSxL/g0sS/4JKEv+CShL/gkoT/4FKE/+BShP/gUoT/4BK - E/+ASRP/gEkT/39JE/9/SRP/f0kT/35JE/9+SRT/fkkU/31IFP99SBT/fUgU/3xIFP98SBT/fEgU/3tI - FP97SBT/e0cU/3pHFP96RxX/ekcV/3lHFf95RxX/eUcV/3hHFf94RhX/eEYV/3dGFf93RhX/d0YV/3ZG - Ff92RhX/dkYW/3ZGFv91RRb/dUUW/3VFFv90RRb/dEUW/3RFFv9zRRb/c0UW/3NFFv9zRBb/ckQW/3JE - Fv9yRBf/cUQX/3FEF/9xRBf/cUQX/3BEF/9wRBf/cEMX/3BDF/9vQxf/b0MX/29DF/9vQxf/bkMX/25D - F/9uQxj/bkMY/21CGP9tQhj/bUIY/21CGP9sQhj/bEIY/2xCGP9xRRn/QSgP6QAAAMoAAADJAAAArAAA - AGcAAAAAAAAAAAAAAABlVEMlj0kD8JNRDv+TUQ7/k1AO/5JQDv+SUA//klAP/5FQD/+RUA//kFAP/5BP - D/+QTw//j08P/49PD/+OTw//jk8P/45PEP+NThD/jU4Q/41OEP+MThD/jE4Q/4tOEP+LThD/i00Q/4pN - EP+KTRH/ik0R/4lNEf+JTRH/iE0R/4hNEf+ITBH/h0wR/4dMEf+HTBH/hkwR/4ZMEv+GTBL/hUsS/4VL - Ev+ESxL/hEsS/4RLEv+DSxL/g0sS/4NKEv+CShL/gkoT/4JKE/+BShP/gUoT/4FKE/+AShP/gEkT/39J - E/9/SRP/f0kT/35JE/9+SRP/fkkU/31JFP99SBT/fUgU/3xIFP98SBT/fEgU/3tIFP97SBT/e0gU/3pH - FP96RxT/ekcV/3lHFf95RxX/eUcV/3hHFf94RxX/eEYV/3hGFf93RhX/d0YV/3dGFf92RhX/dkYV/3ZG - Fv91Rhb/dUUW/3VFFv90RRb/dEUW/3RFFv90RRb/c0UW/3NFFv9zRRb/ckQW/3JEFv9yRBf/ckQX/3FE - F/9xRBf/cUQX/3FEF/9wRBf/cEMX/3BDF/9vQxf/b0MX/29DF/9vQxf/bkMX/25DF/9uQxj/bkMY/21D - GP9tQhj/bUIY/3JFGf9BKA/pAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGVUQyWRSgPwlVEO/5VR - Dv+UUQ7/lFEO/5RRDv+TUQ7/k1EO/5JQDv+SUA7/klAP/5FQD/+RUA//kVAP/5BQD/+QTw//j08P/49P - D/+PTw//jk8P/45PEP+NTxD/jU4Q/41OEP+MThD/jE4Q/4xOEP+LThD/i04Q/4tNEP+KTRD/ik0R/4lN - Ef+JTRH/iU0R/4hNEf+ITBH/iEwR/4dMEf+HTBH/hkwR/4ZMEf+GTBL/hUsS/4VLEv+FSxL/hEsS/4RL - Ev+ESxL/g0sS/4NLEv+CShL/gkoS/4JKE/+BShP/gUoT/4FKE/+AShP/gEkT/4BJE/9/SRP/f0kT/39J - E/9+SRP/fkkU/35JFP99SBT/fUgU/31IFP98SBT/fEgU/3xIFP97SBT/e0gU/3tHFP96RxT/ekcV/3pH - Ff95RxX/eUcV/3lHFf94RxX/eEcV/3hGFf93RhX/d0YV/3dGFf92RhX/dkYV/3ZGFv92Rhb/dUUW/3VF - Fv91RRb/dEUW/3RFFv90RRb/c0UW/3NFFv9zRRb/c0QW/3JEFv9yRBb/ckQX/3FEF/9xRBf/cUQX/3FE - F/9wRBf/cEQX/3BDF/9wQxf/b0MX/29DF/9vQxf/b0MX/25DF/9uQxf/c0YZ/0IoD+kAAADKAAAAyQAA - AKwAAABnAAAAAAAAAAAAAAAAZlRDJZJKAvCXUg3/llIN/5ZSDf+WUg7/lVIO/5VRDv+VUQ7/lFEO/5RR - Dv+TUQ7/k1EO/5NQDv+SUA7/klAP/5JQD/+RUA//kVAP/5BQD/+QTw//kE8P/49PD/+PTw//jk8P/45P - D/+OTxD/jU4Q/41OEP+NThD/jE4Q/4xOEP+LThD/i04Q/4tOEP+KTRD/ik0R/4pNEf+JTRH/iU0R/4hN - Ef+ITRH/iEwR/4dMEf+HTBH/h0wR/4ZMEf+GTBL/hkwS/4VLEv+FSxL/hEsS/4RLEv+ESxL/g0sS/4NL - Ev+DShL/gkoS/4JKE/+CShP/gUoT/4FKE/+BShP/gEoT/4BJE/+ASRP/f0kT/39JE/9+SRP/fkkT/35J - FP99SRT/fUgU/31IFP98SBT/fEgU/3xIFP97SBT/e0gU/3tIFP96RxT/ekcU/3pHFf95RxX/eUcV/3lH - Ff95RxX/eEcV/3hGFf94RhX/d0YV/3dGFf93RhX/dkYV/3ZGFf92Rhb/dUYW/3VFFv91RRb/dEUW/3RF - Fv90RRb/dEUW/3NFFv9zRRb/c0UW/3JEFv9yRBb/ckQX/3JEF/9xRBf/cUQX/3FEF/9xRBf/cEQX/3BD - F/9wQxf/b0MX/29DF/90Rhj/QigO6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABmVUMllEsC8JlT - Df+YUw3/mFIN/5dSDf+XUg3/l1IN/5ZSDf+WUg7/llIO/5VRDv+VUQ7/lFEO/5RRDv+UUQ7/k1EO/5NR - Dv+SUA7/klAO/5JQD/+RUA//kVAP/5FQD/+QUA//kE8P/49PD/+PTw//j08P/45PD/+OTxD/jk8Q/41O - EP+NThD/jE4Q/4xOEP+MThD/i04Q/4tOEP+LTRD/ik0Q/4pNEf+JTRH/iU0R/4lNEf+ITRH/iEwR/4hM - Ef+HTBH/h0wR/4ZMEf+GTBH/hkwS/4VMEv+FSxL/hUsS/4RLEv+ESxL/hEsS/4NLEv+DSxL/gkoS/4JK - Ev+CShP/gUoT/4FKE/+BShP/gEoT/4BKE/+ASRP/f0kT/39JE/9/SRP/fkkT/35JFP9+SRT/fUgU/31I - FP99SBT/fEgU/3xIFP98SBT/e0gU/3tIFP97RxT/ekcU/3pHFf96RxX/eUcV/3lHFf95RxX/eEcV/3hH - Ff94RhX/d0YV/3dGFf93RhX/dkYV/3ZGFf92Rhb/dkYW/3VFFv91RRb/dUUW/3RFFv90RRb/dEUW/3NF - Fv9zRRb/c0UW/3NEFv9yRBb/ckQW/3JEF/9xRBf/cUQX/3FEF/9xRBf/cEQX/3VHGP9DKQ7pAAAAygAA - AMkAAACsAAAAZwAAAAAAAAAAAAAAAGZVQyWVSwLwmlMN/5lTDf+ZUw3/mVMN/5lTDf+YUw3/mFMN/5hS - Df+XUg3/l1IN/5dSDf+WUg3/llIO/5VSDv+VUQ7/lVEO/5RRDv+UUQ7/k1EO/5NRDv+TUQ7/klAO/5JQ - D/+SUA//kVAP/5FQD/+QUA//kFAP/5BPD/+PTw//j08P/45PD/+OTw//jk8Q/41OEP+NThD/jU4Q/4xO - EP+MThD/i04Q/4tOEP+LThD/ik0Q/4pNEP+KTRH/iU0R/4lNEf+ITRH/iE0R/4hMEf+HTBH/h0wR/4dM - Ef+GTBH/hkwS/4ZMEv+FSxL/hUsS/4RLEv+ESxL/hEsS/4NLEv+DSxL/g0sS/4JKEv+CShP/gkoT/4FK - E/+BShP/gUoT/4BKE/+ASRP/gEkT/39JE/9/SRP/fkkT/35JE/9+SRT/fUkU/31IFP99SBT/fEgU/3xI - FP98SBT/e0gU/3tIFP97SBT/ekcU/3pHFP96RxX/eUcV/3lHFf95RxX/eUcV/3hHFf94RhX/eEYV/3dG - Ff93RhX/d0YV/3ZGFf92RhX/dkYW/3VGFv91RRb/dUUW/3VFFv90RRb/dEUW/3RFFv9zRRb/c0UW/3NF - Fv9yRBb/ckQW/3JEF/9yRBf/dkcY/0QpDukAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAZ1VDJZZL - AfCaUwz/mlMM/5pTDf+aUw3/mlMN/5lTDf+ZUw3/mVMN/5lTDf+ZUw3/mFMN/5hSDf+XUg3/l1IN/5dS - Df+WUg3/llIO/5ZSDv+VUQ7/lVEO/5RRDv+UUQ7/lFEO/5NRDv+TUQ7/klAO/5JQDv+SUA//kVAP/5FQ - D/+RUA//kFAP/5BPD/+PTw//j08P/49PD/+OTw//jk8Q/45PEP+NThD/jU4Q/4xOEP+MThD/jE4Q/4tO - EP+LThD/i00Q/4pNEP+KTRH/iU0R/4lNEf+JTRH/iE0R/4hMEf+ITBH/h0wR/4dMEf+GTBH/hkwR/4ZM - Ev+FTBL/hUsS/4VLEv+ESxL/hEsS/4RLEv+DSxL/g0sS/4JKEv+CShL/gkoT/4FKE/+BShP/gUoT/4BK - E/+AShP/gEkT/39JE/9/SRP/f0kT/35JE/9+SRT/fkkU/31IFP99SBT/fUgU/3xIFP98SBT/fEgU/3tI - FP97SBT/e0cU/3pHFP96RxT/ekcV/3lHFf95RxX/eUcV/3hHFf94RxX/eEYV/3dGFf93RhX/d0YV/3dG - Ff92RhX/dkYW/3ZGFv91RRb/dUUW/3VFFv90RRb/dEUW/3RFFv90RRb/c0UW/3NFFv94Rxf/RSkN6QAA - AMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABnVUMllkwB8JtUDP+bVAz/m1MM/5tTDP+aUwz/mlMM/5pT - DP+aUw3/mlMN/5pTDf+ZUw3/mVMN/5lTDf+ZUw3/mFMN/5hTDf+YUg3/l1IN/5dSDf+XUg3/llIN/5ZS - Dv+VUg7/lVEO/5VRDv+UUQ7/lFEO/5NRDv+TUQ7/k1EO/5JQDv+SUA//klAP/5FQD/+RUA//kFAP/5BQ - D/+QTw//j08P/49PD/+OTw//jk8P/45PEP+NTxD/jU4Q/41OEP+MThD/jE4Q/4tOEP+LThD/i04Q/4pN - EP+KTRD/ik0R/4lNEf+JTRH/iE0R/4hNEf+ITBH/h0wR/4dMEf+HTBH/hkwR/4ZMEv+GTBL/hUsS/4VL - Ev+ESxL/hEsS/4RLEv+DSxL/g0sS/4NLEv+CShL/gkoS/4JKE/+BShP/gUoT/4FKE/+AShP/gEkT/4BJ - E/9/SRP/f0kT/35JE/9+SRP/fkkU/31JFP99SBT/fUgU/3xIFP98SBT/fEgU/3tIFP97SBT/e0gU/3pH - FP96RxT/ekcV/3lHFf95RxX/eUcV/3lHFf94RxX/eEYV/3hGFf93RhX/d0YV/3dGFf92RhX/dkYV/3ZG - Fv91Rhb/dUUW/3VFFv91RRb/dEUW/3lIF/9FKQ3pAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGdV - QyWXTAHwnFQM/5xUDP+bVAz/m1QM/5tUDP+bVAz/m1QM/5tTDP+aUwz/mlMM/5pTDP+aUw3/mlMN/5pT - Df+aUw3/mVMN/5lTDf+ZUw3/mVMN/5hTDf+YUg3/l1IN/5dSDf+XUg3/llIN/5ZSDf+WUg7/lVEO/5VR - Dv+UUQ7/lFEO/5RRDv+TUQ7/k1EO/5NQDv+SUA7/klAP/5FQD/+RUA//kVAP/5BQD/+QTw//j08P/49P - D/+PTw//jk8P/45PEP+OTxD/jU4Q/41OEP+MThD/jE4Q/4xOEP+LThD/i04Q/4tNEP+KTRD/ik0R/4lN - Ef+JTRH/iU0R/4hNEf+ITBH/iEwR/4dMEf+HTBH/hkwR/4ZMEf+GTBL/hUwS/4VLEv+FSxL/hEsS/4RL - Ev+ESxL/g0sS/4NLEv+DShL/gkoS/4JKE/+BShP/gUoT/4FKE/+AShP/gEoT/4BJE/9/SRP/f0kT/39J - E/9+SRP/fkkU/35JFP99SBT/fUgU/31IFP98SBT/fEgU/3xIFP97SBT/e0gU/3tIFP96RxT/ekcU/3pH - Ff95RxX/eUcV/3lHFf94RxX/eEcV/3hGFf93RhX/d0YV/3dGFf93RhX/dkYV/3ZGFv92Rhb/e0gX/0Yp - DekAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAZ1VDJZhMAfCcVAz/nFQM/5xUDP+cVAz/nFQM/5xU - DP+bVAz/m1QM/5tUDP+bVAz/m1QM/5tUDP+bUwz/mlMM/5pTDP+aUwz/mlMN/5pTDf+aUw3/mVMN/5lT - Df+ZUw3/mVMN/5lTDf+YUw3/mFIN/5dSDf+XUg3/l1IN/5ZSDf+WUg7/lVIO/5VRDv+VUQ7/lFEO/5RR - Dv+TUQ7/k1EO/5NRDv+SUA7/klAP/5JQD/+RUA//kVAP/5BQD/+QUA//kE8P/49PD/+PTw//j08P/45P - D/+OTxD/jU8Q/41OEP+NThD/jE4Q/4xOEP+LThD/i04Q/4tOEP+KTRD/ik0Q/4pNEf+JTRH/iU0R/4lN - Ef+ITRH/iEwR/4dMEf+HTBH/h0wR/4ZMEf+GTBL/hkwS/4VLEv+FSxL/hUsS/4RLEv+ESxL/g0sS/4NL - Ev+DSxL/gkoS/4JKEv+CShP/gUoT/4FKE/+BShP/gEoT/4BJE/+ASRP/f0kT/39JE/9+SRP/fkkT/35J - FP9+SRT/fUgU/31IFP98SBT/fEgU/3xIFP97SBT/e0gU/3tIFP96RxT/ekcU/3pHFf96RxX/eUcV/3lH - Ff95RxX/eEcV/3hGFf94RhX/d0YV/3dGFf99SRb/RyoN6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAA - AABnVUMlmUwB8J1UDP+dVAz/nVQM/51UDP+dVAz/nFQM/5xUDP+cVAz/nFQM/5xUDP+cVAz/m1QM/5tU - DP+bVAz/m1QM/5tUDP+bUwz/mlMM/5pTDP+aUwz/mlMM/5pTDf+aUw3/mlMN/5lTDf+ZUw3/mVMN/5lT - Df+YUw3/mFIN/5hSDf+XUg3/l1IN/5ZSDf+WUg3/llIO/5VRDv+VUQ7/lFEO/5RRDv+UUQ7/k1EO/5NR - Dv+TUA7/klAO/5JQD/+RUA//kVAP/5FQD/+QUA//kE8P/49PD/+PTw//j08P/45PD/+OTxD/jk8Q/41O - EP+NThD/jE4Q/4xOEP+MThD/i04Q/4tOEP+LTRD/ik0Q/4pNEf+JTRH/iU0R/4lNEf+ITRH/iEwR/4hM - Ef+HTBH/h0wR/4ZMEf+GTBH/hkwS/4VMEv+FSxL/hUsS/4RLEv+ESxL/hEsS/4NLEv+DSxL/g0oS/4JK - Ev+CShP/gUoT/4FKE/+BShP/gEoT/4BKE/+ASRP/f0kT/39JE/9/SRP/fkkT/35JE/9+SRT/fUgU/31I - FP99SBT/fEgU/3xIFP98SBT/e0gU/3tIFP97SBT/ekcU/3pHFP96RxX/eUcV/3lHFf95RxX/eEcV/35K - Fv9IKg3pAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGdVQyWZTQDwnlUM/55VDP+eVQz/nVUM/51U - DP+dVAz/nVQM/51UDP+dVAz/nFQM/5xUDP+cVAz/nFQM/5xUDP+cVAz/m1QM/5tUDP+bVAz/m1QM/5tU - DP+bVAz/m1MM/5pTDP+aUwz/mlMM/5pTDf+aUw3/mlMN/5lTDf+ZUw3/mVMN/5lTDf+ZUw3/mFMN/5hS - Df+XUg3/l1IN/5dSDf+WUg3/llIO/5VSDv+VUQ7/lVEO/5RRDv+UUQ7/k1EO/5NRDv+TUQ7/klAO/5JQ - Dv+SUA//kVAP/5FQD/+QUA//kFAP/5BPD/+PTw//j08P/49PD/+OTw//jk8Q/41PEP+NThD/jU4Q/4xO - EP+MThD/jE4Q/4tOEP+LThD/ik0Q/4pNEP+KTRH/iU0R/4lNEf+JTRH/iE0R/4hMEf+HTBH/h0wR/4dM - Ef+GTBH/hkwR/4ZMEv+FSxL/hUsS/4VLEv+ESxL/hEsS/4NLEv+DSxL/g0sS/4JKEv+CShL/gkoT/4FK - E/+BShP/gUoT/4BKE/+ASRP/gEkT/39JE/9/SRP/f0kT/35JE/9+SRT/fkkU/31IFP99SBT/fUgU/3xI - FP98SBT/e0gU/3tIFP97SBT/e0cU/3pHFP96RxX/f0oW/0grDekAAADKAAAAyQAAAKwAAABnAAAAAAAA - AAAAAAAAaFVDJZpNAPCfVQv/nlUL/55VC/+eVQv/nlUM/55VDP+eVQz/nVUM/51UDP+dVAz/nVQM/51U - DP+dVAz/nVQM/5xUDP+cVAz/nFQM/5xUDP+cVAz/nFQM/5tUDP+bVAz/m1QM/5tUDP+bVAz/m1MM/5pT - DP+aUwz/mlMM/5pTDP+aUw3/mlMN/5pTDf+ZUw3/mVMN/5lTDf+ZUw3/mFMN/5hSDf+YUg3/l1IN/5dS - Df+WUg3/llIN/5ZSDv+VUQ7/lVEO/5RRDv+UUQ7/lFEO/5NRDv+TUQ7/k1AO/5JQDv+SUA//kVAP/5FQ - D/+RUA//kFAP/5BPD/+PTw//j08P/49PD/+OTw//jk8Q/45PEP+NThD/jU4Q/4xOEP+MThD/jE4Q/4tO - EP+LThD/i00Q/4pNEP+KTRH/iU0R/4lNEf+JTRH/iE0R/4hMEf+ITBH/h0wR/4dMEf+HTBH/hkwR/4ZM - Ev+FTBL/hUsS/4VLEv+ESxL/hEsS/4RLEv+DSxL/g0sS/4NKEv+CShL/gkoT/4FKE/+BShP/gUoT/4BK - E/+AShP/gEkT/39JE/9/SRP/f0kT/35JE/9+SRP/fkkU/31JFP99SBT/fUgU/3xIFP98SBT/fEgU/3tI - FP+BSxX/SisM6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABoVUMlm00A8J9VC/+fVQv/n1UL/59V - C/+fVQv/nlQK/55VC/+eVQv/nlUL/55VDP+eVQz/nlUM/51VDP+dVAz/nVQM/51UDP+dUwz/nFML/5xT - C/+cUwv/nFQL/5xUDP+cVAz/nFQM/5tUDP+bVAz/m1QM/5tUDP+bVAz/m1QM/5tTDP+aUwz/mlMM/5pT - DP+aUw3/mlMM/5lSDP+ZUgz/mVIM/5hSDP+YUgz/mFIM/5hSDP+YUQz/llEM/5dRDP+WUQz/lVEM/5ZR - DP+VUQz/lFAN/5VQDf+TUA3/lFAN/5RRDf+TUQ7/k1EO/5JQDv+SUA3/kU8O/5BPDf+RTw7/kE8O/5BP - Dv+QTw//j08P/49PD/+PTw//jk8P/45PEP+NTxD/jU4Q/41OEP+MThD/jE4Q/4tOD/+KTQ//ik0P/4pM - D/+JTA//iUwP/4hMEP+JTBD/iU0R/4hNEf+ITBH/h0wR/4dLEP+GSxD/hksQ/4VLEP+FSxD/hEoR/4VL - Ef+FSxL/hEsS/4RLEv+DSxL/g0sS/4NLEv+CShL/gkoS/4JKE/+BShP/gUoT/4FKE/+ASRL/f0gS/39I - Ev9+SBL/fkgS/35IEv99SBL/fkgT/35JFP99SBT/fUgU/4NLFf9KKwzpAAAAygAAAMkAAACsAAAAZwAA - AAAAAAAAAAAAAGhVQyWcTgDwoFUL/6BVC/+gVQv/n1UL/6JYD/+rYRn/r2gg/7BqJP+xbCf/sW0p/7Jv - K/+ycC3/sm8t/7JvLP+wbiv/r2so/65oJP+sZR//qWEa/6RcFP+fVg7/nFQM/51TC/+cVAv/nFQM/5xU - DP+cVAz/nFQM/5xUDP+bVAz/m1QM/5tUDP+bVAz/m1QM/5tUDf+eVxD/pV4X/6ZgGv+mYBr/pmAa/6Zg - Gv+mYBr/pWAa/6VgGv+lYBr/pWAa/6RgGv+kXxr/pF8a/6NfGv+jXxr/ol8a/6JfGv+hXRn/mVUS/5VS - D/+UUQ7/lVIQ/51ZFv+fXRv/n14b/59dG/+eXRv/nVsa/5VUE/+RUA//kVAP/5BQD/+QTw//kE8P/49P - D/+PTw//jk8P/45PD/+OTxH/kVMV/5laG/+ZWx3/mFsd/5hbHf+YWh3/l1oc/5NVGP+KThL/ik0R/4lO - Ef+LUBT/lFcb/5VZHf+UWR7/lFke/5NZHv+TWB3/jlQZ/4dNE/+GTBL/hUwS/4VLEv+FSxL/hEsS/4RL - Ev+ESxL/g0sS/4NLEv+DShL/gksT/4hRGf+NVh7/jVcg/41XIP+MViD/jFYg/4xVH/+GUBr/gEoU/39J - E/9+SRP/hEwU/0wsDOkAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAaFVDJZ1OAPChVgv/oVYL/6BW - C/+iWA3/omAd/3dOJf9mRyj/WD4l/043If9GMh7/NycY/zgoGf84KRn/NygY/zwrGv9MNiD/XUIm/25M - Kv+GWi7/mWUw/6psLv+vaiX/p18Y/59WDv+dUwv/nFQL/51UDP+cVAz/nFQM/5xUDP+cVAz/nFQM/5xU - DP+bVAz/n1cQ/5pdHv+CVSj/hlsv/4ZaLv+FWi7/hVou/4VaL/+FWi//hVov/4VaL/+FWi//hFov/4Ra - L/+EWi//hFov/4RZL/+EWS//hFkv/39UKf+XWh//mlUR/5ZTDv+bWxv/hFUm/4BXLv+CWTD/gVkw/4FZ - MP99Uyn/k1og/5dUEv+SUA7/klAO/5JQD/+RUA//kVAP/5BQD/+QUA//kE8P/5ZXGP+SXSn/e1Qs/35X - Mf9+VzH/fVcx/31XMf97VS7/gFMm/5NXG/+MThD/jVAS/4tVH/93Tyj/e1Yw/3xWMv97VjH/e1Yx/3hT - L/+AVSn/kVce/4dNEv+HTBH/h0wR/4ZMEf+GTBH/hkwS/4VLEv+FSxL/hUsS/4RLEv+LVBz/glYq/3VR - L/93VTL/dlQy/3ZUMv93VTP/c1Eu/3dPJv+HURv/gEoT/4BJE/+GTBT/TCwL6QAAAMoAAADJAAAArAAA - AGcAAAAAAAAAAAAAAABoVUMlnU4A8KFWC/+hVgv/oVUK/6ZbEP+fZSr/GhQQ/wIDBf8MCwr/EA4M/xIP - Df8TEA3/ExAO/xMQDv8TEA7/EhAN/xEODP8PDQv/DAwL/wwLCv8bFhH/LyQX/11CJv+PYDD/rm4t/6tj - HP+fVw//nVQM/51UDP+dVAz/nVQM/51UDP+dVAz/nFQM/5xTC/+nXxf/glUo/wABBf8GBgf/CQkJ/wsL - Cv8LCwr/DAsK/wwLCv8MCwr/DAsK/wwLCv8MCwr/DAsK/wwLCv8MCwr/DAsK/wkJCf8HBgf/AAEF/4BU - Kf+jXRf/m1QP/59kKf8kGxP/AAIE/wgIB/8JCAj/BwYH/wABBf9+Uyn/oFwZ/5RQDf+UUQ7/k1EO/5NR - Dv+TUA7/klAO/5JQDv+TUhH/pGku/0MwH/8AAgT/CQkI/wwLCv8LCgn/CAgH/wABBP8uIRb/oWYr/41O - D/+SUhT/ilop/xUQDv8DAwX/CAcH/wsKCf8KCQj/AQIE/ygeFv+YZDD/i1AU/4lMEP+ITRH/iE0R/4hM - Ef+HTBH/h0wR/4dMEf+GTBH/h00T/5lkL/83KRz/AAEE/woJCP8MCwn/CgkI/wcGBv8AAQT/TTci/5Fa - I/+CShL/gkoT/4dNFP9NLQvpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGhVQiWeTgDwolYK/6JW - C/+iVQr/qFsR/6JoL/8hGhP/EQ4L/yEbFP8nIBj/KCAZ/ykhGf8oIBj/KCAY/ycfF/8mHxf/Jh4X/yUd - Fv8kHRb/IhsU/xwWEv8UEQ7/DAsK/xEPDP8+LRz/hlsv/69tKv+lXRX/nlUM/55VDP+eVQz/nVUM/51U - DP+dVAz/nFML/6lhGv+HWi//BgYH/xcTDv8gGhP/IxwW/yMcFv8jHBb/IxwW/yMcFv8jHBb/IxwW/yMc - Fv8jHBb/IxwW/yMcFv8jHBb/IBoT/xcTDv8GBgf/hVov/6VfGf+cVQ//pGox/yofFv8MCwn/HRcS/x8Z - E/8XEw7/BwYH/4RZL/+iXxr/llEM/5ZSDv+VUQ7/lVEO/5RRDv+UUQ7/lFAO/6FgH/+BWjL/DAsK/xcS - Dv8gGhT/IxwW/yIbFf8cFxH/CQkH/zUmGf+lajD/j08P/49PEP+iaS//PCwd/wgHBv8aFRD/IRoU/yAZ - E/8VEQ3/EQ4M/4ZcM/+VWBr/ikwP/4pNEP+KTRH/iU0R/4lNEf+JTRH/iE0R/4hMEP+OVBn/jGE1/xoV - Ef8SDwv/HxkT/yIbFf8eGBL/Eg8L/w0MCv9+WTT/kFcf/4NKEf+DSxL/iU4T/04tC+kAAADKAAAAyQAA - AKwAAABnAAAAAAAAAAAAAAAAaVZCJZ9PAPCjVwr/o1YK/6JVCf+oWxD/omgu/yMbFP8YFBD/KSEZ/zAm - Hf8wJh3/LiUc/ysjGv8oIBj/Jh8X/yUeFv8mHhf/Jh8X/ycgGP8pIBn/KSEZ/yggGP8lHhb/HhgS/w8O - C/8NCwv/Tzgi/6VrMf+qYhr/n1UL/55VC/+eVQv/nlUM/55VDP+dVAv/qWIa/4daLv8JCQn/IBoT/yoi - Gv8uJRz/LiUc/y0kG/8sJBv/LCMa/ysjGv8rIhr/KyIa/ysiGv8rIhr/KyIa/ysiGv8nHxf/HRcS/wgI - B/+FWi//pl8Z/51VDv+kajD/KyAX/xQRDf8nHxj/KSEZ/yAaE/8KCQn/hFov/6RgGv+XUQz/l1IN/5dS - Df+WUg3/llIN/5ZSDf+YVRL/pmsy/zcqHP8QDgv/JR4W/ywjG/8uJRz/LSQb/yYeF/8QDgz/NSca/6Zr - MP+RUA//kE8O/6BiI/9qSy3/CgkI/yEaFP8qIhr/KyIa/yIbFf8LCgn/Z0ot/51gJf+MTg//jE4Q/4tO - EP+LThD/i00Q/4pNEP+KTRH/iUwQ/5hdI/9vTzD/CwoJ/yEbFP8qIhr/LCQb/yYfF/8TEA3/KB4W/5Vk - NP+JTxb/hUsR/4VLEv+KTxP/Ty0L6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABpVkIloE8A8KNX - Cv+jVwr/o1YJ/6hdEP+iaS7/IxsU/xoWEf8sIxv/Mige/zAnHf8sIxv/IhwV/xUSD/8RDw3/EA4M/xEO - DP8SEA7/GBQQ/yEbFf8nHxj/KiIa/ywjG/8rIhr/Jx8X/x0YEv8JCAn/LSIX/59oMv+qYhn/n1UL/59V - C/+fVQv/nlUL/55UCv+qYhn/h1su/wsLCv8jHBb/LiYc/zMpH/8xJx7/LyUc/ysiGv8oIBj/Jh8X/yUe - F/8lHhb/JR4W/yUeFv8lHhb/JR4W/yEbFP8YEw//BgYH/4ZaL/+nYBn/nlYO/6VqMP8sIRf/GBQP/ysj - Gv8uJRv/JBwW/wsLCv+EWi//pWAa/5hSDP+ZUw3/mVMN/5hTDf+YUg3/l1IN/6dlI/9yUC7/DAsK/yEb - FP8tJBv/Mige/zMpH/8yKB7/KiIZ/xQQDv82KBr/qGwv/5JQDv+RTw3/m1kZ/49gM/8YEw//HhgT/ywk - G/8wJh3/KSEZ/xIPDf8/Lx//oWgv/45QEf+NThD/jU4Q/41OEP+MThD/jE4Q/4xOEP+LThD/oGcu/0Qy - If8RDgv/KCAY/zAnHf8wJh3/JyAY/w8NC/9QOyb/m2Qs/4dMEf+HTBH/hkwR/4xQEv9RLgvpAAAAygAA - AMkAAACsAAAAZwAAAAAAAAAAAAAAAGlWQiWgTwDwpFcK/6RXCv+kVgn/qV0Q/6NpLv8jGxT/GhYR/ywj - G/8xKB7/LiUc/yIbFf8rIRf/aUsu/2dHKf9mRyj/XkIn/0cyH/8tIhf/ExAO/xAPDP8fGRP/KCEZ/y0k - G/8tJRz/KiIa/yIbFf8LCgn/MSQY/6luMv+nXRT/n1UL/59VC/+fVQv/n1QK/6tiGP+IWy7/CwsK/yMc - Fv8uJhz/Mige/y8lHP8pIRn/HBcS/xIPDf8ODQz/DQwL/w0MC/8NDAv/DQwL/w0MC/8NDAv/CwoJ/wYG - B/8AAQX/g1Yp/6deFv+eVg7/pWsw/ywhF/8YFA//KyMa/y4lG/8kHBb/CwsK/4VaLv+mYBr/mlIM/5pT - Df+aUw3/mVMN/5lTDP+eWRT/o2sz/ygfFv8WEg7/KSEZ/zAnHf8zKR//Mykf/zIoHv8qIhn/ExAO/zYo - Gv+pbC//lFEO/5RQDf+VUxD/o2ow/zImGf8VEQ7/KSEa/zAnHf8sIxr/GhUR/yEaE/+WZDP/lVUV/49O - Df+PTw//jk8P/45OD/+OTg//jE4P/5FTFf+XZTT/JBwU/xkUEP8rIxr/MSce/y4lHP8jHBX/DwwL/3hV - Mv+WWyD/iUwQ/4hNEf+ITRH/jlAS/1EuCukAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAaVZCJaFP - APClVwr/pVcK/6RWCf+pXRD/o2ku/yQbFP8aFhH/LCMb/zEnHv8sIxv/FxQQ/z8vHv/Fgj//s2oh/7Jp - IP+zayP/tnAq/65uMP+QYDH/UDki/xQQDf8XEw//KB8Y/y0kG/8vJh3/KyMa/yIbFf8JCAj/TDYh/7Jv - K/+iWQ7/oFYL/6BVC/+fVAr/rGIY/4hbLv8LCwr/IxwW/y8lHP8xKB7/KyMa/xwXEv9LOCX/fFg0/3NP - K/9zTyz/c08s/3NPLP9zTyz/c08s/3NPLP9zTyz/c1At/25JJv+XWyD/oVgQ/59WDv+lazD/LCEX/xgU - D/8rIxr/LiUb/yQcFv8LCwr/hlou/6dgGv+aUgv/mlMM/5pTDP+aUwz/mlQO/61pJv9jRSn/CwoK/yQd - Fv8uJBz/Mige/zMpH/8zKR//MSge/yoiGf8TEA7/NygZ/6ttLv+WUg7/lVIN/5VRDv+mZib/XkQp/w0M - Cv8mHxf/LyYc/y4lHP8jHBb/Dg0L/39YMf+eXh7/kU8O/5FQD/+QUA//kFAP/49QD/+PTg7/m1we/35Y - Mv8RDgz/IxwV/y4lHP8xJx7/KyMa/xkUEP8kHBT/lmU0/5BTFv+KTQ//ik0Q/4pNEf+QURL/Ui4K6QAA - AMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABpVkIlolAA8KZYCv+lWAr/pVcJ/6pdEP+kaS7/JBsU/xoW - Ef8sIxv/MSce/yoiGv8UEQ//OikZ/7dxK/+kVwr/o1cK/6NXCv+jWAv/plsO/69jGP+3cSz/jV8y/yQc - E/8UEQ7/JyAY/y4lHP8vJh3/KiIa/x0XE/8MCwr/glgu/69mHP+hVgv/oVYL/6BVCv+sYxj/iVsu/wsK - Cv8jHBb/LyUc/zAnHf8pIRn/EhAO/2pMLv+8dzP/rWUc/61lHf+tZR3/rWUd/6xlHf+sZR7/rGUe/6xl - Hv+rZR7/q2Mb/6FZEv+dVAz/oFcP/6drMP8sIRf/GBQP/ysjGv8uJRv/JBwW/wsLCv+GWi7/p2Ea/5tT - C/+bVAz/m1QM/5tUDP+jXRb/nGcz/xwWEf8ZFRD/KSEZ/y8mHf8wJx3/MSce/zIoHv8xJx7/KiEZ/xMQ - Dv83KBn/rG4u/5hSDf+XUgz/l1EM/6JeGv+JXTH/Eg8N/yEaFP8tJBv/LyYd/yggGP8SDw3/W0Qs/7Z7 - Qf+nay7/p2sv/6drL/+may//pmsv/6ZqL/+ze0L/V0Aq/xIPDf8oIBj/MCYd/zAmHf8oIBj/EQ4M/0Uz - If+hZy3/jU4Q/4xOEP+MThD/i04Q/5FSEf9TLwrpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGpW - QiWiUADwplgJ/6ZYCf+mVwn/rF4Q/6VqLv8kGxT/GhYR/ywjG/8xJx7/KiIZ/xMQDv85KRn/t3Es/6RX - Cv+kVwr/pFcK/6RXCv+jVwn/o1YJ/6RZDP+1ayD/mWY0/yAZEv8YFBD/KSEZ/y8mHf8vJhz/Jx8Y/xAO - DP81Jhr/r24u/6RZDv+hVgr/oVUK/61jGP+JWy7/CwoK/yMcFv8vJRz/MCcd/ycgGP8PDgz/ZEYo/7Bn - IP+fVAr/n1QK/59UCv+fVAr/nlQK/55UCv+eVAr/nlQK/55UCv+eVAr/nlUL/55VC/+hWA//p2ww/ywh - F/8YFA//KyMa/y4lG/8kHBb/CwsK/4ZaLv+oYRr/nFML/5xUDP+cVAz/nVUO/65tKv9SOyT/DAsK/yUe - Fv8sIxv/LiQc/ysiGv8rIxv/LyYc/y8mHf8pIRn/ExAO/zcoGf+tbi7/mVMN/5lTDf+YUgz/nFYR/6Np - MP8qIBf/FxMP/yoiGv8wJh3/LCQb/yIbFf8jHBX/PC4f/zcoGv82KBr/Niga/zYoGv82KBr/Nyga/zst - H/8jHBX/IhsV/ywkG/8xJx7/LyUc/yQdFv8NDAv/dVIw/51fIP+OTg7/jk8Q/45PEP+NThD/lFIR/1Qv - CukAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAalZCJaNQAPCnWAn/p1gJ/6dXCP+sXg//pWou/yQb - FP8aFhH/LCMb/zEnHv8qIhn/ExAO/zkpGf+4cSz/pVcK/6VXCv+lVwr/pVcK/6RXCv+kVwr/pFcK/6RX - Cv+3bSL/g1kw/xEPDf8iGxX/LSQb/zEnHv8sJBv/IBoU/w4MC/+KXC7/rmMY/6JVCf+hVQr/rmMY/4pb - Lv8LCgr/IxwW/y8mHP8wJh3/Jh8X/w4MC/9kRij/sGkh/6BWC/+gVgv/oFUL/6BVC/+gVQv/n1UL/59V - C/+fVQv/n1UL/59VC/+fVQv/nlUK/6FYDv+nbC//LCEX/xgUD/8rIxr/LiUb/yQcFv8LCwr/h1ou/6lh - Gv+cUwv/nVQM/5xUDP+nYBr/kGEy/xURDv8dFxL/KiEZ/ysjGv8mHxf/LSMa/zEmHP8pIRn/LiUc/ykh - Gf8TEA7/NygZ/65uLf+aUw3/mlMM/5pTDf+ZUw3/rGoo/1M8Jf8PDQz/JyAY/y8mHf8wJh3/LCMa/yMc - Fv8YFBD/FREO/xQQDv8UEA7/FBAO/xQQDv8VEQ7/GBQQ/yQcFv8sIxr/MCYd/zEnHv8sIxv/GxYR/x4X - Ev+VZDP/l1YW/5BPDv+QTw//j08P/49PD/+VUxD/VS8J6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAA - AABqVkIlpFAA8KhYCf+oWAn/p1cI/61eD/+lai7/JBsU/xoWEf8sIxv/MSce/yoiGf8TEA7/OikZ/7ly - K/+mWAr/plgK/6VYCv+lVwr/pVcK/6VXCv+lVwr/pVcK/6daDf+1ci//PS0c/xQRDv8pIRn/MScd/zAm - Hf8mHxf/DAwK/1M6Iv+1bSX/olcK/6JVCP+vYxf/ilst/wsKCv8jHBb/LyYc/zAmHf8mHxf/DgwL/2VG - KP+waSH/oVYL/6FWC/+hVgv/oFYL/6BWC/+gVgv/oFUL/6BVC/+gVQv/n1UL/59VC/+fVQr/olgO/6hs - L/8tIRf/GBQP/ysjGv8uJRv/JBwW/wsLCv+HWy7/qmIa/51UC/+dVAz/n1cP/7BvLv9CMB//Dw0M/ycf - F/8sIxv/KCAY/xoWEf9SPSj/Oy0f/yIcFf8sJBv/KSEZ/xMQDv84KBn/r24t/5tTDP+aUwz/mlMM/5pS - C/+mYRz/gFcv/w4NC/8iHBX/LiUc/zEoHv8wJh3/LSQb/yohGf8nHxj/Jh4X/yUeFv8lHhb/Jh4X/ycf - GP8qIRn/LSQb/zAmHf8yKB7/MCcd/yggGf8SDw3/QjAf/6ZqLv+TUQ//klAP/5FQD/+RUA//kVAP/5dU - EP9XMAnpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGpWQiWlUQDwqFkJ/6hZCf+oWAj/rl4P/6Zq - Lv8kGxT/GhYR/ywjG/8xJx7/KiIZ/xMQDv86KRn/unIr/6ZYCf+mWAn/plgJ/6ZYCv+mWAr/plgK/6VY - Cv+lVwr/pVcJ/7RpH/97Uy3/DQwL/yUeF/8vJh3/MSce/yohGf8VEQ7/LyMX/69uLf+mWQ3/olYI/69k - F/+KXC3/CwoK/yMcFv8vJhz/MCYd/yYfF/8ODAv/ZUYo/7FpIf+iVgv/oVYL/6FWC/+hVgv/oVYL/6FW - C/+hVgv/oFYL/6BWC/+gVgv/oFYL/6BVCv+jWA7/qWwv/ywhF/8YFA//KyMa/y4lG/8kHBb/CwsK/4db - Lv+qYhj/nVQK/55VC/+sZR3/hFkw/w8NC/8gGRT/KyIa/ysiGv8gGhT/HBYQ/4djPv8vJBn/HxoU/ysj - G/8pIRn/ExAO/zgoGf+vbi3/m1QM/5tUDP+bVAz/m1ML/59ZEv+gaTH/IxsU/xoVEP8rIxr/MSge/zEn - Hv8uJRz/KiIZ/yYfF/8jHBX/IhwV/yIcFf8jHRX/Jh8X/yoiGv8uJRz/MSce/zIoH/8vJhz/JR0W/wwL - Cv9uTS3/pGIh/5RRDv+TUQ7/k1EO/5NRDv+SUA7/mVQP/1gwCekAAADKAAAAyQAAAKwAAABnAAAAAAAA - AAAAAAAAalZCJaVRAPCpWQn/qVkJ/6lYCP+vXw//p2ou/yQbFP8aFhH/LCMb/zEnHv8qIhn/ExAO/zop - Gf+6civ/p1gJ/6dYCf+nWAn/p1gJ/6ZYCf+mWAn/plgJ/6ZYCf+mVwn/rmEU/51nMP8aFRD/HxkU/y0k - G/8yKB7/LCMb/xsXEf8cFhH/nWYu/6teEf+jVQj/sGQX/4tcLf8LCgr/IxwW/y8mHP8wJh3/Jh8X/w4M - C/9lRif/smkg/6JWCv+iVgr/olYL/6JWC/+iVgv/oVYL/6FWC/+hVgv/oVYL/6FWC/+hVgv/oFYK/6NZ - Dv+pbC//LCIX/xgUD/8rIxr/LiUb/yQcFv8LCwr/iFsu/6tiGP+eVAn/olkQ/61uMP8yJRj/ExAN/ygg - GP8tJBv/JyAY/xIPDP9GNCL/onZJ/xwWEP8gGhT/LCMa/ykhGf8TEA7/OCgZ/7BuLf+cVAz/nFQM/5xU - DP+cVAz/nFUN/65tK/9HMx//EQ8M/yggGP8wJh3/MCYd/ysiGv8iGxX/ExAN/w0MC/8MCwr/DAsK/w4M - C/8UEQ7/IhsV/ysjGv8wJx3/Mige/ywkG/8dFxL/GhUQ/5VkMv+dWxb/lVEN/5VRDv+VUQ7/lFEO/5RR - Dv+bVQ//WDEJ6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABqVkIlplEA8KpZCf+qWQn/qVgI/69f - D/+nai7/JBsU/xoWEf8sIxv/MSce/yoiGf8TEA7/OikZ/7tyK/+oWAn/qFgJ/6dYCf+nWAn/p1gJ/6dY - Cf+nWAn/p1gJ/6ZYCP+qXA3/rW4v/ywhF/8ZFRD/LCMb/zIoHv8tJBz/IRsV/w4NDP+QXy3/sGIV/6RV - CP+xZBf/i1wt/wsKCv8jHBb/LyYc/zAmHf8mHxf/DgwL/2VGJ/+yaiD/o1cK/6NXCv+jVwr/o1YK/6JW - Cv+iVgr/olYK/6JWC/+iVgv/olYL/6FWC/+hVgr/pFkO/6ptL/8tIhf/GBQP/ysjGv8uJBv/IxwV/wsL - Cv+JWy7/rGIY/55UCv+waSL/dVEt/wsKCv8iHBX/LCMb/ywjG/8hGxT/DQsJ/4tiOP+hcUH/GRQP/yAa - FP8sIxv/KSEZ/xMQDv84KBn/sW4t/51UDP+dVAz/nFQM/5xUDP+cUwv/qmQe/3dSLv8NCwr/JB0W/y4l - HP8uJRz/IRsV/zMnG/+NZj7/h1wx/4VZLv+FWS7/h1wx/4plP/8xJhv/IhwV/y8mHP8xJx7/KSEZ/xMQ - Dv84KRv/qWsv/5lUD/+XUgz/l1IN/5dSDf+WUg3/llIO/5xWD/9ZMQnpAAAAygAAAMkAAACsAAAAZwAA - AAAAAAAAAAAAAGtWQiWnUQDwqlkI/6pZCP+qWAf/sF8P/6hqLv8kGxT/GhYR/ywjG/8xJx7/KiIZ/xMQ - Dv86KRn/vHMr/6hZCf+oWQn/qFkJ/6hYCf+oWAn/qFgJ/6hYCf+nWAn/p1gI/6hZCv+4ci3/OCgZ/xUS - D/8rIxr/Mige/y8lHP8jHBb/CgoK/4ZZLf+yZRn/pFYI/7FkF/+LXC3/CwoK/yMcFv8vJhz/MCYd/yYf - F/8ODAv/ZkYn/7NqIP+kVwr/pFcK/6NXCv+jVwr/o1cK/6NXCv+jVwr/o1YK/6JWCv+iVgr/olYK/6JW - Cv+lWQ7/qm0v/y0iF/8YFA//KyIa/y0kG/8jHBX/CgoK/4haLf+sYhf/pVsR/6dsMf8nHhX/FxIP/ykh - Gf8tJRz/KCAY/xMQDf80Jhj/uHk6/41fMf8ODQv/IhwV/ywkG/8pIRn/ExAO/zgpGf+yby3/nVUM/51U - DP+dVAz/nVQM/51TC/+kXBT/mmUx/xsWEf8cFxL/LCMb/y0kG/8hGxX/IRoU/6JvOv+vaSL/p2AY/6dg - GP+vaiP/nWw6/x4YEv8iHBX/LiUc/y8lHP8lHhf/DAsK/2lJK/+pZyP/mVMN/5lTDf+ZUw3/mFMN/5hS - Df+YUg3/nlYO/1oxCOkAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAa1ZCJadSAPCrWgj/q1oI/6tZ - B/+xXw7/qGot/yQbFP8aFhH/LCMb/zEnHv8qIhn/ExAO/zopGf+8cyv/qVkJ/6lZCf+pWQn/qVkJ/6lZ - Cf+oWQn/qFkJ/6hZCf+oWAn/qFgJ/7tyKv87Khn/FBEO/yoiGv8yKB7/LyYd/yQdFv8MCwr/dk8q/7Rn - G/+lVgf/smUX/4xdLf8LCgr/IxwW/y8mHP8wJh3/Jh8X/w4MC/9mRif/tGog/6RXCv+kVwr/pFcK/6RX - Cv+kVwr/pFcK/6NXCv+jVwr/o1cK/6NXCv+jVwr/o1YJ/6ZZDf+qbS7/LSIX/xgUD/8rIhr/LSQb/yIc - Ff8PDQz/jl0u/6thF/+zayP/a0oq/wsKCf8kHRb/LCQb/ywjG/8hGxX/DQwK/35VLP+6cir/h1os/wsJ - Cv8jHBX/LSQb/yohGf8TEA7/OCkZ/7JvLP+eVQv/nlUL/55VDP+eVQz/nlUM/55VDf+vbi3/Oiob/xMQ - Df8pIRn/LSQb/yUeFv8NDAv/eFIs/6ljHP+bUgr/m1MK/6plH/9tSyr/DAwL/yYfF/8uJhz/LSQb/x8Z - E/8UEQ3/kGAw/6NdF/+aUgz/mlMN/5pTDf+ZUw3/mVMN/5lTDf+gVw7/XDII6QAAAMoAAADJAAAArAAA - AGcAAAAAAAAAAAAAAABrVkIlqFIA8KxaCP+sWgj/q1kH/7FgDv+pay3/JBwU/xoWEf8sIxv/MSce/yoi - Gf8TEA7/OikY/71zKv+qWQn/qlkJ/6pZCf+pWQn/qVkJ/6lZCf+pWQn/qVkJ/6lZCP+pWgr/vHQs/zwq - Gf8UEQ//KiIa/zIoHv8vJh3/JB0W/wwLCv92Tyr/tWcb/6ZWB/+zZRb/jF0t/wsKCv8jHBb/LyYc/zAm - Hf8mHxf/DgwL/2ZHJ/+0aiD/pVcK/6VXCv+lVwr/pVcK/6RXCv+kVwr/pFcK/6RXCv+kVwr/pFcK/6RX - Cv+jVwn/ploN/6ttLv8tIRf/GBQP/ysiGv8tJBv/IBoU/xkTEP+XYi7/sGYc/6ZrMf8kGxT/GBMQ/yoh - Gf8uJBz/KCAY/xIQDf80Jxn/rm4u/69mHP+KXC7/DAsK/yQdFv8tJBv/KiIZ/xMQDv84KRn/s28s/59V - C/+fVQv/n1UL/55VC/+eVQv/nlUL/65oIv9rSir/DAsK/yUeF/8sJBv/JyAY/xAODP9MNiL/sGwp/51U - DP+cVQ3/r20s/0MwHv8SDw3/KSAZ/y8lHP8qIRr/FRIO/zMmGf+pbC//nVYP/5tTC/+aUwz/mlMM/5pT - DP+aUwz/mlMN/6FXDv9cMgjpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGtWQiWpUgDwrFoI/6xa - CP+sWQf/smAO/6prLf8kHBT/GhYR/ywjG/8xJx7/KiIZ/xMQDv86Khj/vnQp/6pZCP+qWQj/qlkI/6pZ - CP+qWQn/qlkJ/6pZCf+pWQn/qVkI/6tcDP+0cC3/MiQX/xcTEP8rIxr/Mige/y4lHP8jHBX/CgoK/4dZ - LP+1Zhj/plYH/7NlFv+NXS3/CwoK/yMcFv8vJhz/MCYd/yYfF/8ODAv/Zkcn/7VrIP+mWAr/plgK/6VY - Cv+lWAr/pVcK/6VXCv+lVwr/pVcK/6VXCv+kVwr/pFcK/6RXCf+nWg3/rG0u/y0hF/8YFA//KyIa/ywk - G/8fGRP/GBMP/5ZiLv++dSz/ZEUm/woJCv8kHRb/LSQb/ywjG/8hGxT/DAsK/39WLv+wZh3/rmQb/39W - Lf8MCwr/JB0W/y0kG/8qIhn/ExAO/zkpGf+0byz/oFUL/59VC/+fVQv/n1UL/59VC/+fVAr/qV8W/5Nh - MP8UEQ3/HxoT/ysjGv8qIhn/GBQQ/ygeFf+lazD/oVgQ/6NZEv+fZzH/IRkT/xoWEf8rIxr/LiUc/yYf - F/8NDAr/X0Mn/61pJP+bVAz/m1QM/5tUDP+bVAz/m1QM/5tUDP+bUwz/oVcN/1wyB+kAAADKAAAAyQAA - AKwAAABnAAAAAAAAAAAAAAAAa1dCJalTAPCtWgj/rVoI/61ZB/+zYA7/qmst/yQcFP8aFhH/LCMb/zEn - Hv8qIhn/ExAO/zoqGP++dCn/q1oI/6taCP+rWgj/q1oI/6tZCP+qWQj/qlkI/6pZCP+qWAj/sGAQ/6hr - MP8jGxP/HRcS/y0kG/8yKB7/LiQb/yEaFP8PDQv/k2As/7JjFP+nVwf/tGYW/45dLf8LCgr/IxwW/y8m - HP8wJh3/Jh8X/w4MC/9nRyf/tmsf/6ZYCf+mWAn/plgJ/6ZYCf+mWAr/plgK/6ZYCv+lWAr/pVcK/6VX - Cv+lVwr/pVcJ/6haDf+sbS7/LSEX/xgUD/8qIhr/LCMb/x8ZE/8YEw//nGg0/7J3O/8jGxL/GBMQ/ykh - Gf8tJBv/JyAY/xEPDP86Khz/sG4u/6RZDv+vZRv/dE4q/wwLCv8lHhb/LiQc/yoiGf8TEA7/OSkZ/7Rw - LP+gVgv/oFYL/6BVC/+gVQv/oFUL/59VCv+hVw7/rW4v/zElGP8VEg7/KSEZ/ywjGv8hGhT/EQ8M/41f - MP+oYBj/q2Ia/4BXLv8MCwr/IxwV/y0kG/8tJBv/IRoU/xIPDf+NXjH/p2AZ/5xTC/+cVAz/nFQM/5xU - DP+cVAz/m1QM/5tUDP+iWA3/XTMH6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABrV0IlqlMA8K5b - CP+uWwj/rVoH/7NgDv+qay3/JBwU/xoWEf8sIxv/MSce/yoiGf8TEA7/OyoY/750Kf+sWgj/rFoI/6xa - CP+rWgj/q1oI/6taCP+rWgj/q1oI/6pZB/+5aRr/iFsu/w4NC/8lHRb/LyUc/zIoHv8rIxr/GhUR/yEZ - Ev+mai3/r18P/6hYB/+1Zhb/jl0t/wsKCv8jHBb/LyYc/zAmHf8mHxf/DgwL/2dHJ/+2ax//p1gJ/6dY - Cf+nWAn/p1gJ/6dYCf+mWAn/plgJ/6ZYCf+mWAr/plgK/6ZYCv+lVwn/qFsN/61tLv8tIRf/FxQP/yoi - Gv8sIxv/HxkT/xkUD/+pdkP/dFIw/wwLCv8kHRb/LCQb/ysiGv8fGRP/Dw0L/4tdL/+wZhv/olUJ/7Bm - HP91UCv/DQwL/yUeFv8uJRz/KiIZ/xMQDv85KRn/tXAs/6FWC/+hVgv/oVYL/6FWC/+gVgv/oFYL/6BV - C/+yayT/XUEm/w0MC/8mHxf/LCMb/yYeF/8NDAv/Zkco/65oIf+wayX/VTwk/w8NDP8nHxj/LyUc/yoi - Gv8XEw//KyAW/6drMP+gWBD/nVQL/51UDP+dVAz/nFQM/5xUDP+cVAz/nFQM/6NYDf9eMwfpAAAAygAA - AMkAAACsAAAAZwAAAAAAAAAAAAAAAGxXQiWrUwDwrlsH/65bB/+uWgb/tGEN/6tsLf8kHBT/GhYR/ywj - G/8xJx7/KiIZ/xMQDv87Khj/v3Qp/61aCP+sWgj/rFoI/6xaCP+sWgj/rFoI/6xaCP+rWgj/rVwL/752 - LP9GMh//EhAO/ykhGf8wJx3/MCcd/yggGf8SDw3/NycY/7hxKv+rWgv/qVgH/7VmFv+OXS3/CwoK/yMc - Fv8vJhz/MCYd/yYfF/8ODAv/Z0cn/7drH/+oWAn/qFgJ/6hYCf+nWAn/p1gJ/6dYCf+nWAn/p1gJ/6dY - Cf+mWAn/plgJ/6ZYCP+pWwz/rm4u/y0iF/8XFA//KiIa/ywjG/8fGRP/KyEV/6V3Sf8vIxj/GRQQ/ykh - Gf8sJBv/Jh4X/w0MCv9KNR//tnAr/6VZDP+jVgj/sWcc/3ZQK/8NDAv/JR4W/y4lHP8qIhn/ExAO/zkp - Gf+2cCz/olYL/6JWC/+hVgv/oVYL/6FWC/+hVgv/oVUK/6xjGP+LXS//EA4M/yEbFf8rIxr/KCAY/xIP - Df8/LRv/tHEv/61uMP8vIxf/FhIO/yoiGv8uJRz/Jx8Y/w4NDP9XPST/sWwn/55VC/+eVQz/nVUM/51U - DP+dVAz/nVQM/51UDP+dVAz/pFgN/14zB+kAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAbFdCJatT - APCvWwf/r1sH/69aBv+1YQ3/rGws/yQcFP8aFhH/LCMb/zEnHv8qIhn/ExAO/zsqGP+/dSn/rVoI/61a - CP+tWgj/rVoI/61aCP+sWgj/rFoI/6xaCf++byD/il0v/xEPDf8hGxX/LSQb/zEnHv8uJRz/JR0W/wkJ - Cf9pRyb/u20e/6pZCP+pWAf/tmYV/49dLP8LCgr/IxwW/y8mHP8wJh3/Jh8X/w4MC/9oRyf/uGwf/6lZ - Cf+oWQn/qFkJ/6hZCf+oWAn/qFgJ/6hYCf+nWAn/p1gJ/6dYCf+nWAn/p1gI/6pbDP+vbi3/LSIX/xcU - D/8qIhr/LSQb/yEbFf84Khz/c1Q0/xkVD/8lHhb/LCMa/ykhGf8ZFRD/GxYQ/55oMv+uYhb/pFYJ/6RW - Cf+yZxz/dlAr/w0MC/8lHhb/LiUc/yoiGf8TEA7/OSkZ/7ZwLP+iVgr/olYK/6JWCv+iVgv/olYL/6JW - C/+hVgr/pVoQ/6lsMP8oHhX/GBQQ/yoiGf8qIhn/GhUR/yMbE/+rcjr/mmc2/xUSDv8fGRP/LCQb/y0k - G/8jHBX/DgwL/4RZLv+rYxr/nlQK/55VC/+eVQv/nlUL/55VDP+eVQz/nlUM/51VDP+kWA3/XjMH6QAA - AMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABsV0IlrFMA8LBbB/+wWwf/r1oG/7VhDf+sbCz/JBwU/xoW - Ef8sIxv/MSce/yoiGf8TEQ7/OyoY/8B1KP+uWwf/rVoH/61aB/+tWgf/rVoH/61aCP+wXgz/wXEh/59p - M/8iGRL/GBQQ/ykhGf8vJx3/MCcd/yoiGf8ZFRD/GRQP/6VqL/+zYhH/q1oH/6tZB/+3ZhX/j14s/wsK - Cv8jHBb/LyYc/zAmHf8mHxf/DgwL/2hHJ/+4bB//qVkJ/6lZCf+pWQn/qVkJ/6lZCf+oWQn/qFkJ/6hZ - Cf+oWQn/qFgJ/6hYCf+oWAj/qlsM/69uLf8tIhf/FxQP/yoiGv8uJRz/JyAZ/zQoHf83Kh3/IxwV/yoi - Gv8rIxr/JBwV/woKCf9nSCj/uG4l/6VXC/+lVwr/pVYJ/7JnHP92UCv/DQwL/yUeFv8uJRz/KiIZ/xMQ - Dv85KRn/tnEs/6NXCv+jVwr/o1cK/6NWCv+iVgr/olYK/6JWCv+iVgv/tG4o/1A4Iv8QDQz/Jx8Y/ysi - Gv8hGxX/Eg8M/5xvQv98WTX/DQsK/yUeFv8tJBz/KyIa/xkUEP8lHBT/pmsx/6RaEf+fVAr/n1UL/59V - C/+fVQv/n1UL/55VC/+eVQv/nlUL/6VZDP9fMwfpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAGxX - QiWtVADwsFwH/7BcB/+wWwb/tmEN/6xsLP8kHBT/GhYR/ywjG/8xJx7/KyMa/xUSD/8+LBr/x3su/7Jf - C/+xXgr/sl8L/7RhDv+4ZhT/vm8e/712L/9/Vi3/IBkS/xUSDv8oIBj/LiUc/zAmHf8sJBv/IhsV/wcI - CP9kRSb/vXAj/61bCf+sWgj/q1kH/7dmFf+PXiz/CwoK/yMcFv8vJhz/MCYd/yYfF/8ODAv/aEcn/7ls - Hv+qWQj/qlkJ/6pZCf+pWQn/qVkJ/6lZCf+pWQn/qVkJ/6lZCf+pWQn/qFkJ/6hYCP+rXAz/sG4t/y4i - F/8XFA//KyIa/zAmHf8uJRz/KiIa/ycgGf8sJBv/LSQb/yggGP8UEA7/LCAW/69wMP+rXhD/plgJ/6ZY - Cv+lVwn/s2cc/3dQK/8NDAv/JR4W/y4lHP8qIhn/ExAO/zkpGf+3cSz/pFcK/6RXCv+kVwr/o1cK/6NX - Cv+jVwr/o1cK/6NWCf+wZRv/f1Yt/w0MC/8jHBX/KiIa/yYfF/8SDwz/f106/1hBKv8WEg7/KSEZ/y4l - HP8oIBj/EA4M/0o0H/+zbin/oFYM/6BVC/+gVQv/oFUL/59VC/+fVQv/n1UL/59VC/+fVQv/plkM/18z - B+kAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAbFdCJa1UAPCxXAf/sVwH/7FbBv+3Yg3/rW0s/yQb - FP8aFhH/LCMb/zEoHv8tJBv/GxcS/zsrHP+1ej//tHAt/7dxK/+1cCz/rG0u/5xlLv94USr/Oioa/w4M - C/8ZFRD/KCAY/y0kG/8vJh3/LSQb/yUeFv8NDAv/LyMX/7JvLv+yYQ//rVoI/6xaCP+sWQf/uGYV/5Be - LP8LCgr/IxwW/y8mHP8wJh3/Jh8X/w4MC/9pSCf/um0e/6tZCP+qWQj/qlkI/6pZCP+qWQj/qlkJ/6pZ - Cf+qWQn/qVkJ/6lZCf+pWQn/qVkI/6xcDP+wby3/LiIX/xcTD/8rIxr/MSce/zEnHv8wJx3/MCYd/y8m - Hf8rIxr/IBoU/w0MC/+DWC7/tmod/6dYCf+mWAn/plgJ/6ZXCP+0aBz/d1Er/w0MC/8lHhb/LiUc/yoi - Gf8TEA7/OSkZ/7hxLP+lVwr/pFcK/6RXCv+kVwr/pFcK/6RXCv+kVwr/o1cJ/6ldEf+kajD/IRkT/xoW - Ef8pIRn/KSEZ/x4YE/9OOSX/PC4e/x8aFP8sIxv/LSQb/yQdFv8NCwr/f1Yt/69lHP+hVgr/oVYL/6BW - C/+gVgv/oFYL/6BVC/+gVQv/oFUL/6BVC/+nWQz/XzMH6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAA - AABsV0IlrlQA8LJcB/+yXAf/sVsG/7diDf+ubSz/JRsU/xoWEf8sIxv/Mige/y8mHf8oIRn/IBkT/yce - Ff8uIxf/MCMX/y4iF/8lHBX/FREO/w0MC/8VEg//IxwW/yohGf8tJBv/LSUc/ysiGv8kHRX/Dw0L/yIa - E/+jaTD/uWgY/61aCP+tWgj/rVoI/61ZB/+5ZhX/kF4s/wsKCv8jHBb/LyYc/zAmHf8mHxf/DgwL/2lI - J/+6bR7/q1oI/6taCP+rWgj/q1oI/6taCP+rWQj/qlkI/6pZCP+qWQj/qlkJ/6pZCf+qWQj/rFwM/7Bv - Lf8uIhf/FxMP/ysjGv8yKB7/Mykf/zMpH/8yKB7/LyUc/ycfF/8PDQz/QzAd/7hyLP+qWw3/p1gJ/6dY - Cf+nWAn/p1cI/7VoG/94USv/DQwL/yUeFv8uJRz/KiIZ/xMQDv85KRn/uHIs/6VXCv+lVwr/pVcK/6VX - Cv+lVwr/pFcK/6RXCv+kVwr/pVgL/7ZvKv9GMR7/Eg8N/yggGP8sIxv/KiIZ/yggGP8rIhn/KiIa/y4l - HP8rIxr/GxYR/x8YEv+haTD/qF0S/6FVCv+hVgv/oVYL/6FWC/+hVgv/oVYL/6FWC/+gVgv/oFYL/6ha - DP9gMwfpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAG1XQSWvVADwslwG/7JcBv+yWwX/uGIN/65t - LP8kHBP/GRUQ/ysjGv8xJx7/MCcd/y0kHP8oIBn/HxoU/xoWEv8YFBD/GBQQ/xsWEv8gGxT/JR4W/ygg - GP8qIhr/LCMb/yoiGv8nHxf/HRcS/wkJCf8oHhT/oGcv/71sGv+vXAj/rlsH/65bCP+uWwj/rloH/7ln - Ff+QXiz/CwoK/yMcFv8vJhz/MCYd/yYfF/8ODAv/aUgn/7ttHv+sWgj/rFoI/6xaCP+rWgj/q1oI/6ta - CP+rWgj/q1oI/6taCP+rWQj/qlkI/6pZB/+tXAv/sW8t/y4iF/8XEw//KyMa/zIoHv8zKR//Mykf/zEn - Hv8rIhr/HBcS/xURDv+ZZTD/s2UX/6hZCf+oWAn/qFgJ/6hYCf+nVwj/tWgb/3hRK/8NDAv/JR4W/y4l - HP8qIhn/ExAO/zopGf+5civ/plgK/6ZYCf+mWAr/pVgK/6VXCv+lVwr/pVcK/6VXCv+lVwn/s2ge/3ZQ - K/8MCwr/JB0W/y0kG/8vJhz/LSQc/y0kHP8wJh3/LyYc/yggGP8SDw3/RjEe/7RvKv+jVwv/olYK/6JW - Cv+iVgv/olYL/6JWC/+hVgv/oVYL/6FWC/+hVgv/qVoM/2A0B+kAAADKAAAAyQAAAKwAAABnAAAAAAAA - AAAAAAAAbVdBJa9VAPCzXQb/s10G/7NcBf+4Ygz/rm4s/yMbE/8UEA3/JR4W/ysjGv8sIxv/KyMb/yoi - Gv8pIRn/JyAY/ycfF/8nHxf/Jx8Y/ycgGP8oIBj/KCAY/yYfF/8jHRX/GxYR/w4MC/8PDQz/VToh/7Bv - Lv+7aRj/r1sI/69bB/+vWwf/r1sH/65bB/+uWgb/umcU/5FeLP8JCQn/IBoT/yoiGv8rIxr/IxwV/wwL - Cv9pSCf/vG0e/61aCP+sWgj/rFoI/6xaCP+sWgj/rFoI/6xaCP+sWgj/q1oI/6taCP+rWgj/q1oH/65d - C/+ycC3/LSEW/xMQDf8nHxj/LiQc/y8mHP8uJRz/KiIa/yIcFf8KCgn/YEIm/7txJ/+qWgr/qVkJ/6lZ - Cf+oWQn/qFkJ/6hYCP+2aBv/eFEr/woKCf8iGxT/KiEZ/yYeF/8QDgz/OSkY/7pyK/+nWAn/plgJ/6ZY - Cf+mWAn/plgK/6ZYCv+mWAr/plgK/6VXCf+uYBT/nWYw/xcTD/8bFhH/KCAY/y0kG/8tJBv/LSQb/y0k - G/8qIhr/IRsU/woKCf91UCv/smgd/6NXCv+jVwr/o1cK/6NWCv+iVgr/olYK/6JWCv+iVgv/olYL/6JW - C/+pWgz/YDQH6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABtV0ElsVUA8LRdBv+zXQb/s1wF/7hi - C/+ubCn/GhUQ/wMEBf8TEA3/GhUR/x0XEv8eGRP/IBoU/yIbFf8iGxX/IhsV/yIbFP8fGRP/HRgS/xkU - EP8UEQ7/Dw0M/woKCv8aFRD/SDId/5NfLP/AdCf/t2QQ/7BbB/+wWwf/r1sH/69bB/+vWwf/r1sH/69a - Bv+7ZxT/kl8r/wUGB/8XEw7/IBoT/yEaFP8ZFA//BgYH/2pIJ/+8bh7/rVoI/61aCP+tWgj/rVoI/61a - CP+tWgj/rFoI/6xaCP+sWgj/rFoI/6xaCP+sWgf/r10L/7JwLf8sIBX/DAoJ/x0XEv8jHBX/IxwW/yMc - Ff8eGRL/Dw0L/yIbEv+sbjD/sWAS/6pZCP+pWQn/qVkJ/6lZCf+pWQn/qVgI/7dpG/95Uiv/BgYH/xgT - D/8fGRP/HBcR/wkICP85KBj/unMr/6dYCf+nWAn/p1gJ/6dYCf+nWAn/p1gJ/6ZYCf+mWAn/plgJ/6dZ - DP+1cS3/NygZ/wsKCf8dFxL/IhwV/yMcFv8jHBb/IxwV/x8ZE/8TDwz/GBMP/59oMP+rXxP/pFYJ/6RX - Cv+jVwr/o1cK/6NXCv+jVwr/o1cK/6NWCv+jVgr/olYK/6paC/9hNAbpAAAAygAAAMkAAACsAAAAZwAA - AAAAAAAAAAAAAG1XQSWxVQDwtF0G/7RdBv+0XQX/uGEK/7FnHf9ZOhz/NSUW/yofFf8kHBP/HBYR/xcT - D/8VEg7/CgoK/woKCv8KCgr/CwsK/xYSDv8aFRD/Jh0U/zMlF/9UOSD/fFIp/6hrLf/Bcyb/vGkW/7Je - Cv+xXAf/sFwH/7BcB/+wXAf/sFwH/7BbB/+wWwf/r1oG/7pmEf+OWSX/AAEG/wUGB/8JCQn/CQkJ/wYG - B/8AAAX/ZUMh/7xrGf+uWwf/rlsI/65bCP+uWwj/rVsI/61aCP+tWgj/rVoI/61aCP+tWgj/rFoI/6xa - B/+vXQv/sGsm/yUbEv8AAQX/BwcI/woKCv8LCgr/CgoK/wcHCP8BAwf/elEp/7xtHv+qWgn/qlkI/6pZ - CP+qWQn/qlkJ/6pZCf+pWAj/t2cY/3RMJP8AAAb/BgYH/wgICf8HBwj/AAAE/zMjFP+5byT/qFgJ/6hY - Cf+oWAn/qFgJ/6dYCf+nWAn/p1gJ/6dYCf+nWAn/plgJ/7drHv9nRSX/AAAF/wcHCP8KCgr/CwoK/wsK - Cv8LCgr/CAgI/wABBP83Jxj/tG4p/6ZZDP+kVwn/pFcK/6RXCv+kVwr/pFcK/6RXCv+kVwr/o1cK/6NX - Cv+jVwr/q1sK/2I0BukAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAbVdBJbJVAPC1XQb/tV0G/7Vd - Bv+0Xgf/t2EN/8NvHP/Ddij/tnAq/7BuLP+naSv/omcr/59mLP+VXyr/lF8q/5RfKv+VXyn/n2Us/6Ro - K/+wbiz/vXMp/8NyIv/AbBr/uWQP/7NdCf+yXAf/sVwH/7FcB/+xXAf/sVwH/7FcB/+xXAf/sVwH/7Bc - B/+wXAb/s2AL/6xjGv+PWiX/k18r/5JeK/+SXiv/kl8r/49aJ/+jYB7/s2EP/69bB/+uWwf/rlsH/65b - B/+uWwf/rlsI/65bCP+uWwj/rVsI/61aCP+tWgj/rVoI/65bCf+wYxb/lFsi/49cKv+QXiz/kF4s/5Be - LP+QXiz/j10r/5FbJv+xaB//rl4N/6taCP+rWgj/q1oI/6tZCP+qWQj/qlkI/6pZCP+uXg7/ol8e/4tZ - J/+PXi3/j10t/49eLf+MWyr/lFsh/69iFf+pWQn/qVkJ/6hZCf+oWQn/qFkJ/6hYCf+oWAn/qFgJ/6dY - Cf+nWAn/q10Q/6VjIf+JWCf/jV0t/41dLf+MXS3/jF0t/4xdLf+MXS3/iVoq/5tfJP+sYRb/pVcK/6VX - Cv+lVwr/pVcK/6VXCv+lVwr/pFcK/6RXCv+kVwr/pFcK/6RXCv+sWwr/YjQG6QAAAMoAAADJAAAArAAA - AGcAAAAAAAAAAAAAAABtV0Els1YA8LZeBv+1Xgb/tV0G/7VdBv+1XQb/tV0G/7VeB/+4YQr/umMM/7xl - Dv+9Zg//vWcQ/8BpEv/AaRP/wGkT/79pEv+8ZxD/u2UO/7hiC/+1Xwj/s1wG/7NcBf+yXAX/slwG/7Jc - Bv+yXAb/slwH/7JcB/+yXAf/sVwH/7FcB/+xXAf/sVwH/7FcB/+xXAj/tGAL/7xnEv+8aBT/vGgU/7xo - FP+8aBT/u2cS/7ZgDf+vXAj/r1sH/69bB/+vWwf/r1sH/69bB/+vWwf/rlsH/65bB/+uWwf/rlsI/65b - CP+uWwj/rlsI/65cCv+2YxD/uWcU/7lmFf+4ZhX/uGYV/7hmFf+4ZhX/tmQS/65cC/+sWgj/rFoI/6xa - CP+rWgj/q1oI/6taCP+rWgj/q1oI/6paCf+vXg3/tmQT/7ZmFv+2Zhb/tmYW/7ZlFf+yYRD/qloL/6lZ - Cf+pWQn/qVkJ/6lZCf+pWQn/qVkJ/6hZCf+oWQn/qFkJ/6hYCf+nWQr/q10O/7NjFP+zZRb/s2UW/7Nl - Fv+zZRb/smUW/7JlFv+yYxX/rV4Q/6dZC/+mWAn/plgK/6ZYCv+mWAr/pVgK/6VXCv+lVwr/pVcK/6VX - Cv+lVwr/pFcK/6xbCv9iNAbpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAG1XQSWzVgDwtl4F/7Ze - Bv+2Xgb/tl4G/7ZeBv+1Xgb/tV0G/7VdBf+1XQX/tVwF/7RcBf+0XAX/tFwF/7RcBf+0XAX/tFwF/7Rc - Bf+zXAX/s1wF/7RdBf+zXQb/s10G/7NdBv+zXQb/s10G/7NcBv+zXAb/slwG/7JcBv+yXAb/slwH/7Jc - B/+yXAf/slwH/7FcB/+xXAf/sVsG/7FbBv+wWwb/sFsG/7BbBv+wWwb/sFsG/7BcB/+wWwf/sFsH/7Bb - B/+wWwf/r1sH/69bB/+vWwf/r1sH/69bB/+vWwf/rlsH/65bB/+uWwf/rlsH/65aB/+tWgf/rVoH/61a - B/+tWQf/rVkH/61ZB/+tWQf/rVoI/61aCP+sWgj/rFoI/6xaCP+sWgj/rFoI/6xaCP+sWgj/q1oI/6ta - B/+rWQf/q1kH/6pZB/+qWAf/qlgH/6pZB/+qWQj/qlkI/6pZCf+qWQn/qlkJ/6lZCf+pWQn/qVkJ/6lZ - Cf+pWQn/qVkJ/6lZCf+oWQj/qFgI/6hYCP+oVwj/p1cI/6dXCP+nVwj/p1cI/6dXCP+nVwj/p1gJ/6dY - Cf+nWAn/plgJ/6ZYCf+mWAn/plgK/6ZYCv+mWAr/pVgK/6VXCv+lVwr/rVsK/2M0BukAAADKAAAAyQAA - AKwAAABnAAAAAAAAAAAAAAAAbldBJbRWAPC3XgX/t14F/7ZeBf+2XgX/tl4F/7ZeBf+2Xgb/tl4G/7Ze - Bv+2Xgb/tV4G/7VdBv+1XQb/tV0G/7VdBv+1XQb/tV0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7Rd - Bv+zXQb/s10G/7NdBv+zXQb/s10G/7NdBv+zXAb/slwG/7JcBv+yXAb/slwG/7JcB/+yXAf/slwH/7Fc - B/+xXAf/sVwH/7FcB/+xXAf/sVwH/7FcB/+wXAf/sFwH/7BcB/+wXAf/sFsH/7BbB/+wWwf/r1sH/69b - B/+vWwf/r1sH/69bB/+vWwf/r1sH/65bB/+uWwf/rlsH/65bB/+uWwj/rlsI/65bCP+tWwj/rVoI/61a - CP+tWgj/rVoI/61aCP+tWgj/rFoI/6xaCP+sWgj/rFoI/6xaCP+sWgj/q1oI/6taCP+rWgj/q1oI/6ta - CP+rWgj/q1kI/6pZCP+qWQj/qlkI/6pZCf+qWQn/qlkJ/6pZCf+pWQn/qVkJ/6lZCf+pWQn/qVkJ/6lZ - Cf+oWQn/qFkJ/6hZCf+oWAn/qFgJ/6hYCf+oWAn/p1gJ/6dYCf+nWAn/p1gJ/6dYCf+nWAn/plgJ/6ZY - Cf+mWAn/plgJ/6ZYCv+uXAr/ZDUG6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABuV0EltFYA8Lde - Bf+3XgX/t14F/7deBf+3XgX/t14F/7deBf+2XgX/tl4F/7ZeBf+2XgX/tl4G/7ZeBv+2Xgb/tV4G/7Vd - Bv+1XQb/tV0G/7VdBv+1XQb/tV0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/s10G/7Nd - Bv+zXQb/s10G/7NdBv+zXAb/s1wG/7JcBv+yXAb/slwG/7JcB/+yXAf/slwH/7JcB/+xXAf/sVwH/7Fc - B/+xXAf/sVwH/7FcB/+xXAf/sFwH/7BcB/+wXAf/sFsH/7BbB/+wWwf/sFsH/69bB/+vWwf/r1sH/69b - B/+vWwf/r1sH/69bB/+uWwf/rlsH/65bB/+uWwj/rlsI/65bCP+tWwj/rVoI/61aCP+tWgj/rVoI/61a - CP+tWgj/rFoI/6xaCP+sWgj/rFoI/6xaCP+sWgj/rFoI/6taCP+rWgj/q1oI/6taCP+rWgj/q1kI/6pZ - CP+qWQj/qlkI/6pZCP+qWQn/qlkJ/6pZCf+pWQn/qVkJ/6lZCf+pWQn/qVkJ/6lZCf+pWQn/qFkJ/6hZ - Cf+oWQn/qFgJ/6hYCf+oWAn/p1gJ/6dYCf+nWAn/p1gJ/6dYCf+nWAn/p1gJ/65cCf9kNQXpAAAAygAA - AMkAAACsAAAAZwAAAAAAAAAAAAAAAG5YQSW1WADwuF4F/7heBf+4XgX/uF4F/7deBf+3XgX/t14F/7de - Bf+3XgX/t14F/7deBf+2XgX/tl4F/7ZeBf+2XgX/tl4G/7ZeBv+2Xgb/tl4G/7VeBv+1XQb/tV0G/7Vd - Bv+1XQb/tV0G/7VdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/s10G/7NdBv+zXQb/s10G/7Nd - Bv+zXQb/s1wG/7JcBv+yXAb/slwG/7JcBv+yXAf/slwH/7JcB/+xXAf/sVwH/7FcB/+xXAf/sVwH/7Fc - B/+xXAf/sFwH/7BcB/+wXAf/sFwH/7BbB/+wWwf/sFsH/69bB/+vWwf/r1sH/69bB/+vWwf/r1sH/69b - B/+uWwf/rlsH/65bB/+uWwf/rlsI/65bCP+uWwj/rVsI/61aCP+tWgj/rVoI/61aCP+tWgj/rVoI/6xa - CP+sWgj/rFoI/6xaCP+sWgj/rFoI/6taCP+rWgj/q1oI/6taCP+rWgj/q1oI/6tZCP+qWQj/qlkI/6pZ - CP+qWQn/qlkJ/6pZCf+qWQn/qVkJ/6lZCf+pWQn/qVkJ/6lZCf+pWQn/qFkJ/6hZCf+oWQn/qFgJ/6hY - Cf+oWAn/qFgJ/6dYCf+nWAn/r1wJ/2Q1BekAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAblhBJbZY - APC5XwX/uF8F/7hfBf+4XwX/uF8F/7heBf+4XgX/uF4F/7deBf+3XgX/t14F/7deBf+3XgX/t14F/7de - Bf+3XgX/tl4F/7ZeBf+2XgX/tl4F/7ZeBv+2Xgb/tl4G/7VeBv+1XQb/tV0G/7VdBv+1XQb/tV0G/7Vd - Bv+0XQb/tF0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7NdBv+zXQb/s10G/7NdBv+zXQb/s10G/7Nc - Bv+yXAb/slwG/7JcBv+yXAf/slwH/7JcB/+yXAf/sVwH/7FcB/+xXAf/sVwH/7FcB/+xXAf/sVwH/7Bc - B/+wXAf/sFsG/7BbBv+vWgb/r1sG/7BbBv+vWwf/r1sH/69bB/+vWwf/r1sH/69bB/+vWwf/rlsH/65b - B/+uWwf/rlsI/65bCP+uWwj/rVsI/61bCP+tWgj/rVoI/61aCP+tWgj/rVoI/6xaCP+sWgj/rFoI/6xa - CP+sWgj/rFoI/6xaCP+rWgj/q1oI/6taCP+rWgj/q1oI/6tZCP+qWQj/qlkI/6pZCP+qWQj/qlkJ/6pZ - Cf+qWQn/qVkJ/6lZCf+pWQn/qVkJ/6lZCf+pWQn/qVkJ/6hZCf+oWQn/qFkJ/6hYCf+wXAn/ZTUF6QAA - AMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABuWEEltlgA8LlfBf+5XwX/uV8F/7lfBf+5XwX/uF8F/7hf - Bf+4XwX/uF8F/7heBf+4XgX/uF4F/7heBf+3XgX/t14F/7deBf+3XgX/t14F/7deBf+3XgX/tl4F/7Ze - Bf+2XgX/tl4F/7ZeBv+2Xgb/tl4G/7ZeBv+1Xgb/tV0G/7VdBv+1XQb/tV0G/7VdBv+1XQb/tF0G/7Rd - Bv+0XQb/tF0G/7RdBv+0XQb/tF0G/7NdBv+zXQb/s10G/7NdBv+zXQb/s10G/7NcBv+yXAb/slwG/7Jc - Bv+yXAb/slwH/7JcB/+yXAf/sVwH/7FcB/+xXAf/sVwH/7FcCP+0YAv/vGcS/7xoFP+7ZxL/tWAM/7Bc - CP+wWwf/sFsH/7BbB/+vWwf/r1sH/69bB/+vWwf/r1sH/69bB/+vWwf/rlsH/65bB/+uWwf/rlsH/65b - CP+uWwj/rlsI/61bCP+tWgj/rVoI/61aCP+tWgj/rVoI/61aCP+sWgj/rFoI/6xaCP+sWgj/rFoI/6xa - CP+rWgj/q1oI/6taCP+rWgj/q1oI/6taCP+rWQj/qlkI/6pZCP+qWQj/qlkJ/6pZCf+qWQn/qlkJ/6lZ - Cf+pWQn/qVkJ/6lZCf+pWQn/qVkJ/7BdCf9lNQXpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAG5Y - QSW3WADwul8F/7pfBf+5XwX/uV8F/7lfBf+5XwX/uV8F/7lfBf+5XwX/uV8F/7hfBf+4XwX/uF8F/7hf - Bf+4XgX/uF4F/7heBf+4XgX/t14F/7deBf+3XgX/t14F/7deBf+3XgX/t14F/7ZeBf+2XgX/tl4F/7Ze - Bf+2Xgb/tl4G/7ZeBv+1Xgb/tV4G/7VdBv+1XQb/tV0G/7VdBv+1XQb/tV0G/7RdBv+0XQb/tF0G/7Rd - Bv+0XQb/tF0G/7RdBv+zXQb/s10G/7NdBv+zXQb/s10G/7NdBv+zXAb/slwG/7JcBv+yXAb/slwH/7Jc - B/+yXAb/tWAL/61kGv+PWiX/lF8s/5BaJv+oYhz/tWEN/7FcB/+wXAf/sFwH/7BcB/+wWwf/sFsH/7Bb - B/+wWwf/r1sH/69bB/+vWwf/r1sH/69bB/+vWwf/r1sH/65bB/+uWwf/rlsH/65bCP+uWwj/rlsI/61b - CP+tWwj/rVoI/61aCP+tWgj/rVoI/61aCP+sWgj/rFoI/6xaCP+sWgj/rFoI/6xaCP+sWgj/q1oI/6ta - CP+rWgj/q1oI/6taCP+rWgj/q1kI/6pZCP+qWQj/qlkI/6pZCf+qWQn/qlkJ/6lZCf+pWQn/sV0J/2U1 - BekAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAb1hBJbdYAPC6XwT/ul8E/7pfBP+6XwX/ul8F/7pf - Bf+6XwX/uV8F/7lfBf+5XwX/uV8F/7lfBf+5XwX/uV8F/7hfBf+4XwX/uF8F/7hfBf+4XgX/uF4F/7he - Bf+4XgX/t14F/7deBf+3XgX/t14F/7deBf+3XgX/t14F/7ZeBf+2XgX/tl4F/7ZeBf+2Xgb/tl4G/7Ze - Bv+2Xgb/tV4G/7VdBv+1XQb/tV0G/7VdBv+1XQb/tV0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7Rd - Bv+zXQb/s10G/7NdBv+zXQb/s10G/7NdBv+zXAb/slwG/7JbBf+9ZxD/kFok/wABBv8FBQf/AAAG/3hN - I/+/ahb/sVsG/7FcB/+xXAf/sVwH/7FcB/+wXAf/sFwH/7BcB/+wXAf/sFsH/7BbB/+wWwf/r1sH/69b - B/+vWwf/r1sH/69bB/+vWwf/r1sH/65bB/+uWwf/rlsH/65bB/+uWwj/rlsI/65bCP+tWwj/rVoI/61a - CP+tWgj/rVoI/61aCP+tWgj/rFoI/6xaCP+sWgj/rFoI/6xaCP+sWgj/q1oI/6taCP+rWgj/q1oI/6ta - CP+rWgj/q1kI/6pZCP+qWQj/qlkI/6pZCP+yXQn/ZjUF6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAA - AABvWEEluFkA8LtgBP+7YAT/u18E/7tfBP+6XwT/ul8E/7pfBP+6XwT/ul8F/7pfBf+6XwX/uV8F/7lf - Bf+5XwX/uV8F/7lfBf+5XwX/uV8F/7lfBf+4XwX/uF8F/7hfBf+4XwX/uF4F/7heBf+4XgX/uF4F/7de - Bf+3XgX/t14F/7deBf+3XgX/t14F/7deBf+2XgX/tl4F/7ZeBf+2XgX/tl4G/7ZeBv+2Xgb/tV4G/7Ve - Bv+1XQb/tV0G/7VdBv+1XQb/tV0G/7VdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/s10G/7Nd - Bv+zXQb/s1wF/79pE/+VYCv/BQUH/w0KCP8FBQb/fVMq/8BsGf+yWwb/slwH/7JcB/+xXAf/sVwH/7Fc - B/+xXAf/sVwH/7FcB/+xXAf/sFwH/7BcB/+wXAf/sFsH/7BbB/+wWwf/sFsH/69bB/+vWwf/r1sH/69b - B/+vWwf/r1sH/69bB/+uWwf/rlsH/65bB/+uWwj/rlsI/65bCP+uWwj/rVsI/61aCP+tWgj/rVoI/61a - CP+tWgj/rFoI/6xaCP+sWgj/rFoI/6xaCP+sWgj/rFoI/6taCP+rWgj/q1oI/6taCP+rWgj/q1oI/7Nd - CP9mNQXpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAG9YQSW5WQDwu2AE/7tgBP+7YAT/u2AE/7tg - BP+7YAT/u2AE/7tfBP+6XwT/ul8E/7pfBP+6XwT/ul8F/7pfBf+6XwX/ul8F/7lfBf+5XwX/uV8F/7lf - Bf+5XwX/uV8F/7lfBf+4XwX/uF8E/7heBP+4XgT/uF0E/7heBP+4XgT/uF4F/7deBf+3XgX/t14F/7de - BP+3XQT/tl0E/7ZdBP+2XgT/tl4F/7ZeBf+2XgT/tl0E/7ZdBP+1XgX/tl4G/7VeBv+1XQb/tV0F/7Vc - Bf+1XAX/tFwF/7VdBv+0XQb/tF0G/7RcBf+0XAX/tFwF/7NcBf+0XAX/v2kT/5VgK/8GBgf/Ew8L/wcH - B/99VCn/wGwZ/7JbBP+yWwX/slsF/7JcBv+yXAf/slwH/7JcB/+xXAf/sVwH/7FbBv+xWwb/sVsG/7Bb - Bv+xXAf/sFwH/7BcB/+wXAf/sFwH/7BbB/+vWwb/r1oG/69aBv+vWgb/r1oG/69bBv+vWwf/r1sH/69b - B/+uWwf/rlsH/65bB/+uWwf/rlsI/65bCP+uWwj/rVsI/61aCP+tWgj/rVoI/61aCP+tWgj/rVoI/6xa - CP+sWgj/rFoI/6xaCP+sWgj/rFoI/6taCP+rWgj/s14I/2Y2BekAAADKAAAAyQAAAKwAAABnAAAAAAAA - AAAAAAAAb1hBJblZAPC8YAT/vGAE/7xgBP+8YAT/vGAE/7tgBP+7YAT/u2AE/7tgBP+7YAT/u2AE/7tf - BP+7XwT/ul8E/7pfBP+6XwT/ul8E/7pfBf+6XwX/ul8F/7lfBf+5XwX/uV8F/7lfBv+8Ygj/wWcN/8Rq - EP/EaxH/wmgP/7xjCv+4Xwb/uF8F/7heBf+4Xwb/u2IJ/8NpEP/DahL/w2kQ/7xjCv+3Xwb/t18G/79m - Df/DahH/wmoR/79mDf+2Xwf/tl4F/7ZfB/++Zg7/wmoS/8FqEv++Zg7/tV4I/7VdBv+1Xgj/vWUN/8Fp - Ev/BaRL/vWUN/7RdB//AaRP/lWAr/wcICP8WEg3/CQkJ/31TKf/Cbxv/u2QN/75oEf+7ZQ7/tV8I/7Jc - Bv+yXAb/slwG/7JcBv+yXQj/umQO/75oE/++aBT/umQP/7JdCf+xXAf/sVwH/7FcB/+xXAf/sl0J/7di - Df+7ZxL/vGgU/7tnEv+4Yw//s14L/7BcCP+vWwf/r1sH/69bB/+vWwf/r1sH/69bB/+vWwf/rlsH/65b - B/+uWwf/rlsI/65bCP+uWwj/rlsI/61bCP+tWgj/rVoI/61aCP+tWgj/rVoI/6xaCP+sWgj/rFoI/6xa - CP+0Xgj/ZzYF6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABvWEElulkA8L1gBP+8YAT/vGAE/7xg - BP+8YAT/vGAE/7xgBP+8YAT/vGAE/7tgBP+7YAT/u2AE/7tgBP+7YAT/u2AE/7tgBP+7XwT/ul8E/7pf - BP+6XwT/ul8E/7pfBf+6YQf/w2sV/8FzJv+qaSr/mmEp/5ZfKP+hZSn/uXEp/8hzHP+9ZAv/uV8F/7xi - Cf+zZhn/lFwj/5hhK/+UXCX/rWQb/7tjC/+8ZhD/nl4e/5ReKf+UXin/nl4f/7xmEf+3XwX/vGYR/51e - H/+UXin/lF4p/51eH/+7ZhL/tl8G/7tmEv+dXh//k14p/5NeKf+dXR//umUQ/8FpE/+VYCv/CAgI/xgT - Dv8LCgr/hlwz/82COP+jZSj/lV8o/6JmKf+9cyf/v2sW/7RfCP+zXQb/s10G/7hlEv+bXR//kV0p/5Je - Kv+YXCD/tWUV/7JdCP+yXAf/sl0J/7xoFf+/cib/qmos/5VgKv+RXir/lmAr/6NnLP+3cCn/u2oY/7Fe - Cv+wWwf/sFsH/7BbB/+vWwf/r1sH/69bB/+vWwf/r1sH/69bB/+vWwf/rlsH/65bB/+uWwf/rlsH/65b - CP+uWwj/rlsI/61bCP+tWgj/rVoI/61aCP+tWgj/rVoI/7VeCP9nNgXpAAAAygAAAMkAAACsAAAAZwAA - AAAAAAAAAAAAAG9YQSW6WQDwvWAE/71gBP+9YAT/vWAE/71gBP+9YAT/vGAE/7xgBP+8YAT/vGAE/7xg - BP+8YAT/vGAE/7xgBP+7YAT/u2AE/7tgBP+7YAT/u2AE/7tgBP+7XwT/u18E/8JoDv+RWCD/MSIV/xcS - Dv8HBwj/AwQG/w4MC/8mHBP/cEok/8J0Jv++ZAz/xGkP/5RbI/8AAAb/BQUH/wAABv97TyL/xG0U/8h0 - IP81JRP/AAAF/wAABf81JRT/x3Qg/7deBf/HdCD/NSUU/wAABf8AAAX/NSUU/8d0IP+2XgX/xnQg/zUl - FP8AAAX/AAAF/zUkFP/GcyD/wWoT/5VgK/8ICAn/GhUQ/xQRDf9oSiz/STUg/xIPDP8GBwj/Ew8M/zko - GP+YYiz/wnAe/7VfCf+zXQb/xHMh/zUkFP8AAAX/AAEF/yYbEv+2bST/tV8J/7NeCf/Abx//nGQs/0Mv - G/8cFhD/CAcI/wMEBv8IBwj/FxIO/yofFP9+TyD/umcU/7FcBv+wXAf/sFwH/7BcB/+wXAf/sFsH/7Bb - B/+wWwf/r1sH/69bB/+vWwf/r1sH/69bB/+vWwf/r1sH/65bB/+uWwf/rlsH/65bCP+uWwj/rlsI/65b - CP+tWwj/tV4I/2g2BekAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAb1hBJbtaAPC+YQT/vmEE/71h - BP+9YQT/vWAE/71gBP+9YAT/vWAE/71gBP+9YAT/vGAE/7xgBP+8YAT/vGAE/7xgBP+8YAT/vGAE/7xg - BP+7YAT/u2AE/7tgBP+7YAP/x20S/4dVJP8AAAT/AQIF/wQEBv8EBAb/BQUF/wgHBv8AAgb/XD0g/8Vx - H//HbRT/mGEq/wUFB/8NCgj/BAUG/4FVKf/Gbxj/yngm/z0qGP8EBAX/BAQF/zwqGP/Kdyb/uF4G/8p3 - Jv88Khj/BAQF/wQEBf88Khj/yHcm/7deBv/Idyb/PCoY/wQEBf8EBAX/PCoY/8d3Jf/CahP/lmAr/wgJ - Cf8cFhH/HRgS/xcSDf8AAQP/AQIF/wUEBf8LCQj/BQUG/w4NC/+NWyv/wm4Z/7RdB//Gdyf/PCkY/wQF - Bv8HBgb/LSEV/7hyK/+2YQr/wW8b/4dZKv8QDQz/AwQF/wUFBf8EBAX/BQUG/wQEBf8CAgT/AAAD/3VM - JP+/axf/sVsG/7FcB/+xXAf/sVwH/7FcB/+xXAf/sFwH/7BcB/+wXAf/sFsH/7BbB/+wWwf/r1sH/69b - B/+vWwf/r1sH/69bB/+vWwf/r1sH/65bB/+uWwf/rlsH/65bB/+2Xwj/aDcF6QAAAMoAAADJAAAArAAA - AGcAAAAAAAAAAAAAAABvWEElu1oA8L5hA/++YQP/vmED/75hBP++YQT/vmEE/75hBP+9YQT/vWAE/71g - BP+9YAT/vWAE/71gBP+9YAT/vWAE/7xgBP+8YAT/vGAE/7xgBP+8YAT/vGAE/7xgA//DZwz/rGgj/y0g - E/9WOh//gVYq/4hcMP9PNyD/Dw0K/w0LCf8SDw3/qGcm/85zGf+ZYCn/BQYH/xMPC/8GBgf/gVUp/8Zv - GP/KeCb/PCkY/wYHB/8HBwf/PCkY/8t4Jv+5Xwb/yngm/zwpGP8HBwf/BwcH/zwqGP/Kdyb/uF4G/8l3 - Jv88Khj/BwcH/wcHB/88Khj/yHcl/8NqEv+WYCr/CQkJ/xwXEf8dFxH/DgwK/zUmGP9uSyr/RzIe/w0L - Cf8SDwv/CAcH/yUbE/+1byr/umIM/8Z2J/88KRj/CAgH/wsJCP8uIRX/unIq/75oEv+qayr/GhUP/wkI - B/8PDAn/GxUO/1U7If9wTCn/bkso/2RFJf89Khf/nF4h/7plEP+yXAb/slwH/7JcB/+xXAf/sVwH/7Fc - B/+xXAf/sVwH/7FcB/+xXAf/sFwH/7BcB/+wXAf/sFwH/7BbB/+wWwf/sFsH/69bB/+vWwf/r1sH/69b - B/+vWwf/r1sH/7dfB/9oNwTpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAHBYQSW8WgDwv2ED/79h - A/+/YQP/vmED/75hA/++YQP/vmED/75hBP++YQT/vmEE/75hBP+9YQT/vWEE/71gBP+9YAT/vWAE/71g - BP+9YAT/vWAE/7xgBP+8YAT/vGAE/71hBv+8ZhD/uGse/814JP/Ufib/45FA/5RnOv8ODQv/FBAM/wQE - B/+XXSX/0ncd/5lgKf8HCAj/FhEN/wgICf+BVCj/x28Y/8t4Jv89Khf/CQkI/wkJCP89Khj/y3gm/7lf - Bv/LeCb/PSoY/wkJCP8JCQj/PCoY/8p4Jv+4Xwb/yXgm/zwqGP8JCQj/CQkI/zwqGP/IdyX/w2oS/5Zg - Kv8ICQn/GhUQ/xIQDf8/Lhv/xH44/8t4Jf/MgDL/aEgn/wsKCf8VEQ3/BQUH/4RWKf/CbRj/xnYn/zwq - GP8LCgn/DgwK/y4hFv+6cir/xnIf/2xHJP8DBQb/ExAN/ygeFP+xfUj/25RM/9WLQP/UiT//1YxB/9KJ - P//HeSv/uGUS/7NdB/+yXAb/slwG/7JcBv+yXAf/slwH/7JcB/+yXAf/sVwH/7FcB/+xXAf/sVwH/7Fc - B/+xXAf/sVwH/7BcB/+wXAf/sFwH/7BbB/+wWwf/sFsH/69bB/+vWwf/t18H/2k3BOkAAADKAAAAyQAA - AKwAAABnAAAAAAAAAAAAAAAAcFhBJbxaAPC/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/vmED/75h - A/++YQP/vmED/75hA/++YQT/vmEE/75hBP++YQT/vWEE/71gBP+9YAT/vWAE/71gBP+9YAT/vWAE/75i - Bv/HbBL/yHcl/59lK/9dPyL/HhcP/xQQDf8NCwn/FBAN/6tpJv/Ocxn/mWEp/wcICP8WEQ3/CAgJ/4JU - KP/Ibxf/y3gl/z0qF/8JCQj/CQkI/z0qGP/MeCb/ul8G/8t4Jv89Khj/CQkI/wkJCP89Khj/y3gm/7lf - Bv/KeCb/PSoY/wkJCP8JCQj/PCoY/8l3Jf/EahL/l2Aq/wgICf8YFA//CwsL/39WLf/JdB7/tl0E/8Bo - EP+0czL/IBkS/xIPDP8ICAj/Vjof/8VzIP/Idyf/PCoY/wsKCf8ODAr/LiEV/7pyKv/Jdyb/RC4Z/woJ - Cf8ZFA//Jh0U/0YyHv88Khn/PCkX/zspF/87KRf/OykX/zwpFv+jYSD/umQN/7NcBf+zXQb/s10G/7Nc - Bv+yXAb/slwG/7JcBv+yXAb/slwH/7JcB/+yXAf/sVwH/7FcB/+xXAf/sVwH/7FcB/+xXAf/sVwH/7Bc - B/+wXAf/sFwH/7BcB/+4Xwf/ajcE6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABwWEElvVoA8MBh - A//AYQP/wGED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/75hA/++YQP/vmED/75h - A/++YQT/vmEE/75hBP++YQT/vWEE/71hBP+9YAX/xWoQ/7VvKf9LMxz/CwoK/wUFBv8NCwn/CAgI/wIE - B/9qRiP/yHId/8htE/+aYSr/BwgI/xYRDf8ICAn/glUo/8hwF//MeSX/PSoX/wkJCP8JCQn/PSoY/8x4 - Jv+6XwX/zHgm/z0qGP8KCgn/CgoJ/z0qGP/LeCb/uV8G/8t4Jv89Khj/CgkJ/woJCP89Khj/yngl/8Rr - Ev+XYCr/CAgJ/xcSDv8JCgn/gVUq/8VuF/+3XQL/umEI/751Lf8wJBf/Dw0L/woJCf88KRb/yHYl/8h3 - J/88Khf/CwoJ/w4MCv8uIhX/u3Mq/8p5KP86Jxb/CwoJ/x0XEf8VEQ3/AAAD/wAAAv8AAAL/AAAC/wYF - Bv8FBQX/AAAF/5JcJ//AaRH/tFwF/7RdBv+zXQb/s10G/7NdBv+zXQb/s10G/7NcBv+zXAb/slwG/7Jc - Bv+yXAb/slwH/7JcB/+yXAf/slwH/7FcB/+xXAf/sVwH/7FcB/+xXAf/sVwH/7lgB/9qNwTpAAAAygAA - AMkAAACsAAAAZwAAAAAAAAAAAAAAAHBYQSW9WwDwwGID/8BiA//AYgP/wGID/8BhA//AYQP/wGED/8Bh - A/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/75hA/++YQP/vmED/75hA/++YQP/vmED/8Fk - B//EdSX/PCoY/wACBP8QDgr/CwkI/woJCf8yIxb/hVUn/8h0Iv/AZAj/yGwR/5piKv8HCAj/FhEN/wgI - Cf+CVSj/yXAX/815Jf89Khf/CgoJ/wwLCv9ALRr/znsp/7tgBf/Neyj/Pysa/w0LCv8NCwr/QC0a/856 - KP+6YAb/zHoo/z0rGf8LCgn/CgkI/zwpF//KeCT/xWsS/5hgKv8ICAn/GBMO/wsKCv+DVyz/x3AZ/7hd - Av+9Ywr/u3Qv/ysgFf8RDgz/CgkJ/z4qF//IdiT/yHgn/zwqF/8LCgn/DgwK/y4iFf+7cyr/yXck/1I4 - Hv8JCQn/FxMO/yMbEv9BLxz/PCkX/z4rGf83KBj/FREN/xANCv8KCQn/mWIq/79oEf+0XAX/tF0G/7Rd - Bv+0XQb/tF0G/7RdBv+zXQb/s10G/7NdBv+zXQb/s10G/7NdBv+zXAb/slwG/7JcBv+yXAb/slwG/7Jc - B/+yXAf/slwH/7FcB/+xXAf/uWAH/2o3BOkAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAcFhBJb5b - APDBYgP/wWID/8FiA//BYgP/wGID/8BiA//AYgP/wGID/8BhA//AYQP/wGED/8BhA/+/YQP/v2ED/79h - A/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/++YAL/yGsN/59iJf8HBwj/Eg4L/xIPDP9DMB3/n2ky/8h7 - Lf/VeiD/wmcM/7xfA//JbBH/m2Iq/wcICP8WEQ3/CAgJ/4JVKP/JcBf/zXkl/z0qF/8LCwr/Eg8M/ywg - Ff/EfTb/0Xgf/8R9Nf8tIRb/FBEO/xMQDf8sIRb/xX02/9F4H//CezX/KyAV/xEPDP8JCQj/RC4Z/8p1 - Iv/GaxL/mGAq/wgJCf8ZFA//DgwL/15CJf/RgTD/w2sT/9B5Iv+WYzH/EQ8M/xYSDv8HBwj/Wj0g/8dy - H//Jdyb/PCoY/wsKCf8NDAr/LyIW/7xyKf/HcRv/e1An/wUFB/8ODAr/NSca/9GOSf/MfS3/1YY3/614 - Qv8SDwz/DQsJ/xoUEP+raiv/vGQN/7VcBf+1XQb/tV0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7Rd - Bv+0XQb/s10G/7NdBv+zXQb/s10G/7NdBv+zXAb/s1wG/7JcBv+yXAb/slwG/7JcB/+6YAf/azcE6QAA - AMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABwWEElvlsA8MFiA//BYgP/wWID/8FiA//BYgP/wWID/8Fi - A//BYgP/wGID/8BiA//AYgP/wGID/8BiA//AYQP/wGED/8BhA//AYQP/v2ED/79hA/+/YQP/v2ED/79g - Av/Jaw3/oGMm/wkICf8SDgv/DAwK/5BlOP/klUT/x3sv/6BhIv+2Zxj/wWUI/8ptEf+bYir/BgcI/xUR - Df8HBwj/g1Uo/8pwF//OeSX/PSoX/wsKCf8YEw//DAoJ/1c8Iv+lbzn/X0Il/xIPDP8cFxH/GBQP/woJ - CP9YPSL/pG85/19CJf8RDgz/FxMO/wYHCP9iQSL/yXIb/8ZrEf+ZYSr/BwgI/xkUD/8VEg7/EA4L/3FO - Kv+ucTX/lGIy/ysgFf8RDgv/FRAM/wcHCP+NWij/xG0V/8l4Jv88Khj/CwoJ/w0MCv8vIhb/vHIp/8Fo - EP+xbSr/HBUQ/wgHB/8KCQj/flUt/9GENP/Mgjj/Wj8j/wgHB/8FBgb/OykZ/8J0Jv+3YAj/tl4F/7Ve - Bv+1XQb/tV0G/7VdBv+1XQb/tV0G/7VdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/s10G/7Nd - Bv+zXQb/s10G/7NdBv+zXQb/s1wG/7tgBv9rNwTpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAHBY - QCW/WwDwwmID/8JiA//CYgP/wmID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8Bi - A//AYgP/wGID/8BiA//AYQP/wGED/8BhA//AYQP/v2EC/8JkB//CciX/MiQV/wIDBf8ODAn/HRUO/z0r - Gf8wIhX/CQkL/4VUIv/KbhL/ym0Q/5tjKv8FBQf/DwwK/wUFB/+DVij/ynEX/896Jv89Khf/BgcH/xQQ - DP8RDgr/AQIE/wQFBv8KCQj/FxIO/xYSDv8XEg7/FRAM/wACBP8EBAb/CgkI/xURDf8QDQr/CAgJ/5li - Kf/FaxD/x2wR/5piK/8FBgf/Ew8M/xgTDf8KCAf/AQME/xIODP8JCAf/DQsJ/xQQDP8DBAX/Piwa/8N1 - J/+8Ywr/yngm/z0qGP8LCgn/DQsK/y8iFv+8dCr/u2IJ/8hyHP93Tyb/AgQH/wYFBv8RDAr/SjUg/z0r - G/8MCQj/CAcG/wgICf+QXSr/w20W/7ZeBf+2XgX/tl4F/7ZeBv+2Xgb/tl4G/7VeBv+1XQb/tV0G/7Vd - Bv+1XQb/tV0G/7VdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7RdBv+0XQb/tF0G/7NdBv+zXQb/u2EG/2s4 - BOkAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAcVhAJb9bAPDCYgL/wmIC/8JiAv/CYgL/wmID/8Ji - A//CYgP/wmID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8BiA//AYgP/wGID/8Bi - A//AYgP/wGED/8puE/+qaSr/KR4T/wIEBv8AAgX/AAAD/wAABP8AAAX/WTkb/8xxFf/KbQ//mWAn/wAA - Bf8EBAX/AAAF/39TJf/McRb/znkk/zUlFv8AAAP/AAIF/3dUMf8vIhf/AAEF/wYGBv8GBgf/AgMH/2VF - J/+hbTr/GxQO/wEDBf8GBgb/BQYH/wIEB/9aPSD/yXYi/71iBf/IbBH/lV8o/wAABf8AAAT/KR4U/3NR - L/8QDQv/AAIF/wQEBv8FBgf/AQMG/zEjFv+xbiz/w2kS/7pfBv/LeCf/PSoY/wsKCf8NCwr/LyIW/750 - Kv+8Ygj/u2IJ/8V1JP9wSiX/EA4M/wACBf8AAAP/AAAD/wIDBf8LCgr/dE0m/8VzIf+5YQj/t14F/7de - Bf+3XgX/tl4F/7ZeBf+2XgX/tl4F/7ZeBv+2Xgb/tl4G/7ZeBv+1Xgb/tV0G/7VdBv+1XQb/tV0G/7Vd - Bv+1XQb/tF0G/7RdBv+0XQb/tF0G/7RdBv+8YQb/bDgE6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAA - AABxWUAlwFwA8MNjAv/DYwL/w2IC/8NiAv/CYgL/wmIC/8JiAv/CYgL/wmID/8JiA//CYgP/wmID/8Ji - A//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//AYgP/wGIF/8twFP+8cif/f1Im/1Q5 - Hf8/Kxb/Vjke/3RLI/+oYx//xGgM/8hoCv+kYB3/NiQT/0AsGP83JRT/klgd/8lsD//BbBf/VzgY/zgm - Ff81JBL/sHAw/713MP9rRiL/PSoW/0QtGP9/UiX/xXYm/894If+uayn/ZkMh/z0pFv9DLRj/hFUn/8V0 - JP/BZQv/vGAD/8VpDf+UWR3/NiQU/zcmFf9XORr/zoI1/6NoK/9iQSH/PioX/0QuGf92TSX/uXAo/8Vs - E/+6XwX/ul8E/8x4Jv89Khj/CwoJ/w0LCv8vIhb/vnQq/7xiCP+5XgT/vWQL/8dzH/+maSv/aUck/0Yv - Gv9DLRn/Y0Ii/51kKv/FciD/u2IK/7deBf+4XgX/t14F/7deBf+3XgX/t14F/7deBf+3XgX/t14F/7Ze - Bf+2XgX/tl4F/7ZeBf+2Xgb/tl4G/7ZeBv+1Xgb/tV4G/7VdBv+1XQb/tV0G/7VdBv+1XQb/tF0G/7xh - Bv9sOATpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAHFZQCXAXADww2MC/8NjAv/DYwL/w2MC/8Nj - Av/DYwL/w2MC/8NiAv/CYgL/wmIC/8JiAv/CYgL/wmIC/8JiA//CYgP/wmID/8JiA//BYgP/wWID/8Fi - A//BYgP/wWID/8FiA//BYgP/wGID/8ZoCv/Ochb/0Hce/9B5Iv/Qdx//znIX/8dqDP/AYgT/v2IF/8dt - FP/biDT/1YxC/9yLOv/Mcxv/v2MH/8FkCf/Lchj/0Hkj/892H//DaRD/xWoN/8xzGf/OeCH/zncg/8tw - Fv/BZQn/vmEF/8VpDv/Mcxv/zXgj/812IP/Kbxb/wGQJ/71gBP+9YAT/vWEG/8JpEf/MdiD/zXkk/8ly - Gv+/Zgz/xWsQ/8pzHP/MdyP/y3ch/8lxGP/AZgv/u2AF/7tgA/+7YAT/zHgm/z0qGP8LCgn/DQsK/y8i - Fv++dCr/vWII/7pfBP+6XwX/umAH/8JpEP/HcRv/yXUi/8l2I//Hchz/w2oR/7phCP+4XwX/uF8F/7hf - Bf+4XgX/uF4F/7heBf+4XgX/t14F/7deBf+3XgX/t14F/7deBf+3XgX/t14F/7ZeBf+2XgX/tl4F/7Ze - Bf+2Xgb/tl4G/7ZeBv+2Xgb/tV4G/7VdBv+1XQb/vWEG/2w4BOkAAADKAAAAyQAAAKwAAABnAAAAAAAA - AAAAAAAAcVlAJcFcAPDEYwL/xGMC/8RjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8Ni - Av/DYgL/wmIC/8JiAv/CYgL/wmIC/8JiA//CYgP/wmID/8JiA//CYgP/wWID/8FiA//BYgP/wWIC/8Fi - Av/BYgP/wWID/8FiA//BYgL/wGIC/8BiA//BYwb/yHIc/3FJIf8qHRH/TTMa/7VrI//FaQz/v2ED/79h - A/+/YQP/v2ED/79hA/+/YQL/v2ED/79hA/++YQP/vmED/75hA/++YQP/vmED/75hA/++YQT/vmEE/75g - BP+9YQT/vWAE/71gBP+9YAT/vWAE/71gBP+9YAT/vWAE/7xgBP+8YAP/vGAE/7xgBP+8YAT/vGAE/7xg - A/+8YAT/u2AE/7tgBP/MeSb/PSoY/wsKCf8NCwr/LyIW/790Kf+9Ygf/ul8D/7pfBP+6XwT/ul8E/7pf - BP+6XwX/uV8F/7lfBf+5XwT/uV8F/7lfBf+5XwX/uV8F/7lfBf+4XwX/uF8F/7hfBf+4XwX/uF4F/7he - Bf+4XgX/uF4F/7deBf+3XgX/t14F/7deBf+3XgX/t14F/7deBf+2XgX/tl4F/7ZeBf+2XgX/tl4G/7Ze - Bv+/Ygb/bTkE6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAABxWUAlwVwA8MRjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYgL/wmIC/8Ji - Av/CYgL/wmIC/8JiAv/CYgP/wmID/8JiA//CYgP/wmID/8FiA//BYgP/wWID/8FiA//BYgP/wWEC/8pr - C/+jYyP/BgcJ/wQEBv8AAAT/YkAe/85yF//AYAL/wGED/8BhA//AYQP/v2ED/79hA/+/YQP/v2ED/79h - A/+/YQP/v2ED/79hA/+/YQP/vmED/75hA/++YQP/vmED/75hBP++YQT/vmEE/75hBP+9YQT/vWAE/71g - BP+9YAT/vWAE/71gBP+9YAT/vWAE/7xgBP+8YAT/vGAE/7xgBP+8YAT/vGAE/856Jv89Khf/CAgH/wsJ - CP8vIhX/wHUp/75jB/+7YAP/u2AE/7tfBP+6XwT/ul8E/7pfBP+6XwT/ul8F/7pfBf+6XwX/ul8F/7lf - Bf+5XwX/uV8F/7lfBf+5XwX/uV8F/7lfBf+4XwX/uF8F/7hfBf+4XwX/uF4F/7heBf+4XgX/uF4F/7de - Bf+3XgX/t14F/7deBf+3XgX/t14F/7deBf+2XgX/tl4F/79iBf9tOQPpAAAAygAAAMkAAACsAAAAZwAA - AAAAAAAAAAAAAHFZQCXCXADwxWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Rj - Av/EYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYgL/w2IC/8JiAv/CYgL/wmIC/8Ji - Av/CYgP/wmID/8JiA//CYgP/wmID/8FiA//BYQL/yWoL/6hmI/8LCgv/AQMF/wAABf9rRSD/znIW/8Bi - Av/AYgP/wGID/8BiA//AYQP/wGED/8BhA//AYQP/wGED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/79h - A/+/YQP/vmED/75hA/++YQP/vmED/75hBP++YQT/vmEE/75hBP++YQT/vWEE/71gBP+9YAT/vWAE/71g - BP+9YAT/vWAE/71gBP+8YAT/znom/z0qF/8EBAb/BgYG/y8hFf/BdSn/v2MH/7tgA/+7YAT/u2AE/7tg - BP+7YAT/u2AE/7tfBP+7XwT/ul8E/7pfBP+6XwT/ul8E/7pfBf+6XwX/ul8F/7lfBf+5XwX/uV8F/7lf - Bf+5XwX/uV8F/7lfBf+5XwX/uF8F/7hfBf+4XwX/uF8F/7heBf+4XgX/uF4F/7heBf+3XgX/t14F/7de - Bf+3XgX/wGIF/245A+kAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAcVlAJcJcAPDFYwL/xWMC/8Vj - Av/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Nj - Av/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2IC/8JiAv/CYgL/wmIC/8JiAv/CYgL/wmID/8Ji - A//CZAX/yXAZ/4tXJP8/Khb/YD4e/7xvIv/FaAv/wWID/8FiA//BYgP/wWID/8FiA//AYgP/wGID/8Bi - A//AYgP/wGED/8BhA//AYQP/wGED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/75h - A/++YQP/vmED/75hA/++YQT/vmEE/75hBP++YQT/vWEE/71hBP+9YAT/vWAE/71gBP/NdR//NiQT/wAA - Bf8AAQX/JxwS/75wIv+/Ygf/vGAD/7xgBP+8YAT/vGAE/7tgBP+7YAT/u2AE/7tgBP+7YAT/u2AE/7tg - BP+7XwT/ul8E/7pfBP+6XwT/ul8E/7pfBf+6XwX/ul8F/7pfBf+5XwX/uV8F/7lfBf+5XwX/uV8F/7lf - Bf+5XwX/uF8F/7hfBf+4XwX/uF8F/7heBf+4XgX/uF4F/7heBf/AYgX/bjkD6QAAAMoAAADJAAAArAAA - AGcAAAAAAAAAAAAAAABxWUAlw10A8MZkAv/GZAL/xWQC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8Vj - Av/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8NjAv/DYwL/w2MC/8Nj - Av/DYwL/w2MC/8NjAv/DYwL/w2IC/8NiAv/CYgL/wmIC/8JiAv/DZAb/zXAT/9F3Hf/QdBn/xmgL/8Ji - BP/BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//AYgP/wGID/8BiA//AYgP/wGED/8Bh - A//AYQP/wGED/8BhA/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/75hA/++YQP/vmED/75h - A/++YQT/vmEE/75hBP++YQT/vmEE/8JpEP+jYB7/mGAo/5lgKf+fXx//v2gS/75hBf+9YAT/vGAE/7xg - BP+8YAT/vGAE/7xgBP+8YAT/vGAE/7xgBP+7YAT/u2AE/7tgBP+7YAT/u2AE/7tgBP+7XwT/u18E/7pf - BP+6XwT/ul8E/7pfBP+6XwX/ul8F/7pfBf+5XwX/uV8F/7lfBf+5XwX/uV8F/7lfBf+5XwX/uV8F/7hf - Bf+4XwX/uF8F/8FjBf9uOQPpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAHFZQCXDXQDwxmQB/8Zk - Av/GZAL/xmQC/8ZkAv/GZAL/xWQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8Nj - Av/DYwL/w2MC/8NiAv/CYgL/wmIC/8JiAv/CYgL/wmIC/8JiA//CYgP/wmID/8JiA//CYgP/wWID/8Fi - A//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wGID/8BiA//AYgP/wGID/8BhA//AYQP/wGED/8Bh - A/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/++YQP/vmED/75hA/++YQP/vmIF/8dp - C//JbRD/yW0R/8ZpDP++Ygb/vWAE/71gBP+9YAT/vWAE/71gBP+9YAT/vGAE/7xgBP+8YAT/vGAE/7xg - BP+8YAT/vGAE/7xgBP+7YAT/u2AE/7tgBP+7YAT/u2AE/7tgBP+7YAT/u18E/7pfBP+6XwT/ul8E/7pf - BP+6XwX/ul8F/7pfBf+6XwX/uV8F/7lfBf+5XwX/uV8F/7lfBf+5XwX/wmMF/285A+kAAADKAAAAyQAA - AKwAAABnAAAAAAAAAAAAAAAAcllAJcRdAPDGZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAL/xmQC/8Zk - Av/GZAL/xmQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8Ni - Av/DYgL/wmIC/8JiAv/CYgL/wmIC/8JiAv/CYgP/wmID/8JiA//CYgP/wWID/8FiA//BYgP/wWID/8Fi - A//BYgP/wWID/8FiA//BYgP/wGID/8BiA//AYgP/wGID/8BhA//AYQP/wGED/8BhA//AYQP/v2ED/79h - A/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/++YQP/vmAC/75gAv++YAL/vmAC/75hA/++YQT/vmEE/75h - BP+9YQT/vWAE/71gBP+9YAT/vWAE/71gBP+9YAT/vWAE/7xgBP+8YAT/vGAE/7xgBP+8YAT/vGAE/7xg - BP+8YAT/u2AE/7tgBP+7YAT/u2AE/7tgBP+7YAT/u18E/7tfBP+6XwT/ul8E/7pfBP+6XwT/ul8F/7pf - Bf+6XwX/uV8F/7lfBf/CYwX/bzkD6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAAByWUAlxF0A8Mdk - Af/HZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAL/xmQC/8ZkAv/GZAL/xmQC/8Vk - Av/FZAL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYgL/w2IC/8Ji - Av/CYgL/wmIC/8JiAv/CYgP/wmID/8JiA//CYgP/wmID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8Fi - A//BYgP/wWID/8BiA//AYgP/wGID/8BiA//AYQP/wGED/8BhA//AYQP/v2ED/79hA/+/YQP/v2ED/79h - A/+/YQP/v2ED/79hA/+/YQP/vmED/75hA/++YQP/vmED/75hBP++YQT/vmEE/75hBP+9YQT/vWEE/71g - BP+9YAT/vWAE/71gBP+9YAT/vWAE/7xgBP+8YAT/vGAE/7xgBP+8YAT/vGAE/7xgBP+8YAT/u2AE/7tg - BP+7YAT/u2AE/7tgBP+7YAT/u2AE/7tfBP+6XwT/ul8E/7pfBP+6XwT/ul8F/8NjBf9wOQPpAAAAygAA - AMkAAACsAAAAZwAAAAAAAAAAAAAAAHJZQCXEXQDwx2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAH/xmQC/8ZkAv/GZAL/xmQC/8ZkAv/FZAL/xWMC/8Vj - Av/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2IC/8JiAv/CYgL/wmIC/8Ji - Av/CYgL/wmID/8JiA//CYgP/wmID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8Bi - A//AYgP/wGID/8BiA//AYQP/wGED/8BhA//AYQP/wGED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/79h - A/+/YQP/vmED/75hA/++YQP/vmED/75hA/++YQT/vmEE/75hBP++YQT/vWEE/71gBP+9YAT/vWAE/71g - BP+9YAT/vWAE/71gBP+8YAT/vGAE/7xgBP+8YAT/vGAE/7xgBP+8YAT/vGAE/7tgBP+7YAT/u2AE/7tg - BP+7YAT/u2AE/7tfBP+7XwT/w2ME/3A5A+kAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAcllAJcVd - APDIZAH/yGQB/8hkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8Zk - Af/GZAH/xmQB/8ZkAf/GZAH/xmQC/8ZkAv/GZAL/xmQC/8ZkAv/FZAL/xWQC/8VjAv/FYwL/xWMC/8Vj - Av/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Nj - Av/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2IC/8NiAv/CYgL/wmIC/8JiAv/CYgL/wmID/8Ji - A//CYgP/wmID/8JiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//AYgP/wGID/8Bi - A//AYgP/wGED/8BhA//AYQP/wGED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/75h - A/++YQP/vmED/75hA/++YQT/vmEE/75hBP++YQT/vWEE/71hBP+9YAT/vWAE/71gBP+9YAT/vWAE/71g - BP+8YAT/vGAE/7xgBP+8YAT/vGAE/7xgBP+8YAT/vGAE/7tgBP+7YAT/u2AE/7tgBP/EZQT/cDoD6QAA - AMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAAByWUAlxV4A8MhlAf/IZAH/yGQB/8hkAf/IZAH/yGQB/8hk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8ZkAf/GZAH/xmQB/8Zk - Af/GZAH/xmQB/8ZkAv/GZAL/xmQC/8ZkAv/GZAL/xWQC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8Vj - Av/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8Nj - Av/DYwL/w2MC/8NjAv/DYwL/w2MC/8NiAv/CYgL/wmIC/8JiAv/CYgL/wmIC/8JiA//CYgP/wmID/8Ji - A//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//AYgP/wGID/8BiA//AYgP/wGID/8Bh - A//AYQP/wGED/8BhA/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/75hA/++YQP/vmED/75h - A/++YQP/vmEE/75hBP++YQT/vmEE/71hBP+9YAT/vWAE/71gBP+9YAT/vWAE/71gBP+9YAT/vGAE/7xg - BP+8YAT/vGAE/7xgBP+8YAT/vGAE/8VlBP9wOgPpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAHJZ - QCXGXgDwyGUB/8hlAf/IZQH/yGUB/8hlAf/IZQH/yGQB/8hkAf/IZAH/yGQB/8hkAf/IZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAf/GZAH/xmQB/8Zk - Av/GZAL/xmQC/8ZkAv/GZAL/xWQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8Nj - Av/DYwL/w2MC/8NiAv/DYgL/wmIC/8JiAv/CYgL/wmIC/8JiA//CYgP/wmID/8JiA//CYgP/wWID/8Fi - A//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wGID/8BiA//AYgP/wGID/8BhA//AYQP/wGED/8Bh - A/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/++YQP/vmED/75hA/++YQP/vmEE/75h - BP++YQT/vmEE/71hBP+9YQT/vWAE/71gBP+9YAT/vWAE/71gBP+9YAT/vGAE/7xgBP+8YAT/xWUE/3E6 - A+kAAADKAAAAyQAAAKwAAABnAAAAAAAAAAAAAAAAcllAJcZeAPDJZQH/yWUB/8llAf/JZQH/yWUB/8hl - Af/IZQH/yGUB/8hlAf/IZQH/yGUB/8hkAf/IZAH/yGQB/8hkAf/IZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAL/xmQC/8Zk - Av/GZAL/xmQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8Nj - Av/DYgL/wmIC/8JiAv/CYgL/wmIC/8JiAv/CYgP/wmID/8JiA//CYgP/wWID/8FiA//BYgP/wWID/8Fi - A//BYgP/wWID/8FiA//BYgP/wGID/8BiA//AYgP/wGID/8BiA//AYQP/wGED/8BhA//AYQP/v2ED/79h - A/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/vmED/75hA/++YQP/vmED/75hBP++YQT/vmEE/75h - BP+9YQT/vWAE/71gBP+9YAT/vWAE/71gBP/GZQT/cToD6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAA - AAByWUAlxl4A8MllAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hlAf/IZQH/yGUB/8hl - Af/IZQH/yGUB/8hkAf/IZAH/yGQB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAL/xmQC/8ZkAv/GZAL/xmQC/8Vk - Av/FZAL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYgL/w2IC/8Ji - Av/CYgL/wmIC/8JiAv/CYgP/wmID/8JiA//CYgP/wmID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8Fi - A//BYgP/wWID/8BiA//AYgP/wGID/8BiA//AYQP/wGED/8BhA//AYQP/v2ED/79hA/+/YQP/v2ED/79h - A/+/YQP/v2ED/79hA/+/YQP/vmED/75hA/++YQP/vmED/75hBP++YQT/vmEE/75hBP+9YQT/vWEE/8Zl - BP9xOgPpAAAAygAAAMkAAACsAAAAZwAAAAAAAAAAAAAAAHJZQCXIXgDwymUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/IZQH/yGUB/8hlAf/IZQH/yGUB/8hl - Af/IZAH/yGQB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAH/xmQC/8ZkAv/GZAL/xmQC/8ZkAv/FZAL/xWQC/8Vj - Av/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2IC/8JiAv/CYgL/wmIC/8Ji - Av/CYgL/wmID/8JiA//CYgP/wmID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8Bi - A//AYgP/wGID/8BiA//AYgP/wGED/8BhA//AYQP/wGED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/79h - A/+/YQP/v2ED/75hA/++YQP/vmED/75hA/++YQT/x2YE/3I6A+kAAADKAAAAyQAAAKwAAABnAAAAAAAA - AAAAAAAAcllAJcheAPDKZQH/ymUB/8plAf/KZQH/ymUB/8plAf/JZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/IZQH/yGUB/8hlAf/IZQH/yGUB/8hlAf/IZAH/yGQB/8hk - Af/IZAH/yGQB/8hkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8Zk - Af/GZAH/xmQB/8ZkAf/GZAH/xmQC/8ZkAv/GZAL/xmQC/8ZkAv/FZAL/xWQC/8VjAv/FYwL/xWMC/8Vj - Av/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Nj - Av/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2IC/8NiAv/CYgL/wmIC/8JiAv/CYgL/wmID/8Ji - A//CYgP/wmID/8JiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//AYgP/wGID/8Bi - A//AYgP/wGED/8BhA//AYQP/wGED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/79hA/+/YQP/v2ED/75h - A//HZgP/cjoC6QAAAMoAAADJAAAArAAAAGcAAAAAAAAAAAAAAAByWUAlyF4A8MplAP/KZQD/ymUA/8pl - AP/KZQH/ymUB/8plAf/KZQH/ymUB/8plAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yGUB/8hlAf/IZQH/yGUB/8hlAf/IZQH/yGQB/8hkAf/IZAH/yGQB/8hk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8ZkAf/GZAH/xmQB/8Zk - Af/GZAH/xmQB/8ZkAv/GZAL/xmQC/8ZkAv/GZAL/xWQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8Vj - Av/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8Nj - Av/DYwL/w2MC/8NjAv/DYwL/w2MC/8NiAv/CYgL/wmIC/8JiAv/CYgL/wmIC/8JiA//CYgP/wmID/8Ji - A//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8FiA//AYgP/wGID/8BiA//AYgP/wGID/8Bh - A//AYQP/wGED/8BhA/+/YQP/v2ED/79hA/+/YQP/v2ED/8hmA/9yOgLpAAAAygAAAMkAAACsAAAAZwAA - AAAAAAAAAAAAAHNZQCXJXwDwy2UA/8tlAP/KZQD/ymUA/8plAP/KZQD/ymUA/8plAP/KZQD/ymUB/8pl - Af/KZQH/ymUB/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yGUB/8hlAf/IZQH/yGUB/8hlAf/IZQH/yGQB/8hkAf/IZAH/yGQB/8hkAf/IZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAf/GZAH/xmQB/8Zk - Av/GZAL/xmQC/8ZkAv/GZAL/xWQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8Nj - Av/DYwL/w2MC/8NiAv/DYgL/wmIC/8JiAv/CYgL/wmIC/8JiA//CYgP/wmID/8JiA//CYgP/wWID/8Fi - A//BYgP/wWID/8FiA//BYgP/wWID/8FiA//BYgP/wGID/8BiA//AYgP/wGID/8BhA//AYQP/wGED/8Bh - A//AYQP/yGYD/3I6AukAAADKAAAAyQAAAKsAAABnAAAAAAAAAAAAAAAAc1lAJclfAPDLZgD/y2YA/8tm - AP/LZgD/y2UA/8tlAP/KZQD/ymUA/8plAP/KZQD/ymUA/8plAP/KZQD/ymUB/8plAf/KZQH/ymUB/8pl - Af/KZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hl - Af/IZQH/yGUB/8hlAf/IZQH/yGUB/8hkAf/IZAH/yGQB/8hkAf/IZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAL/xmQC/8Zk - Av/GZAL/xmQC/8VkAv/FZAL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8Nj - Av/DYgL/wmIC/8JiAv/CYgL/wmIC/8JiAv/CYgP/wmID/8JiA//CYgP/wmID/8FiA//BYgP/wWID/8Fi - A//BYgP/wWID/8FiA//BYgP/wGID/8BiA//AYgP/wGID/8BiA//JZgP/czoC6QAAAMoAAADJAAAAqwAA - AGYAAAAAAAAAAAAAAABzWUAlyV8A8MtmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tl - AP/LZQD/ymUA/8plAP/KZQD/ymUA/8plAP/KZQD/ymUA/8plAf/KZQH/ymUB/8plAf/KZQH/ymUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hlAf/IZQH/yGUB/8hl - Af/IZQH/yGUB/8hkAf/IZAH/yGQB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAL/xmQC/8ZkAv/GZAL/xmQC/8Zk - Av/FZAL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYgL/w2IC/8Ji - Av/CYgL/wmIC/8JiAv/CYgP/wmID/8JiA//CYgP/wmID/8FiA//BYgP/wWID/8FiA//BYgP/wWID/8Fi - A//BYgP/wWID/8lnA/9zOwLpAAAAygAAAMcAAACmAAAAYAAAAAAAAAAAAAAAAHNZQCXKXwDwzGYA/8tm - AP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tlAP/LZQD/ymUA/8pl - AP/KZQD/ymUA/8plAP/KZQD/ymUA/8plAf/KZQH/ymUB/8plAf/KZQH/ymUB/8plAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/IZQH/yGUB/8hlAf/IZQH/yGUB/8hl - Af/IZAH/yGQB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAH/xmQC/8ZkAv/GZAL/xmQC/8ZkAv/FZAL/xWQC/8Vj - Av/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2IC/8JiAv/CYgL/wmIC/8Ji - Av/CYgL/wmID/8JiA//CYgP/wmID/8JiA//BYgP/wWID/8FiA//BYgP/ymcD/3Q7AukAAADKAAAAxAAA - AJ0AAABUAAAAAAAAAAAAAAAAc1lAJcpfAPDMZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/LZgD/y2YA/8tm - AP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZQD/y2UA/8plAP/KZQD/ymUA/8pl - AP/KZQD/ymUA/8plAP/KZQH/ymUB/8plAf/KZQH/ymUB/8plAf/JZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/IZQH/yGUB/8hlAf/IZQH/yGUB/8hlAf/IZAH/yGQB/8hk - Af/IZAH/yGQB/8hkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8Zk - Af/GZAH/xmQB/8ZkAf/GZAH/xmQC/8ZkAv/GZAL/xmQC/8ZkAv/GZAL/xWQC/8VjAv/FYwL/xWMC/8Vj - Av/FYwL/xWMC/8VjAv/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8Nj - Av/DYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/DYwL/w2IC/8NiAv/CYgL/wmIC/8JiAv/CYgL/wmIC/8Ji - A//CYgP/wmID/8JiA//KZwP/dTsC6gAAAMkAAAC9AAAAjQAAAEMAAAAAAAAAAAAAAABzWUAiyl8A7cxm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tm - AP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZQD/y2UA/8plAP/KZQD/ymUA/8plAP/KZQD/ymUA/8pl - AP/KZQH/ymUB/8plAf/KZQH/ymUB/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yGUB/8hlAf/IZQH/yGUB/8hlAf/IZQH/yGQB/8hkAf/IZAH/yGQB/8hk - Af/IZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8Zk - Af/GZAH/xmQB/8ZkAv/GZAL/xmQC/8ZkAv/GZAL/xWQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8Vj - Av/FYwL/xWMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/DYwL/w2MC/8Nj - Av/DYwL/w2MC/8NjAv/DYwL/w2MC/8NiAv/CYgL/wmIC/8JiAv/CYgL/wmIC/8tnA/9wOQLpAAAAxQAA - AK0AAAByAAAALgAAAAAAAAAAAAAAAHZaQBDNYADezGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tm - AP/LZgD/y2YA/8tmAP/LZgD/y2UA/8tlAP/KZQD/ymUA/8plAP/KZQD/ymUA/8plAP/KZQD/ymUB/8pl - Af/KZQH/ymUB/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8hlAf/IZQH/yGUB/8hlAf/IZQH/yGQB/8hkAf/IZAH/yGQB/8hkAf/IZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAf/GZAH/xmQB/8Zk - Av/GZAL/xmQC/8ZkAv/GZAL/xmQC/8VkAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8Vj - Av/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8Nj - Av/DYwL/w2MC/8NiAv/DYgL/zGcC/1wuAeIAAAC5AAAAkAAAAFEAAAAZAAAAAAAAAAAAAAAAAAAAALtY - ALnPZwD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tm - AP/LZgD/y2UA/8tlAP/KZQD/ymUA/8plAP/KZQD/ymUA/8plAP/KZQD/ymUB/8plAf/KZQH/ymUB/8pl - Af/KZQH/ymUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hl - Af/IZQH/yGUB/8hlAf/IZQH/yGUB/8hkAf/IZAH/yGQB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAL/xmQC/8Zk - Av/GZAL/xmQC/8VkAv/FZAL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/EYwL/w2MC/8NjAv/DYwL/w2MC/8NjAv/KZgL/NBoBzwAA - AJ0AAABnAAAALQAAAAoAAAAAAAAAAAAAAAAAAAAAj0IAaNZrAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tl - AP/LZQD/ymUA/8plAP/KZQD/ymUA/8plAP/KZQD/ymUA/8plAf/KZQH/ymUB/8plAf/KZQH/ymUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/IZQH/yGUB/8hl - Af/IZQH/yGUB/8hkAf/IZAH/yGQB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAf/GZAH/xmQC/8ZkAv/GZAL/xmQC/8Zk - Av/FZAL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8Rj - Av/EYwL/xGMC/8RjAv/EYwL/yWYC/6tXAvYOBwCmAAAAcAAAADoAAAASAAAAAgAAAAAAAAAAAAAAAAAA - AABCGwAU3m8A4cxmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8tm - AP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tlAP/LZQD/y2UA/8pl - AP/KZQD/ymUA/8plAP/KZQD/ymUA/8plAf/KZQH/ymUB/8plAf/KZQH/ymUB/8plAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/IZQH/yGUB/8hlAf/IZQH/yGUB/8hl - Af/IZAH/yGQB/8hkAf/IZAH/yGQB/8hkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8ZkAf/GZAH/xmQB/8ZkAf/GZAH/xmQC/8ZkAv/GZAL/xmQC/8ZkAv/FZAL/xWQC/8Vj - Av/FYwL/xWMC/8VjAv/FYwL/xWMC/8VjAv/FYwL/xGMC/8RjAv/EYwL/xGMC/8RjAv/QaQL/YzIBwwAA - AGcAAAA8AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACRSQBc1msA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/LZgD/y2YA/8tm - AP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZQD/y2UA/8plAP/KZQD/ymUA/8pl - AP/KZQD/ymUA/8plAP/KZQH/ymUB/8plAf/KZQH/ymUB/8plAf/JZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yGUB/8hlAf/IZQH/yGUB/8hlAf/IZAH/yGQB/8hk - Af/IZAH/yGQB/8hkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8Zk - Af/GZAH/xmQB/8ZkAf/GZAH/xmQB/8ZkAv/GZAL/xmQC/8ZkAv/GZAL/xWQC/8VjAv/FYwL/xWMC/8Vj - Av/FYwL/xWMC/8VjAv/EYwL/zWcC/6pWAuIPCABfAAAAMAAAABUAAAAFAAAAAQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAACwWACL224A/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tm - AP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZQD/y2UA/8tlAP/KZQD/ymUA/8plAP/KZQD/ymUA/8pl - AP/KZQH/ymUB/8plAf/KZQH/ymUB/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8llAf/JZQH/yGUB/8hlAf/IZQH/yGUB/8hlAf/IZQH/yGQB/8hkAf/IZAH/yGQB/8hk - Af/IZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8Zk - Af/GZAH/xmQB/8ZkAv/GZAL/xmQC/8ZkAv/GZAL/xWQC/8VkAv/FYwL/xWMC/8tmAv/CYgLtLRcBVgAA - ABsAAAANAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOwWACG0WkA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tm - AP/LZgD/y2YA/8tmAP/LZgD/y2UA/8tlAP/KZQD/ymUA/8plAP/KZQD/ymUA/8plAP/KZQD/ymUB/8pl - Af/KZQH/ymUB/8plAf/KZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8ll - Af/JZQH/yWUB/8hlAf/IZQH/yGUB/8hlAf/IZQH/yGUB/8hkAf/IZAH/yGQB/8hkAf/IZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/GZAH/xmQB/8ZkAf/GZAH/xmQB/8Zk - Af/GZAL/xmQC/8ZkAv/QaQL/ul4C2jsdAUQAAAAGAAAABgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpVQBU1GoA0cxmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xmAP/MZgD/zGYA/8xm - AP/MZgD/zGYA/8xmAP/MZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tmAP/LZgD/y2YA/8tm - AP/LZgD/y2UA/8tlAP/LZQD/ymUA/8plAP/KZQD/ymUA/8plAP/KZQD/ymUB/8plAf/KZQH/ymUB/8pl - Af/KZQH/ymUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8llAf/JZQH/yWUB/8hl - Af/IZQH/yGUB/8hlAf/IZQH/yGUB/8hkAf/IZAH/yGQB/8hkAf/IZAH/yGQB/8dkAf/HZAH/x2QB/8dk - Af/HZAH/x2QB/8dkAf/HZAH/x2QB/8dkAf/HZAH/xmQB/8ZkAf/GZAH/yWYB9JpNAZhXLAEbAAAAAAAA - AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AADVZAALyl8AUMpfAJ7KXwDDyl8A08pfAN7KXwDeyl8A3spfAN7KXwDeyl8A3spfAN7KXwDeyl8A3spf - AN7KXwDeyl8A3spfAN7KXwDeyl8A3spfAN7KXwDeyl8A3spfAN7KXwDeyl8A3spfAN7KXwDeyl8A3spf - AN7KXwDeyl8A3spfAN7KXwDeyl8A3spfAN7KXwDeyl8A3spfAN7KXwDeyl8A3spfAN7KXwDeyl8A3spf - AN7JXwDeyV8A3slfAN7JXwDeyV8A3slfAN7JXwDeyV8A3slfAN7JXwDeyV8A3slfAN7JXwDeyV8A3she - AN7IXgDeyF4A3sheAN7IXgDeyF4A3sheAN7IXgDeyF4A3sheAN7IXgDeyF4A3sheAN7HXgDex14A3sde - AN7HXgDex14A3sZeAN7GXgDexl4A3sdeAN7HXgDex14A3sdeAN7GXgDexl4A3sZeAN7GXgDexl4A3sVe - AN7FXgDexV4A3sVeAN7FXQDexV0A3sVdAN7FXQDexV0A3sVdAN7FXQDexV0A3sRdAN7EXQDexF0A3sRd - ANvEXQDLxF0AuMRdAHjGXgApAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2YxAE9mM - QBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmM - QBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmM - QBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmMQBLZjEAS2YxAEtmMQBLZjEAS2YxAEtiM - QBLYjEAS2IxAEtiMQBLYjEAS2IxAEtiMQBLYjEAS2IxAEtiMQBLYjEAS2IxAEtiMQBLYjEAS2IxAEteM - QBLXjEAS14xAEteMQBLXjEAS14xAEteMQRLXjEES14xBEteMQRLXjEES14xBEteMQRLXjEES14xBEteM - QRLXjEES14xBEteMQRLXjEES14xBEteMQRLXjEES1oxBEtaMQRLWjEES1oxBEtaMQRLWjEES1otBEtaL - QRLWi0ES1otBEtaLQRLWi0ES1otBEtaLQRLVi0ET1YtBDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA/+AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAD/wAAAAAA - AAAAAAAAAAAAAf4AAAAAAAAAAAAAAAAAAAH+AAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAPwA - AAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAA - AADwAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAA - AAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAA - AAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAA - AAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAA - AADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAA - AAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAA - AAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAA - AAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAA - AADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAA - AAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAA - AAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAA - AAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAA - AADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAA - AAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAA - AAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAA - AAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAA - AADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAA - AAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAA - AAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAA - AAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAA - AADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAA - AAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAA - AAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAA - AAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAA - 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 - DsaXnz7/B2DzVA/TNNGGAAAAAElFTkSuQmCC - - - \ No newline at end of file diff --git a/SimpleDLNA/FormServer.Designer.cs b/SimpleDLNA/FormServer.Designer.cs deleted file mode 100644 index 19ceab42..00000000 --- a/SimpleDLNA/FormServer.Designer.cs +++ /dev/null @@ -1,543 +0,0 @@ -namespace NMaier.SimpleDlna.GUI -{ - sealed partial class FormServer - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - this.groupName = new System.Windows.Forms.GroupBox(); - this.textName = new System.Windows.Forms.TextBox(); - this.groupOrder = new System.Windows.Forms.GroupBox(); - this.checkOrderDescending = new System.Windows.Forms.CheckBox(); - this.comboOrder = new System.Windows.Forms.ComboBox(); - this.groupTypes = new System.Windows.Forms.GroupBox(); - this.checkImages = new System.Windows.Forms.CheckBox(); - this.checkAudio = new System.Windows.Forms.CheckBox(); - this.checkVideo = new System.Windows.Forms.CheckBox(); - this.groupDirectories = new System.Windows.Forms.GroupBox(); - this.listDirectoriesAnchor = new System.Windows.Forms.Label(); - this.buttonRemoveDirectory = new System.Windows.Forms.Button(); - this.buttonAddDirectory = new System.Windows.Forms.Button(); - this.listDirectories = new System.Windows.Forms.ListView(); - this.colDirectory = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.buttonCancel = new System.Windows.Forms.Button(); - this.buttonAccept = new System.Windows.Forms.Button(); - this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components); - this.folderDialog = new System.Windows.Forms.FolderBrowserDialog(); - this.tabbedOptions = new System.Windows.Forms.TabControl(); - this.tabPageViews = new System.Windows.Forms.TabPage(); - this.comboNewView = new System.Windows.Forms.ComboBox(); - this.buttonViewDown = new System.Windows.Forms.Button(); - this.buttonViewUp = new System.Windows.Forms.Button(); - this.buttonRemoveView = new System.Windows.Forms.Button(); - this.buttonAddView = new System.Windows.Forms.Button(); - this.listViews = new System.Windows.Forms.ListView(); - this.colViewName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colViewDesc = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.tabPageRestrictions = new System.Windows.Forms.TabPage(); - this.textRestriction = new System.Windows.Forms.TextBox(); - this.comboNewRestriction = new System.Windows.Forms.ComboBox(); - this.listRestrictions = new System.Windows.Forms.ListView(); - this.colRestriction = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colRestrictionType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.buttonRemoveRestriction = new System.Windows.Forms.Button(); - this.buttonAddRestriction = new System.Windows.Forms.Button(); - this.groupName.SuspendLayout(); - this.groupOrder.SuspendLayout(); - this.groupTypes.SuspendLayout(); - this.groupDirectories.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit(); - this.tabbedOptions.SuspendLayout(); - this.tabPageViews.SuspendLayout(); - this.tabPageRestrictions.SuspendLayout(); - this.SuspendLayout(); - // - // groupName - // - this.groupName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.groupName.Controls.Add(this.textName); - this.groupName.Location = new System.Drawing.Point(12, 12); - this.groupName.Name = "groupName"; - this.groupName.Size = new System.Drawing.Size(520, 46); - this.groupName.TabIndex = 2; - this.groupName.TabStop = false; - this.groupName.Text = "Name"; - // - // textName - // - this.textName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.textName.Location = new System.Drawing.Point(6, 19); - this.textName.Name = "textName"; - this.textName.Size = new System.Drawing.Size(485, 20); - this.textName.TabIndex = 0; - this.textName.Validating += new System.ComponentModel.CancelEventHandler(this.textName_Validating); - // - // groupOrder - // - this.groupOrder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.groupOrder.Controls.Add(this.checkOrderDescending); - this.groupOrder.Controls.Add(this.comboOrder); - this.groupOrder.Location = new System.Drawing.Point(12, 64); - this.groupOrder.Name = "groupOrder"; - this.groupOrder.Size = new System.Drawing.Size(520, 46); - this.groupOrder.TabIndex = 3; - this.groupOrder.TabStop = false; - this.groupOrder.Text = "Order"; - // - // checkOrderDescending - // - this.checkOrderDescending.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.checkOrderDescending.AutoSize = true; - this.checkOrderDescending.Location = new System.Drawing.Point(431, 19); - this.checkOrderDescending.Name = "checkOrderDescending"; - this.checkOrderDescending.Size = new System.Drawing.Size(83, 17); - this.checkOrderDescending.TabIndex = 1; - this.checkOrderDescending.Text = "Descending"; - this.checkOrderDescending.UseVisualStyleBackColor = true; - // - // comboOrder - // - this.comboOrder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.comboOrder.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboOrder.FormattingEnabled = true; - this.comboOrder.Location = new System.Drawing.Point(6, 19); - this.comboOrder.Name = "comboOrder"; - this.comboOrder.Size = new System.Drawing.Size(419, 21); - this.comboOrder.TabIndex = 0; - // - // groupTypes - // - this.groupTypes.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.groupTypes.Controls.Add(this.checkImages); - this.groupTypes.Controls.Add(this.checkAudio); - this.groupTypes.Controls.Add(this.checkVideo); - this.groupTypes.Location = new System.Drawing.Point(12, 116); - this.groupTypes.Name = "groupTypes"; - this.groupTypes.Size = new System.Drawing.Size(520, 46); - this.groupTypes.TabIndex = 4; - this.groupTypes.TabStop = false; - this.groupTypes.Text = "Types"; - this.groupTypes.Validating += new System.ComponentModel.CancelEventHandler(this.checkTypes_Validating); - // - // checkImages - // - this.checkImages.AutoSize = true; - this.checkImages.Location = new System.Drawing.Point(133, 19); - this.checkImages.Name = "checkImages"; - this.checkImages.Size = new System.Drawing.Size(60, 17); - this.checkImages.TabIndex = 2; - this.checkImages.Text = "Images"; - this.checkImages.UseVisualStyleBackColor = true; - // - // checkAudio - // - this.checkAudio.AutoSize = true; - this.checkAudio.Location = new System.Drawing.Point(74, 19); - this.checkAudio.Name = "checkAudio"; - this.checkAudio.Size = new System.Drawing.Size(53, 17); - this.checkAudio.TabIndex = 1; - this.checkAudio.Text = "Audio"; - this.checkAudio.UseVisualStyleBackColor = true; - // - // checkVideo - // - this.checkVideo.AutoSize = true; - this.checkVideo.Location = new System.Drawing.Point(15, 19); - this.checkVideo.Name = "checkVideo"; - this.checkVideo.Size = new System.Drawing.Size(53, 17); - this.checkVideo.TabIndex = 0; - this.checkVideo.Text = "Video"; - this.checkVideo.UseVisualStyleBackColor = true; - // - // groupDirectories - // - this.groupDirectories.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.groupDirectories.Controls.Add(this.listDirectoriesAnchor); - this.groupDirectories.Controls.Add(this.buttonRemoveDirectory); - this.groupDirectories.Controls.Add(this.buttonAddDirectory); - this.groupDirectories.Controls.Add(this.listDirectories); - this.groupDirectories.Location = new System.Drawing.Point(13, 334); - this.groupDirectories.Name = "groupDirectories"; - this.groupDirectories.Size = new System.Drawing.Size(519, 138); - this.groupDirectories.TabIndex = 6; - this.groupDirectories.TabStop = false; - this.groupDirectories.Text = "Directories"; - // - // listDirectoriesAnchor - // - this.listDirectoriesAnchor.AutoSize = true; - this.listDirectoriesAnchor.Location = new System.Drawing.Point(441, 74); - this.listDirectoriesAnchor.Name = "listDirectoriesAnchor"; - this.listDirectoriesAnchor.Size = new System.Drawing.Size(0, 13); - this.listDirectoriesAnchor.TabIndex = 2; - // - // buttonRemoveDirectory - // - this.buttonRemoveDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonRemoveDirectory.Location = new System.Drawing.Point(438, 48); - this.buttonRemoveDirectory.Name = "buttonRemoveDirectory"; - this.buttonRemoveDirectory.Size = new System.Drawing.Size(75, 23); - this.buttonRemoveDirectory.TabIndex = 2; - this.buttonRemoveDirectory.Text = "Remove"; - this.buttonRemoveDirectory.UseVisualStyleBackColor = true; - this.buttonRemoveDirectory.Click += new System.EventHandler(this.buttonRemoveDirectory_Click); - // - // buttonAddDirectory - // - this.buttonAddDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonAddDirectory.Location = new System.Drawing.Point(438, 19); - this.buttonAddDirectory.Name = "buttonAddDirectory"; - this.buttonAddDirectory.Size = new System.Drawing.Size(75, 23); - this.buttonAddDirectory.TabIndex = 0; - this.buttonAddDirectory.Text = "Add"; - this.buttonAddDirectory.UseVisualStyleBackColor = true; - this.buttonAddDirectory.Click += new System.EventHandler(this.buttonAddDirectory_Click); - // - // listDirectories - // - this.listDirectories.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.listDirectories.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.colDirectory}); - this.listDirectories.Location = new System.Drawing.Point(6, 19); - this.listDirectories.Name = "listDirectories"; - this.listDirectories.Size = new System.Drawing.Size(429, 113); - this.listDirectories.Sorting = System.Windows.Forms.SortOrder.Ascending; - this.listDirectories.TabIndex = 3; - this.listDirectories.UseCompatibleStateImageBehavior = false; - this.listDirectories.View = System.Windows.Forms.View.Details; - this.listDirectories.Validating += new System.ComponentModel.CancelEventHandler(this.listDirectories_Validating); - // - // colDirectory - // - this.colDirectory.Text = "Directory"; - this.colDirectory.Width = 200; - // - // buttonCancel - // - this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.buttonCancel.Location = new System.Drawing.Point(457, 478); - this.buttonCancel.Name = "buttonCancel"; - this.buttonCancel.Size = new System.Drawing.Size(75, 23); - this.buttonCancel.TabIndex = 1; - this.buttonCancel.Text = "&Cancel"; - this.buttonCancel.UseVisualStyleBackColor = true; - // - // buttonAccept - // - this.buttonAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonAccept.DialogResult = System.Windows.Forms.DialogResult.OK; - this.buttonAccept.Location = new System.Drawing.Point(376, 478); - this.buttonAccept.Name = "buttonAccept"; - this.buttonAccept.Size = new System.Drawing.Size(75, 23); - this.buttonAccept.TabIndex = 0; - this.buttonAccept.Text = "&OK"; - this.buttonAccept.UseVisualStyleBackColor = true; - // - // errorProvider - // - this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink; - this.errorProvider.ContainerControl = this; - // - // tabbedOptions - // - this.tabbedOptions.Controls.Add(this.tabPageViews); - this.tabbedOptions.Controls.Add(this.tabPageRestrictions); - this.tabbedOptions.Location = new System.Drawing.Point(12, 168); - this.tabbedOptions.Name = "tabbedOptions"; - this.tabbedOptions.SelectedIndex = 0; - this.tabbedOptions.Size = new System.Drawing.Size(520, 160); - this.tabbedOptions.TabIndex = 6; - // - // tabPageViews - // - this.tabPageViews.Controls.Add(this.comboNewView); - this.tabPageViews.Controls.Add(this.buttonViewDown); - this.tabPageViews.Controls.Add(this.buttonViewUp); - this.tabPageViews.Controls.Add(this.buttonRemoveView); - this.tabPageViews.Controls.Add(this.buttonAddView); - this.tabPageViews.Controls.Add(this.listViews); - this.tabPageViews.Location = new System.Drawing.Point(4, 22); - this.tabPageViews.Name = "tabPageViews"; - this.tabPageViews.Padding = new System.Windows.Forms.Padding(3); - this.tabPageViews.Size = new System.Drawing.Size(512, 134); - this.tabPageViews.TabIndex = 0; - this.tabPageViews.Text = "Views"; - this.tabPageViews.UseVisualStyleBackColor = true; - // - // comboNewView - // - this.comboNewView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.comboNewView.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboNewView.FormattingEnabled = true; - this.comboNewView.Location = new System.Drawing.Point(6, 6); - this.comboNewView.Name = "comboNewView"; - this.comboNewView.Size = new System.Drawing.Size(419, 21); - this.comboNewView.TabIndex = 0; - // - // buttonViewDown - // - this.buttonViewDown.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonViewDown.Location = new System.Drawing.Point(431, 102); - this.buttonViewDown.Name = "buttonViewDown"; - this.buttonViewDown.Size = new System.Drawing.Size(75, 23); - this.buttonViewDown.TabIndex = 4; - this.buttonViewDown.Text = "Down"; - this.buttonViewDown.UseVisualStyleBackColor = true; - // - // buttonViewUp - // - this.buttonViewUp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonViewUp.Location = new System.Drawing.Point(431, 73); - this.buttonViewUp.Name = "buttonViewUp"; - this.buttonViewUp.Size = new System.Drawing.Size(75, 23); - this.buttonViewUp.TabIndex = 3; - this.buttonViewUp.Text = "Up"; - this.buttonViewUp.UseVisualStyleBackColor = true; - // - // buttonRemoveView - // - this.buttonRemoveView.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonRemoveView.Location = new System.Drawing.Point(431, 35); - this.buttonRemoveView.Name = "buttonRemoveView"; - this.buttonRemoveView.Size = new System.Drawing.Size(75, 23); - this.buttonRemoveView.TabIndex = 2; - this.buttonRemoveView.Text = "Remove"; - this.buttonRemoveView.UseVisualStyleBackColor = true; - this.buttonRemoveView.Click += new System.EventHandler(this.buttonRemoveView_Click); - // - // buttonAddView - // - this.buttonAddView.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonAddView.Location = new System.Drawing.Point(431, 6); - this.buttonAddView.Name = "buttonAddView"; - this.buttonAddView.Size = new System.Drawing.Size(75, 23); - this.buttonAddView.TabIndex = 1; - this.buttonAddView.Text = "Add"; - this.buttonAddView.UseVisualStyleBackColor = true; - this.buttonAddView.Click += new System.EventHandler(this.buttonAddView_Click); - // - // listViews - // - this.listViews.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.listViews.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.colViewName, - this.colViewDesc}); - this.listViews.FullRowSelect = true; - this.listViews.Location = new System.Drawing.Point(6, 33); - this.listViews.Name = "listViews"; - this.listViews.Size = new System.Drawing.Size(419, 95); - this.listViews.TabIndex = 5; - this.listViews.UseCompatibleStateImageBehavior = false; - this.listViews.View = System.Windows.Forms.View.Details; - // - // colViewName - // - this.colViewName.Text = "Name"; - this.colViewName.Width = 200; - // - // colViewDesc - // - this.colViewDesc.Text = "Description"; - this.colViewDesc.Width = 200; - // - // tabPageRestrictions - // - this.tabPageRestrictions.Controls.Add(this.textRestriction); - this.tabPageRestrictions.Controls.Add(this.comboNewRestriction); - this.tabPageRestrictions.Controls.Add(this.listRestrictions); - this.tabPageRestrictions.Controls.Add(this.buttonRemoveRestriction); - this.tabPageRestrictions.Controls.Add(this.buttonAddRestriction); - this.tabPageRestrictions.Location = new System.Drawing.Point(4, 22); - this.tabPageRestrictions.Name = "tabPageRestrictions"; - this.tabPageRestrictions.Padding = new System.Windows.Forms.Padding(3); - this.tabPageRestrictions.Size = new System.Drawing.Size(512, 134); - this.tabPageRestrictions.TabIndex = 1; - this.tabPageRestrictions.Text = "Restrictions"; - this.tabPageRestrictions.UseVisualStyleBackColor = true; - // - // textRestriction - // - this.textRestriction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.textRestriction.Location = new System.Drawing.Point(6, 6); - this.textRestriction.Name = "textRestriction"; - this.textRestriction.Size = new System.Drawing.Size(274, 20); - this.textRestriction.TabIndex = 0; - // - // comboNewRestriction - // - this.comboNewRestriction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.comboNewRestriction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboNewRestriction.Items.AddRange(new object[] { - "MAC", - "IP", - "User-Agent"}); - this.comboNewRestriction.Location = new System.Drawing.Point(305, 6); - this.comboNewRestriction.Name = "comboNewRestriction"; - this.comboNewRestriction.Size = new System.Drawing.Size(120, 21); - this.comboNewRestriction.TabIndex = 1; - // - // listRestrictions - // - this.listRestrictions.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.listRestrictions.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.colRestriction, - this.colRestrictionType}); - this.listRestrictions.FullRowSelect = true; - this.listRestrictions.Location = new System.Drawing.Point(6, 33); - this.listRestrictions.Name = "listRestrictions"; - this.listRestrictions.Size = new System.Drawing.Size(419, 95); - this.listRestrictions.TabIndex = 4; - this.listRestrictions.UseCompatibleStateImageBehavior = false; - this.listRestrictions.View = System.Windows.Forms.View.Details; - // - // colRestriction - // - this.colRestriction.Text = "Restriction"; - this.colRestriction.Width = 200; - // - // colRestrictionType - // - this.colRestrictionType.Text = "Type"; - this.colRestrictionType.Width = 200; - // - // buttonRemoveRestriction - // - this.buttonRemoveRestriction.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonRemoveRestriction.Location = new System.Drawing.Point(431, 35); - this.buttonRemoveRestriction.Name = "buttonRemoveRestriction"; - this.buttonRemoveRestriction.Size = new System.Drawing.Size(75, 23); - this.buttonRemoveRestriction.TabIndex = 3; - this.buttonRemoveRestriction.Text = "Remove"; - this.buttonRemoveRestriction.UseVisualStyleBackColor = true; - this.buttonRemoveRestriction.Click += new System.EventHandler(this.buttonRemoveRestriction_Click); - // - // buttonAddRestriction - // - this.buttonAddRestriction.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonAddRestriction.Location = new System.Drawing.Point(431, 6); - this.buttonAddRestriction.Name = "buttonAddRestriction"; - this.buttonAddRestriction.Size = new System.Drawing.Size(75, 23); - this.buttonAddRestriction.TabIndex = 2; - this.buttonAddRestriction.Text = "Add"; - this.buttonAddRestriction.UseVisualStyleBackColor = true; - this.buttonAddRestriction.Click += new System.EventHandler(this.buttonAddRestriction_Click); - // - // FormServer - // - this.AcceptButton = this.buttonAccept; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.AutoValidate = System.Windows.Forms.AutoValidate.EnableAllowFocusChange; - this.CancelButton = this.buttonCancel; - this.ClientSize = new System.Drawing.Size(544, 508); - this.Controls.Add(this.tabbedOptions); - this.Controls.Add(this.buttonAccept); - this.Controls.Add(this.buttonCancel); - this.Controls.Add(this.groupDirectories); - this.Controls.Add(this.groupTypes); - this.Controls.Add(this.groupOrder); - this.Controls.Add(this.groupName); - this.MaximizeBox = false; - this.Name = "FormServer"; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Edit Server"; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormServer_FormClosing); - this.groupName.ResumeLayout(false); - this.groupName.PerformLayout(); - this.groupOrder.ResumeLayout(false); - this.groupOrder.PerformLayout(); - this.groupTypes.ResumeLayout(false); - this.groupTypes.PerformLayout(); - this.groupDirectories.ResumeLayout(false); - this.groupDirectories.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit(); - this.tabbedOptions.ResumeLayout(false); - this.tabPageViews.ResumeLayout(false); - this.tabPageRestrictions.ResumeLayout(false); - this.tabPageRestrictions.PerformLayout(); - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.GroupBox groupName; - private System.Windows.Forms.TextBox textName; - private System.Windows.Forms.GroupBox groupOrder; - private System.Windows.Forms.CheckBox checkOrderDescending; - private System.Windows.Forms.ComboBox comboOrder; - private System.Windows.Forms.GroupBox groupTypes; - private System.Windows.Forms.CheckBox checkImages; - private System.Windows.Forms.CheckBox checkAudio; - private System.Windows.Forms.CheckBox checkVideo; - private System.Windows.Forms.GroupBox groupDirectories; - private System.Windows.Forms.Button buttonRemoveDirectory; - private System.Windows.Forms.Button buttonAddDirectory; - private System.Windows.Forms.ListView listDirectories; - private System.Windows.Forms.ColumnHeader colDirectory; - private System.Windows.Forms.Button buttonCancel; - private System.Windows.Forms.Button buttonAccept; - private System.Windows.Forms.ErrorProvider errorProvider; - private System.Windows.Forms.Label listDirectoriesAnchor; - private System.Windows.Forms.FolderBrowserDialog folderDialog; - private System.Windows.Forms.TabControl tabbedOptions; - private System.Windows.Forms.TabPage tabPageViews; - private System.Windows.Forms.ComboBox comboNewView; - private System.Windows.Forms.Button buttonViewDown; - private System.Windows.Forms.Button buttonViewUp; - private System.Windows.Forms.Button buttonRemoveView; - private System.Windows.Forms.Button buttonAddView; - private System.Windows.Forms.ListView listViews; - private System.Windows.Forms.ColumnHeader colViewName; - private System.Windows.Forms.ColumnHeader colViewDesc; - private System.Windows.Forms.TabPage tabPageRestrictions; - private System.Windows.Forms.TextBox textRestriction; - private System.Windows.Forms.ComboBox comboNewRestriction; - private System.Windows.Forms.ListView listRestrictions; - private System.Windows.Forms.ColumnHeader colRestriction; - private System.Windows.Forms.ColumnHeader colRestrictionType; - private System.Windows.Forms.Button buttonRemoveRestriction; - private System.Windows.Forms.Button buttonAddRestriction; - } -} \ No newline at end of file diff --git a/SimpleDLNA/FormServer.cs b/SimpleDLNA/FormServer.cs deleted file mode 100644 index 5d221765..00000000 --- a/SimpleDLNA/FormServer.cs +++ /dev/null @@ -1,297 +0,0 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Net; -using System.Windows.Forms; -using NMaier.SimpleDlna.GUI.Properties; -using NMaier.SimpleDlna.Server; -using NMaier.SimpleDlna.Server.Comparers; -using NMaier.SimpleDlna.Server.Views; -using NMaier.SimpleDlna.Utilities; -using Form = NMaier.Windows.Forms.Form; - -namespace NMaier.SimpleDlna.GUI -{ - internal sealed partial class FormServer : Form - { - public FormServer() - { - Init(); - Text = "New Server"; - checkVideo.Checked = true; - SizeDirectoryColumn(); - SizeColumns(listViews); - SizeColumns(listRestrictions); - } - - public FormServer(ServerDescription description) - { - Init(); - - textName.Text = description.Name; - - checkVideo.Checked = - (description.Types & DlnaMediaTypes.Video) == DlnaMediaTypes.Video; - checkAudio.Checked = - (description.Types & DlnaMediaTypes.Audio) == DlnaMediaTypes.Audio; - checkImages.Checked = - (description.Types & DlnaMediaTypes.Image) == DlnaMediaTypes.Image; - - foreach (var i in comboOrder.Items) { - if (((IItemComparer)i).Name == description.Order) { - comboOrder.SelectedItem = i; - break; - } - } - checkOrderDescending.Checked = description.OrderDescending; - - foreach (var v in description.Views) { - var i = new ListViewItem(new[] - { - v, ViewRepository.Lookup(v).Description - }); - listViews.Items.Add(i); - } - foreach (var d in description.Directories) { - var i = new ListViewItem(d); - listDirectories.Items.Add(i); - } - var t = comboNewRestriction.Items[0].ToString(); - foreach (var r in description.Macs) { - var i = listRestrictions.Items.Add(r); - i.Tag = 0; - i.SubItems.Add(t); - } - t = comboNewRestriction.Items[1].ToString(); - foreach (var r in description.Ips) { - var i = listRestrictions.Items.Add(r); - i.Tag = 1; - i.SubItems.Add(t); - } - t = comboNewRestriction.Items[2].ToString(); - foreach (var r in description.UserAgents) { - var i = listRestrictions.Items.Add(r); - i.Tag = 2; - i.SubItems.Add(t); - } - - SizeDirectoryColumn(); - SizeColumns(listViews); - } - - public ServerDescription Description - { - get { - DlnaMediaTypes types = 0; - if (checkVideo.Checked) { - types |= DlnaMediaTypes.Video; - } - if (checkAudio.Checked) { - types |= DlnaMediaTypes.Audio; - } - if (checkImages.Checked) { - types |= DlnaMediaTypes.Image; - } - var views = (from ListViewItem i in listViews.Items - select i.Text).ToArray(); - var dirs = (from ListViewItem i in listDirectories.Items - select i.Text).ToArray(); - var macs = (from ListViewItem i in listRestrictions.Items - where (int)i.Tag == 0 - select i.Text).ToArray(); - var ips = (from ListViewItem i in listRestrictions.Items - where (int)i.Tag == 1 - select i.Text).ToArray(); - var uas = (from ListViewItem i in listRestrictions.Items - where (int)i.Tag == 2 - select i.Text).ToArray(); - var rv = new ServerDescription - { - Name = textName.Text, - Order = ((IItemComparer)comboOrder.SelectedItem).Name, - OrderDescending = checkOrderDescending.Checked, - Types = types, - Views = views, - Ips = ips, - Macs = macs, - UserAgents = uas, - Directories = dirs.ToArray() - }; - return rv; - } - } - - private void AddOrderItems() - { - var items = from v in ComparerRepository.ListItems() - orderby v.Key - select v.Value; - foreach (var v in items) { - var i = comboOrder.Items.Add(v); - if (v.Name == "title") { - comboOrder.SelectedIndex = i; - } - } - } - - private void AddViewItems() - { - var items = from v in ViewRepository.ListItems() - orderby v.Key - select v.Value; - foreach (var v in items) { - comboNewView.Items.Add(v); - } - } - - private void buttonAddDirectory_Click(object sender, EventArgs e) - { - if (folderDialog.ShowDialog() == DialogResult.OK) { - var path = folderDialog.SelectedPath; - var found = from ListViewItem i in listDirectories.Items - where StringComparer.InvariantCulture.Equals(path, i.Text) - select i; - if (!found.Any()) { - listDirectories.Items.Add(path); - } - } - SizeDirectoryColumn(); - } - - private void buttonAddRestriction_Click(object sender, EventArgs e) - { - var valid = false; - var re = textRestriction.Text; - switch (comboNewRestriction.SelectedIndex) { - case 0: - valid = IP.IsAcceptedMAC(re); - break; - case 1: - IPAddress o; - valid = IPAddress.TryParse(re, out o); - break; - case 2: - valid = !string.IsNullOrWhiteSpace(re); - break; - default: - break; - } - if (!valid) { - errorProvider.SetError( - textRestriction, "You must provide a valid value"); - return; - } - var item = listRestrictions.Items.Add(re); - item.SubItems.Add(comboNewRestriction.SelectedItem.ToString()); - item.Tag = comboNewRestriction.SelectedIndex; - SizeColumns(listRestrictions); - } - - private void buttonAddView_Click(object sender, EventArgs e) - { - var i = comboNewView.SelectedItem as IView; - if (i == null) { - return; - } - listViews.Items.Add( - new ListViewItem(new[] {i.Name, i.Description})); - SizeColumns(listViews); - } - - private void buttonRemoveDirectory_Click(object sender, EventArgs e) - { - foreach (var i in listDirectories.SelectedItems) { - listDirectories.Items.Remove((ListViewItem)i); - } - SizeDirectoryColumn(); - } - - private void buttonRemoveRestriction_Click(object sender, EventArgs e) - { - foreach (var i in listRestrictions.SelectedItems) { - var item = (ListViewItem)i; - var index = (int)item.Tag; - textRestriction.Text = item.Text; - comboNewRestriction.SelectedIndex = index; - listRestrictions.Items.Remove(item); - } - SizeColumns(listRestrictions); - } - - private void buttonRemoveView_Click(object sender, EventArgs e) - { - foreach (var i in listViews.SelectedItems) { - listViews.Items.Remove((ListViewItem)i); - } - SizeColumns(listViews); - } - - private void checkTypes_Validating(object sender, CancelEventArgs e) - { - if (!checkVideo.Checked && !checkAudio.Checked && !checkImages.Checked) { - errorProvider.SetError(checkImages, "Must select at least one"); - e.Cancel = true; - } - else { - errorProvider.SetError(checkImages, string.Empty); - } - } - - private void FormServer_FormClosing(object sender, FormClosingEventArgs e) - { - e.Cancel = DialogResult == DialogResult.OK && !ValidateChildren(); - } - - private void Init() - { - InitializeComponent(); - Icon = Resources.server; - AddOrderItems(); - AddViewItems(); - comboNewRestriction.SelectedIndex = 0; - } - - private void listDirectories_Validating(object sender, CancelEventArgs e) - { - if (listDirectories.Items.Count == 0) { - errorProvider.SetError( - listDirectoriesAnchor, "Must specify at least one directory"); - e.Cancel = true; - } - else { - errorProvider.SetError(listDirectoriesAnchor, string.Empty); - } - } - - private static void SizeColumns(ListView lv) - { - var mode = ColumnHeaderAutoResizeStyle.ColumnContent; - if (lv.Items.Count == 0) { - mode = ColumnHeaderAutoResizeStyle.HeaderSize; - } - for (var c = 0; c < lv.Columns.Count; ++c) { - lv.Columns[c].AutoResize(mode); - } - } - - private void SizeDirectoryColumn() - { - var mode = ColumnHeaderAutoResizeStyle.ColumnContent; - if (listDirectories.Items.Count == 0) { - mode = ColumnHeaderAutoResizeStyle.HeaderSize; - } - colDirectory.AutoResize(mode); - } - - private void textName_Validating(object sender, CancelEventArgs e) - { - if (string.IsNullOrWhiteSpace(textName.Text)) { - errorProvider.SetError(textName, "Must specify a name"); - e.Cancel = true; - } - else { - errorProvider.SetError(textName, string.Empty); - } - } - } -} diff --git a/SimpleDLNA/FormServer.resx b/SimpleDLNA/FormServer.resx deleted file mode 100644 index 7193b5e2..00000000 --- a/SimpleDLNA/FormServer.resx +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 112, 3 - - - 31 - - - 7, 1 - - \ No newline at end of file diff --git a/SimpleDLNA/FormSettings.Designer.cs b/SimpleDLNA/FormSettings.Designer.cs deleted file mode 100644 index ddf885f9..00000000 --- a/SimpleDLNA/FormSettings.Designer.cs +++ /dev/null @@ -1,191 +0,0 @@ -namespace NMaier.SimpleDlna.GUI -{ - partial class FormSettings - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.numericPort = new System.Windows.Forms.NumericUpDown(); - this.toolTip = new System.Windows.Forms.ToolTip(this.components); - this.textCacheFile = new System.Windows.Forms.TextBox(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.buttonBrowseCacheFile = new System.Windows.Forms.Button(); - this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); - this.checkStartMinimized = new System.Windows.Forms.CheckBox(); - this.checkFileLogging = new System.Windows.Forms.CheckBox(); - this.buttonOK = new System.Windows.Forms.Button(); - this.checkAutoStart = new System.Windows.Forms.CheckBox(); - this.groupBox1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.numericPort)).BeginInit(); - this.groupBox2.SuspendLayout(); - this.SuspendLayout(); - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.numericPort); - this.groupBox1.Location = new System.Drawing.Point(14, 14); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(303, 55); - this.groupBox1.TabIndex = 1; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Port"; - // - // numericPort - // - this.numericPort.DataBindings.Add(new System.Windows.Forms.Binding("Value", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "port", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); - this.numericPort.Location = new System.Drawing.Point(7, 22); - this.numericPort.Maximum = new decimal(new int[] { - 65535, - 0, - 0, - 0}); - this.numericPort.Name = "numericPort"; - this.numericPort.Size = new System.Drawing.Size(80, 23); - this.numericPort.TabIndex = 0; - this.toolTip.SetToolTip(this.numericPort, "Port of the http server.\r\nLeave at 0 to automatically have a port selected on sta" + - "rtup.\r\n\r\n(Requires restart)"); - this.numericPort.Value = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.port; - // - // textCacheFile - // - this.textCacheFile.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "cache", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); - this.textCacheFile.Location = new System.Drawing.Point(7, 22); - this.textCacheFile.Name = "textCacheFile"; - this.textCacheFile.Size = new System.Drawing.Size(194, 23); - this.textCacheFile.TabIndex = 1; - this.textCacheFile.Text = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.cache; - this.toolTip.SetToolTip(this.textCacheFile, "Location of the cache directory.\r\nLeave blank to use the default location (TEMP)." + - "\r\n\r\n(Requires restart)"); - // - // groupBox2 - // - this.groupBox2.Controls.Add(this.buttonBrowseCacheFile); - this.groupBox2.Controls.Add(this.textCacheFile); - this.groupBox2.Location = new System.Drawing.Point(14, 76); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(303, 55); - this.groupBox2.TabIndex = 2; - this.groupBox2.TabStop = false; - this.groupBox2.Text = "Cache directory"; - // - // buttonBrowseCacheFile - // - this.buttonBrowseCacheFile.Location = new System.Drawing.Point(209, 20); - this.buttonBrowseCacheFile.Name = "buttonBrowseCacheFile"; - this.buttonBrowseCacheFile.Size = new System.Drawing.Size(87, 27); - this.buttonBrowseCacheFile.TabIndex = 0; - this.buttonBrowseCacheFile.Text = "Browse"; - this.buttonBrowseCacheFile.UseVisualStyleBackColor = true; - this.buttonBrowseCacheFile.Click += new System.EventHandler(this.buttonBrowseCacheFile_Click); - // - // checkStartMinimized - // - this.checkStartMinimized.AutoSize = true; - this.checkStartMinimized.Checked = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.startminimized; - this.checkStartMinimized.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "startminimized", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); - this.checkStartMinimized.Location = new System.Drawing.Point(14, 165); - this.checkStartMinimized.Name = "checkStartMinimized"; - this.checkStartMinimized.Size = new System.Drawing.Size(109, 19); - this.checkStartMinimized.TabIndex = 4; - this.checkStartMinimized.Text = "Start minimized"; - this.checkStartMinimized.UseVisualStyleBackColor = true; - // - // checkFileLogging - // - this.checkFileLogging.AutoSize = true; - this.checkFileLogging.Checked = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.filelogging; - this.checkFileLogging.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "filelogging", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); - this.checkFileLogging.Location = new System.Drawing.Point(14, 138); - this.checkFileLogging.Name = "checkFileLogging"; - this.checkFileLogging.Size = new System.Drawing.Size(200, 19); - this.checkFileLogging.TabIndex = 3; - this.checkFileLogging.Text = "Log diagnostic messages to a file"; - this.checkFileLogging.UseVisualStyleBackColor = true; - // - // buttonOK - // - this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; - this.buttonOK.Location = new System.Drawing.Point(230, 192); - this.buttonOK.Name = "buttonOK"; - this.buttonOK.Size = new System.Drawing.Size(87, 27); - this.buttonOK.TabIndex = 0; - this.buttonOK.Text = "OK"; - this.buttonOK.UseVisualStyleBackColor = true; - // - // checkAutoStart - // - this.checkAutoStart.AutoSize = true; - this.checkAutoStart.Location = new System.Drawing.Point(14, 192); - this.checkAutoStart.Name = "checkAutoStart"; - this.checkAutoStart.Size = new System.Drawing.Size(203, 19); - this.checkAutoStart.TabIndex = 5; - this.checkAutoStart.Text = "Start automatically with Windows"; - this.checkAutoStart.UseVisualStyleBackColor = true; - this.checkAutoStart.CheckedChanged += new System.EventHandler(this.checkAutoStart_CheckedChanged); - // - // FormSettings - // - this.AcceptButton = this.buttonOK; - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(331, 232); - this.Controls.Add(this.checkAutoStart); - this.Controls.Add(this.buttonOK); - this.Controls.Add(this.checkFileLogging); - this.Controls.Add(this.checkStartMinimized); - this.Controls.Add(this.groupBox2); - this.Controls.Add(this.groupBox1); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.Name = "FormSettings"; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Settings"; - this.groupBox1.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.numericPort)).EndInit(); - this.groupBox2.ResumeLayout(false); - this.groupBox2.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.GroupBox groupBox1; - private System.Windows.Forms.NumericUpDown numericPort; - private System.Windows.Forms.ToolTip toolTip; - private System.Windows.Forms.GroupBox groupBox2; - private System.Windows.Forms.Button buttonBrowseCacheFile; - private System.Windows.Forms.TextBox textCacheFile; - private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog; - private System.Windows.Forms.CheckBox checkStartMinimized; - private System.Windows.Forms.CheckBox checkFileLogging; - private System.Windows.Forms.Button buttonOK; - private System.Windows.Forms.CheckBox checkAutoStart; - } -} diff --git a/SimpleDLNA/FormSettings.cs b/SimpleDLNA/FormSettings.cs deleted file mode 100644 index 26bfccf0..00000000 --- a/SimpleDLNA/FormSettings.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Windows.Forms; -using NMaier.SimpleDlna.GUI.Properties; -using Form = NMaier.Windows.Forms.Form; -using SystemInformation = NMaier.SimpleDlna.Utilities.SystemInformation; - -namespace NMaier.SimpleDlna.GUI -{ - public partial class FormSettings : Form - { - private const string APP_KEY_NAME = "SimpleDLNA"; - - private readonly StartupUtilities startUpUtilities; - - public FormSettings() - { - InitializeComponent(); - Icon = Resources.preferencesIcon; - - if (!SystemInformation.IsRunningOnMono()) { - startUpUtilities = new StartupUtilities(StartupUtilities.StartupUserScope.CurrentUser); - checkAutoStart.Checked = startUpUtilities.CheckIfRunAtWinBoot(APP_KEY_NAME); - } - else { - checkAutoStart.Visible = false; - } - } - - private void buttonBrowseCacheFile_Click(object sender, EventArgs e) - { - if (folderBrowserDialog.ShowDialog() == DialogResult.OK) { - textCacheFile.Text = folderBrowserDialog.SelectedPath; - } - } - - private void checkAutoStart_CheckedChanged(object sender, EventArgs e) - { - if (checkAutoStart.Checked) { - startUpUtilities.InstallAutoRun(APP_KEY_NAME); - } - else { - startUpUtilities.UninstallAutoRun(APP_KEY_NAME); - } - } - } -} diff --git a/SimpleDLNA/FormSettings.resx b/SimpleDLNA/FormSettings.resx deleted file mode 100644 index 1f63bee2..00000000 --- a/SimpleDLNA/FormSettings.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - - 107, 17 - - \ No newline at end of file diff --git a/SimpleDLNA/GlobalSuppressions.cs b/SimpleDLNA/GlobalSuppressions.cs deleted file mode 100644 index 667cee0d..00000000 --- a/SimpleDLNA/GlobalSuppressions.cs +++ /dev/null @@ -1,25 +0,0 @@ -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dlna", Scope = "namespace", Target = "NMaier.SimpleDlna")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "GUI", Scope = "namespace", Target = "NMaier.SimpleDlna.GUI")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dlna", Scope = "namespace", Target = "NMaier.SimpleDlna.GUI")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "DLNA")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ngen", Scope = "type", Target = "NMaier.SimpleDlna.NgenInstaller")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "NMaier.SimpleDlna.NgenInstaller.#Install(System.Collections.IDictionary)")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ngen", Scope = "member", Target = "NMaier.SimpleDlna.NgenInstaller.#Install(System.Collections.IDictionary)")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "FormAbout", Scope = "member", Target = "NMaier.SimpleDlna.GUI.FormAbout.#InitializeComponent()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "SimpleDLNA", Scope = "member", Target = "NMaier.SimpleDlna.GUI.FormMain.#InitializeComponent()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "LocalAppData", Scope = "member", Target = "NMaier.SimpleDlna.GUI.FormMain.#cacheDir")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "NMaier.SimpleDlna.GUI.FormMain.#LoadConfig()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Scope = "member", Target = "NMaier.SimpleDlna.GUI.PathEnvironmentInstaller.#Install(System.Collections.IDictionary)")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Scope = "member", Target = "NMaier.SimpleDlna.GUI.PathEnvironmentInstaller.#Rollback(System.Collections.IDictionary)")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect", Scope = "member", Target = "NMaier.SimpleDlna.GUI.Program.#Main()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "NMaier.SimpleDlna.GUI.ServerDescription.#Directories")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "NMaier.SimpleDlna.GUI.ServerDescription.#Ips")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "NMaier.SimpleDlna.GUI.ServerDescription.#UserAgents")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "NMaier.SimpleDlna.GUI.ServerDescription.#Views")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ips", Scope = "member", Target = "NMaier.SimpleDlna.GUI.ServerDescription.#Ips")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "NMaier.SimpleDlna.GUI.ServerDescription.#Macs")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "NMaier.SimpleDlna.GUI.ServerListViewItem.#StartFileServer()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Scope = "type", Target = "NMaier.SimpleDlna.GUI.FormMain")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "NMaier.SimpleDlna.GUI.FormMain.#LoadDescriptors()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "NMaier.SimpleDlna.GUI.FormMain.#notifyContext_Opening(System.Object,System.ComponentModel.CancelEventArgs)")] diff --git a/SimpleDLNA/PathEnvironmentInstaller.cs b/SimpleDLNA/PathEnvironmentInstaller.cs deleted file mode 100644 index 8c16b15d..00000000 --- a/SimpleDLNA/PathEnvironmentInstaller.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Collections; -using System.ComponentModel; -using System.Configuration.Install; -using System.IO; -using System.Linq; -using System.Reflection; -using Microsoft.Win32; - -namespace NMaier.SimpleDlna.GUI -{ - [RunInstaller(true)] - public class PathEnvironmentInstaller : Installer - { - private const string ENV_PATH = "EnvironmentPath"; - - private const string REG_ENV = "Environment"; - - private const string REG_PATH = "PATH"; - - private readonly DirectoryInfo directory = - new FileInfo(Assembly.GetExecutingAssembly().Location ?? string.Empty).Directory; - - public override void Install(IDictionary stateSaver) - { - base.Install(stateSaver); - if (!directory.Exists) { - return; - } - - using (var registry = Registry.CurrentUser.OpenSubKey(REG_ENV, true)) { - var path = registry?.GetValue( - REG_PATH, string.Empty, - RegistryValueOptions.DoNotExpandEnvironmentNames) as string; - if (path == null) { - return; - } - var c = StringComparer.CurrentCultureIgnoreCase; - var exists = from p in path.Split(';') - where c.Equals(p, directory.FullName) - select p; - if (exists.Any()) { - return; - } - stateSaver[ENV_PATH] = path; - var newpath = directory.FullName; - if (!string.IsNullOrWhiteSpace(path)) { - newpath = $"{path};{newpath}"; - } - registry.SetValue(REG_PATH, newpath, RegistryValueKind.ExpandString); - } - } - - public override void Rollback(IDictionary savedState) - { - base.Rollback(savedState); - if (!savedState.Contains(ENV_PATH)) { - return; - } - using (var registry = Registry.CurrentUser.OpenSubKey(REG_ENV, true)) { - registry?.SetValue( - REG_PATH, savedState[ENV_PATH], registry.GetValueKind(REG_PATH)); - } - } - - public override void Uninstall(IDictionary savedState) - { - base.Uninstall(savedState); - if (!directory.Exists) { - return; - } - - using (var registry = Registry.CurrentUser.OpenSubKey(REG_ENV, true)) { - var path = registry?.GetValue( - REG_PATH, string.Empty, - RegistryValueOptions.DoNotExpandEnvironmentNames) as string; - if (string.IsNullOrEmpty(path)) { - return; - } - var c = StringComparer.CurrentCultureIgnoreCase; - var paths = from p in path.Split(';') - where !c.Equals(p, directory.FullName) - select p; - var cleaned = string.Join(";", paths); - if (StringComparer.CurrentCultureIgnoreCase.Equals(path, cleaned)) { - return; - } - registry.SetValue(REG_PATH, cleaned, registry.GetValueKind(REG_PATH)); - } - } - } -} diff --git a/SimpleDLNA/Program.cs b/SimpleDLNA/Program.cs deleted file mode 100644 index 0376fd23..00000000 --- a/SimpleDLNA/Program.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.IO.Pipes; -using System.Threading; -using System.Windows.Forms; - -namespace NMaier.SimpleDlna.GUI -{ - internal static class Program - { - [STAThread] - private static void Main() - { - using (var mutex = new Mutex(false, @"Global\simpledlnaguilock")) { -#if !DEBUG - if (!mutex.WaitOne(0, false)) { - using (var pipe = new NamedPipeClientStream( - ".", "simpledlnagui", PipeDirection.Out)) { - try { - pipe.Connect(10000); - pipe.WriteByte(1); - } - catch (Exception) { - } - return; - } - } - GC.Collect(); -#endif - - using (var main = new FormMain()) { - try { - Application.Run(main); - } - catch (Exception ex) { - log4net.LogManager.GetLogger(typeof(Program)).Fatal( - "Encountered fatal unhandled exception", ex); - MessageBox.Show( - string.Format( - "Encountered an unhandled error. Will exit now.\n\n{0}\n{1}", - ex.Message, ex.StackTrace), - "Error", - MessageBoxButtons.OK, - MessageBoxIcon.Error - ); - throw; - } - } - } - } - } -} diff --git a/SimpleDLNA/Properties/AssemblyInfo.cs b/SimpleDLNA/Properties/AssemblyInfo.cs deleted file mode 100644 index 8e262aa8..00000000 --- a/SimpleDLNA/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SimpleDLNA GUI")] -[assembly: AssemblyDescription("Graphical User Interface to SimpleDLNA")] -[assembly: Guid("189e24aa-5520-43a8-8903-1d7e18cdeb7b")] diff --git a/SimpleDLNA/Properties/Resources.Designer.cs b/SimpleDLNA/Properties/Resources.Designer.cs deleted file mode 100644 index 1311973d..00000000 --- a/SimpleDLNA/Properties/Resources.Designer.cs +++ /dev/null @@ -1,273 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace NMaier.SimpleDlna.GUI.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NMaier.SimpleDlna.GUI.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap about { - get { - object obj = ResourceManager.GetObject("about", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap active { - get { - object obj = ResourceManager.GetObject("active", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap add { - get { - object obj = ResourceManager.GetObject("add", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap banner { - get { - object obj = ResourceManager.GetObject("banner", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap close { - get { - object obj = ResourceManager.GetObject("close", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap delete { - get { - object obj = ResourceManager.GetObject("delete", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap edit { - get { - object obj = ResourceManager.GetObject("edit", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap error { - get { - object obj = ResourceManager.GetObject("error", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap go { - get { - object obj = ResourceManager.GetObject("go", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap homepage { - get { - object obj = ResourceManager.GetObject("homepage", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap idle { - get { - object obj = ResourceManager.GetObject("idle", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap inactive { - get { - object obj = ResourceManager.GetObject("inactive", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap info { - get { - object obj = ResourceManager.GetObject("info", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] LICENSE { - get { - object obj = ResourceManager.GetObject("LICENSE", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap loading { - get { - object obj = ResourceManager.GetObject("loading", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap preferences { - get { - object obj = ResourceManager.GetObject("preferences", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). - /// - internal static System.Drawing.Icon preferencesIcon { - get { - object obj = ResourceManager.GetObject("preferencesIcon", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap refreshing { - get { - object obj = ResourceManager.GetObject("refreshing", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap remove { - get { - object obj = ResourceManager.GetObject("remove", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). - /// - internal static System.Drawing.Icon server { - get { - object obj = ResourceManager.GetObject("server", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap warn { - get { - object obj = ResourceManager.GetObject("warn", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} diff --git a/SimpleDLNA/Properties/Resources.resx b/SimpleDLNA/Properties/Resources.resx deleted file mode 100644 index c28ca9f6..00000000 --- a/SimpleDLNA/Properties/Resources.resx +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\Resources\active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\banner.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\inactive.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\LICENSE;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\server.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\refreshing.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\info.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\warn.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\about.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\close.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\edit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\homepage.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\idle.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\loading.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\preferences.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\preferences.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\remove.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - \ No newline at end of file diff --git a/SimpleDLNA/Properties/Settings.Designer.cs b/SimpleDLNA/Properties/Settings.Designer.cs deleted file mode 100644 index 12510b3c..00000000 --- a/SimpleDLNA/Properties/Settings.Designer.cs +++ /dev/null @@ -1,86 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace NMaier.SimpleDlna.GUI.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] - public string cache { - get { - return ((string)(this["cache"])); - } - set { - this["cache"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("0")] - public decimal port { - get { - return ((decimal)(this["port"])); - } - set { - this["port"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool MustUpgrade { - get { - return ((bool)(this["MustUpgrade"])); - } - set { - this["MustUpgrade"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool filelogging { - get { - return ((bool)(this["filelogging"])); - } - set { - this["filelogging"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool startminimized { - get { - return ((bool)(this["startminimized"])); - } - set { - this["startminimized"] = value; - } - } - } -} diff --git a/SimpleDLNA/Properties/Settings.settings b/SimpleDLNA/Properties/Settings.settings deleted file mode 100644 index 8a76ab1f..00000000 --- a/SimpleDLNA/Properties/Settings.settings +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - 0 - - - True - - - False - - - False - - - \ No newline at end of file diff --git a/SimpleDLNA/Resources/LICENSE b/SimpleDLNA/Resources/LICENSE deleted file mode 100644 index b648188a..00000000 --- a/SimpleDLNA/Resources/LICENSE +++ /dev/null @@ -1,17 +0,0 @@ -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Taglib# is licensed under the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 -Please see: https://github.com/mono/taglib-sharp/blob/master/COPYING - -log4net is licensed under the Apache License, Version 2.0 -Please see: http://logging.apache.org/log4net/license.html - -GetOptNet is licensed under an MIT LICENSE: -Please see: https://github.com/nmaier/getoptnet/blob/master/LICENSE diff --git a/SimpleDLNA/Resources/about.png b/SimpleDLNA/Resources/about.png deleted file mode 100644 index 8b223a95b1ab1a05f79694c4e24f86619988063b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1078 zcmV-61j+k}P)V>VQ)ppwWkGCdYh@s4baZe!FE3+qWnpw_c4cF4ZEbIE zb1rXkXD@7NV`Xl0WpgiLc`b8cFEcJMFJ6OMyZ`_LI7vi7R5*=o(@$)Zbr=Wm@9+2i zX}kVeyRq7a&21f1XDiv15Hv1kGiHH!ArUZ`XgFxpgv5(@;xOf4P!~-+c+mqUUQmJu zLp*qpWE`|I{uBkaF*?>v+O=KVw|(FD_t#s4;`jc1lIO|uC0c7dn8RmbwAS*wlolB+ zMMf*8gyd^V(AA5lURu!_{~90<0&@$6A)>vv<2JIxeSv|2u+h&LC#71uxxUqCHXJuE zCHZXelY`}lfc*pb$m&hE(hZZ1R7E*b$NC3&gGTTGUxuOOJ5wj z)CKl`d}V~%>Z9W`>A8qa2a1(8d@d0V8jwQccBui&q}UO$P~L9UfBx;yKd93_dhwg% z6?*tA3}woeUZ3oMnO~k@IiR^Idao;2- z0f07&`H7vq##4JnVo#Q8E*zJk)$!o@tb3c5(}vUT!0EUsRvb(W?;Pw27_pP}P1EEeuz>DC4qXDC-|Ak=^z2tp_gHyR}Uu}E}nyOA@Y{PDqf zAmMQdE+iP2@O>YXqkVXNZZ`nn)stu7bTpLGAcUgraU^1q@Lk1orV;`G46OmB0i_hA zRFG13S8$qjc+!GlnlSAEq*5SSQ>BHbTB$qhl}0OQQ4j!x5Ku}0Lb`xffYKUDYiOkq zvQ1QKRYnB6VM@uCZ*J6^2c{lHC}1KQwvmb_F`Nu{f#>&R(P0Y3avRjL5e-?oT>hI2 zsS3ui*~hk)wqsMtXdsj$r?caeyM`XAHa%>$T=-1FHYtLZf&A4%WAXQVNeK4twQ~!< zK2)Y>-}!1pEB;|B5!pMG>Wd`f(H_n@?roNNaihfR)!HvYuoKsR{QUm^wh;j4=jZ89 wYrzSrb&g0sC#4WX${Rwl!nN-|y@~(iA3wmrd5^XfvH$=807*qoM6N<$f_LQS8~^|S diff --git a/SimpleDLNA/Resources/active.png b/SimpleDLNA/Resources/active.png deleted file mode 100644 index 63ef5038483134ba0ed7d70b3d8747c2131ee287..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1056 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 JPDHLkV1mAPc}xHR diff --git a/SimpleDLNA/Resources/delete.png b/SimpleDLNA/Resources/delete.png deleted file mode 100644 index 61935852eb545604d8739b9fe54d44722f915316..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 482 zcmV<80UiE{P)fOEhIoLbW&@}OZm*ZaE=fnHE zQ~b*{V2t7U1AIMwp2>oYkY=-aXMr#c)nIy@ja{(X+L?kZ< zL4Yv^V+`eTIX`S->P)2^qNERY3;<4ZcwkNNp7Zp5;AjKf{B7T6H z7K$;wTN)8fToCQSV$+QqO#Q&sZ0iseT9M6oFhjF#YAe3W{|(Ih&u?blgZ~U+lHy(Z zfEnP}R(g1dys47_mq#z10cH*!ci4`$5?D>W0r2hlIkux$PfFdaJ1vdV-c&$Y6qM6=z7>zUrb8|$BG>39|jmV1jOTU#EGRpi+xRHO?}@de@`-W?HM1Qj5D_ogg}SY zdLN|}^?H57O9w%Kn@Oz|d&_(+O?3c05d+({v28n2?E5}$CdJ@bk;TUuUX_^(h)oH!))dmc3|x7NH+_f7=kKWb2fXhZ zrnAjAMhLXlWV2a*$wSOL4(~qIS$aJMy=iu>tN_|Hp>9hMh9SE@rg`+GoBO#O-SQ{L5?nn?G7$uQNU|ANHWktGp13@enLu*Z~ zRzquzloG8qLI{Kqt=k(B1Emy><7_&0#$AVO?!Z)ABOQ*>c;b#rrNa{^^MrT_o{ z7j#8fbU}4=Xm4@=Okr?uAVXnnVQpbz;I3%t(rfz`wriW8pij{kaM`9+xT}E(>N5!9LK%si2u+lYplV>V4A<)caI<%X`mqw~ZDJ<)nmF(e04isrMW+QP#b_3QH$N9P?UAp}DB9bk7m zNkk<{0>DnIb(g&g7z$jpnc3Q2)I((Ul5 zl1oTbVI0MO-{a21M#B_R#9l-oXcPp6(?)2~B7y{4Mu9@O$#RS~LMu0okc%jC6BNCq zMPfd15iMrWDWnuP(IPA}ow0!)<9P4f`?UyPGZWN-v-$pq!}*{8hcSkHhP!mEu~WAd zo8?nd1jeIrclCk3aF;a@j#!~$nl%(P0Jzf98$5aR>}dqE;fU4n-v&x*nhu}wwKrd{ z4f;b9;fU2%OeY#6`YVQ=TOJkJo9%;vsn26nmF>ePxAA!V*2;(ZnPFo%AB#FaHw-$p z>A83xDHKX5gpddX0EtgSc(|1Lcd)Cxp7`{*Gd4M}fH9|HQD+7~1Grv}*vDrmsZm0K z5C{Q60m5V1o+G_9&%wGQR!!BO+NWc8C&Ce{BNlb~H9*c=C7oHocC*-S7Ns<$C1sQZ zLijB|M!48sj(1C=)P(9pYjao0(5pv%$FEw)G{Dl2Io>Bnm(2P=eF~WywGEfv2*dEE+1BNH1p0gO_(!va6Ym6#!ZeU0XL$ zmOyFA$XqYlC#eqYr*8WRCf~&E#M}5+`DMhod1o}n6nu_w#4?v#yZPlMNv2Zf#pvLQ?bsc$8%}?|wxEMGI60fdRAO~{ zc52bv6uF?Yza^+BugrY=o*FhT7dA)!rvyS0Urwj)#iE6g^YI%&-U+mBcICDJ0000< KMNUMnLSTZVNH5j^ diff --git a/SimpleDLNA/Resources/homepage.png b/SimpleDLNA/Resources/homepage.png deleted file mode 100644 index ac5957ad62d73408cd754a27453b4ce601a2b042..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 928 zcmV;R17G}!P)Mh53JODVWnpw>WFU8GbZ8({Xk{Qr zNlj3Y*^6%g00QhuL_t(I%dL}LXj^3*hoASH_nc#sG-;dWqm6CW(4s83b+X9Bt0|~3 z6mOI%-9=?M5O0K`ptn*G#rs`|6-PnD>5WW=H?uIcvzCo^E3WHYKeL=HA5C(SbCR6b z3)#f&*5~^FdoKR`eu4)${@&~<;4NLs{R%AQ`wgX7&~)wW+|1M$58jLW!S}zMGrL#P4P+<|J^kR=q!LjUR<=1mzj7BLp1miL0MTgZr{|x^iYGDyl!|!#OL6OV`f;PXlOge)!c#$#{SGXl@)s^XbSCXaYk@OhXc|B#CG* zL-81~z96~mqojuij=b@~*=YbR90{B}oE@c7E^@~W5Fg%$Qs65I} diff --git a/SimpleDLNA/Resources/idle.png b/SimpleDLNA/Resources/idle.png deleted file mode 100644 index 2d1b665b35053a0167f9474c96b4fff862b22512..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 912 zcmV;B18@9^P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGh)&Kwv)&Y=jd7JV>VQ)ppw zWkGCdYh@s4baZe!FE3+qWnpw_c4cF4ZEbIEb1rXkXD@7NV`Xl0WpgiLc`b8cFEcJM zFJ6OMyZ`_I7IZ~ebW?9;ba!ELWdLwtX>N2bZe?^JG%heZ==Es;00M|fL_t(IPi<3K zPg7wKy}oID67^YQqQOUB{0lDONlpA6#wSCFCSpwNMl5YGEJ+EaX+udjD76;45n9?p z7nZVFl(tY>0v6FkvE!L9z2p*@WODC!^PMwi&dimF=uA#bOx$w2-H%-^*Gs3<`C@c* z^pV|ezj5B(QwNX7bH(fRz5&7K>FMdz{QP_&l}Z%?fj|xR$@+G0KA7Z z1C-s_**Pv2i&Q8SXk%kT?o-H?gR9|k^F$O5hba-_Z7@N$z-xvsZ?lgZcfN%$Jw-CFesjwzfiNVus|sKORLp>V5}g3qb3S z^?JEn7803+t1*ZZ1;j`}_(!MHB|AGiFP;!^4h|09$A(2wxr&K2u$5ve4B~x2HemQ~ zfYTa{=B|u8A>i!m>uW)N8X6kfg3Eg#`w7>N@FyPj^z_sL{-{!^&i|Q|i3PcheBRyN mt-`3@!|i7e~TRUY>G{f`F#0000V>VQ)ppwWkGCdYh@s4baZe!FE3+qWnpw_c4cF4ZEbIE zb1rXkXD@7NV`Xl0WpgiLc`b8cFEcJMFJ6OMyZ`_K;Ymb6R5*=olg(>XXB5Vt^WJ-B z?%Xsp$t0RF#>7ZMV$^PMqFhhw6sv^s*BPOMZ`iE zrL8sXrk$9YwrVs=Ce6&`&di;A-}gPI3u`h)51hr}oae{ka2^s7tdHu=!Zwb)QA=h! znAljkBTU6jhZpXzpQTnn_1l3?$1xLDW%qGztP8vD&-GpC_~9)CgKzf;rN@8!qZqMU4BrkSWc%0PCg>}V&M62vqiCR!D+jljAEXqpf6+CYwQ&SDge;(naYFmGHa#lL((14l#|BN1EE-^Nknk}i=K;ZL*vJ? z{rfh{qtC!e4QwKaji0Wq9FR%@ZW@i;emtD{K3e`~dg`5tl~W1;97&z8+_^Frh0CE7 zj)D9Flo!BBy#nRupi=EXP(YMFfO2U;m+ws%ol1E2xmPZJ-n|#BF6D-gjO2#i>!RjE zlK2rsEUeQ3O>Oe{_pjrnzkZlymg5H|!nXY&J{8*6c=ufkaDO{Z6 zT4`32M)gyjw4FY9@+D?!jh`>)h6S|SGTsz{F&5KJOScbAmhY{f{SRCenPm1WKoS4| N002ovPDHLkV1m#|!MFeb diff --git a/SimpleDLNA/Resources/info.png b/SimpleDLNA/Resources/info.png deleted file mode 100644 index 2b32f87e46ea9f615dabc6f67c80dc2e40f743d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 555 zcmV+`0@VG9P)6J!Ic9`NlC?y$%=f2PEh&31KJ|N_=lA*ayv*zM zvN6YNIamVgenPwDcD#B9Zr?n^cW<7NE6iuEkDf!P zyTytf>^6}@F6%#j>D8Y*b*ROFXb=k$Kr%=N8Pc36-Kl6-ICJXAW$k;9eBaSiCk{jC zNq(Z_kDfSknbv&Ex9;4_4z$?rIdWO0;gZ*yt|_4OL;OKeEnaivvf|YfzRGYRJ5aHC z&XLPBi-&yaik*`iC|a2|d3O~djf>Wk#9ptj0 zA!B{ojCBr&g&-f~`H%~8Ko-aZ8tGddH*TIKmjWtq6E29xNWE$PH}MnO4G@YzS@M*n zHbO7XhYI2rIplsn2}2+#0Tq9+8#Qbib-6tS(IX}S-;>gAAi4kjE5(&yIZO~Y5SqZ; t;CugXK#Bx_LGTIMWCwggb)d`l> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - Lapo Calamandrei - - - - - Hylke Bons, Jakub Steiner, Nils Maier - - - - - - - - - - - - - diff --git a/SimpleDLNA/Resources/loading.png b/SimpleDLNA/Resources/loading.png deleted file mode 100644 index 5f881ea31d01907b17aa6d0ed794c78fa1da4ffe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1084 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 diff --git a/SimpleDLNA/Resources/refreshing.png b/SimpleDLNA/Resources/refreshing.png deleted file mode 100644 index 6d1a3b14268fb7aa24e07dc5b0d889fb49455a08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1082 zcmV-A1jYM_P)V>VQ)ppwWkGCdYh@s4baZe!FE3+qWnpw_c4cF4ZEbIE zb1rXkXD@7NV`Xl0WpgiLc`b8cFEcJMFJ6OMyZ`_LJV``BR5*=olS^nEbpXb{|IF;n zK4*9H>V_uWG);}^uF};~RPfLg2`OF*QbY>UgQ7ywlLbLSvYF=*IC3bi7*x8w#ng7#+Q2Ow@|9*#$?;}bn+?o@!(A#U}5vlmF5`0)m zD!E{5l4~n-XCGTu3bz5|R>8zfWss=gxr~WIzRT+EP3YZ}GE&>}ob_hQX}Nw`2=ey% zH;>ov5=_p_AJvF@`dA@-@c#aIu@eg7_zaXu5GV*C<;9ha)r-ruCC0+D7v4K{;ih2n zjY~tCDPKQ*q<DMTn~=hL1V|o(uM;&5ziL#xzW%duL6M9s+Pxg zr}g^|4cP~3TRvQ$qO`9IC&x#SiRoxLE*#f|>viCEd{i4Q#`3!d;+8)C&@<--G%3Ws zdvmeAfJx#841P!u0j&?H6MZNu|@IGzum3DRvRQ!J204Kmz6kg>7> z6JT6`G65mPe+>gTQre66U!26mgL!Zof>H`EV946Z1d*($NzMU4R|=2{kW%8#ZN#G{ z#_~N#SQ;4T5K@9DrAft=p`=`0Z?xJYyOJOP2q7SZ+=N$aO}z8*_gGxtMk19)B9TJO zG|<@Eq=eH&LkPNb_4>ARth5I)%RnTeLn9izfZ?+r7Vy>2mp~~)G#W$1h#+d2NW~(m zUjK)2AuIZ+@q3!{J9eorW%UpDXVRNa2rrp`Q)d{a>oz61A`ef+7!BOAeBnOwr$wyGl&XO2Hw*nekRosz(0p}~j(KE-U;Q#;t07*qoM6N<$f>Q73 AYXATM diff --git a/SimpleDLNA/Resources/remove.png b/SimpleDLNA/Resources/remove.png deleted file mode 100644 index 04a7e7095f7a3b94a464ccf24bfaf0c0e1a3aded..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1070 zcmV+}1kwA6P)V>VQ)ppwWkGCdYh@s4baZe!FE3+qWnpw_c4cF4ZEbIE zb1rXkXD@7NV`Xl0WpgiLc`b8cFEcJMFJ6OMyZ`_LFiAu~R5*=olTB!wbsWdP|NoOT zd79T{iFxAG#%)fDUDq`PnFH}#ae=-L%cOG;&4qD&9(Xs4tZWyn9eeTJ_9;Mt9gO3bbtkW@c zvk6iP)M$WP7J~0ggNR_HQjoR{@n;R(>A~CXdJZKYjM%;62v<@)?oU~9wA&!1pjs_- zKD`W8tHH1=cv2~dN(J?c7a;08&_Y1Bnux@cAtl_CTxtzs#7S#_2+$g&?{$MnL-t)L zDWR1DNd*vbNm6sA`77F37 zyJbg_UgcV;jmGBY9)*IMnI`z57vz6o8ez|4$edFe*A zS}t9g{%JkW0ieO;$J^Jx{dK>ww_}WtgE?IoQo>{UF)(PtqZD|ng~79DQElAaFDxxA z^#l0m9+mU2zc8jX=F(3;H=52om1euUT-EC!A;5wGDAUv{3;9}Maef67Gr1eZtphQA z^XjuvrsR9RaP(X(eJmPHT0!XwRxfXN?X9(5ySeveM|3aEE|i`Bt?{3I@zR+z)9y&0 ot<807*qoM6N<$f+U9TkN^Mx diff --git a/SimpleDLNA/Resources/server.ico b/SimpleDLNA/Resources/server.ico deleted file mode 100644 index 3f812e32e50259d44a952a757965347c867a2484..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26305 zcmeG^2|SeB+wY9A?@Lm)X+cF%Zip~SMb=X2Dod0Up#^0dRFX9+ilS1fq!FQPLxonQ z#m-n-8Ef`szUNF$|L*J1Kz2qe14Y0Fv}_M0bJ<&JBk=Ksfl58;2A!JH=o`^gOQ-$|AUJS zXyo_>VE;YZ7cX8caq;5C=QnQLc$Jlv^##y#c6RnFJ3G5Qzct3PWy@wgefo6d$&)9H zhYuez?%%)9c>MS=6PlZw8TpW&S@13W(HPa$)l6tE46<8dId{MOFhK@)vH$-B_$<{ zyLaz?0mMgaY;3NTm6Z~Jyorg47~RM&kRIaW<9|thKj{y24kOwtDk^>gNDsf)A9TRi z(9qEJ@#9BEe}Df^fKI26A31Vl!xv<~a&!3bVI#1WzSpl`545+p545$lF(EZI_2@5k zVK6X^1vEhn`#F$t&?c1%gilD!&(Ix)k&)y1_xe`?|Gy*v7L82>nD!?? z0=`Aoj%LX>Um_wR(yLdm_AxRt3NSP@4Em!0eF8N#H8%lb$!|uEVT2`1mY7p0lo7N> zAfVA`%oeRV2w2akMbE9Rt<2xSx1cqV2Dl;Wz_`AV1}1)3bBAkcYMARDS~C!yTeog8 z0r_s^Khe5?d~;)CBlEitA3iXGgM*s@@4UZ&A6v0v#d5$u#KMo(euSf_sE7$H{K&80 zxpRk6Utj+PKdgDRfP4Bk^3LoA>y8S<3xh2DDCR)xC2Q?LYaikt#Up4^Thbm+TMWhxL7cg&)N~=pLeVa8qeqXJYdN9?#TH2ZuqHkGE4-t=2tTa* z1BfrQ&cZztA1n4k_>m4!Ooaf^g1$re!^6YBD}IEF1qcTM)-!6qe(vb#_^$Yo&Jmx# z2P}HNH-45~vt*3s0n$0r2f~Tu&H`i~ot>TEjeoGG0W>zmDGZ3=nRp?FXA~9|GJ!Q0 zSuOGn5EK0w{J0GpHi)fRvt};Du1nXgTelqIEdvV+3ln(18^xVS?l*7VWL&;{nK{>T zb8~+Z!+jmo<>%)!@k2a29vT{Y5yn~rV;TdjG&eUV!MF>Ijg66CM)?f72-mJ%TMT~o zN1%N#iV*<+;vRd@MtE&se)C`EFKVGgDA4T(zRC^0H3T2R{|P;Yb9Z-F*tv730f3X6o15#79Xoabcsn~g9|!!S zO-)Tq--71h9|0tPh~+0B{-?RRy86PHd!coQ)@ASBy%w-GECSppm;22N&3~5u3knLp z=$xhdUuuybM*K%aMAXCJEE)eMo?rVB;fHxWfaW%`udns|YxhY1-QC>?|99~}Ec}Sq zpXWZm^nCmF?eC5s>6}WXGIKwa|NR!Ab>VySkLEwJZzS8_0~81J^z?jJ`6D0qXY~KQ z@gx6(_(rz1Y7_ zxchGn_-B7}baWJfc(M`V>|U7rOaOn-3v+@A;G25EKlj3#)eX3P|IGM|U%D_HV-m^_ zKLzyemw^m^9sq~hU;F0k_Y4?^L1qKsWT1K|luR*u08}SM7a3}&|6cz};9m*+D}jF{ z@Q+FW#qX$o#QhzB6UM*;{5LLy3+;oT`j5@2eH2@8M ze*PtY70_5bJUk0w>{$S!0Dspd0<}*w$lb=BoSY`UC%~8^GiJg8_Bw)YM z1@iWx$;nB^`1tr27#ka7AV6{6*MMS9^o&~8@2LH{FAB4Qf`W$T&6{Tfbjt($UAr+; zS@c8P%&Z5ZnjivHw?s7~RL4d6Gs<64O%dgj=sn8uQGEmDS}5m2_pH7s=KU|xFS2sw zN=K+Q4gQ?|va&KJJt)UPJfLS(mqC0XI#KS4YM_XpU!z}HS$QqU9(Kqu9)Q2&;($8V zhD(<&4g8#bBy&V3s-Lpss^_BLko=*hKB%s)j_hCL?;xBt zCe+Buo&?Co&FO8KVguT zme&7s`jN~LEy!kAJh0{isxhJb8s++kAM}jwzotJVB;+HEjZ&7s_4=BALd`tUJ$sgIk@4+A8=l?SOzsDc? z{hy*A`EVp(v^F8TM$c%zA|H?ZCGs_BzOv>rniD?0O%h> z^rILU**20lvUT)~=tp~?zqc2He$ULzWXd1W5BrhKH5&FNM__;I9NFllc7dI4h1_H9*|TStBqt}MeDli%W6cJ<%V8gJBgE*Q5N`!RtQ!jT-w2@ZDC|AP z!|!Kc-?9K|!A$zm-VvhtYe4fA&4E7($o3HZP}6710OT|Zw44XqN(5St1E0}APZ-b> z46(>Qu)nQ9lOfnHinG65=o}r`3lYxKsKObU6#$lSZ;k8-+Kr$~Te!D}^Nvv<{~;v* zKeFHXN4`Py!GT%ejkkbghg zt3W;z#l@_>LUjLU0QG~jhfMi{{SU)_$jUDQ{hMySrXR(W$ktJA_$`3!AKBjL`TJjs zpIP!pa~AE%f9(_h%suj-|I+{G4DDE`!|3~t}-}>esn!g`W{TtQbz6VT9 zO#IjU=jP3uXTrY4M|6$`)$xDt%*pTlj>bS|^3a$L4i2CHD(sKj^S6AtY11YXI72vy z)=gx)zenS*{f=ly`g3t{`3PgK`W9NgwGZgQBQP*<0ND}Z9Ww4d~60O<|l{eG~SjemuPzt|VQWy_WvID<3}E!xxj!vJ)T z0XY9f{LJp3jwzwPi9**mv^}utgZj}hOc1qH4CDN*mh~O9tbX6KC1Y^G?)opbuzQW@ z{GRxJcRY}fE|SMEh6SQ_900ZG;1;xD=BBIod8VU!3csO&KJ1~PKW)HaTxhp?%%ZauPwWXstbPbJeb-7 zpK$H*FkJ<|sKPzAnmkt)8iKQ)36!Zaqj|?2*x|2OR1Ed?*7+pSPjfe{?|)SuU2VN! z)AEaabGZ#GJos}T+8nTXwlsG2JkO4mX$GfeuU_=SHgl0>7fzbbxI6y?kJW-@aUPzJ zmybJ4{mTyF7MxS=w{`T9f3N{l{#Zddk3?gWL1yS2V@7E7FPCeUb#Q7^TxwT zyf{`lyr~F3izG*Hv#dzdicu!U)UP03-gR_<=0R_>N`qH|8*?TeF)RqNbFDUT3cS*Z zI(Yat+bscnuIBI}yy3Bq0`|dboihgy!Am}T&dgzNLac(FHTS%2venC$H3n^D5BgD{ zKt#Nv+Sd2l(6d#t`*g>9LWcS)broJ;N)D)-5is6czG%6f*MaV0Mv<}KP@}h8DdS

os<3Fn4J3I@@!!rsm{(7w7j>99|YP(xXQw**BwgscNY$c z-}H2wTYqEALvi=cnoJl@Ozl)( z!Fu0U)OR+#id`_FboZ6_Vkv^`i5}u&od-sJdX^IBG43= z8%C|9U9Vdh_b^RMNKVLjeaS0|eMj~6CXlZ`P)Y9OqM)3=puB^Wr%aIm2;Jk`Zv(Ea~t_#)IY;v7uQhoW(q)Qv! zf|*hWbE>N8y@TG%OvhF3@2f7zJ?YKOocvfCTb#;Rd_5<1j)HJdr5-;$;ep%>>8Bhx zRSl&CAD8Z=CA(eolsC^LEwnB2yH$N__gkl#lraA#b)Lr+)3j2!@fRF#WKPbtxaec& z*LyJD)gflP!fG9hD(xx5OB7X`{N(QU`mWQ;*~Pw>Gn*9C$zLSMo3iHo$|;*Jo^s91 z4Dc5oev{~4a4&qSue9bKE>W!MY;D(kYaSpWSoMBsY;yeIi9LIh`G>Z|JIzwwShF-y z%X{aIc_}x%B3|P^2y6?&Zmr?qFF(bY=nhmUOqLBD%N9K+1giJ3njuP-Ue$=3UrMka z?rAZ6Xe!zDT<+u?3n^pFOA4sr5+#Sq2GsD{bXGNO6OzZvW0%i%k;S(NWBJ+Y(+_M? zx5vj!2Nc5c*z-$fL+zzm#a=YY`|RZPLEO}+^YEzyzNcbVw9hVw@@AOJoAt?*hm>o0 z1AZ8Mj+-bMPgR(Z813mQ*|iYIe5rz~&^E@ZqHnYPn1Hp*$Ybvjea6@>K~eHYG~i_( z?7D$Xj_b*zGn)MRO+?8`DWBddPYGxZQ;6Wx3tEh;SPDcr;Dy|bu^S=Gq4X20?E(wm zEt4(fJeYtvaR7c5++j6&tX2=kUo->jfAhFse8I+T$Bx!!Imgez#sm8e^%B+GR%_^d z=K7=%SxmCB%_@mp~;DWzD@wyrSfH z_V|?0U;A1fdsadq34WqUKpxu1iB_8|NO4k^#H?NhjNcVocR2U3hwE0rd-a2 zaFb;|F)MA1eFS9TH@L76v(0!=jo?qe1}+OSCN5t(v*PbwxL!5P=+Lse1mbQOZpB3cNozx&uqgS_7fGFs<|d7nJ6(zs;q=0RrN!%4JmVgy;cTxzm6?ilhdE;p3E_--~EDPS{&!~tx+Ifg5kDdHv zb}aF(5y#p07#d^781jzDbiPv4Zzuz4UPvAT)V`QV)a`NOd>_-B1KY%BlFm5t8N$0bQ{+HRTkSEx8HQZ_nX6KDqv}ngGB~c9ds+ppA z`&5`hUsT&D8spLa+Kw@5m4=Ov_gBhebN{#27vd@ez_yNF!3ugxc~=xpK0GmB@pfq8 zQCnC>=YQ4!I0Fv5MLw6W@UEMs+Ibk`lUX`^zU5A+8D}GPL0zx-dW7B>yJ(X5=Kehb zDOp+!6AbIN=H9-&e4`lXJbVu~mdI9T_V}@P14EM?N7M}pu;fp`QrBYEt6AieH`xH-rFJL^K8Xb=>tOoJD;ZL$<@emjk zoa0uP9@oPmAmx+1wR0h7f?!45tOUu5#N{UyA5Ck2rB@NhmSFT~?i=yl z5x2^c9J^X3`W~&Q>Fj#@X2GNN<62&;!!i5XFz#qwiu!2>k+!|-H9VCxxa%*4XnJJG zyyB=U)4;kdgJcLU8gno)=gzptTsthyLL#r+O;b6{^dwXbsfnh&gmO> z-Ip`z4Yh$q>Yg;E3!j0jE;*}Xo;PW)BG%=lBJw1X!?9<%JdM-%m1%$|Cf(#e)Oc*T zJu4dohhRXDwJ5oP_)`C|*p?||2&dDzWU5t!hwGasa~93RlclDc z;;6R`FiIB~T>D0wc6-%=orfE=lJV4}R7_=+&CTt5t?LN1?m&j`EgTz1XML`Fa|rma zvIm8}Lm6Io_|;!fNAK>qUO4#TjJEHYy^VXTPd`7uD!PCFz=yrU+X$yxeXsRwut~2E zG4;95`!1?lo6^NT*5uF#%m4z(7R_-G&Yd@RA4YoFNLBsj90?H&LA8Q1p{i*L`WzCH78 z#yeQZIn(P~3N2y&>^MSSSyLpGTz#jbn5??9Xyi>@${Q2)#&yzC-1)03Y9}B*EA)MU zr#Rh@)h!yV+Ywqg`r+zJN=9$rL*?X;(ShS_dprgc-HY~hJvgqYY+bm2@2rBIeU*We zS+DDE?x-(<*f>5!5hAf_`ovH(L-JK2rAUS`t^+Y)cXWt%M_HsKr+ZVuNDjZGT0@b` zbNNM5*SkseT~DHQCw&MKhCQd(=y=Bo>I~Clf@8aEJBM^U7{1+w>KtRTAp_R4?`VwE zdo|t(7Qp-wrJNxT=npUEHkR+%eWY?-FuCFswoSpbh;klJ(%50aLp>}!D_~DAt@X}5 zUdPad?d4Sjsq)^4g=LZsoeKq~MMoG-Js(i8Xy>XKUEO_-`w5OonNJd&JI9u&M2ujJ zL%}obdrr)^;b@(htT?Vixg{|6F35lH#Jls+nwyL1Jwrdz-0kpz3l6xyEq$xnV&&G} z*4s0Z22q`r3eF%4+r}|rVWxdSN7;_e^rq=0%%f%IP z-c}b6w}z|JeAQdE{4={kyPNq&9h2G4?0a)EXjm&G6a0bs_=H2xmSI?@x-jq3+@rJ% zh?|=t^>1-D@OFhZJ9^lcKL$?6Y6KmsreDK-f;x+cOB}z1$mM&UwR5W*?=}~fsL~ev# z`^vy1V|V<7P=~)nN5sA|o!#VHWKmba@mD)M*3zS9cO8n`9>4yo<=#?XdhZ6Cr@J6m zjdW-hYR<=AY%22GC*A&VT21wRAOEF&S2ZUsr;I;dT@j~kAr8wEN2k}z^;Q!tAdPe? zw;sgnX@}_{8AYQXmiLTOGB)K~mN~D_-}8Pgf4B5=V0d~>M%a+qhga8Z+|teNI6K?> zi@)02)401gK-;ytd~{j5ByA$RH$XH!(VLc~Q*FVc~t5@@B6tK_o=d9U-Kdom~;5{X8`bTQ>yRgdZ_in4_xKo?E zL+FW=uIM2Sa*#b&9zS3Cn0N3|d$F8VcXG!lG9h%&o&j9CLJ()KPF&zT9ix2ABh6)e zxVI@`p<`@m<=Gc=xk*Kh0ZTh`XnHt%L7fL11uuLQ;KpPX1DgGZz(c3#h2-S#lZ)5~9Qxe9XLp$ZkKOEerAa(CFcxiQ}Jfe(A3P^ETe5l2T?gj>x%H9S)F*tavYe6_LP{aMjVTMK*3B;~OULRgd6()97}mshK8)I^^W zh;lem;$vT05a)wq<0ac^L;6&LeK|XMs-T?FMfYhx@-ee$4R(4RTdsWNcy&B$18ZuF*xh|PrbflRLk1LsTCWTjisPe4YM3(hD8o1tqZITG89E_y+ zFAQpw^O04SRM$JF=JG*#oRe1gW;l;s&Bi`oPRD%(rEz+_8_i78HCL{tNUT1-bpXuJ z9~@boXN~lIiPhAx;w@lnIBJ&XaM1*eH3|L4FCC*1!DMd~zj&Lkfbxh=SY>XZW zC;2B--*JB1T39@6Rd*)ndeWhZY7T|IyS({r362G=g7xbYd;6^Ej}w9;8-3taALuxA73a7@$DL1X2CanYy3%`XWNleBA_o} z@_@Z8eK?%wQ!wr^Jg?LB$=pjjTXszAG=4|v?j3BE$EHmshboPjU=Zr@PF-MZ&`P_C<`-)@loCYAv+>mM zAdR(a#c}WIZgzOqEj+=C(!DEqA+_;x>K0N~r=V89mWJB=;)lg<_!u2r-Xj@)%Xuh0 zSdX)R`e63f`l26jl^tyD-XoMXDCu$iobdb7@9giN_DGK1*ZS=Yhqd|ssx{K`@W(7C z^&u%*I|VasF;Tl%sTN?JqWoj_ocH&Z@eSLzCSs81vjK}xF*)&O*IDdD95Bzr)b1l~17AH?|6s#g` zAfyOEb%L1?3E+r|mg!t>JjcXM`R2JWz7SI-haI5TP-^|(RW4LxRv` zr!MByIA(RK{p|`px#JV4Q|&U~02cNrRGmnRiyC5cVql4!8+Rvm7ehF;rA~ImL5om} zgMqs7DVS^H?VDUp-VXG-n@ytw9imZ?HE;i%QL_mcEi!C4U!mcBM!m|9F)^8&o7nrp@XshU!=24^6* zCh`RYGrC}=kT5?L@Pl050tkdrx*YH^0ibHAkqmwQ1m5^UnkUQ5r@yND=(CxgT`*tj z%(3uK>>(ON7F&G&w89Ga)O0O`{z!7!>?Ey|yP%Z7EDb>>N~fwDV~Y-g0*_f@0TTmO z17BYJayh9EPqhg)EY;+#PTvrR70bT5Jcs_^Mx}~YK=BWOTCU0WCv&(-*{FnIg5xq$ z67fnVLx!n9)sOXRxSnm~)m%dHKUCX0cA?gJgFX~!enk2ZV<&cU>$?|?Y<*^NI9TOq zs`QW|J(g}!cNE68tLyDH&>CH?8)C4A+j5E)kGtheR++*L$EC%auQft&Sk&usM=!yk zDr)SQ*Zsk{^uzgaF=ENb6|KsI<>!4|)m6#8-Z~2voRD~PunJXq&)goKQvF!N1Y^uc zp^-SAk?mNzT1%whxV5=o>ZXLWr?T&7tsrh-by|@_AS%V|6F=_!$O%t%YQ0t#;!(^* zCx*F{>&HXoKQt^l`#ff##X}b38Fj-8`Gfw>DdA&QKRr}3n@90v<72H5mG{HLnM7j^ zmsPkJB$2jhHg&>9%5Ee6E~}a^NQ>I=9K1SjHdJXotLwxgG0eNViRc$|*e^+qom965 zV@k)TOu$!Py*WN-yeRv8cU2Ugq#KfVWoCL-)qi-5J?U)Yo!>=V+R=wQr#AKq8DNB z@pm!89c8{@Ct31{ktwE7kKBf;T6K70{Uc+wA*VA$zXQYJ%0&{Kz^i962>7^{Qtbul zvzUR+=xjQZ3B+muJM={E?i8LnJJxOMnQKd4t}ngeTYF=Rr#YbfEGZ)|;FPcGgpQ$> zm*r}$6N5J{(?+MvhFCg_XcY3Ph!#GFhwLk3Cv>6_%HEM7AR~kY@PcA(g>j18Nn>%~qsh?prRlG>3V_FLgp}M>3P}rn4VDFTa4E967$v7l zYbjoUw`x;1mY;*7AalwjV8*94U&isW+pl8FQNmNR=uj?>#f(0JZ!Sl2M^-tpT1)S zTgIwRd=?3wIL1@M$CX&)gcq6*w!O>-YaiB(bGvhhpL^+0!|tYYE5ch-U;J`ww2qw8|V*Z6@O>_9ej@NMlpT*=+$Aq_ya&(hlrIx4H0& zN%)Pdn8&a3ljNhuc|1@qL`d?Vyg68MFTCbuKQ1x zsj-z_R7=G4c|m7S#jz!>D{(b9wiw|%ebByvl$2K-OV(a>hFYZ$NOd=YKbbu{$xHmk zG*r&yN#e(CYbx0H(pqUym!$pbTm;M)eG|+lXQDH!QpCQz9#Xefd-gA;#}wW1Af^nE zSa_(<&2*(X6LAjJYEDMjbTwCN>08B;HTMn>mwXUN8{bCI&-bE_Zs#G@ZW74!ZA*5V;vn}`MnZrh zdmFN!&lV_9Z>Y5l_emWvDKhaf=h=P( z=!kn>eMTgi@m)(5vv)R*o|wapJ)|oak1q;>=x(3c(q4Tj5CO~gQclDC=p~w=q5ZyND8EDyN5$QGgW@mXyk;s#x*vm(V9$1a8 zIse@-vX|d>*bXcUwD+v-j!kwB@wds|w$Q)=Yri`!C$|_XM1-1t9jHKPFiqhm@av3EcJGI$qX9FjxfkC92DFo3Ti#CyK}6kk`X^KS>i0T&K2rJ zF-!qnFP_xI4HoDQ);M}n@G)MU*2kD@6OxbXbOW2u`mn@y<;6^34p!=0jWAQq_o|g`YS< z(u$vNq-BYTT_JXIa^)8+vB8@|k>@tBGB(pARR~wDK*^PrWv`b_=_0KRcrjQNXjS~N z`JwwzcXuxP1_7C-RKvLX^RqFfT*g>4L!Npz7q@K}#da(MAak??{xnlsK=>t=d-E(iIiab+%RXu6Un}kGfRdVOLSh zoeg=t(x>pmOHbBfMNpF?XnZWQInLhl(z`0^F%NTAn>HNvIsmTk0?ZrR93^@}f|<^U zlN2njW0K%0qO=EVcmXG8Is3ez2a~86LV^S2jV_d=?ml>FF)LV`JUL zW@Nm|mIueaHf@D21Fh1FpPV0a!6&}uHOESKdc@AhX^g%*FWI7zEF~1==+nS9feSsb z4#%#pl-5P63w%1**E}$upA*>ASvhDw0Aa-Ng84X_tL9uR9Saz42?hD7?dxm*1qb%o zD}ra}XRi^KkjDxx>{BD8{CIPFq-T;DXpB%i*Syi4N2;ZKx%CuExEG)EV!LcsyFVddP0k5$8?FQWVa9cF@QXm%@%-73e(k%r#S0YE%2@@`ta;>R` zT2Ff7m`J@s&%1I{*Q}C$$ya_d3%5jW_%6wUx*nIIoN}(&xZ$C@n)o_ZB+to&)-c`I z6Mf0rg`A^qMYH?{-fl?YAkcO)QP;K%!eSvu%^V67RVe!^7I@MC>oNY5KVnX4^R!@( zkIO8uE0)*lq!3Co(e>mGUdmRI3=eq+BYxdv)_fm7F?Mo^QcKO)0d7$y8_2s^7i72H zmHre(!b;%tb|x|g(L)*{LSErnN<1VZskd1r$@)_~jMIIrpDtz_>^GC}9qo0*$Allq zW+;wsX>tgtwR)_}oAi|8aOc^NcxvsQzSe1jc?_t8b9;39L)FN$M_?&)4c8D;plf)p zsuLdMH?UEgkt*H2aW-9}+|E>@)d0Ndy31=XERO0=E}0f!hbaqY%sqv>KZ@hos$tHQ z6&)`mHFqZpxkG4Y!Wz4>lvWOFQFjGjw)_Z%u-pOg+^ z$a2q5;T$YtYnkf|44h)l-hzmi0)Ob{nZ&?9IpWsMm%eG4E{QS=N=#G3?wMgclDM?# zLS#|NAGUe8A0v>pyP!N_MAm5xWK6IE7qoI+>RPQ;`b5v=;l(g!>}K0O%b9Q2Y+|SU zr48cb-Qxk60(Nut4D2<;o-xLdn=b7%)xJ#CkI8+|y5R@cc`DZ@-nO44LN2j8t24Mq z)8D0>2Yj=az-k+B$!?;tmrJ>T{)mJ}le|*rhq85(?qbTfI?31zE@3ho44HI84Yyhm z%hC6pdk{;SqG-czZ$jR9*Um{HMGULvw*H`l*_g+JjkujlF6<>C7;M>YhhFEd;uN;x=(v5C{ZCpcyG!bG0* zZv9j2w4ntY^R{yw*u>}5E;xCQ)YX}sKAsyM1amkGs|X;cK8B+fL6PHUVal6q?mZpY z)hTN^In`-Qx0^tnircq5#$J`ixJrgX!q8KJwX;+=?tg!wd3~CBkTm(GV^}=C{y2Hx z0<2^!spk|qgl#?P<*wHcq+#PV-=wZ&dup=0$*D(tvvrLE_t{ZtwZ--i83kgP9U=HJ zX2nhz!`E;uJ(3%>lCtzEY`ng-=O4aQX_E>y^&OE7NFT#xhw4^*>6ifkHHclb!^`3?ADj_Q2mhi2+Cm8i1 zfTFUk#$nGnSp!o()7~YI5A$6bF29%)n6$AqSx9kbf2drspQd?9lgQF$cH*#ykorv8 zDSU=5jZ0TUVz%q7+uO;wbq# zM>vg^ER^0wI>b&6_g!tCz?G+i^WwX;9kvk`>n2>`Omoo3SLb+3(Pfq6hgX%w>Q1Y< zImSDBlFU8>Q1$5G9A=^=xF0VVIfYm6wRNV%I)3xU!-Sm%l`XMFyV5m!=XP?Am8&a_ zOcP`uTSp5PCX47(wHF^QEXkOzaaT}Efg^Mb_d0F6K7Q!1a(T;SujUVyNy8cK-i{L) zk7bP~gI$NFCSeB-lRG4wlqpv^l7yt*aSDc1a0j<>%@WD;Dr}3f_N`w#k2X%8!dM$w%*(tKNRh~ zCQ&x6eDgY}w&)Qy2MBq*D__s%TXsY-m?xm8vyC%Wl-=7T=xlVyWAFP#*8>YC-^uF6 z5BrXmS05i|udjE<69aub7Ym66_XW^|tfpzKNfYAITrTTv+_11tG3H}eL~(wg-`ru# zzR=e}Ic#-zbIc@mO$pjDy;E4|Kwp44eH!cQc~cEW8}VW8&J(e%cJ)DNLiM)7=6qgZ zQ>-}hM>=H`i|*DO=IBbubIiUP*x)r7eg1T>k?2sJfWB~`XE3d1iO`-y3o=xdef)e1 zUN|aLLtJ9j6Ms5#TZ**cNbqg8Lk{SSkb}hjG%b6HLvVUW;?P;BIsU(YJuX{adHwX@ TBJl(0Os(MxQ~iu(_QC%H`&R*L diff --git a/SimpleDLNA/Resources/warn.png b/SimpleDLNA/Resources/warn.png deleted file mode 100644 index 92809728336efb8ebb2b6fada25a01b99a6f5212..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 782 zcmV+p1M&QcP)AVO?!Z)ABOQ*>c;b#rrNa{^^MrT_o{ z7j#8fbU}4=Xm4@=Okr?uAVXnnVQpbeCnn_CMKV!?vg>e64(jjey65la$@4Z&;#kyM04ByDJf z`fQt4r_9Vfcka3OymU82=<`Tzg2UdMQSkjNo0$^v!)Gr=_hjx>_@+=i*x#{oFJih8 zQ$m6gVpc;?0{;V_FQQoupD*CE8hLA+wE1Ydyvwf(tJ^Kywl+ z+R=p2#*k$ebxj)ex46~Ky7UO$&)YXf3$3L6+7jnj-%q2$@SjJc$KT2yF~$+9Ye$nSFg4 zgx^%Q-=?tY04|wiX5u)Rn<4C6M-nSZ2w@z9a}Bbz!QZ%a9<4v)>%=LtbQ(}Rb>bL| zhtS5LKF50xD1Z7gev;n_AlMjjEeO5molOU}tgRdYlqIS;OGFGoM=vhi_@% M07*qoM6N<$g1LfAod5s; diff --git a/SimpleDLNA/ServerDescription.cs b/SimpleDLNA/ServerDescription.cs deleted file mode 100644 index 766cf1bf..00000000 --- a/SimpleDLNA/ServerDescription.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using NMaier.SimpleDlna.Server; - -namespace NMaier.SimpleDlna.GUI -{ - [Serializable] - public sealed class ServerDescription - { - public ServerDescription() - { - UserAgents = Ips = Macs = Views = Directories = new string[0]; - } - - public bool Active { get; set; } - - public string[] Directories { get; set; } - - public string[] Ips { get; set; } - - public string[] Macs { get; set; } - - public string Name { get; set; } - - public string Order { get; set; } - - public bool OrderDescending { get; set; } - - public DlnaMediaTypes Types { get; set; } - - public string[] UserAgents { get; set; } - - public string[] Views { get; set; } - - public void AdoptInfo(ServerDescription other) - { - if (other == null) { - throw new ArgumentNullException(nameof(other)); - } - Directories = other.Directories; - Name = other.Name; - Order = other.Order; - OrderDescending = other.OrderDescending; - Types = other.Types; - Views = other.Views; - Macs = other.Macs; - Ips = other.Ips; - UserAgents = other.UserAgents; - } - - public void ToggleActive() - { - Active = !Active; - } - } -} diff --git a/SimpleDLNA/ServerListViewItem.cs b/SimpleDLNA/ServerListViewItem.cs deleted file mode 100644 index c4745d63..00000000 --- a/SimpleDLNA/ServerListViewItem.cs +++ /dev/null @@ -1,200 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Windows.Forms; -using log4net; -using log4net.Core; -using NMaier.SimpleDlna.FileMediaServer; -using NMaier.SimpleDlna.Server; -using NMaier.SimpleDlna.Server.Comparers; - -namespace NMaier.SimpleDlna.GUI -{ - internal class ServerListViewItem : ListViewItem, IDisposable - { - private readonly FileInfo cacheFile; - - internal readonly ServerDescription Description; - - private readonly HttpServer server; - - private FileServer fileServer; - - private State internalState = State.Idle; - - internal ServerListViewItem(HttpServer server, FileInfo cacheFile, ServerDescription description) - { - this.server = server; - this.cacheFile = cacheFile; - Description = description; - - Text = Description.Name; - SubItems.Add(Description.Directories.Length.ToString()); - SubItems.Add(internalState.ToString()); - ImageIndex = 0; - } - - private State InternalState - { - get { return internalState; } - set { - internalState = value; - UpdateInfo(); - } - } - - public void Dispose() - { - if (fileServer != null) { - fileServer.Dispose(); - fileServer = null; - } - } - - private void BeginInvoke(Action func) - { - ListView.BeginInvoke((Action)(() => - { - try { - func(); - } - finally { - if (ListView != null) { - var mode = ListView.Items.Count == 0 - ? ColumnHeaderAutoResizeStyle.HeaderSize - : ColumnHeaderAutoResizeStyle.ColumnContent; - foreach (var c in ListView.Columns) { - ((ColumnHeader)c).AutoResize(mode); - } - } - } - })); - } - - private void StartFileServer() - { - if (!Description.Active) { - InternalState = State.Stopped; - return; - } - var start = DateTime.Now; - try { - InternalState = State.Loading; - var ids = new Identifiers(ComparerRepository.Lookup(Description.Order), Description.OrderDescending); - foreach (var v in Description.Views) { - ids.AddView(v); - } - var dirs = (from i in Description.Directories - let d = new DirectoryInfo(i) - where d.Exists - select d).ToArray(); - if (dirs.Length == 0) { - throw new InvalidOperationException("No remaining directories"); - } - fileServer = new FileServer(Description.Types, ids, dirs) - { - FriendlyName = Description.Name - }; -#if !DEBUG - if (cacheFile != null) { - fileServer.SetCacheFile(cacheFile); - } -#endif - fileServer.Changing += (o, e) => { InternalState = State.Refreshing; }; - fileServer.Changed += (o, e) => { InternalState = Description.Active ? State.Running : State.Stopped; }; - fileServer.Load(); - var authorizer = new HttpAuthorizer(); - if (Description.Ips.Length != 0) { - authorizer.AddMethod(new IPAddressAuthorizer(Description.Ips)); - } - if (Description.Macs.Length != 0) { - authorizer.AddMethod(new MacAuthorizer(Description.Macs)); - } - if (Description.UserAgents.Length != 0) { - authorizer.AddMethod(new UserAgentAuthorizer(Description.UserAgents)); - } - fileServer.Authorizer = authorizer; - server.RegisterMediaServer(fileServer); - InternalState = State.Running; - var elapsed = DateTime.Now - start; - LogManager.GetLogger("State").Logger.Log( - GetType(), - Level.Notice, - $"{fileServer.FriendlyName} loaded in {elapsed.TotalSeconds:F2} seconds", - null - ); - } - catch (Exception ex) { - server.ErrorFormat("Failed to start {0}, {1}", Description.Name, ex); - Description.ToggleActive(); - InternalState = State.Stopped; - } - } - - private void StopFileServer() - { - if (!Description.Active || fileServer == null) { - return; - } - server.UnregisterMediaServer(fileServer); - fileServer.Dispose(); - fileServer = null; - - InternalState = State.Stopped; - } - - private void UpdateInfo() - { - BeginInvoke(() => - { - SubItems.Clear(); - - Text = Description.Name; - SubItems.Add(Description.Directories.Length.ToString()); - SubItems.Add(InternalState.ToString()); - ImageIndex = (int)InternalState; - }); - } - - internal void Load() - { - InternalState = State.Loading; - StartFileServer(); - } - - internal void Rescan() - { - if (fileServer == null) { - throw new ArgumentException("Server is not running"); - } - var vs = fileServer as IVolatileMediaServer; - if (vs == null) { - throw new ArgumentException("Server does not support rescanning"); - } - vs.Rescan(); - } - - internal void Toggle() - { - StopFileServer(); - Description.ToggleActive(); - StartFileServer(); - } - - internal void UpdateInfo(ServerDescription description) - { - StopFileServer(); - Description.AdoptInfo(description); - StartFileServer(); - } - - private enum State - { - Idle = 0, - Running = 1, - Stopped = 2, - Refreshing = 3, - Loading = 4 - } - } -} diff --git a/SimpleDLNA/Settings.cs b/SimpleDLNA/Settings.cs deleted file mode 100644 index 992be85a..00000000 --- a/SimpleDLNA/Settings.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; - -namespace NMaier.SimpleDlna.GUI.Properties -{ - internal sealed partial class Settings - { - public Settings() - { - try { - if (MustUpgrade) { - Upgrade(); - MustUpgrade = false; - Save(); - } - } - catch (Exception) { - } - } - - [UserScopedSetting] - [DefaultSettingValue("")] - public List Descriptors - { - get - { - return this["Descriptors"] as List; - } - set - { - this["Descriptors"] = value; - } - } - } -} diff --git a/SimpleDLNA/SimpleDLNA.csproj b/SimpleDLNA/SimpleDLNA.csproj deleted file mode 100644 index aaced777..00000000 --- a/SimpleDLNA/SimpleDLNA.csproj +++ /dev/null @@ -1,258 +0,0 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {9BAEFB29-C818-446B-9BB5-014E6A0CBB49} - WinExe - Properties - NMaier.SimpleDlna.GUI - SimpleDLNA - v4.5.1 - - - 512 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - ..\ - true - - - - - sdlna.ico - - - true - bin\Debug\ - DEBUG;TRACE - full - x86 - bin\Debug\SimpleDLNA.exe.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - ..\sdlna.ruleset - false - false - - - bin\Release\ - TRACE - true - pdbonly - AnyCPU - bin\Release\SimpleDLNA.exe.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - ..\sdlna.ruleset - false - true - false - - - true - - - sdlna.key.snk - - - true - - - - ..\packages\log4net.2.0.5\lib\net45-full\log4net.dll - True - - - - - - ..\packages\System.Data.SQLite.Core.1.0.103\lib\net451\System.Data.SQLite.dll - True - - - - - - - - - - Properties\GlobalAssemblyInfo.cs - - - NgenInstaller.cs - Component - - - Form - - - FormAbout.cs - - - Form - - - FormMain.cs - - - Form - - - FormServer.cs - - - Form - - - FormSettings.cs - - - - Component - - - - - - - - - FormAbout.cs - - - FormMain.cs - - - FormServer.cs - - - FormSettings.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - - - - {50E06B21-E11A-42F0-81E2-0911E771E861} - fsserver - - - {56667283-ebcd-4d63-bf61-ff319cb28a0b} - NMaier.Windows.Forms - - - {232A96F6-A2BF-44C8-B623-6E411F6296F2} - server - - - {EF29F98A-B8B6-4591-BA29-E71BCC308E98} - thumbs - - - {A8960A7A-887C-40D7-9632-002E94BFC830} - util - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - \ No newline at end of file diff --git a/SimpleDLNA/StartupUtilities.cs b/SimpleDLNA/StartupUtilities.cs deleted file mode 100644 index 912e1e25..00000000 --- a/SimpleDLNA/StartupUtilities.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Windows.Forms; -using Microsoft.Win32; - -namespace NMaier.SimpleDlna.GUI -{ - public class StartupUtilities : IDisposable - { - public enum StartupUserScope - { - AllUsers, - CurrentUser - } - - private readonly RegistryKey appKey; - - public StartupUtilities(StartupUserScope userScope) - { - switch (userScope) { - default: - appKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); - break; - case StartupUserScope.AllUsers: - appKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); - break; - } - } - - public void Dispose() - { - appKey?.Dispose(); - } - - ///

- /// Checks for autorun registry entry - /// - /// "key" to search for in startup registry - /// True if app is set to start with windows. - public bool CheckIfRunAtWinBoot(string name) - { - // if the key exists and has a value, then autostart is enabled - return appKey.GetValue(name) != null; - } - - /// - /// Sets application to run at windows boot, using an name as the registry key name, current executable path - /// - /// Name the startup key will use, should be unique - public void InstallAutoRun(string name) - { - InstallAutoRun(name, Application.ExecutablePath); - } - - /// - /// Sets application to run at windows boot, using an name as the registry key name, and any supplied path - /// - /// Name the startup key will use, should be unique - /// Path to the executable to run - public void InstallAutoRun(string name, string path) - { - appKey.SetValue(name, path); - } - - /// - /// - /// - public void UninstallAutoRun(string name) - { - appKey.DeleteValue(name, false); - } - } -} diff --git a/SimpleDLNA/app.config b/SimpleDLNA/app.config deleted file mode 100644 index 2bb9f6f9..00000000 --- a/SimpleDLNA/app.config +++ /dev/null @@ -1,27 +0,0 @@ - - - - -
- - - - - - - - - 0 - - - True - - - False - - - False - - - - diff --git a/SimpleDLNA/packages.config b/SimpleDLNA/packages.config deleted file mode 100644 index d0adffdb..00000000 --- a/SimpleDLNA/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/SimpleDLNA/sdlna.ico b/SimpleDLNA/sdlna.ico deleted file mode 100644 index 29c8997dd6bd08c3704d7740fd1af9c491f7707a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 138027 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

v(nsyIcIzvgyp6^9RP)_;2{l|@VoT%7+|HfL>5 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 diff --git a/SimpleDLNA/sdlna.key.snk b/SimpleDLNA/sdlna.key.snk deleted file mode 100644 index 7e30ff02411640e5807b8ad0cd32d48cb745a656..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098wMZfhN->^Nl!3Q5v`Qf>P>)O;|H|uoq zuPj4V8M{Ea1kspx>7m=~Ae!YB7=t~Qz7(eePd3*)*b-~%a=s#O%-qg-@GPL*z6kU% z_rZ(=MtAVlNt1D>hD!9B=erFs`79ybW%gd3zM6N_Iz>{qvKFQq3-ak6OzAl8eiW^5 zOmPO^+X<^b0=H&n5wTcZ@h~o%(e5cR`ANyM%ct%9+9zyuRGC)FvaweMtNrl97Qn?s zamy#uD|T9Fa{c1Xe}>8%>_pA#h$%?caA9j1AF}orjgSmyI)uGpHuDJnF1OsUd=E1f zk2K3S76+h```Oc3U-Wme{HL>gKQqG%c4rE&?-jpk?Bd~E{~Iw+B~Ie<1%V#pR@X6h zUL0C=sJ5rU`+_8=T9L8`X>Kum>Bx}^(cTRDci3P0&#SZP`)nVOm(7?_n}f*+*Mp7U zmFRHUQ!6(|%D+=Co!{Q0Z~W}FwtXwCa7kH`hx=NoeGPF&^xO(LADYK>4*RHvW)k>x z|D7R^sunBQ6`EaX1o|FX8_=_^$?&Ia*X5JrY%JL}CCd})RcW>S)I30*%)=lme~(fB zxem@c$eEzgW0%I70=#Mmb6fA5FbAk;x{*bL8hUCD9;m6A>$BHKjd@@%*%&I!(*-hm zqlVmC Date: Sat, 12 Sep 2026 12:36:42 -0500 Subject: [PATCH 04/37] Convert build system from .NET Framework 4.5.1 to SDK-style net10.0 Rewrites the build from the VS2013-era, non-SDK format to SDK-style projects targeting net10.0. Code changes needed to make this actually compile follow in subsequent commits; this commit is the build plumbing. Removed .nuget/{NuGet.exe,NuGet.targets,NuGet.Config} The pre-automatic-restore bootstrap. `dotnet restore` handles this. */packages.config (5) Superseded by PackageReference. */Properties/AssemblyInfo.cs (5), GlobalAssemblyInfo.cs The SDK generates assembly info from MSBuild properties. Note the old GlobalAssemblyInfo.cs declared AssemblyVersion("1.2.*"); wildcard versions are incompatible with deterministic builds, so the version is now pinned to 1.2.0.0. util/App.config, sdlna/app.config Contained only for the .NET Framework loader. sdlna.ruleset A legacy FxCop ruleset ("Microsoft.Analyzers.ManagedCodeAnalysis"), referenced with RunCodeAnalysis=false. Inert under Roslyn analyzers. */sdlna.key.snk (5 duplicates) All five were byte-identical to the root copy; projects now sign against the single key at the repository root. sdlna.sln Replaced (see below). Added Directory.Build.props TargetFramework, assembly identity (formerly GlobalAssemblyInfo.cs) and strong-name settings, shared by all projects. Directory.Packages.props Central package management; projects reference packages by name and versions live in one place. AssemblyAttributes.cs ComVisible(false) and CLSCompliant(true), the two attributes that have no MSBuild property equivalent. Linked into every project. sdlna.slnx The .NET 10 SDK emits the new XML solution format by default. Five projects, down from eight. Package updates, all verified to restore against net10.0: log4net 2.0.5 -> 3.4.0 TagLibSharp (was "taglib") 2.1.0 -> 2.3.0 GetOptNet 1.2.0 -> 4.0.8 Microsoft.IO.RecyclableMemoryStream 1.1.0 -> 3.0.1 System.Data.SQLite.Core 1.0.103 -> Microsoft.Data.Sqlite 10.0.12 (new) SkiaSharp 4.152.0 + Linux/macOS native assets log4net 3.4.0 was chosen over the API-identical 2.0.17 because 2.0.17 carries a known moderate-severity advisory (GHSA-4f7c-pmjv-c25w). The 3.x API surface this project uses -- BasicConfigurator.Configure(appender...), LogManager.GetRepository(), ConsoleAppender, RollingFileAppender, PatternLayout, custom Level.Notice via ILog.Logger.Log -- was verified to compile and run unchanged. Dropped entirely: EntityFramework and EntityFramework.SqlServer. Both were referenced by util but no source file in the repository used them. `dotnet restore` succeeds for all five projects. --- .gitignore | 10 +- .nuget/NuGet.Config | 6 - .nuget/NuGet.exe | Bin 1664000 -> 0 bytes .nuget/NuGet.targets | 144 ------------------- AssemblyAttributes.cs | 10 ++ Directory.Build.props | 43 ++++++ Directory.Packages.props | 26 ++++ GlobalAssemblyInfo.cs | 21 --- fsserver/Properties/AssemblyInfo.cs | 6 - fsserver/fsserver.csproj | 131 ++--------------- fsserver/packages.config | 5 - fsserver/sdlna.key.snk | Bin 596 -> 0 bytes sdlna.ruleset | 12 -- sdlna.sln | 77 ---------- sdlna.slnx | 7 + sdlna/Properties/AssemblyInfo.cs | 6 - sdlna/app.config | 3 - sdlna/packages.config | 6 - sdlna/sdlna.csproj | 187 +++--------------------- sdlna/sdlna.key.snk | Bin 596 -> 0 bytes server/Properties/AssemblyInfo.cs | 6 - server/packages.config | 4 - server/sdlna.key.snk | Bin 596 -> 0 bytes server/server.csproj | 213 ++-------------------------- thumbs/Properties/AssemblyInfo.cs | 7 - thumbs/packages.config | 4 - thumbs/sdlna.key.snk | Bin 596 -> 0 bytes thumbs/thumbs.csproj | 107 ++------------ util/App.config | 22 --- util/Properties/AssemblyInfo.cs | 6 - util/packages.config | 7 - util/sdlna.key.snk | Bin 596 -> 0 bytes util/util.csproj | 135 ++---------------- 33 files changed, 150 insertions(+), 1061 deletions(-) delete mode 100644 .nuget/NuGet.Config delete mode 100644 .nuget/NuGet.exe delete mode 100644 .nuget/NuGet.targets create mode 100644 AssemblyAttributes.cs create mode 100644 Directory.Build.props create mode 100644 Directory.Packages.props delete mode 100644 GlobalAssemblyInfo.cs delete mode 100644 fsserver/Properties/AssemblyInfo.cs delete mode 100644 fsserver/packages.config delete mode 100644 fsserver/sdlna.key.snk delete mode 100644 sdlna.ruleset delete mode 100644 sdlna.sln create mode 100644 sdlna.slnx delete mode 100644 sdlna/Properties/AssemblyInfo.cs delete mode 100644 sdlna/app.config delete mode 100644 sdlna/packages.config delete mode 100644 sdlna/sdlna.key.snk delete mode 100644 server/Properties/AssemblyInfo.cs delete mode 100644 server/packages.config delete mode 100644 server/sdlna.key.snk delete mode 100644 thumbs/Properties/AssemblyInfo.cs delete mode 100644 thumbs/packages.config delete mode 100644 thumbs/sdlna.key.snk delete mode 100644 util/App.config delete mode 100644 util/Properties/AssemblyInfo.cs delete mode 100644 util/packages.config delete mode 100644 util/sdlna.key.snk diff --git a/.gitignore b/.gitignore index f2680446..4f5e134a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,8 @@ -util/x86 -util/x64 -packages/ -*/bin -*/obj +bin/ +obj/ *.suo *.user *.DotSettings *.dat -setup/Debug -setup/Release -setup/*.cmd pages/ cov-int* diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config deleted file mode 100644 index 67f8ea04..00000000 --- a/.nuget/NuGet.Config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.nuget/NuGet.exe b/.nuget/NuGet.exe deleted file mode 100644 index 8dd7e45ae75d1a55fc669f09bdef4a49b16a95dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1664000 zcmb@v51brDng8G0Gut!MyPIS(o1G*}NCG4@y95#t*xf)#h=BYPBJw9HV!#jrhK3m; z!n(u8h=>>v5jjLu0*Hu+h=_=YxyT_RXV61L%mE@s!U)~PGbIx9YR)+sAz)z+RhYxP;P-g@-0v)07#U%5wD zSGY^U`j~?~@5r{CcWrIXJJZ~r_WZVvwxZ{qIL-4yhhBCb;aP-7`Igd2*mvb7q~(`y z?+3(#%U{l0e39o((tl&$$)h9j7Q^>Q3B&h{AOTyyzBJA2Y<>Pa!=HyQH5mJw<#}%# zd-C=;cjbr9<@v@Fl6py9lX9nIBzfN+wR-JT04 z@;c>BbO*I0)1Z{e_u9P^U+eUKH{7YZ@Vk;1yyud<_uuD?tHJh3$30i(_joshw0T~+ z{y>ixgh6iPsCF;!$3S6B)xyEqlG)gE@Oto1P}b4EFoLRo@bo4@Ff57VcA`28H6qV; zNUcIJqM^dLz(;;)XOa|R3K|yT5}%HLA;|{q3F8idUGj*$0zXDdVV~EA(pTnpdaET@ z%H18-AEZ1Th1|&7w=4N!&4Ou7f}t+S_VwULY5Bt-f<=F4ad1asidvweD^OurxJ6{v z%o#ap-jlVzQKoWI-U$?}0i*m-88+Ro2M8djPXrwmRHLL0{b4ZlmS&l1wDZ|9iXMhR z?F0#vIt=2;d?LN`L}YK!s4>C|=LWS)g`}HsXR&rQ;oNpojiwM+yOo&g21?Y{RqDxY zEJZz_m3*-_vCTWXoR6zK_PKgY^gd5vs8YH9khFbkZ76NCHndw(8$lcLp|$BK4AI11 zU$A{~Mvg{wg?K7ip)EfaX;arwgo&(OqE=x$(s(*FL(&ymHABmKxF7ctsS@jrcOcm3 zjl-fDitXqRqf`05o&4O024Dt;hB-_F4nxNrrU8ecat_mg!zho#G~h7Q$YC0A7!r4w z1{{V4I7|Z$qrDxb0kA*#5yc9+BUCUP+zG^w$Ulf?@;rnx@GJxg`Y&iipFfN!^L?Jw z(}lA6pg9?Q6ixV`sR;S$<_o)Ov*A_A7aBBo)3odj&pLGrM+McW24P>>0$X6w7VS?v+67we2K!3DW;p;*pGdy-^e^XqTCk&BlS3}iIxCx6wI-ud0$ zp_qEGaxVHcU3Bm~5&v4uUR#*+yJM1v9b_Pq=`8llTzDNKoDbO5Q^^l3gt%1B-yr0b z_FVL&aJUoZ<@VYtZ30RhR)TUcWl;%QBwG&Ry#y+qoDDUZ}zR5>i?t0ziB zmM&X;;Jq}?z}4iNi?)jV&Xu5QMzj#p2!qmJ=_q$JkaAPOs8motKyndOqZ){$8BZ;f zctJHP-ySa#eyCFaq+G7M(&@LCJL3bv2GCLuq|0wla{dJ+DR*h)R`lGP`}*{`wR);> zQ+1%OOejz2$!{!AsJ8Rrw64!vg3!~y9nmfM&(JHjkdXTmY&QSti=GVmmH7qlXu?#r zoQoGzB0L;Xc7|$6)Xm5tcAyX=NesXcL#bE0AuUeRZzyamxnlUmAi{_SMQ2mb@CO;1 z@CKK_I^`H2#6zFgJAZ=r5|M}npRBv1PB+0-$&I{~?_z%BVELMmA320?zxaA^DBtzB z@gbvIe^)8O_Vi;;Wbo^E9rK~_1yhTHh}vD*N>wr7{YpRhA#yG`2M^vyrM#(rm$Kb@ z0t9m-gcH{On6gd8Pq*qR4okT<(v@lxeedj2L48G79V4uk@zGI;5OIHWtfN!Es{Tfs z7hF)r;v#%TAlwv@Xnu@E_(b`>3UZ%96jBsl_@{|4e4O->Vfoa7Xs|3C zUqKrkSU-_`E^sXHh_{H3wj3y$NF6(iGNkqo%_dEjb|~9aMT!xuX}Drl2H$>7Id~B% zi%oy~(Ud#QQBh({?lP79cuD^%xFc+W1SNvW+I(j+>zC&c8cmtJa>&lh1*BRi(YB5)6o)5hMJ$b0xk~D8=t1Zs_fjO2>jBdO}jwebTD73^hqH zR* zUqOrb%f4u6Fj(c$k1$d=g*1Dha*hwjmh|}%z0moNZsOe?`VrXU>^C2>5cw05iFs~Nvih=k?4{riJMb)cxx#XHkZ0e@7j`+BJNJ8s$B*PfNkqn zWeh~O`_B~$>aBfIY$bDFrt5g5t9igzIuOg|6?%&5?_h;dwooV9h1!K_cdDaVL0>n; zNPYKt(pKmrqnB$l4G`Zuf2KF5O~*^hC?XgV%U!#($xAz%A00+iL{s(C0*E(=7~J~@ zFNM}U$7e`k2N0b%xh*8>F{DB#m5a z&y9C^We5xy{o+})D~%yUxL8x=iBvMS`QB3RoNtMn;d$@%BZ?B%&*5W4B<)9skV53W zXDV+EKr0N+$T^W9b`S2zD#*n(63>| zza-*y^>p^|JmN;A{HZ;pUh~s>X#loh3sOu2V0-9*7JrEJeZBLK@^(hIDPh^K9VY^p zZ2a20n?YX+OgBS}i48cPlu@i?Yg)*ZfWihz+{G<%+q1Y}jD>hIF4H6rY<$XMtUxaN z84{&k3&ZHO7C1>O1nFezUdi7T^S)+LB3dknhsi!1xQUhy;tvz<@N0ieNgBuFjtspG z{0s0b-3Nz(6+~83|e&YnmVIOknsqF^$ zG3HgBcd#bb%B~b$NYZFj*hxxFKDFGf6_JzWEzC8}6*3jwIm)KBiz#&l~D zv2K_c)C}fC7>Z!(`;@7UK&aRML|RQqsd?gw7TRfN)b7ZVxESdXk!qB8%WeBNZ0#mST_^&aT{LG&74O_*?tyC+C2Iv)&5Q_Dz$ zngl`p#!fZBsSmM?NGi(sjP3+sE?>W_tV{g$1K@y*Bh^&b7db)+f)POM}3A;Oal&Em|_}m*#0S|0f!xsVj6H5VsZMV z0Wj)&Ddl1^Cq8!c9x4-E1t8^mJIk6FPvmolz@q|J=1=v$LR`1X0y{+PKk&)MNPIot zIECV+#2-gLbcW}id*Vv~2HHv4I5p1<@HEk`VstuROtde8|KJQF{c3a>$qU73BVT^O zFUD6Bh_2y-q6%xrN}LK<2D+BkJs^X$1L|9md!^kkl=EoLb&^inaIc(ZSzkv^Qn$+d zY2H@8r)WLU^`s*dl#x7>-Mje;{pgBjETbOT$g^8FqpvhRK^5pOyYkg|7V(Na@p+3X z4q1+LZf>QW?vQ#ySqnkL?Bq*+UWYS)d=M#mG?7HmK~ z%{hM3mc6uHANIIPUFtt$CNF!0Co!M|{>XduOIvQNDkJX#jW!^Tj(m)Mg@r}f25)BQ zo+4xrMxWw?xx`5#gr8v|bOsXC5pp>4ZqoZQm<5CHBw;@OG-&6*?u3i+m4v(47nBl| z;&V{2Qe5XV7?x~VU9oLF(T&wow*_ZmctV(u_+Tj=C$?(kO+oK!F zMy)d?n~;xg;IR--BeHQ%o0reGcSnChU)51}3!%C$)gAq1GM3p)y^MeKXYLC7E^y_LR*edlel%gk54tW$;U|b{8 zDZMs`d}f?GTp`m32`~5Fdv_}DY2GivXxwsAXw3to*Pu?@N!<@9^q0Vgb`n0?scKJ- z?;_Zr{6=aheIw<#vrZU?2-o z{j35=FWp)p{ain;La3|JuTS3!;;9+wEa=wCu{_Jx3d+|jHZDe?-9DAi1Iiwri^L>M zZw}*~U^PG&L1$v>9S*AAB@e2vEn5zIeYw~;sHN^-X$neEjZ#5r&2?;GGU#~=ypH|7 z3MPZ~`ib60K#(TBju-)LoN8ZAyJJ3jmA2r}fDcWzsdIbq zr06PXik`kP^%FIuSEkM1)0d-1Rx9m+43qJ0D45y|?ENA)c28={>EaRd*u3bIM7`E(=Q>|mS^`oD~Hh59Kp z$OU6#Y~URVt65Fi4M~s7wMTzN1bq|o-O-<=x^o0vdq0H>gZ2se_z2|GQOM7Ey>JIr zsiUu9v=chj*W>m$-r=i?3>8S{$F~qIG2$O;UuNDA{ZukYpZAcpr*Kq^o6ITRA>Xnu zuL066@^ks_`d1~J+h|~Xy3jinoK(n#DNM4AvW$eyZCnJ$Lo+h^E-C%!arx{XIa(rz zg`{>q5{z$!M>79#E0IC{Ym(hJB|G)if94NMB4^uN(wM@8+QQv_MCk(cl@i`U?CLyB z|8e!vfXZQ*QQ2V{a2QUF!!+Qq<5Nrn4m%;mG~lokQ%nO6Tb^PX0DHSX{C2Qp2_jmE zPp@(oP|Dgnf1Y{$SN@=(LbsLF?m5x?dI`%$D)8A-7X?ng-kY< zVip90V*O)$j+{o~;;?)sBuCJZwtk5G#MKmb)!H-T*{LU$P@gUg>0rXqk*}q!zPOiq z)C1$rB26%L@f0|+tk2lKh$KC_FX&Ra+@pUYD>ZI@0{j4=g3GRjW6M|`i|#4DjO=t$ zP+e4kaSO^``Pa!{uI#}5P7Evc4x=BDxaIjBU<&9mR9L>O!(O3MCINRvW+p3KzK9z3X7(wZ!I#Md=tR;|r0B$guC zB9a|!rP|2ebsBK(rt(k;L=4XTy4=(vfane?6Vo-2LDGKPGnc*T+Og!gu^d*FoVhYnFY?tBe0Ec?UKlVha8p$iGtR=_G3pNitd-x@<#DJphZn_Q!E@k*ZE z#G^;V?HHV=q!N`-t;wPiq2*$UN~mgCRO^+OL?u+G2~`zIr6#02maz!I(WU!Jfww2o zyEN;W!>PE7O6hqKXIXObw*hcF#DW&$yLpgN-_0c=Z(W=2S7ZB#2?qD!ktr|1?&v#^ z4(=n_Ys>W1t|tGMok0eO#CY8U<;I}u5^fB%ai-O=l1zxyGR8vTM|=hea4$g5hH11` zcl~>WI}3HXFZ1E*h9jj3Wx=lgeGu)xF#|?eX0tgT|A0_w%S0&^Q;;y;Bp;ZQFy1UN zh4_aOen7&NK>8{BbH(^UzV&DddLLF7%a~nzGObR_?q5rBb$;GFcjEiyLIl?!qWc9~ zG520UCou)*{4skXe;1orn}^71h_>-+?Zt5;tDg99M0A++gaNglM6J9Ny(jl>>mnI8 zwCr8Z_graT6`pQ#gaar!3p~2XkqDUS#~QNJw#JF@TZjo+78g~=o=AhpSR}eGXH-8(csF?Ga`DHpW^;5BIX9`>`Dxwe z=zKDPRdJ(7;TvBf2GEW3Vl3P^535fotErM@5dAwo&K#YM&8=MtM_rMLFNK7HxN_w6 ztTd11`tulMR^vuaXFy{bznU+Z3jaau^v|T0w0wW#U0AJjj{7^RRR1|qqk?Kwgvk4K zo#!k+qVoqj)nVp<{snzGKYk2y{Kj_ialC%X_ZJ`>PYWV+z|G~xEi|jlR2KuUtCG&& zcJcm7diq>B;h6~IS`pmiaEyN`YzHtmShFVxvvqi%ME;5}>s`2>;m|)2TNHf=hBgq) z7h{IXFrvx(2R{tZEvrWPO1n&~Iaw~<0RuyZ?NECc)RZj=+tsSjeoVyu=v zh$N&t=z|!Z7<;4-V%=oO;Xw=sU%9;Wh9FsemyP=@mpbX6GrWg?pZe6ktc!Z{kcr=T zk1Xx|E9J#|r><->rFsfLbvhyIH5|aAUe0FF@gksOot*mBv0kl@_JzlCO~#zT<@5xCmI=Lqy1FblX8 zqgY|3*j*_VD;Ugjv0N&LD*XZJOxQj;j-1yDwC(g{p_EQmKzyR_K#+S3arU&VQQL3y`I7kw3w) zA0B6^y}A7F5|F>%`BOZ`7a1GNIn^9l@@{Ge;if(WssZX;b`*m6b~1?6rxaduS!($w z5Owqj|9~)9w@5IUTTmlX(EhJJLo^c+)F<-MxfQq3>vBiHe@Yi<88vleW8y}o8P2Mu z_<0x7lO@uQrFt7a=mm1di^;h3*z*2f7efK4l=RI~^dO}1Vv5hP zn@>|Vbn75_qMJs4kN};ysJb^;C)$r_6vw-^5Z0B_fLI!ag%=>!{e#+}4xbFJ;UL-t zdFrxqrBq*rbA)<^bll?z5-5??>7-VQ_yh$j9exhgda4TEMmRdTF zt@pmt-==ESJAVi7DCD|;>eOFQ`&|DwSd5$@lMamYzokyJy3oO};PH!4G~V4}r|AYk z{og@H1=T1ye%2phfBQRf1)qf!A^8tTWTfnmFzP{fXRa7M#dNmuo)%v8kD&gN@Dfy` zw2kFlZGV?vh<*k^{AUO-3QMIO^6_8fiB? z)!P$U?~Flcg$QL0>i;c7f@+kUFy`c4{5q(vcz5Y>+LEq#(-8(wrb6tq=$bcQ zvgjTC7fmN!SSL@pRLXC_Vu*f<@oks>Bik9SUCPc}R0=6A>x+dt9X*WO_$aw0^GkIw zDyg?wN|qWES#I<$ob7x?+4rOKi4VpZv*tWTZ4zxF(;WxbKaGpR3iD(?X4l`XdIx>Q zcr6u}qYG7YQ(xt9R;6XItp5U?kAB66oGUGR_mdB1xtwbtgr;jkC+0OISdI#+QBF;% zI)`@Ruc9H1_q8OTTO|nu)hL&MzSmD%w!^D)U?G_mW6XZo#d*5|-;?ukkuP^3OW7j- z5(sOLk_o4)>Q7SGI0Q?!9qxPcignue-|roDhZ{N$*E2iVQ5wlvls@m2T=W>N%3DOg zkm7d0GD2VVtoeKW_$cJ6wyt&+YMHzYBW-au#okBsI{GE)!a%pmKG{Pjh&ths&hCzc z%ne7iTVW7)5jQwj!TU&8t!+-V-Az(h^j1O^zTF~*jAV)g@dVPUA9zU8nQoJ6Ji;MU zI-mIGAA#?_V`cKAuaj6e*gCp9lX))j($;*qC1SUc>5h4+2G;&YiIO;7;tNV{*Uve4 zx?);Ly*;tx#fb4aRI^*G4{&Hr4~DtspeoYCIrqYUWVmp}&A1b97+pwoy0yklF4dcq)S?wxfA^(I@ zR`NNt^m(z8_p6S&b)8))k~MkEpBY>_dptt*K%cRA(#meK{xL4N||Euh;)VKam;8Suz7r8_itl6Mk*2RPQO6 z__d4Dpd69u&&hiVaQd;+v7CDTjZ<2>HKSfo@1ZqD1=T2dS%EaY^LOz+=kp#7d2=@U zW%6!aA5gom795vY4f+W0E+%WMV-vBidKKnuy}3Qq4^o-Jun-QONpS3#^Iu_Kp9(1r zh*tMEPHidVAEl7jBb`w}HA?qI8t-o*VsLgN^r)a3<;H3hmd!~gf&AFqr_w&~1%@+> zJEIX}YW)?8Al^`64sc^^!S&f`>I`-fo{+CEW#|dmm|BzTQzxGgCe79mM=3-b<#qVSQ*;uG1Psi(1 z^c#eg@N-l$lJT<0+i8?)?S=8YIHA|dt2mBVQN=@@+}cCCtj~D+Q+CH}Ev>;u%wRWY z5YN-K@1lg65fAW$ZNVPM+5u_210-F13}p;+&MtHQ`QI?iof#&#OW5d$k@(uh#O_Y; zx_X_R@_936?mQQky;4z)MdXo-dC`p*0&3MxhQu8StBp^d8Jk$V2qI>$N%<=CyVz;= zyaTmfM=aV^6Ny7NQKf&ri^8B zf0~IqkX`HVN-}jjqOB*j)VgbS$$7y!Z_2NgJZ@&&m)4PW<-@3@JNUJ|G;jf#C$Afy zzw5KImP%X6oB-J#3X5EVsWL( zCFs%Pky>;-JJBoNi**?a|K`rM*v=iiACYjW_ETv>t$-i>mEyVO!LJG5VU6n0EF{XE zaMSkJbqF*a#de3yRZ26W&Ic7Fq4kw_N*g$M##$e6LJ79iDgjHh_T9xU*?3-*p}80 zt1r?R>`}ppE~^My2x_m5Z=W$+&pgFDm@;uXM)%%#5gzB>&j*86d$RSO%iMZT#tV05 z;1I3XpD6AiUG@LJGXuSxr`(JFkFu2gYM4vTTy>0{eqx5&disgkC5v}jkc(6vVn+rq zAlTFC4~vPJ)5W_QpGWxqu*MxpT;@4GU53j%$;X*9gw5)Svnluma+nVzAq-m_@RB?4fsw4-ulH*vqN~Q<0q}eAh@sD?6P^ngmI*E}rGt_4c2YuB}Y>4nVeVL$>wT)KAHcd=QTVXMe4JZGTR%4*LIiPH<-mK5{PUlXHTr zs8RMgK`FubbApm>Ff56qJk9$*oD<{}pjN;Uvmy}8bw>yPTRg7M&}P|32e(V4>tGxm zTtgYtZ55{E$f9ERbMLh86(1!<;>f z<`7QC!tG9!;&Qt4q{)#v;g78r-|3x%j}V@%;{*do!YMfuF}n%Wj%9sg{4kqKMp!@J z&FW@^zZyiW)wq4?-uaXDJpwvoS&vie{$%~Xr1%2?Z0k=*&{?*Qf*N-%t4=UDPRtDx z5Y$=YXII3Pl4%!EyjXf_e&B4F&=ize`>l*V^jjJ4hUh1$L~b2lY}qF1kxgayp4C9V zFll$@RnKW(D(rZ--7R{vn9ZB@u4;H8{p3eug!3-WTq5Pfud6>psP7%;t^Z|uCNL-a zxpEc@dDBtcsh`kSSD}ML^Y!)kkFs)5(!;~j&$XQ9TQd-NygHm9$A-Rlliv}FB2p^Uh!$DQp8$X>K6FJ6fy54IS-n|mQEbk z{>(re-A4C*Y*#7CuplSEl> zk}yMDD)ZW^Fq_~!K#(}2UyO)(8PY;B5Zz+oRuF%3BEycE*_ zn7n(#Vv~2w|JF9*#lGoaOHf-dDP1-l+yORz#QFh~wd&%6J~6V0Dq>>;E;c%os{#^7 z+C?)#6P(j$<8h{Rf*&@9hr+JPx+K#{i8^7ss2-Lylc-f=QDU4p1t>`fiM-`*k(UTB z)B3U?nW&L=xV5BIyXbBraGDgq6*DAvUf@%+?Sl~u>bqjeBBs=Gbe36l@^1gFX>zyL zE8QxR95yC*pA_OqEZ~6TRf=~bEM815?%{2mWUt`&I+TptD{!R<;)5xMQ_9?stY*|+ zPO}>j;nWT-kL%R3kCEoz)VOp^I?vnbnsiL+*1gtu{J+WrQMAZI<@A3NO2EQXAEK!D z^AYdP$J{s9xOVmU%IO(H6>TYbxx(4lUA;4~Gspg2b&=$?Z7JVq9yt%H7EGDEoffc8 z-Kr(WWyb%Cm2qdgF5f;LzmS#_ySJS#p$>`cST;eIT>cM^PcKS`uCx%cX08S0IP-XQ zm4Z5ztM7Y96?CvOJ41|y7zCv=8?4|?Wl|zk(utippR|zf4cek7!!9yZ*-LSx-6`Dy zN>}Ew*%b27Yzuj4Hiq1d6f>ntnxfFs>1*7T)#|jV_mkKcJRlu=sGMtyK=!}!T4cPH zY_%m|D!FPHM`eX;nR`;U&gPBT$zJb!@Hk$1G<8=kSUB);Vgj{b%{Qi|P;;Fz&wMK@ zj~rA#Sa-`}t|MXMR3TOm!8!{z^QhLy@^+C&k3}Zrv$jVH+O#^eOO6PvNzb2*TeM8x z=_q^GeLb~z(>+EP?}YL7O6mP*I16*;u0Hm^Hri+HZgEtNLzAvkl^ z4)wihKe++rb`g?O&Ms~hspMzQD$XqJFJscw0gB*Nl{B5G*4Dsuy7MyBv(0~U1??%9 z=%|xBwWQj`^R!Z|($-Pn%CsnM6xftLid!s7kyPYG@Wd5iYT8rSST1mOMfwLJCDe;g zf|$cj;eiJuOt%ijn&lx>qwnob)pA;fUUxy@{{fR8m(%Pr)4EFt;rAvwd?5O=^CvZc z+`vXtOaoxO^H1=m=eRDFcCG)O?KbXA>c;b9KyeyBbS6~#T44gp>;R|Xa8`0Lfx5Lv z=R1JM_-a0y$bo{;`@{H}R`_6nuWLn?3UVtS1GkVB$25P8^Erg{fMw&*tpvJb)H-6n zMw<+D65qN;*phjzV+w1)lIsBK>bb)^yci|SYE_9FD`;)DJYU-^Pi;Y(HlaUQo~3lj z^9p&E@)zgmYYuZA9)A|7GubcxWV7r^+a0wheZ!hYpGnm)9wyQ>6bN?$`cCT;o6(O^X)u zDf=kSHptn8lc8o!rCi&)$2)seTBvrZgrse1&q_#IrM6F%khDkbFbRo-YxhVzX8_`hq#g7OZhWx>M@1)6n>4&m9%SD`1LTcO_(+Orz+p_Z9i0ZiD)VRSnfZ6A z{YS-uWZt5!mz$c}b$L&pcN;M$Nxw}dpRTJ`^_6hOJ{cJO2(9L|4SIXpH=ZWj&SK-Y zeARvYc094y1KJ>{FF|rKLlLXl5lt?ypz8b){ZFnIYgqysOpBA8a38B8+2%EgT&EK0(nCM>E_vHrz~ zUT987YWJiGTV5w2VM!7udY@$RQcCHDQ%dgql@6JYc}&CAccg13Hrve-<+;xZKF0G1 zr!JC7zXPUfOQdH!91b6L4Fjq-_I~7;u2%F8>i1~-OQR>tWBWG6I5Vuxn3j%~bk%&k zH@!4Ih?e6eiR5XiKE>0?B-ukK>Ha5Nl9IVIwqx63JuRhn$|MJAr2gnG)pB~O0eFC2 zl42SFlXFS^k^z78%eRUu9V{P*@Uh)v<9DQvh)wobKkfP|Jq9b5_wyqkm9O@Zi{*=Z z1V6^N_b&o(a}P57=<1c zRHLHB5OtLrjIB*x#|Rlx4MzplsA!4IH&|;&o~(%u>`03+3LYg-fzNpj-Y_IpOC5+M zO*rp~tWy#Gur%=C-f(eA+}UPcFdH{oiLG#?O)DYdKr!4}_O5LUPIUVdq9<>I+k3~_ za23pQI+E7b3ST4?x~7p%6d{IywwnUK-1HOEc>}9v(g($j)_%m9JhX=WcN8v&sBWMa z-thjzLEfzlNsKd`eUK)}>8+di1P4Kxu&Z52#?J1ww00G11#Ve>~ zO(;fjct`L)I!U6M_fnMYxw8qfp+$?9i58(s;i#Y*6(O7csVBFeUYf=kT(KUV z18*V2qS_92(8b=$NnDW&-dR}NmNtdcFBcVwkx%xwe)#77tz=$(x_3x2ukK|X`988) zv0c5cXesh>&3XyikPodFeV8h9NykbU6k=)?cGhtrahrQ>6$^iydxy{ zjWAw`k3S6zHf^1s+$N*E7~i+Q|C4h^Vzcz!b?k%wIkTr{nObb0KA)KK zIlT1_T#f4UE@-_6H+4V7Nl)Ufytl{YJ$e~qV`83>gj>fjS|G|ek-~X z9n1$#rtlxcIYd!DF83XXUz*8YCahbgK$4w-bJblAflQP7WplQ_bKppmA%pLh9+RPX z5SZraKT{xzl|3mHFxl_jr$1$yb#DLzGJd`+GyN7tV0^{G>o?1m*!86j#tL- zg^caLV337b+M8j3<71DLyL)}6bKvVDT(?>8I(-jU{GtRc<1MRR&9^JY!}_kbj1;AK zHEFsdvI}*G&;cMkQ48YCZ=LDdZn2c!jdM!@Npve8uR4!ZF{*t>)}x>P%yi5)sr z1|{k<{!*Ugt)Qm&_ZLi0dY2qm)<;j%5L$<7$N%X46^5oX3tT%hEvlM(ZO0vCj5^HQ z-09v$@x9q?3*O=UJnl2ziCjmdvnSJi?;Wn2=xT4yUEd+sok+j`V%oHmLrU8e2ImI;Ku$xm%0}lI2ifO=Mx1^W` z9QJv^DAQNdI1RYCTT@H}4*Ob)X#lLk-BF^or>X9*`ulYMQ=yUgxckKqM+m7E@2h)#pZkA|D1(vRJ<|KTrC=;(bYyxY@yF3mC784aR~ zNybLhWKDA}5AL{JF}jR!I?r=^%d51WtDE_hNyDp20*t+1?GHR4m@t&QoFfHs+NjXf8mCQBsEdu zo`cDJ`x#mgA0wIH-op1P;hU4p1=XkspP)ac%Z9vCi>Ja%ATfQDb>f8enXqnMRMs~? zLVbB{Ba6t=Xe3!eVdwqO&HhV+qQ-zRV6s-MN~gN2bCOy9A*Z=HNo9T@dxhR=(a&Kq zxmCT{gK2y1TCyHn{l1Y&Zd;%)5;5bhQ5D@gC^Y_oL=Mj3FI<$?u^`v7^X5?MD@@XJ zwr7w}ZY`b_=UCk!qE+b&^lb|Eg4KMz=`{bYRAsx@@Z4)MU8N}tcPEbmd)#99oY&m) zN`NZ4dno`N=gkSohfx!lhkT9#YCyu%#FP!&fA!B`-J|ufc|a`7c;t> zEE-pf6fUBe9lEVkXmE*40{9X7o30P*HWa@yps&k0TPbZ2QH~FYZ1lAPPD#s^1j%`s zB5|zweH%!IoduVe#e^UksPtA1!ejt9)r@PiSgO)4OZ<-39XD6voJp67!ZdN zhbjkhKpDb$SGntH{MPGfl5Q?n1IeAYa>`v4O#EBXu%R49(5qsb17=d7!;p2WHIy+T zr^heT;h|8~J4MFjz<_{{ESJ6LbuNBYUeV(nIMFB!E#c59mE44h?A1md;jR6FH-Sgy zE7QD}`94Q=fSC*LP`Qc3?_?y>A&j*}UisZ{Afm%1tNTnMZj^_DbhUoY$45`%us6Qh zqI>@Uqx$Jcd{j`45+f8w$B;sPsY2diKNFy5(FJgK5@=bNs@;?d!}VWAen+n>bQ?=m z_v$#KzqC^^MzV6=whS-YZjC&N=%dRi2Y?PCzsouhJ0_D&-Y(CjXJM<}U2v+YOtx#L zp0M_OTDFd+RJz+iok8s zPXtp_Ej`Vhbav|#Y&Ttjz*^H|U_6$axJTyBmgc=in)haUz^I@a6}>}R_E=E}UaW&J zhb5OEjCUwMFDE~1;tkLW6ycqa^aYJ?wXpk~useq|qk?Kw%plAwV#>)Kx=d2mu1F=} z3^+Vxy!b+L58_i4YD9+mmU|ILWM-30@>rv)a!{6ej-GvxZ++)2<6By^?~ulIn)naW z^?%C;!Z|$S{W!U!^9{mST9=tqB5*MCYd#xEB75`(Z zCZ*@qalI1bPm@f_gjipTF+KGUUk_Jr2aN7V;Gm6&g=d_{6;_LF8kB zqAwFO)~`Cmws_}hT|Q4ty3bn?ay_Gvy73LI5p{ZcQ|v(bN>e`B$O%#omV~LoT}6mEj>$4IVG4gm!yD?oC88R6R%G zbf{`t=j4_Fu36k|b`qBuXAzB)%vk+>Zx+nX*ZMz7rehu^ZpA79UW;{3q?EOn^;Ge{ z7%ABAp%c2p2YPJz8XBQf+lE75$^&T}VCU z&!5>Bf0)=Qi$!Dj)g-k=iBh~rpxWIqcYxc@ADe&7?9(%ey8kuF8?CkQ;Get)~%pW}U4^^5M(uf5MX=bO^1xuJ~tSh}^)Jgn(-)SaJTCQP6I z0@ZdSqx$Ij+$TqJ#Te-MiE7J91b31p?N?n=Xzf?qpP#63Z*i5_hUC%1wS%}o?m$uy zHwdP80B(QI0$Ecg^$pzBtov#f0{lOnv%ogqgJR42+jo=i`{Y~pA2a}a;=Z3^8gSVC zDW(C3{UF6O;IK_8rU8fjV~S}2Ox~OLFTO{$es?4D!Pz|e(aF@T{;xcXhpzR0ng?Eq zh@auRkE?U}N^NcjNurPBN%02g1>=8HLZ^J(0x8L&hd5nS)Oq2!O&&UV=-#Q;cfX46 zO`qw)_JpE1qv`_5ODmi~%cs9WSzktf?Cy>pa3wmFBDbbIaV(`Q^pG<7jmV`{M|+T?dUWE}{*@DODT zw~C^txBIA0iRZvyCo`*EDV*$0G6s6n z^_@~TzuC=_^cC(lyoT^a(6Fj42A5Us_^XU((La%5lAqUW#KWNeNe*W-z6bR|UM=b5 zrc%+uV*PgJkX`L_hNf!LYz>*jQi1CHhEzjaEP-Q`uJ-z+px9n28~!;;yO8z=PosT7um%_V+`UR=eypQ_4z-1qS#(x+oyUf)l+_)UC8 z7u}EB>AGUBv5ijRE|qF>aP1)P?7tuCkE^U_(ilT10*R#+xwF7sTD32b&fqAa+$NHX ze!*wziQG0`IMUsdPM+(lJ(os0)9l9CysQCvmuR_Hkr8Zvf?=L2LuS9;yU@W;hq~VZ zp1E^kZkoo#Z@vg7cQfn&r`oaOiEyv|^p{`@?qUYD)lP1`^LO^>>E0*Ezy5~46Fwn7 zfvW)YXPQPn#5>sXJb`ymKd-tofuCd`z;#~SYs2sz)Gwjm#-9Z%PAK?uy5d{VyHflW z02U7)riIdb2;0bq1%ba%Nq$0`l@r}dm)`;y{2c}FuHd0H81}F?8pVhpKUsniitdGt zx<8mAx!XVev0Yw`=XN3@2St5IC;PC`Y?PW?ORLP&i_FdwZronVBz+U*8khkw7n^og zxqhg~6+;O{XSs`ehW-%>XVfMpX3lvTEkD$t z`imjleR3ql<4^kZdHkP*+{DPvQM>1G{1WeYaB&IckD*e}OIN{|7Bz7>Q}+>`FGV`J z_!6uiUfVYjm@{`r5>;=b6)_4e2OcgK6*_@-?JU|`{<1El`~4-i-H&(M@2;LnjS=E!MRyM z7OulBlA$bZhq8$nZuu=Kw=87LkmV_NhNHTHwZ%5w7Agl>)xA;TIpO>%QY2?R^yEbF zrjrvPm*sMM_hs||StAPSTj=-}*_f zYD&^|>fH5{v?X_7(TLTB9g=YPUQC)!Q8`?%5mS?h@1+q{BE)*P9M_D?*ySOn2T9Jk z__xgC8D6Ho-Zml}{a_j)VG+3BOUk2L$=>}v67RP0#b-{p@nwDHbVOXci`H|OEA?%6 zUy%+ueP4Dzq>=ob=tEG~>!iDYajW@m?8raC8JXdGYiN4?)3m?^Ui!UbPTyJ5yN?jB zw*k4-bLf=(9NqJXr$g?nk_%^a{1_P)jf}Su(RdKfsk`_qfI9nk;i#Y*CBJpmkA2IF zg0gED%8=OHb7DR+o3hFsPcM;H?|70qpbQq5Ng3Lu3|y-5VKU?n?-BVL)`wvUt8oil zQ0>*PrK|<=3nV{w^TKE=kaPp5FQGS!@a59(@g(Zw$J62zy4XccDY;NbMe(Y3`~KfB+V~>ZZRch?KpHdceyKmnl_zC?EBwF=-vX-q{=$qTh(voXn(` z^KCpy5z@2Y!%{9q;@xnLI;#BGBX<>a;~7^se1X#F+Hvg&xa9Q`uNws{2kut#h)dDc zk?EJ=O7n}y=O=IZu*r|-t9z>jJ?6k2d2Yzk-~DkD3r&1)n%J#CBrIP_(Zu!AH-Q|7 z^tA{WPDdn-pHQ1r!+%Hh_4>I{K{YCR9||ot%ALj7bxtB1=b7Yc>~y-bwC?8Q_&Hc` zUmokQ5^xnfKTVXZl8D@U=jXhgXhXbrfZ^F->J5JNmJ@ZdHvB>GbPL?)vTd zeL4CAwHuW-iC&P9$UFKs35lGe7bPT8L;$q!V-gaZr2*;=_KOtL0GRCU9>Vw4V{QH~ z(D3sWf&RdSI*+XI*6yS=pZ^+BwkcvWqiUrF0G$c=Rw2 zB`-(+NfG&Z5oajbz>!yYq`RD3p$l|2&ljX)xvWLjNP8`5xresEK-^KtjWigp^Lpwb zaZMLNlXoxkbWy#6vu$M|##w$A6`G#NbVH-kl|f<*7 zA4m4R^z<%@pR{kAysxHzwTGzU=#yktYu}B~uO&1np{)|ST0;LSp_e7}l!VUdBlNU{ zu9MI+5_(lazmd?yenQU@adQL*;NQk*uUT<_B-KON|xNNS3qW7|R zFWYeZ)|W0PVQGdkC0Tm432^tK07-Gig^*nd`{Q zZ~Os><9?TlpPTv#d42!w3ld*V)}Y;F`+0=XawY&B@;7o5J5KWjWBT@Cc*~zV!>9HXzzCaJHVQ6PrVjk^;) zx~BI$j8if}Gx$S=75t-4Blr?$P9M@puk;&co%!Qc(*N%JB`D4Shh4EaL`H zu-AL2O0obbYdkcf&#dVSn{hJv+oSdjyho)$wT<5b_9dyiy5{u`G=o0L@@6=)4($nK z9vY5(M1rq#lNNfz+EW;Pi;qNpZSvd4-u3X11%)tKLhK3YZ_JxS=cNqt#}&xMPw=>7 zF8a2lm-R<%mbX#TvVK9@P9EpZqBa+1r|(SCe@D_YhP)v4ka0x=BnJDp6w?40cX-c3 z`>G3Rbx-DvVPE6B^2y`AezbtNT+B*|0L|y`x#w@@b=@{EN6Y(li7-u|1j$1_W>%^E z_Hs!4{q6bRza4+p>?HwxT=UPzn-tiWi5#{vjJO6*gg3-7TirN_7Amkv_AJ7gomh+| z0*Flz`QIRI$i0spj=B@)C_2!w(7r9d)tE3+Skg(e+?b}zk0o(qWPlabK3U7j+BWXHJ%c!*&&V zyA!(TgwKzaf$Oi~upg?z+FBq&myo$>+Ua@V?Ylo0A@e8o^`m}@5-oLdnj&?P`{>K< zxkXHsy!PDk>hejsfr|(u8|-nLo=0TaS5GZ+5{HK1DDy}8>fy@cA5wyj!jwhQk@CEQ zxEFY*-r&tWWbO$UWF}N6`q6IWx|~i@@14Q+T15&hNDSiMFtq(uhB;2TyN1b97Y+c*a+5;QD7+}IxnDdmvZ;ANANbj zzuKhFMQ?*(>wLhuEO`*-)e+s}W_I$B6biwy=p7cSCo-W|q3rcrwII3pVadqZkihFG zd-LZY8o87A6R^9LJO)-1Ut~YI*!9F$3Mg2d+QkLCZF?Pt#T97azgqgq<9zlRRg3?Y%DgIRPp!@~9;ZCH<>5 zlFHg$tS9mj-)~>Ozed?}VQ_Gca2x+aiQ|7C8XgTGBn>Rmfa=iNB`0PVj}prSoBKOzkBtSN7z=J~20Ny2xEK+17OPXg zP@G!*LUG!(FBD~JU+-cZ;H+Bh8EAE+kM<^uGPk@+(~hiXv?#X^%a;y~^B!g|ELnwq zJ(wVa$T>($Mz#1~B*1C(DGR>L&*pqa#}sVhY)VMU-wr#u+hX{|)TV2II?H{xTloIE z$gn$l3^r;rY7_TJNAGs_YG{BefEIE<p|{RyNj${o>Ir% z&^j>Qg&=2dC3WqdaRl{WP!2l1M3v$>eAXXNYFdncNr>N5iJ#DKS(iydAVG^Yp;M6>a6*N>*To^}@+kdL#=0eN{idWXYg(>e5SJzxmM<-z z0=`x~LEl4B;W)X;kv3?qWlGskf#;p@Y8=vO?}CU$DSl0e*-{u`L;KTTd#tl+1$X(K>;2(<7rc`N=hB{O z@A4y2sFt0)M5}lM2wO&1Q5Dl-x;7}v?>uXc_LN4ACkC9yb0+zwu|DtS5s4JwK%H5XP+hg~_6+qZxx!ohr$1?a1%w zm7{G?$G_(zbYoilJmFxWm>;f55V7oC@R{CAPIcl-j6kZX*q=@F^g&(r97RZgh7_8413$jR?b$laIa`iw+}uOQp%hJ&az zrn&wBTI)u6D0D_U!J#Prj_fq-D2mNmPbkOdlm0%&w_W$PzX#uBelt_K&)hkBi6kSR zmVN@0S;B;sq)=A#!jZp-;3 z#Qt!(y;z7@XW}P*`2k-Ss2@&Ol~LB|Tv~RSJBMkf^1Ha$EWw9wsKVLQI=Pk~rUt!=^ z8Tdm6{x<_(up~R*l?Hx|fj?s4Z3kuZ-^ajL8@Q~>Wy$k8gMO=l&sdtx=OhEa&cL@C z_>8w2{0;m%1K(=kGY&TR8~AkwE=x06^4x0BPdp@>o^#WgeCh^%lYu{O;H5*e`7bo^ zH3t4g1Ao-Ob8pMecOL_nm9s2)t}^IvG4K}*eBNQ%{9^;Z!@&P+;QJh&&Hp?DzsJB| zGjNV@Wyw=Ht^dF{3!!3FU!t%seyCLN2YvkHt-Am zZ2Bh*`YG?ore9{@8w~s*18+YzoBt96A2INI4E$vSU+~WCeAgKGEe5{Z>})>I8T3<* z%ceirz}Fi1O$Pp$fwv!@o$o#dzS6+2GVlis{AB~5b3%4`kWLff#*&(_#60o1D8ATv*fwipl^R)HvORneu;rUY~WohviTov;8z&<&kcOaDcSr_ zFz{;({7D0s!=PF6lvAczxSWX1!e^YCjh|!S4;c8g_h<82W8j+%e9FpfKC2DRIy0M({C0PiJmmyV7Jh=k=PCpLxq+8Ikj?*S1Lw85%J;H5R$^oJVwMFzgv zz}wEs=6|4p%Ws%x$#cY@zsta1H1IibHvf|h{3-)~#K7Cn&gOrBfv+|2+YJ0U1D|nD zcE0kP_gV5h&Y-{3z{|C4KHS)z$^Q`p@2_XmUt-|f4E*48v-#X$;B9NO=}$KB`waZ2 z#cV#kAI!#=8~D`*{+NMR&dcV%%)l=<@J9^1<3ri}4>RzK4g3KE&z+ym|4u&}Ut-YL z4g4kpf84-J7i8zV(7@Li_!kZQQ3KBnXXm?*fv+;~YYbd|YB{UFKWxyKKAcT|sDWQ( z;F}G+Z6urjfd)Qe;P)E%s|LPbBRk)<27af3KUv7;^O8Zo^M%>;#~Jv=27Zr$zhK}q zMzixh+Q8Qt_?-s+oPk%@W#@aCfy=4hEd3ld=i@JKrS+ zzSh8RF>tvVDoa1N8uV`%`0R_b`7AZ?l?HyXf!|`_4;%Q420roQ+2ved;Kv&HS_7Ax zv$EuQwLyQcfj?#7xl6M7?`q&j7&yN!m|4y%4g78cf6~C;Fz}r}k)7|M1}?AvWy$kQ zgZ_R4uUwkVXO)59Yv2<G|bDM#8U6)P2 z#=svj@OfXz=EEg9nfmjhfgkn7Z2H>_yz5KZ^m`ikasyv);I|q0;|AV#eRg^J4g5F* zztF&MG4P)o_}>hC*NxfbTxQ^_4g3-Vzs0~GGVtdOymUi$Id?Pg!wh`2fnQ?aw;1?C z2L8N(*W0qoU%D|HUt-|r8~7at{=9+Dz9~E3Z>vw=Tp;1j== z&3~zZpJ(8=8u(KNUb!th-$M<2*uZZ$@MjHNZpq1#XZ7pZ_yPkz!oXJ=_=N_3je*~3 z;Ex#iHUn?FJ-c4L2ELDhA8p{b?Uc=bwLyQ2fj@8HyM4ppZ{W8W`11z7+Z_gf1HZ+< zpEvN`zG?6`@coSO{T74%83UhoXLi2J4Ez!U-(=vg8u)^5W#_xvz^^y(Ck(uNS2q8{ z3|#K1&g$>-^DtTXI)l$m2L6zNzi8m)Z)fMbkAW{Y@DT&Q-oPI)@aGM@>+bAwE--NU zje;zB9%s;x82C*F{)mCUY~VA#lU<&J4SbD(UuEF;8TfMs-gQrQdG;}Id9gi9o+laf z*BJO?244PdHvgjx{1O9yz`)z?&E|iAfuC>ScNzFg20rh5+4;&3b7#qOwLyP_fp0bN z>V4V#ml^n_2L6D7zhU5m-_OpsZs4~W_%;KdeSbE8E>Oyp=erI1YYhBx1E2DPZ2rd@ z_!S2JQv>hXl+FJL1HZ(;A2jgxf6V5;)WGGJaH zN3!{R(ZF;6oK3&Vz}I$U(?4v`@A}hh`t=6>lz}hYlFjF81OKyuAN^=HpIZ&Q@Uv|C zQw{un1MmHLHlJQYp640#PZ;>Zf63;5oq@k$;42=>=Cj$r=lmj@{$c}v-oTG|Je$vL z20rnZ+4RpD_VXNr{s9A@_Cz-SH3q)Pz^D8wo6l+kzt6zSPiFI3Y2f!5c-OD9`K&N- z`H|qP@#rpt{xt(%vNfB}#RmR}fmi-Do6m9s|Du6EXW;!$W%EDB!0$HjzZtmvTymB? zmp+}1uQ%|`2A+E+o6k}MUvJ=>4LtW7gTH~VH}K5{o_p5dZ{W}Gm`%Ulpuf++Uor3n zzs=@_Z3h0D zfgkq!Z2ngp_;Uun_w(6&)*1Lu4SdEQviZDV$n#8tev^S$U&!Xa#=til__Tk^<`WzE z0|wsvVm6<14E#X@pYiY6eCh^%lhNNFGU%uLF`NGi1Ha9{Up4T9|0A3K6$ZZ5z;}Bo zo6lMU-(=ujf6C^w+`#2W>$AqAn+*Dw4gBCgXY;wrz@Ibleg2Zo=OP1t%)sZooXuyg zfj?m2Q~sLGXQhEJ*dd$#E`$Dg1E29qHlJk%evyISW8g0u`0W48&i6P2zr?`rGw_!T ze9o)c`7Sr`bq0Qifj?v5<^RggcZq?YW8l{t_@f5i_F8tn3k-aPfnQEoBvS;ezAdXGVs?7d>=nM--~8v%Q-gaZ!z#^4SYr}JKqxw z{0akq*udNK+58VQ@beA)P6L0@z;|uW&Ucw1&lLv!bq4-~flmpHd<}eqfj?y6?S*Xq zOALI(!0$2emkoSDF+1OFfHeBy*`KF1pP)dv2g zf%i_#=6|Yz-)i80Ht>a$viYw!@P`e&QqJb{ZUeu;z+W)%y(ee$A2#sUy0ZKGW`lm` zN;d!X2L7ypFYV6ebAy5BrexEfYT%mjJ7@E`+`wNj@I!aW=5wo|pEnrv+YG#aPB#D8!0$BhR}6gN+-&|A z8u(@dFYKDl=LiG8+`xZs;Hx{c^|Kmf=eyRxe{SFlcFX2-xq-iE;79aj^SQ;q3;o&j zD-C?JfzRGOo6m&?e!n5ltp@$FdD;9QFz~@WvgvO#@Y#E2(_dxarTN+PBL@DGfv;SU z&F2XNKWeXR`eTj$zR94Uy>~XBbq4;7fiHPWHlOPayltOs`V|Jg$-rmto6TpPfj?v5 zOZLm=^Q`7?pxerjPQTobE~?0psx9S z-#pJ$oqF%N=bU@)zEt&w-;I}ltOdWz!f2kGJ4=Tkx+fc<(OpdXKT-w_5N|E%=7J#>>|h{5p$2ueb28 zwBWO5$Lqbqf`4woXYLj+=OPRKo(120_joyHTkzK`_{MYM<(y){zp?c1&sq3~>=7@2 zrUgIVg5PGrKeFKC_l(!Op9R0bf<&!!5^^Tvn}KKHIIsyzn=xa+=9Pu!N*qO1@U_Kv)~t5@TV(TM@XIk(REcjg({BsMw!7=fA zzq0squ7&>^3;u=$U+2g1diS^Bms;@U7QExwc=>x+@Cz*XvlhI#Fkb#F3*K)TFP&}S zf7XI`^vCPn--2Ib!9TFz8y^=h|5yutj|ERvWF*Sn<U+>g-y$4$GB^LZO%ljSAS@=5_#p^xPg5PMtzqH`feiAQ#kp+L!f|pN= zm$RP*zs7=pWWgt&9xp$Yj&DDYxA5O)!9TL#@-7W{GxzTAS3{6)O{*%tg93;wtT&s-cY|B9CQ^0}3TKd|7JTkt0>_%{~3 z`ox51@6D;_R7JRt{ z&s`d?x7UInYQfL9;P+eb+`94Q^J5Et?`83Jo?yWrw%~=!uh@$&bu;1^i%XDxW~+Iac1Ecn?L{BaAO`*pnhZ7ldA3;uuw zPh1x-e=7@qwgrE|g0J(Nc=_`z_-z)v<@$Iz+gb4QE%+-Ie7zguJveDbaF^7}3LJr+Fi`*=AsE%?Wl_VWx2|HBsCzb#(x zRu=pu3x2N!UunTNzdc@WzXiX;f`4hjH@zcXeqg~DTjrZLS@>VD;4OE?>s`-+&$8gh zTJXy)_`??bV+%g=u6R3VSn#z!@E&$i$XTkyo6}mxXO;!O z-_m}bZ{dH=f{%PWUhiHOe2E2r#e$D{B3}N17W^s;{+0z_@5y-ihgf^&V)!mss%UEO_Cmc=_8|@KY@KJr?{c3%>DRNSg; z&Zpz;*~fxkY{6f!;N@rH<CGs1>WMMgtI>G_c%@=(LT#nk0C(yI!<@iJ8N!vdIn($uXM#o$7z|B z*h!R>RhNGJSXROd?x`mZ^Fy%5^rm_au2?-sJ^1KbtsMcTb(_@bRT4? zBM~!rh0(preyHvGbZld~?_%Ykw zGfSFt>6oVs!TCM-eCIx2ta$(vA?noKNc&cxqP*D1IU^ zwIiqsKlrH*L0K5FxD8p^nkl(UGi4F9G^0vj2@b$zp|87fTXqh36v{y3(2yJOS7DEF;z$zTZ&$L(Jy!fUmp!&^C>$U90RhLPLvlzcS|u-$do## zEGcC4BI4OnG1qeij4xyhIVpR^ygC%t7hAnTzH`4b8L7~!c0f|qaKzAWf*RY0q&efj z(ZGsrg*KB78`ykN98wqpZxn`<3wd0d5>ZI&m5^JSnx-jf?YJmXg><1!SD{)ZC?Ywg3O0Y~t0P7XY%v4vkAja4}R?2a1S8-As%c_GsL|tnt01wv-fZI0; z3<>pIR4Jq`GY6FmQC$i3EJB91xOyL82_u8zT?8e-fhs6LI*Er~+6^GZs0J6NoS)Dh z!&$q1H=)r;WV=j3;YsVJ49=%ZCgRd`Ik7a|F==JV92wI^L%!8GbDNUxu8bIM(vBfi30 zm+eg+v^oOSQR%QwGB37urC_TUV1hBW%c+If^L4DxryBJl?JRd~WWseDBr;Fea{Iqw zhn2*U(0Pg@%32IHNcZhz73#)tD*KdO?B=xJf>0MAkim9G5EJA(Xl}`-& z2U$El1?3O$45VSgtILN7Q!kwi5ZRM`DP#@M8hU6Xd{<8bHMWl>cN_v=rq*;Jt=VTYyDFidW3|mDbD9EwE)POUqWw7P6&6W@#a-djN(a(6DUV;&?q2;1|*hQ1D&# z0Yv(G0=Py@AA^8evdI&lAkcV%s06h_^>?9l`H#WOim!f;j4S2~`9f~G0;Wzzk_tIJ z3=Yh&N9tB{;ShBcsa+6OZ0(^BGGSER4#r}uUue~6BfN64Z8=i!6o>d3v_ljw9QD8= z0+;8h=wS3kp5*6CrLIC-mowuaqzEDCcN~`05AaV_(ch&YN-d6aEB^NaJq;C*VG)k< z;jD@0t$|Yx@pHkk5gw?Ke;t!roMDE9_lCpv3HmzlyT0( z^FzqA^5TnuWWAEB_JJexy|@G=h`5rt7nDKf)IXWYEFOMRy~o@sExrW7!3c!r(@BM9 zw>zB-(9n4b9cFhrq2}{uvfgxRY7`A?g^+YF%}bktCWtSHZ;-B*HR!V~oek$ZWCuOg z+5c2ScT7q|y!1iUEv$U``6tnexpehJaBiC)n2kb|3Cy{|R@Y%gvNo7a|ro(bSX z)!Bki=*QI%6k}M3HYp#Tln*Z|AFR_((J8Ix47(f-6MBj>Y$<5h@ts}v zG-ahYDd#K%=VP#~(#_P+<=M(E5t(y6GX_~3T)rWhzX=)tCG_qvqld-5)B`0>nGJ|n z>5ro4()_0 zzi)tb=y4|hij!Q2W1uJC`_2`?`Z7Xts~2M^#VM4W4b0}q;d2>_f zp^eZ%W8vbYlrsZ*&|Vc13vNM-tk;W-chp#jFlsz8O^*Z6%j%)VOAvK1(&iNgGsn+5xrAG7CmQB7GXjd z4E>+s6T)CaBTNXvR0pMxsudU{Yb%EWe;Q?K&Bf?TT{L?^H(0LZgI5kVsM8~YjqCKt zV6!?sD(I=x9l^Ldy+$ylP6yp6$^%9x(-pN9&peW=^R2;)3%+#PWG3 z&ti9?tB-^VQ*d1bl)4fIGD!dr^3QXy3gbM_e0ijvFMnyymqe5$57)C~Q2!s5ffpbH zWdOrTS)IF)xss?}$6L4_XLS9Yx*n?QdZ1aC8|iv*u&&6?7a8}@^|<%N#=U=V+^C<5 z?0m`C`MuE2JB*#Tu4X43Tu^_j>v|?u*Rz9lMRvZ-xG&V>J{KGJ`N45lweuBY=d94q z`;49UtY+t{)U~Xx>xo!hPky_u*Nm<`LtPIWU4N4Qw7;a?N-*l+S-c&Kiruc}L|Ow7q8DQLfxlr$$quGCOX5n#6$vr#Yr6wS{&z1=t`(<(L``wxjF9ow4vy^JUxx{ z8HS!gdaPhsKvaU%F2E9fIWSbVL)kSO4{oAzEDQ1( z$ipyKjqFi1?9E`}06&kTPdQc+0`Y;3k1!zwGj#`HDhd{(Hbx6I7Vp1Vmmb|m;s)JtaDp} zMaqK^Py-CBF9s6=*x)q%v5_W{dW+^X5vhF-0-`iMNt3puNkk<`RU2s{f0K2t5&_#Z z30Ot}-=zSeHC|NhThp`^SR_qC!2UyAbs?nG9nXgVBW)H;gk9Mj#)n`ls54=gHHYz` zDQszT7$2grXl(QW>Z+*$W{A!eWOcmBJJt&`Gr`2DbNwZrSvn2J(Pl37p~SxgoU6wt zYLB1e-k0-{#Ag}o6V(GoH378ekKz{0L`u~Oz_VU$+a|9+#lY{;>qI3;od~v^U)!#U z?XP6pmTW{NNSy>WZeDcf)3xt6@jgx7?Z``1g7o+C*qRwW72`f9jVT)*i%AeWfJm3H z4!k1?wizt9EQgp|IRBD#v7|^VQ(Alwst4+Wl${-#R6a|UJ3+(%(HbvYW@ln|Y-0Nx z*=CWAs067~O=5RyVtbBkJCluQjTg0uiN#7g6FaMk_j&T}LSCX0q<6(*Q(|Z1Q4+fw z2ubYjB#>C9^$SOWX+Bn>S9V4N)2bJ!5&b_T|drgC0~4J7UX2LtwX_3?=5>JxBPk5I@V z*aVWbtO@Wj|6F~tu$)R3W?P?hG1@#MgN(a_As{3FalDDea_2M2qXN=wW*b|9N1YA3 zvR>aLI9S53M9u7iwszJTzAZbvFGO2O`BGNBJ(Iu7Io z6XfhT6RJLeTeD4pV{^UOWO7y%Yo}u{*!N#V?koleA==o=jYxe-9V~S3S`K!}41Fu` z5h48m=#e4)H0V(w{SN4kkX{LTjgTJlVat(ghV%^3YlSqIIy*Dr!#o6ZX2XXnA9CTt z1$@Yd57+UbHHt$4ZQ;Y+3>gwWJj92g;lpcuD1;B0kMJ-|9##|w=z!1<{xFw&@Y&u3 zyqVsLvmd%OgMSW$*jJ3f|9be}5dWM-ZH@n3@Q?D~9EktJ@gLwH10@Ijk%Jb^xe)(X z;lB&>-wRMsc)uvTFA49LhWE?E`xW8+Ds$(tp{%~9`Qh4-2e5UCKVs*}cYxyTXuH_`s@A9~0aT>%W8(TzweqFnwPz7i5=P>4Y~;#rr8L zbMI)dx|Qz1U=E=AS$&3psiLP|g#v8V{t!}1Q|Z>=8z6Zc%=jAjbgR@zE~94j;o!l7 zLz6Dnh}v#VjourG6Z{B#14JcAodbK+&u|ITk#sJBntwAL4FhYtH%WPuQsz+#Q3+D# zLO^X!6VqE{I)Y3@B}if5-Cf(GiRo=JX)+O&Aay?N`8h7xL~jX}c#?QCeLA=995$S$ zjwc-$FMoslek7#A7tVH^IWM8fAmyJ!w~A;(?Kgs;OwKQeLEJEUKs8Rj)%Yjt|U- z=F-%)D6Ix0=X<(}yPp@~t(mk&Uz5!YDikOzwSAhB@II5UfJq=KLF!^A;g==}p`R1Z z0MziW$>iF;O@cn4pra{>s067ckWt&OiRnW!9YZFf5~NVzx@(vu*GC;6k?F@|A}T@Z zQkrxbO=7-xOe%1k>HLR24QCF)v51j%E5}9-)e8aSdaehbulqsgg8>Y*TGN%2$TE!m z+Hrtce|j-gqIeQ8pp^@!@wzHaEVxEN6zXcQ zimn0ba`hla~C*Q8n@5iEO51H1o50SZnH)3B(K29owP ztfbzb7`?i|Drq=H)asuw4IElDl|H?QVfA(;A?KFR{T4>m*XC(iv^LM!h8|Jjz{Joa zD;!W5dVqtlP#)G64&W2lf`mZ6M(bxS(1Cf%Y2iHO&E|Q^5s7dK^kW#8(7e`{Krw&k zbGY0|QWi92V?UZROq6xEf&Hl)HXIn)AOvgxhDm_2O9-*cbEf0&!mjpga60V5N!RLI zu*+4PS(q+XNUyIIoc;>$3|6(%;8rZ|FJ()ju87)`$QG{SvDd-arckOK4z*Z-0FydH zqLt^=eV=l^2fifu+|pDkaE1M>xl_mC!Hm;yNAYiLub#O-`mAt&EjR!*e4$ZL-b2Q{ z(yrZH`w?~4=HVKx(YTm+1ZP7308t6ji}46koUKC}kAygd;S>9u4xBx{4q++SwhV=% z=`;dPe7ug@r_V<8;BvHo7+d@lv^hmR_-q~AfR=If2B?q>&Owx7D)!zX{TGcvLhJXQ9ow%6GP6IP4G33~T+{to8l8N{?IaG7oYH zy|Z0k1m|G{vcg-;diD!EsjFFaE(R6(lWQ6%t4;=T6RH(vhoTZ#e(>}L@O93QAeBdW z-d}Jl@&ePy4#v~Jgfvs((iz3$r^e&yE`I^09xc+B4+SS)QINSeQ;k zWh{6sq0K$*;PLe(pz~f@GSk#|(-BYj=W=0KfKHZnaPXEf=LXpnhx>aOXWRx3`H=Uf z4aqU@)irPdChs%@4$~=Ej7Y}E31?lvdHVRQ(8uqC}SEa4wDi+8j)YG)EKkTiGpNT2SiIUtSoW@A&H4?{)js$s_jHIKd> z3*MpBw@%~Or|bY?eTT0GHr!4??On*dMwvX-+~*&zDFB z-;ILf&O;ZRwKj0PeNo0n)sCkNq>p+5a%5W*-n#vGX;s@#g`ni*6 zL9%)>Z>j1jxUo#-WKFpUJKBJYZ220+{0$~AhY1L?rL<7%kP`EKQxQ`XK(`o2Z&0Lx&ci3 zMqr`1gxUsN$zHClrjz=0Jk%C9$vBuYeoGldB}m;^m!W0NpuC`jwn{6Yv$>EX9lA$XHD2CnUk%Yi&B(Js9V94_tVk=wz`>04xa*43I+Uby_e~&0KQIhwa zOGO{sioU!Ok?%PIi#=$$qqAb09Td%bJcrI)3u##GboBN0IwBtJ6Qw3pJ`1J0%UneW(~dDaixNv`kghNzvQ|28B5GZGFk%_|+{ z>6?-+>4#D6B#~1%gi3_K?ckqY1mG%0O_cE_6)F^K71z_{9<`UA%r{0;j|`UEyAqYj ziD>mBo0Ruw!ku;wrrB>uJD_I5ba}+*7c(QY{?zh{sS{ZntUIv;>W%l?e2Wh=?!&HC5`%P)@ z0n6BU`}$fC26u`3(ACPLTgta3Tm2N~V@)<^oq6CLM>%S1sOn`m>WXWm*s1+d-%K4g zC>{c=<65DM-_h}ubZ>P=nrWq+)zkq7^Wa<%*a$bxT4 z@t_jc)M%AZ3r*6)^^#JTuXcrmu=Zma7=f@UN(o{S`YM`|6%U8*tCiXVO=aa z7eVRzupy!U2!~?lY9Vg9p2Go$TQlj#rhIEgvMYSiV-oF6r_^4ss+dd;lMirYabsOF zL%FtOa416cJrF9dr)Mf3BXdImT(3#$KOrovbcNio?*)54lZ62IRtVW zgG!A5+8hkqoC!=zqXfw|Qr2`>jctLP7w%v-HkD|L-!~3dGsd~IKE~nK7o;nTzPunu zIeghdXifHFWz5NpK&q?gX?w@u$#9!@Yg48#ETl5hsY(~vioHOjITQRHF`{;Hw}iSE zAigS*Fm_@B$3U(d(b1UNVw|x$3%W}7<0evYA4G6>n)Sl;Q5}Xx-p!8e2wvXz2At|p*A!;w}(6luZd@zn<&Y65Ps``-`MbM1b$3+0?vH0%hN!{ zwTEvA)!z$hYje_fp?l)H@+|lpGmaU<$V5bPEnBL5gQDxH8~LFKxHKEw4_{)G;j`l6 z?_bjt7J0M!LR|6*eF1Lb0MpL;`XT@^-Ac5+-tCOu&iKQ{8I4W$G4$GQeF@PypxG!> z!6aQQLpVb(gDx@Hv;!-=Kf}P_0p|GcFhoZk$;lXp#+tbv3fo*b1}lMw^OjQcc*7V+ z<1S+y%*oEe;7r!lg+N?jXGfS22K#A*31P5vB1{NiT=)Av?wi2Ji3R9G{JIyk!I9~LIJgt-a*5QJl}G&vhMpX}koX%>4lb8$6hKA4|ZddRKf^xN=!G-x!t2CeKj5&#w^b-Y4 z86E|LnGE7|)$5!Zgk$T3!xf*&&^fZc|JeF@w69XGjI7fmD(lqg0jh!!<4f*jJ5CQ| zpiVvpP1uR8K8`!yU3-GJWc5kjqB&jK*%kb~;18CO+tp9umMiCbc;d*k@cFbX0xf6r zfsxirMu-jEns{V(73QCy(7klHMB@|TTiAfuOY?&Q3+DFK^Whd z>{eBTMswZ^omuY~KNr!LVB6A}B0fYjSC@7QrTv4_h}L+~uj4WJCocHHSkK1HA78(L zM|>UY0kq!wA~Z?rsbS%M7v?>0A`m=GnP1)`Cto0Q^;>w{=+BO*mtBBTH zTAj6F5dU0#F;}M~Rr)}z{DcSl97w zBzjWSU@4!mH}O8~<=zByv1{!ij{1NA!uni&KX?;z-GlYRYzBur-(mijvz5tcIV$Vn>%*Sr@^-Yw)CLy6a|5%q@)6?Z&@!1eCFT48ftw@# zx6CEKZP3lRD0PL6WIH}rhgQm*zcwqzp1J`YbbWr#G4|B|-}+XY)})L&CK00w(Wp13 z`%~(AsKtIXnq>jN!8D(qln z;^@sJ3i?q`<`39O;(F)5#LbE7$GH3MS#ztOkO)4-wfY$@E_;xPun9c~hWj0CMCwbQ zpMxRz0+*~e8XS)P67;xw$MTrpPZ9dxynKZV%M;V~57*34w?bmVX?JZ&Qw{n#ObsqY z_6!h}Aa%E?3b5am_d2J;{@`l}W$*G|+|j#y!&^TeR+aDdGt8j-)U{%Xc?IBLB`%R| ze>0tJxy!9x(qz&FG|5T8B%%_e(5-hTbPGU4<~(8s+Bp28rGUHvv9wgxU_7EvG)xcB`WT%JynoDNbxk5@Sgi5O|VnT74H zQpSAbaVZuyGv)<)kRyCt

?)OXD;)-b_O(O#DTNKgz`CL63TTzY*Ubkr^SQ2As?u z2~p;Fb}>y+=_XNEK~#qk#V-NYMP(YIG7V9gk(rU9)XXSIHQz5RW+^o*Qp0y_QBG<} zH=G`1kZ>#*r{IKfT_8Lm(AKb-?8>_Gj^m}s85wU1ffyKXUKU|O0Au;z4tM^ATV|{7 zOgzd0G6(swaJ3fYgL)7~z!$-r7y)05ThvZvo4j241N(Ry=?)`1yPLQx=gX+@ydPfVxjdjt6fLOps6v4RXj zbXKxPY@F(LwvN;}0On1tZQUS`hbpBR-}BtTRZuY?iP_pUyX|Ouv+4%GFz}FQ!cqMd zV+E}gaIGXAeN#U{lm`r{PzgCt;hguotb_ez3Z9kJB=i%wdrAFQ-mojVjQ5m&hBw^? zk<#vWOq%GdL>=A=@hinIu$Y8VX*P@P&mmyR4Qr`vM-X*6tA+xR*<3zR*%4@39&`b4 z!cD82VZ9#42VKOq)mW;3h^W|&*b_!#=8rieb|XxMTnrguh31LU^iq5YV;JUDU;#M- zBv(g3nhNd9M**?f&<^Rvbf$ovhxA!<^>92w@)6*juw*%VhhfPTr7@V-n)5B@TY@Je z*u=~jKj{+1WP2`Tgsdv_DQ65zd|7WP@Uc7^mM`Noc~8N0AV)OFkszNmsIjrt*w|_` zwPgxzr9xY1BX}PNue_tpZ+MP&Fhnd4%@l^}5l~(jqDSJ!_N0)Bl9g4Xfc5RoQ?!z@ z?1~bG1X0SEEtTKHT5~|JSSS=|ZNV5b%osDw7=v$?7E6UE%{~Pds1Jm%0jM( z{KHzLD3~*Ql}1V6E*U=b8ZI_3#cGjRZ?5l|nKUI$no{^!<5_cmI428nM=<|?WxUk# zZTXLVQPvZa|9($}*7zp>)2rn_vjg9Y&6M#iMU(%T5e;%ANR$6jn{LbtOIpq=H9s|Pgb1^3b!jtqIh;;TXL8G<^Y2b%L@e%8(>yi&;#*A=KanojigKvdq3fYEb z1y4FO<0H>O#yZ=;M~MZfxmX)9Cz_k`!_#ZSmT?WgCh)aDoc%xciCmcJd>Likps7pI+fV% zq<&874pLW>x|7uJNZkc0((%`NKmG@xs7QD7ma6`dx3*;U9=WHgf0DabeHeGf?U*#x z*%0eH+an!rd-Yxhw^#4u?YR4KT`?S^mJYX6eSlE8`XFzm>OfmZKPk)YpQqmxZb6xxyu}4!t2t>2P^3wg(l` z!Gf-y02#h4>IsjYh-YLk7r4^BJK&m;lTwwxz&#ng0YViv5HKWA$S$5fV0W&NUO+fV zfP3XJuvXs21(lMs2E8#*B=j#Z)a|DieZ2`FUvJ82*f^j|eOXh~*TH&Y6+ZXbPahlW zaNOZiaR4FI!p#sh#0sgRzZ|*X6w_WAEoo;c%B zol<8q&(qgNB)6a0(aXt?JNg{R40^#_Wxg#xbj8Y*D@M8fd?;oy=;%YxXe=r@(=p`b zC}au%<5@X#fzJS61J%MZh0Cw2rBrsGLW#LyIU|v3jl^8D#OV+aNhHe@E>JYP$hfW9 zO&R^Gx;qUXIy0l5Mu3z+%x4}1-79Ofl6q<3SBz4(V45$d1bvOuB3U^l2m_>ivEd16 z^)RCwXS%*A?}dyh@L>_87n&S7L?WASwuYyemuJ7h2hC+&cg7}27C3PJ$iX_igCUeT zhysj%JK=vV;78z}x&8#|M{&}+^1K7;T*7$StW@jYK(*c+=9@L^-qDC{NIjK_!XPeu zmZfSv4PaQOOpZzYl}e`m!h}v_1mpHl#bs16T~x3(^Ai@Ah>=+IHUz_IIkQ!kJe)Qf;lwUZ{&yH zcnjCkTI9UtPE5;!eX z>K*6mgq$Z#h)1O2^bI3tNpC^(YFpx}zl#g}`eC@{^aWbd@T5T>D{001Dgs=+6?o-q zQcWW9W)u1@SuA8dDq(?*yC7lnZw^CMMnFh&hrpc#?A@rxnE464wXvc8JkvaPU@dEB z@Xdm6mYoE{8zNfwi{`q8R&B&`y!7|9@nXhdSkQww&Pns`Z zh94?3XEIuyO}B{F;gb%BcRRCQ&wm{9uz0q@dlJHe85ox6KX3&!Duaf17aQ;04PNY@ zCe^kkO&C*eM`~g)26hZEAs8R0olT*4SC#?k9o6&DnN<%D!TcKo<9o1@COhk{>GQha zPG7wM9_j7qOH(g0&M!dEhMeFf6c?`jt;2PSrm|u(317B;4$-S)xX+u=zXn~|0aEq$ zFs`~b(SC-Ru_&7@e84t(4u@m-ZY>d-niEsYdACvVEJ@e?lt8 zHO^_2oo!jML0P{24t13)Aza-HkLtZ>L~UF{?{DMuVzw|?Z+fuabdz4n5`ji9AF20c>iyGT zy`FvvXt<)l`EQa-mXZtE+IZT8MI2|e(}I@d2}EsgWW^|x75J%vQsIz=vO&EZmPS}@$7+0E8{H4l&2HRCOc5xm( z$d0_xG{9=h*dn6;1Uw3b!Rd*hi>=(fQrZZn$pW11*T zB=-M+X7jPoilONKcq$I5bx{|mfTd-a&6szd8fjK9qt#Nc;4(l);qHGGk3!YD8M#Lc zE&ZptmV_=CS{ORm&Y}ETR91-#7+EA37s%uK4S_07AeWp5`Lxg^kdbS=7=fg)%tfD? z%WJSZnrG&nZkWBhw3qvU1G^jg0C)s%cOHmaK8>#hp;N@mYbcNz`Dq@^WKA2HlJf;~ z7&oC00(U!3XB~|DRhUC{L~ZGwu4xqekPc}ST208H_pEUDwxUrn;5W zVG#E3)SC!LUy|o{wwyhgJ~aluS#3vyT|yv$l!YmEA6grHsp@%j zSt3kQyPyHsFa^$%gByl9G_U=fs8LFE_@G9rV*8T7QEF&>|_MCBD%5YlJfIO*ziVx5W2mKKDNjv!%%~agA>E05i<3 zJcvB>YA=wbfY|tG))%lTI2@J^5S1YHAeiNMT&fgiL_!<^+uy@<_cfBs5LL*yu}2 zVgXPOAwKw7=68jbeVDcnrD!Lr6H%AFeqPP@rDXb7`A=P(u^MBCk2rP^aV$kLmcwf; zjHp&XQ~h1tobz+&*jLK93_Yd1<+0gSS>x-d2;;qY#KF=QPah^w>M@9syz|6*Pt&#H zr1szq;l$W=Geqyu7`oJdZceSqL#Ad84x^FI?j^qYHr{GqAIrOGBPsM7&X}q9Ac=W~ zao@T;R7?Mi#q)mj&-T4v>)$>?7xqJ{lA3#fZxJW?PhwcCw zCL2~vMSh7M4V2*A0akM(hGrdu-LmVHKa0f=Ae*V;eE_Z>PKj6MqvT9TRnmcUzd?VY^3=(Fvw@Z zf+_`Jffqe@4J2;I}l-bOuNt|-*vj2({6D% zJH|R`8ao{L8W-!`zo9l;*%!4#PA5hOY`8k%=jA|PXV++FI*R?NP+7T>jOcTCdTa># z-`?H8n63={FTaSksF7OM>qcrTC4|fPpopy}tRgD>*p#OpML`Ku`Sj|kG<6THnd|KC zOg_t`gJ*6}g6xANuYyld_V^ASYCd+L#i0EWny7S9;ZI;s{RGOVET*Rc!6f-HD6U~F zSg)l%Yw76-93Uz|3X|UM{PGbHH_m+ezv=B}^#lUB)6&9T4>RQ*=Q`f$aJ$gj@%|Xm z3mor7&}{2^!Fe$3PN>7+K%5x=4vnNU;dR;`o!!Lu75QGaUpa^jYvRa>a$z9bI@90z zvY&Ve^Y1exi+k`J!2>CD8=o_odoaqGOe99Q^+cwbNEx9Jl_2#bnD9Nv8b*|LzD%8u zs00b0jC!gYLXp?cs~M4Sd5Ck}FQ{1hE6S9`SU>M3(uOyX5t*_7*RIs5%8^K&>0iuR zj6oOHQLc=1;2YxTft*8;R*X^afLoA%DOi|Wz4r4An3R{alW&j8%TS&L+*j~$nWYQJl_+=X{o_*A)jj045!l(W4@QiO-E8_KJLco!4LYuQeE zmA{Hd)*uu6tICIX#+&ZbK&LDDZ|Fn`oG211>oyR;XsSn*f-_LG)tR`+PeG0}KrxkO zD;z8a-nyJSK=RvJtC#lnE_|T{=as&XOZYb)KIOlMXP#?s#<6WBxTy~&guEMvIO_(^ z<9v*k2V>L5*>jE&ZbvGq3uA-?i~MFd8^}#4mE#l77-Ics908n`2Ee_m9Yf{e7~hPl zr@{+nv>v{=wNo7k$Mf^+0LI5}qNHP|=`G$;)wgkL%#mo%T$Z1H23IaaJlW1P-;8us z8!VAL_tY>N)mYat=ZAhMaj5}cG+5<*eboH3m@Uj$x1W0TdPp5$ehw;Zjb(aN#ydVD zUfO`8-F^yeh#S(P&W51qU?9grY;O)(h%v*#& z1Yqw+m=Fg0Ai{(&*oP4&guy`@A5C;1s!h`_EGXUA)a*piNC`<^$ z|5=0yVX)65ObCO05n)0Y?8^uf!eIZ7Fd+=~RfGv)u>VAu5Wuo1h^R+T;`}qt+V+1P zg$rTg{5QgcFxWQ{CWOIOM3@i;TNz1m|ZcW^c9)E#iFTN#2=8wM3pc92C4+cYzlNI3_AK7w^uequ?^RLe4p%A+$2 zJ7|ubv7cc^E}r=jiIE5nn z&qaTZJoIHur)h&)6G>QYoyJ=c&14gtV`Q7&qHBC90N><@elDrf9N|zzz&^f=sj41| z6IMw$0;{G;*Alo^eUj<`=#JX`r0lmK*=QTZCeyEc%V#Ra)r~}lB6^ZG6`}8w&VE#Y zKZ}mAtC~v5vh=jtF;lD3)M{zk7JX+*?a6|IQxsXGxC`Ge>laJ==?nR)kF;yVx(0`F z=tX{YAO-X%$$u^?DEnYv&c2y+tP)(yfibGphahTj9&0sG2~tm^Lf7!2t2)!6WICTr zL?uW)!&)DWeb0fSBc-euT`5LBmQHL~RcmdMco-%AoDzvjka`vp@rLk@2r>&FwYH`h za~VU1%0wl|41wAF@Jt970D}u4vP$i4Kd(`p>cH93pTeA@Xk)W`!_n)7h=y-29fVBP z7lBrPgD{LUbBLpspxX})K+*c@8A0dZl z-S&4{k1$*NE`I6v$P=TnvT}|=MX!k6%;0bvI75=-e79ffNk0L7GYUj6nqF)+2TNc} zl`(MOMjWEnf=&2-9{u<;T(G;$s8ZRcFez?73t%tH{~#aT38}f7i!i)7uP=dI`H79R zz7(XdE+fF9D$a95tgoJN%HwFw{JygZZZ*NJCOF_{$awU&E|Z^Q z(X)XThTvEae;%qZq&U>nzd{-(bAQcrgiAGl;7{S1iyN4}*ZJ}2;9P~QFJpWrbCRvm?NJW#@8FK{ zOr4+jnt0~ibv7QF^>Qug4B&HtN9#$W)OAQD=cujn{el4Xrj(VkI5vlI@Gp@_dD6cD zUui1)S@V27p7jm5dan{2e2{9LmDnO#r;aFVeXtG6y*S2K9fh z+Pk~#%4i^f+1fA&cJXy?3^inNsahbAs1D^#&8L!Rj58BD=1aRKf&Jt(6>=E0_cx)^ z(YgI1T=*m@sK(^M2jP(+(HOyVP|I0X3&EFMhjCQ}O0gFZ;1*ns+NKUb(}C5Ie{*%@ z7C1+}0H9WcsHjt1K;GZcgG41r{hdthO-x6V=~glkl^}(6CGf8RN~qi9hsWQgcaEv&2foHB{uZ5{=&Y5RRPX{`v&6mS2Hs6bno^Okd0vVo>G8$NdZ&ySLy@dSol43FS!Es}6DU6;uE4O;0Qi zW$Tp;^^VUNBWIlPka{f38k=M6lZnWLd^tecV($L2;7NNNmeIaM2nK(k7{1SWH?>Fg zoA1G}30g?Gqfyfva{mavCgBN**erWrSA7Z}^<@#?RiA-0Uk1mV^H(VPoWHAUNg!O# z{ruWIG=8(X6S;Couxat8X%iq0AdhctT=@Yhb1}GkU_r z_=;{Wbs?W9yZJ>a6V8|Q@nPqELtQdqk`S}K9IZ`^sE!dMVVe+#g!_P9Y>)1Nr}$|) z!-C)N`WX_suzr8pRTsgEFvby#VaD=iM)9*c01<0L3p}z8l|dIDd6(yn%(Fg4N)GqI zBwU}i%JWacXReK{3qSQs`KKtXoqdTG8;j!XD~;GXCT->EMkc`jfN`wwjjJ;f<9Oed zch`<<$W<#vta=rdvX`Ylj1u9mv9d;WzX#z}#2v91E0#EKkIH3?OR3Kw=1QVoIa1mT zs$cOW8RhJNzT^z-0h=C0-N+=PT+z?iMZbx+gu2Bz0{&Zjt=+zJdV+5^-wtQ}_? z*oejOLJPiA(Jv75RFW>i){f`l}F_g(Nl$Bo60wBVOn@aHXfwk2Nv zW)}Pi3x1gef6Rhs-FUrQSn&B4{B{feg$19Oh}V071^=l9zukg=X2H9X@p|{P;6JzE zk6G~lTJVV}i{4f7ozYaji;}2b#|3TV`cg`9j*II>IBfJFo2FM0hH@-e@DLE3NP5j+ z*rSnG)1&7u#A{dokU)MjwTgPezi@x1-E2hVfXGi=n9dM3e1sV44P0FOMybq5jo7yc znXe)UoRY7-m?|EwhmpIzhaFGn1X;UG%HpM&6-4PV?PIHqcfc9igI&d`sI-!5(0m== z7?CjVqfUA5oS@NpqKz0n zrC0~?Y2=MyNUq1PL)ia$hw5ELvrL;NK)8PBIfsDvBDbSvNYhaB}6%LFOzTP6pO@#dr%`bN)7F>zqg*O7#C$PkvI{YpC zT{#aa3BR6o*}<{vL#C-gLU(GV{&#K%2KXtYSPs6qWR;|j0UISp=>e@QlI5e%GjG4o6 z{#uZMb+1B7eqaN|fQw>y55xS5h-qB-aR{ah1#;jNV%*>Umfbynst}BfydEC?{k_`m@fKumK}u zJ;kgCcm!C#gJK*=LSj;je-0lOJ+NzuT5lDTah)CM|6q)rybT{B_132Ca_fs4vQXlte|rT>Lj zYBKfnQD1X~iavs!uOYOi@`z*B`uSz!bZ7g9zfuRHaS2{TG8Q61%>NGb zdmDnrP`}^?XUbvTggys%G!;x)-o>8AEfBT(>ZSNl)pEsFgzp0J%=kI+eq_(t z?8lVK&|Ms~s5B{4*V6J0ZOq6E!GFW~&=fcZuLEH)k*tiwhjvED2kfxQla!v(FQ?31 zy@b?ZQK#}Ao%dD4d05c>!q9V@eUg-4xYp;=Gx!?WjWiZKk-a;B zK9BtUEM0mzjKC~T<-nHngV&Ka`E*LZk2}5r|1NJ>>}UBj!;Au=<69j9+=ltGegiCx zzT21IRXCsW^~(_57&vTzfdjiXQyp0I-Ab#EhGGL5QYBJ6|OosPL?6xxTu7;Gjy8U@Lj zhSh*@L2fAuT>T5ap8f||@ZDY+BMyEoD!+VF#Kd~~WUz!U)tZOU93y^xFin}>P&a|k zlN!$x`8>MuyaAs%(h1Gm7|+vp!E>+zg@GSodL8;I6W}s=O`@1W>kl9Br)iJ-4hoz4 zXTu)s+pX|cvJee!OiKCXKZeL;5pNmM2}OUHC-0FK{ON3a@iYZ6`a*6~IOSf}5VK&} z@DD$TfZ?Qg2p>Vn=y%YfFU6)*3HMC!1_UfD=VebO{HVQt6IgrpC4M}DXK4Ay*8K$h zpM?K$Q1%3}k{JK5!86wO>U$)t`&$9OfaR*u<^|s%{m5myA-8-C81RJy=89wlb~Pz$ z#i)$DRi4ArG6t)vEvgUnHU8FI(-}kET(|DV^Mz7&_mied>Th`NAdfIl02%k=dkk!L zP5a3T#(6x44Hq#!3MdX)h$d6-QaF<8IKK$PlAhX@fegd^2u%tPo$2wosO>`gXwUYD z!@sa6F)Mo0Py(W1Np*8n%=&~zy@d|1I+akWikId2J%ezrV}dYVulFY%lcqQq!$B9r zCiAr;tfFVL@TxQ7!@FOHqz7>aJi$mGSE2-?<=Hx>?4i>NYlWuwj?h}3!x4-A>w-Et* zSnuG5j}(A<7nJ7lz4Xw_T=#g<%?>8us)E1g;+BGH6s7)XQQF{v<#VUD9iqpdpgCx?P@% z!?900Tz<|7srUq`=$lyoT2kAJ5-M4EqTKCgL6yO|izZ|TBno#73U&ll2+u&f_$t`G zSDEI(#i{#!gBIC7bF9Z?mB$xEdKgKvaVGDoM9EIy@oS_Zx|}MN_oh>d}bSc#&v0XyJjm9fKwAyfU|N z9)Ob=IfaZm(?p_y5RDx_`d1Al_X7X{YA2k5SZAEA_X6~3& zc0NGp68NNKss?{l;xt;=8u-v(OeWHL5*j;xuY)-u-N|%xC;C(5TJN4PXLLSu8;e<-Kl(RD2OXy9Yf7;Wo7C>DLu7kt8(f_?oZsBu94jr)W*%$o_`iV_;zupEWI(vncK;6gOVj@kSAjWhNs zN6H6%!TtA3q>X;UcDCjH@8fM1ufyf5c{eRHm(Vc++i@qro3cVNv1V_N63M&0M{ zxarBLe%N1<#(+SghCaJ)@E&!8iAsXT8ZYq**}55piP|HfAOBB`+j_6^z4=Y@B2FIID zmdF98x{^<(OJMI9x{RhW5*K`)z+%+?$hF$GP37ePmY4ssgcFq@^)D3eWUvPJL%C+c zV`VrKRS5EEh4?lrmq325KX%jt(>XyxVh78hE+pZ}M2iDU-RDvW83WFjTGgfRF=k-%w zm~S_`@-u(6?>C7#h+?D(BPv0XCfbOz63h*rRf_J+557afgC5=L5JUze*A@8M+Epyu zY7D#|o;Mx~&`hQH`m8zo!5{kLkCrbrU(+;u{oyMmjW@!f;V=lt*7FaI4wgHt2W<}{ zWxqfOv9W)L2onMr>l$ak{4@4I+&m*r^OjOaQEDi2$0)uKhyy)4MVJr7x%}rD75kq8u+e} zP9cmPvm;ChVC3(ZG}(C+{Q>5Ycpq+n($#UeCiG~iGlR{9I)Uo2w0lxh_?ifJ^^bw{ z;lLffOr#coR<8ioE06^Iq8wmPuLO-x*}3{y1h-;X=cMDoocs>Qsu096WKFp$=KdOp0CMq-)kTbgjy|EUCbLNeMib*{ zCx;a$0`9$z+!6+441$b?2;m02?gZS+#WcJh$2iB-y!3A|`Z>i1!P z(>F&dFQD-%q-(pu=~1_TI)nvI63quu2~wZ1KA@Yys(|?fXK(->7BWG{gFQUC`TN+H zY@?i7OHwGAggiPK(eN!)6l526?}-0h;VhohlmQB!S?{*T9fyMowYhvhKp)M62PoIs zUJk-ciY`Nn%;#-+G(=t%Sc>By!n@QPAu*%cSVi-+kaeGRqd2MPoCg}~66mv-NoL6s zwTYR8-t{VC^TG1}XnPYdxr*xV|K@g2cTdkGWRftG1xVOpF@b;}m09c zHJNtwOCN;pfc=J8S+W?%<}s}Os?Dem%KoJvoC^s|qgWHE_3?yiQX=|%Svi-&g|N`P znIEQQ7R>$Lget!B+=#>}7ZHzDnY0-}!mch&c zOnVAyQ=cY3ei^$p4n3`450f;iwQOQG9+w(SxRyXW07a{@<3CF((^9C8LeYjQCe^I% z90L8%NM4H{fO(X*y8)>9qZ2_XE!@%oIo(1Msrj9TF@JW$PFodH^W8j6aq_mh5cfT# zm*4x56V5LGFo1Z?0OI1(`&Bgy*MNxsj(nGZLgi7@b@?8h$* z#S^CGUJuMcy4m~0%Exrw4uth?_N|u&Eq@Bj#$dU#|LJXd0a{GwTeY&D-X8tU@aHxk zg~btL=8jR5BF*i6Yd;}3`L@^z#*BnYy8eeA~73%nO{cL*w1C@X)i8g*I6XHHO$87MGQW1}0Hsf{g_eK>o zA>)wWlydS*<4N^IHWHt6epENYvrwEkF10*Tg*LPGiAa4F#B5d7T5Elo`b+i>OyQV5 zzY|uY!m^M2J1BKd2-MS)_tHuFIUH~A5|`cO5k<42tq+gvE(voV>%8iI1g-r(zXE?N zay=CY zK&2S4U!Q5#Nwrj&x%{xODhSG-`aZ8rcqK>8RrHq)CCr}Y%vYaNYM;!IkS$GK zQ!D6)=Mh0IDEt*vzZL6|0&}gCY$Q>>o^RZ;noa}=(tclo+TTQNK-2`apzs>hY@s7t z?y~KDKZ-n>lT!V~cG6!MDMpmZ8d0V~ApDJJ?W92a@1i|Tv<0=G@OO|9fOzWHJr=l` z-~I_q#=g$I7TPD=#-x$S0|Ub8kix8FhCZ>`RJT@>8}p6T_3dh{VL|b*z+omoty%n} z>2c5OnpDg&gotcJx(qd*P;puloETA&fuHwyO!X?PDblZ#3*EZ5mON|o(^E;-;Zsfi zK}a$ir`J>FEN_!%?ou=eGt9zUx&WnU@9G>HFJ(IC0i_TCFG2}F1N~H2v8P3%*N|56P_noyH~av-Vg$G>z5u5Z?`l3 zn=u&kevOdBastybzz#J0+r7xOYI%GdKBm-Nn9WUy!0PfHe5~$shy|xx+|UJYil@05 zKlC!uIL-zPt2TsjI7u(O6Hl7Q*xng^0@}QjIL~6lts%Z-cD_F8e4uXa{VS5i=7v>D zwoow3Bvq=RfTXG=&ed*-FIm9PGL~i0__#Z4g=bQ{d{q^#ZQhK=!*FLI7@Iv<6L9 zTWUVzYd(qB_6$c(R4_87{a>2S^=nax;D4B6KHe z>c%(fYoQL5!b38(K}l5ax21wl)5urF?i_oPd{JF?1ef=Bt$mfOeQ|648qIeD_BOVg zhoz`VmqesHuZBqP>!RTWxei_?LKTAR%a~q9TA5}=NIRQR^M`0tob;}2>!*7nw7~;j zZe8}4!&9O=BY(tGay0v=%0QzpcTa7snY*Vow#(hq8++&O=4{M7O35yk8<&sTJ}o(V zT4}hQl@?Kp^Ed;IvvT)J;_u}dHan3LlZk3tXE?{Ej;Xm@nwI(j4KL4-PIGsFs)Kv* zr4H`NC+sEn^2*+Pn)~pR)Qpnq-t@*rurSD(qTw^?+gDh_2&nR=uWQLE`)_kNtewHk z;jl9V<9yaI-(+8sQ+(Bhi}<4V#6E66psmvhXOWCrrn#OCNO9|62BdVfz6Z9l^-h>g z{c4FW7clm;&%%)nqH_po?hm;UK`p2ny2)PaAPsKhdQjuqfnYQbQmW!A9tcy3m(^qG z7uIB?|0cX)UpR*dvM)ST1je$8Y2hKjn;U@CTdTGX6H=Fvt5t^;1xv>Ds0vNAyY<$4 z0d$!;MlClsTwe?+v|h3BxLjLanJeJIFc|7E-ySJsaeZa+5M@zN3ks;M=Csc)AZ;L| zLxm)$1?d#PoG@Opkm$GzcYOPtLX^3==mfQ(ZWrC*$`nj(D5ge>t|PN*L_3PUh0MYP zC3G^Q0hh_2TS#F;rEr*-64Zh!noM$XHxAPXWy)UfVeWu@5UEYZFRhN%| zAGURl6kC+&+r`#g4zj&i(x zyILpkjl-&NXt$p=HzSrR)QP}rab8(ARr<=SrUlAv>m-XPE-0aQDtHMw46`(FGcB6a zKCd8ww@U(ts{{nKps=b~kE_GR->|VaY}^eSZ^Pm&^e}*Q%DNP7Oa8v=`8yJF%HL6Z z$=}iX#I0la#9=`BSryzo1IGey9>)&@b#+*A(s8}V=FgyF0;R5?l%N)e#AHYe@bWI7 z6^E3(j%ZAHR^>Jy38;>o0@u`$_v_QuYDh?4R#ceHB_-9vQPs_8o$5&3;X08VH%|~! zKLTpbAbkXIM5&GGHYFvtJb%p-l?l@Sc-%g}AnT36Xr4sah@ch}1|)0gW6>%`-xI%E zr2IC;;jr~-%PU)o!IPEtR3hjZZng!(HIyqeLKYpK@O&w{mru8~hv{s4tJ>SK9dkBx zZhfAy&u;3tm56rFZHz(7ZFm-4iO*b+fPK4Kr}52myVd`7 zZmkTOr@-3(gDi*XhTcmFek{Ub%IKK3%P0$9 zVFOMARzq{bT_l&ct6xFqhtOdx+Xgh<5!xbdDQSXlm1xSKdj?2}S@Ez1_a}=8x9#IZ zBiLZo14a#KXF{lK16nn2;_nhK>42v2QgwM{Tfr8KzcnP9iwdIIRH8YRpb;-7yUrE&E+Hg8JaGBbZZbrCGj?4xe+S-S+%=_!2V5yPRhT%p9p4G1-oOq_jPV{jg!e&}YMe9&XbZd1(6n=b41GM8Vg? ztTo-n_kR?BKsLTxz_Q0-PpNQbyc`x-h~{N(`%B+paj^ZhplmEYfQ0pzCfQPwmnz9- zTh7ZYb+3{1V90XeIbBK^)H?4^h(JzqP9Ow(%H;&KczQ9dLx2bP+%50r+sAsX@4P|EhIrL zD3J1;K%#S!FOit%yF!!s9m%;${~ZiP1!kufm}P_)vwK6g*Q3@-#j`VE6Cb#}{Q9Fi zz<)t`UonGe%6_C=RXhcR4VAp7!F)%>QZ*RoY0MXgg}_S51sIsr!dzokSbk!4ef)uy z^_=-y`*;iwnUjZTQ0pIG2r|0dFrIxs0I2?@2UCGYM&GO1_V)BE;3v1I+0N7oC^8{E&-OJU5?&UzDG|wk! zL{JL~>#BPp$?RT<3ARV_Q}WT7MWGoeaWG?yP`w8322Gn16>;*i7>lDe;%zpLX5;=D z>7b|E&mX1e=j9PYtRJc%Jbu;B&tiLb9 zH@=%wGX$YAwDPoVLL*bFCKrR?h1+dIMYjzVRtL(-B?Qi{CfgG^&zI{hUvzmKL5S2b zA5+dst?NtzlAHE1?}dq9=KPnej%3p`yG7LR0bx~8H?suKXQ_Dry@M+;d)#{H7&_R_ zp6L=l@>FeJ3U_Cu15L@KW4ACRx`jy(?7l*y@jl6tkXAHJ!mI0~4#4jc$?jY+omz+{ z&5zb*tAV|bdf{#M&KQx67Z=g{*{xH#jC!J3(AHmyQ%)`fDfg(q^cY^peBb(4$f|6d zVAjOUu^!v+g0-N7#hM@keiK%9R#%!(4&iFJz);6&RU+ZPWO6rNJ#AjLvC4iPLSY}M z$S?D{-8H{cJ`X4EuZi1y0|+IXT!xVSnUDDrivz;i+>5BCQZyxb9mGo9zN*lC4^Z>H zoQNZWT2OeKnlCHAImtg2p;OPhqAAe%jnaHAO>-vJM9Hg$raZyl6%eyMhdyv$R^HfS zw&SSG2D3SzaObu^N|MQkgfAWI7T~`k{N%%c(tUfk;(Cnct$04hT0p6FtGDeXowltVDwexRLb=U)3jD1$T!nyaQoNf%IUpQFOpC7D$Bu*t-VYj93N}G%-J(S3L60SE(_>YJ1q#Q3 zIotdBjpN4Om{HiFImudjO2**mf5r20X{)`RNa_ufeTdk)Ev0&VhpIqEHLY7!v-SI( zXq;d)x>}zw8m&7O*=A9T8D3(W*z1MkjQAZX@e@151#;r>rLx;CPJ2bmy5*ZPteLIb z?@6lTJJ=NNaiec?NhOP zL;e8&absMa!vj}$Dx&p+q#y{>~gqAjH?Hz_g9)TLy6b&z^CWOa3}Ny{t619*AK4acXb{ZGZjnA+;Z%LN9p^Or zc7-$STM1|KwYI_f?K&l z-H9!!%xJ7`fKm31^}@YBN~o0RH?>>z;a!QM6jIXZFll|w5wvSrfmqM)W?11Iki4&S z-NB!gN6r+ZJ2+QCKE9UiZLYsq{!bBw_w&P2C1> zJDPHCgLg9#(-Vf8Uw4I%kTf$i!TmZ*7j>m|i;@`Dubs2N@IY=d;Cz-M%>({weC9bt z5B*(u>Z!ERc9*M7<*Qfc!xiVc*p;h|2iK0$M_f#Y8aJA23BWwKuKJXnIe1O92N+W? zaKU-HK0o{$Va%5o+b9vYK11ir{P13V@_C9*^Zs2l`oq=AWW~BEZltf!$6i&WS+@Pw z*H?lo)DMH2DaM=!FTZ~nzLno4qUK>0>vaC9FqLf=m*06(soc7)J^f4J%9}W2BNjxO z{}qPmbb9Qavp0%7`5U%ybRl@Nm5qMI`cQ%XPF|8;Zq_+Vp0!Bxn&lb4c2P)WRJ_R> zO^gPaaQzz`om^L*Y3UWBVVg@g*w|eI0$WA(+z7F8&+o=LsNDP_ojvA=b}y4*b)}%@ zqlENM=k}(np%rr02TX{%sWaoqw@YVijy_SKc%3NTB8q~x^%FJ_vv(Dc zt{2i0Aqi?hVXlxqSwOl$NVf_}Pzwqh3hC|w(v3p8O-O=TP}oRFpDG}ITu8SINl*(4 zZwD!C%n!Gb^ikcDI|z4YC9R_BE4_u4mRG(?Ju~%V@_>xEC_b+fy>`!YEZKD0lTPYX ztUmkmPU+Ok6fJ4huO@5@*DF?0v*)DT8d%zxc-X3a&5^8Srj;?}_Bhy?FFoO?j^G|x z8_34$8LY!@2BQRTqp<9?-ZxTB-yY!Uw|8{ra+o*F zc?2<^U;{}!bJonml0T4`4I`%cl3hk@-IGhO`3aa9Je3D#?!sZ6lm~?0v$Sn~QlYwM zJ-HiK@+p3NU`jrX)76Ox5Bm`d7Y&v3m^3~k@DZeO4~{|_&3jY)>*D0IIFtMM@e*AH zDsggu=1&iFl1`4NbTYr_%Fn#-)6_tl3!1}WpUGh60H!^Pe!gY(OSd6it+#LH%Y0kpRLdi!#Q+_|wegJRQGk%JAMqxxy z3o=?G_bGAZN%_{?q)PgQXNA#FJP1mEco6PscyDJWpU+K{$63UwDUabHFmm+I3Ek*a zlh5N$$N6qMgVo(h<6*+={o;D#Zq2xUrUp~xf*-z?SR#y6=KC5!TWVRH5wS+t^!De> zF}?keeYHM44ZbLezF7<&BeNJ~qVNSM(MLQ?I>{rrd#W}^<07D4mGOq%MEFGl#&<71 zoKiO1g6`YpoVDtcUD5I~b4hFh6*dB>j2j5zohKu^SO@PH1YDlspEKO~vBDc=1-SWGL}sj4a3b7&D{4^N5>vyzpr&^} zWjgDg=s42oU0E9G^!oJwI?;2%^j(A%6P?Cc0_)$>I@A+=fON-q(tYjk*+t)Jx_9O2 z#*3dpKH08nDfu!Ynr9mEWMgXb%uq@m2jue%KWSLNFCXHVu=u$a{lqR?53vjjo93dQ5#AIs(3xBJ7xPiWwA;qQl z3%8|MS--Pce5Smf0%c9VW(?3DJqdhpcFc{5U$t&RXSKc#jIr)X04$uJayW6AV0vF@ z4iX3USOzl(FzHEDkM!qj@KnGr<^o<}-SlS#?N6pSI@Ef~QZMULjXAAnSVu^tdR3}YPhLu{PLWa68gfz z-iXti^k35(5fZsWBk8xe@5>`_jc(0(gF8{ zrzts}K36ZZyu#&FmFBMqN|l&%U5VMB%unl!_M!HJuT`zCh}BZEIbrp3@@t~?%+tb@ zOU-ci@;Fs^83&(N_$0sOhZ7U(HaGBxjYf^aai#gcV9>WP`HI=an7fV7fth!jP&}pP z?}Vhi6$+a(CG1x|2^%X^uit})Nt4CQr|ae94}h1{l2c(~5gR2;_tHAsWp}6yfqZ`yg{B7cw2>%3#&f z{=t=mUtA17u(1hMh?bygav1e0-F?uRr5(uoRPmbDxOAOuH(%D9l!!K^lD|=$)&3Lu z6WC_sG5ia5dRIKCsr$)H<};$z=ef*huy)i!XPVNm$;%Y#|wgR0-#OcMVL1 zGY|HzaE(EeeZKL!e>$2j8p&S}O8aTDl1*%5)wRC@9TC)m!d9wEmG(0Qw35(X6PlnF z6c&Qk{zd_*ETq2)Nl*(4TMOx%1*9$^{ar|cT2R-KI0{PFnc6cI#4#RTh`Egz>rF{&pd~s?swl z2x>tlh4yy}NHrn-OH2uBL4nEN9KZ4K5(+oDh$Q;DWFNAe0x1MsVgb6aL;Z>Bsrs!d z<-$HoU-L48WwY>%)+?1^eZs$?V1TsLzFT0Wp7SecTR+b4vjwCcA-y4f1#RmmY!AOI zh%P6+=5m4p6W2NI?-gS8D%QUhOHd06J1Upb!Sqzk&a&zf{C*+Y_?#m_+xl^ieo#P~ zAS9EZpl$t_1P9YI<1Uwq-O0R~>g&w82@`$#?EVGX4@mcmx9GtgbCTB1D^83wWjC49 z&#IY*f2uVAV@~&OSm(a%!V}s})stzI)?oAu>t?G9OAAbP=Q$Cyt)H+HRGLwj;^sQr<>n~2q zpe9}Xq)sK-tng!F)u_DP-pSj6@yfW+o#O>re5HtAfLmK~86ApFV{~?!Ri(}Tbxq$< z^qwoy8xzf>Ao*3IO~}{kl<(4U<03y&*Lazj`RK6})xN|1G*wtcUp=A$hCY(E!<#zg zrJH6mzR)c`{xNF4QJ7$_Wb#`l0+Ws&eY#q`iVj~jvxiti^^PmL04B3px1?4Jvm*AN zYynHf5)Y@w!-}6w5D|_r%RP~wMH;8T(H?7`fRp&aueJW$$oEXO_sPK2-ly=z&}3CU z+WPM2+Z^C0?5t{Q>16R(hxaw75vF+4`4VpiAH`dZZ*z5i!Y+k)-F8pGnwB5qkMmp| zo=eHD;4bQ-1emc)B9)Fvn`_|r^l4Md=b}4xxDfua{hWzEnPnKt7YP7giw}DvYXTN) zYw^wdI>uztD1{f$N3JbvJRf!nk%lf16Zs2rNFMv zJ2_Y9*=$w0NM4}vFY&8_Qe5Xl$|U}HjeUphDI%?5PQky9UUF;s>Q2T(Cp!I0LX z?p#baJ+7xRv@HTUIKH|VYlU(FlSap8Fegm_qpl=jEfdEW^eVJ*7kp{XEa zNFkJDHWd4lw@D1U(1o+rxw$=mtqU+(&oY0+7*HCyHB#~V))mjkVhgNfEwn-IF_U9@YAx_e6tt0G6=v`aPvh^^N<6~;|}+)T-f?e(}n zO(e~_qi%9)VcS=+6paTLOFLVQLd$PPH8#uCd;pPbt}f-|_A# zn}-RK>F@f=L(-6QC?(ku9GZdcYbEc-Gt^B;<><*>%h)H?^l8}|PI@N-H@Lyh-%c90 zynkm3&F|E#m{lfx+gx^?=zUj4(%nQ?dXaJh2w^mLCVERn%&J0_$;x21@~bt)hKj&n zymXhWlTRKeo5?Pq7GN~jda^69+lA--)$?Y)94EU0ZvTw>oXvFKsd0UGpd*4>P{1xX zJ9EF&Dp6w&mCKZPVGr>9Zl}%ZPSCo@WV-bt5yd0#e3aQGV|G0|eJ zbukGcRK~7tp_&~x$j7b?;D@p6vnJWN^()x-F@v_J`nVYh>yIMY9!hBnTAc&g8;a?h z(<;cK>3){3=Y3lAJTc~4-irqqlu^1?)v(kS;y>8;yEHmTZty?w|JvX`&9*gQ7i=LH z$%U}52CTfkFGW?ucPC|Vk;*`G+e#$KZ74ZdrtKJs-BrWXCOk)<))V(uYt4Ig^eXND zdZG)6qp60+S&7{(E7pTB|44^kt3^h>)Vz&y?OC=X1bThi&@sJb+E7X-3$@hr)+|a3 z19+OC8`h-8w5+t%zftX@Nn5%-?J;rKnS#`au_IqQVik@A1DVXg&fy-g-!A_9!=5Ve zime)a;nUyKJdCMBFNQ<}**t_wSeY-__I-C+q?FTqm(XbadK} zYyG3S+QwFogP34mDWei)OGYJOcO1Pn)RXjBRW~}&m3Fo`w+xu8WL6H%ePG0QxEWK4 zsJ<`jD>Mh&WK=r2@Qk=F*id3DOEtz;EqfK8kR69Wt?Q46)onM9q+9j}OfVu#6H+?A zPt7874&5x`m&D0Nj{QiY`5yQj5wxwJu#ZN3)n)aq?|{eV{nmSwTfbHB5w~8kPi0tM zladASGzrA$KKB>ReW4lN10}ld2h`E-C&0b{+P^BKe}HiJSNeilklw@0%_35H)uY$o zg=JA+^FiaK)cRjBF|1!pxBXIq>VcwqfT#*;L3%}VPW#sdq=STXppXQ$AU(P{r~R7( z(!oMHNJxTOP&iOXFBgyw5z@gz64ZjiLCS=z9=PB{Om<8ksz~G^N#qb>B!}`-C`LzK zi4la#Q+5XTBZtjYZwf_kO~QJG0`Orh6sWmwWneSbWkiikIX7xQa;(9DE<9L?!NC?p zMkl9a-o)Ubkhs0jJl6Dpsku0q9rbP;Rb+3VlNtkCcI*(&JTuzV*Dt<~ekb`%k4kAA z)zuSsQ}u_Y;aOS#`a>ikZZSpl$txo#-E#KO9UINYhG{Wb?uYP%t zhuF#a3?c2`7HA$Onun=U32H&%5LK!QgjI(=uR8Qz5W=B=JAI3vCm>D6lZ8-ae9~D4 z#*l+`kV)3WW6l%kj>U!KQGe->Q0hGSY9|k@+nv995h176K^Pn`y^Z#*j^WMgu|0b8 zaJYq0^eacmC3}xfr{6qMumzl1Ri5bc?LKa7HRR8>`W5$R;qguHFf|iW{I)?tzcnpC zv*#d|LLWhv;YfaPe^l;c-F*!of6(#74j?4%{urNdG(VOn=CXgF9BhBi9EgIuN`4P4 zy{n{g3Ei-T3#jrS&L6Wl=5W}bGMG6W_G$(*2Qcom`5mxzt)rgZxE|VZI6*9_0Bt_q z5<;5JpR@SpaGHO~VCHbxUo)6F9QIlUGY2r8Exemi2wikvfs?*eZK0ItHw^PLq#Z?X38h5s!J!%!zhXOci`mRA7K;}Gr}XH*wMS(Q%jHut9TLIhc}@DV|7>r+_9|4^%x>f# z)Os|F|5T@yrZHoqDG_EQoRKDvUdMM(lqS^ACU~S4z+PSIMz3% zwSK;ILmjBuTXGGbaGAf;#OQm8&Pz935req7@#H#Uu=F@VzAi0DPQ*2I0#JEQ5}19l z@F9lmA!!FV`>fY)=Okw!lgZV2T4?cX&#-))HxB1OAOF@czQM2kIWJ$d089YB0I|b~ z&z<=ff;vz8GOp>WhI0Xo?x6%((1MAVR-8ap^UF~yQCJv6mAL1MN)Q= zlwBlxyU9f28OcO4Iv4(G4+}n96q<#7ZDsj8Dq8!3EPo54qi^+jr}R%+UoIqnadI+@ zFjVcM!cJ_N#cT^{3Xsh!OLmvq*1~W9omyy%s&EBGoa=iGZuN&f46iy_U1eOi8a%8D zyb^0??VWy)XK89Np!~ioN!L73`B`3i|(u9f1n315AXe75F>xVas!)XBG<|2?ui231S zx%i%{Z@cjk@um5~h)S(9uNe{d*xm%xSM_i?2;%dxbgh1Ur04 zQ8N6mGBSx%NrcLoCVVStAZ^ ze%3^m^O5P=cZzK`A3J|182(GK-wdp_ z8cq}_Zv6Wry@yy|{t_)@lhm8|#GH-`niGO?e@Z)W^B|&up8;^ARglcgNu4{JrrbGas+1lR{Y(4;d!4>>2i&sa^a5Yc%WbF0aRaC0s^`7mEDXRzk; z@`^@MmE=kgI_XS_*4#83qslhs>`Xe%C#;5+T7Og3>}vg8pJDxK|MV-;381Q|hsV?Y z*2}FFZ3HXqB=t4Fn#O-!5xE)dANnq@d@YNKzDgi21bMqiDE7&%i>P-Xv?_X4B+e5}RD+$;6~VgxPbxRqM8()caU1U-NjLC+d!ZXm`@1ex5F- z+y5kE^EW1e{+W9({go!5Y&~(oE$NKIxV(Q#zajD!#vEJ7;Fi_x~ z>6kJ9F-b*qjM(tCl8U@shISopI|t!O4y{8%VRxh&?xD=xPEz9$#|P+c`Uz+r!Ot1( ze~T?)_b)}i=ezhF{sQ;k)Wc8t84;pk4|B&$-CVrVj5F=0T@Tc;!LO+K)6aL?x@Hg6 zhpzA-m5J7V1Wl!@Y?Bi%e$Z@-&QKA;yP5IL?kaN~)>pw<@jRN|dRzjxdqS`Iq_rs; z)3_>)DQ;2kc@Ae-K1&JOO35LfTyGbR?(1rF*CVlz&}}%9O&igoKLm%(8x(d5VeD?( zI;1=70Au#UJ8ep!oO~WluQv>_y0VGB`d4d@=SAbM^f6WAo>m`wsXdm$XG|Ug;o~G| za-7e-JRM1N&g5&4WE^qH_RYhSI|-yt4$~ZZ=DmZo ztI3(Txm;Te*Eqs!$$O{x4cHyh_|geA;_3ME)fLAV=IvGoCP&*J;C=F;*e*fYZdY+< z@(Fkt{71VNa5hg{Dw*E}d_+(SYJO5)30m8o{H?PvEK=K4q43^K^C{vCqCd2@hyl<9 zgWp#&{Y2UH6a9m(r&x8+{W|p`G}P61iwUTHro9S)jF0b&k54IKK`p5HU0@^QMVxt| zuFUg`^O8U5f*sm?CDL92JAi%RL{#DRa!*(9gz|V^uHosq@I&L0w!s*uz3?A_yFa*o zoZs%f_XGc(yWXbMCuE!X68=C>$T3;#0c&@7>jr^+3v zJ93QC3A_oeIH?(h;>xlmr>^{azxg@(&4MDaizA%_6Ldp*q4#vmhdMp1I&v_(3OGKN zpPDWO=qss{Hn) zDI}Z>sIRs;gLc&MPv2a68?L;h0yfqrk?Y*u%Qi5Awr!+dC~i+8?c^RXR?QCV z`7Q0U`|GwrM!iux(cj^RM`mZP_g&tG{~*aE90L!t)8w|yl6zActFP`fbO(dBPYxE1 z#=D6(5blKwdpIl}m=uMUhA^r3OkQ&X8o2t1xTPN}nceUqiaR_R5U&Za8O?>j^+i4O zIlb|jg7TdE`)&GJ-Q=ekoh$i`%P_Le>ZTgNo7oEMglG)Ph>ddE8#Tfb~ydZLR)DPz!2_&s5)7JVUd} z+$ghXDz*B-$>heGZa`k0$1(@J05cT9GTaQtcWQ=j4#%IC!OY>X=^4x%4x5p|%mHkt z_NsugYw+*abA6;gA|Uml+wRFaT(VtW`IoYLA3|aBvb^%TeD~uEpC?kdML&N67KcA5 zQH0|7>S4E6oSsK6#LzIQ$MY z*K|!w9x}*pf%sBVRzf`SBS1or0`|*e!vsh^N4#{*T_ySik&cwyl0Os1aQk^ek4Me> zFyG#4{}xj~z%26ys!zqF@wOM(A$Qqf z-+T-{(z(PRw+dgv*Pk@#%X(}&J3B>Bz6s^!({0UfeRMUNyJ@t__ON|m;{f_pPq28F zN&TPZ0LLh8W5@TYtbAqpmVJfv8^?lMO6$jbEqr}=eJ~&8bP(BELwfqymoSxN zGm82@tcT}qm92-XcD@WHbAJAbH*1nPOy(C~Prt`5T#cl8()MyDGrD#Ex7081x)RZ70%3FiK-lhTbhPt{u>#&C2Q*cTB`pVFU;YvwKJGG zfMIJc+0x3^q)O_g96k`p;jMLug7x>him7(&?;H`8>A!&SurO@8#zqZ>I!vZ5j)f*q zQ#3QzS*W%juWO)z{f$^0W-BS)l+wrN!Li-{e!R8S?~*f4m2Mu0Ss7YOzf(7#q0jWq z)lpWaZLVFH${L$j^qDz{_qW^zM0)<`fSmvx)9}>i-Gp}qw)BwDLaAg%Gge9d4bSt{ z#rHQJR&85L91i%#wtK2!U0_4TPBnQJR%eeUGEbAgNYV>UnIGrG2`{|C&OHY(`p6Q+{ z56f(TZ1}ug9}YbDXG1@dlaf%t3PWt-6aL-7xB0SwXqI1I}{W zrrEmqh-InzhQU&qo66iXW21p+4zfQP*<++_=74M9rzbJJPCrkuv*2wW*N=v^c^JP^ zAPyuyfN}6;DafRS4S?i_KwN<|dSgciDBiDlXzqsI1Iu;-m>1W}Y)n5#Bre>}P60#F zG*Y#`Dw{@{M>)lsZxy9`vkn`*x$UsgySp|e>b70oZr@~DCf()aZXc7s#F%VX5%zW4 z@g=*hC|xbr`|4Og_tgi=Nz71*%T~jE-EIv{JJQ>$d+g?kN^`Xr<{2`c~<_e@xtBy8kI|!{W|gX}W^GRl3bFaf|8x zr?`tO?&d2^SJ1agck!6G#dO~+E^la*?GX*`o1pE6JydBZ_w9jqaUZ;n?1ViXsI!1< zu-M68%@&Bl#v60M5%rlRqr=SMumu^+91hzmgP8*u>zsE2%NEG_Th{_g7SLvq>a@+_ zu&pzgIe1nJ#8r`m3DtP+L4@Y)z)kn42i!~f$93o z6fK>HOo?`f7N$g`e<%cKEodDlb~zu;6Dp7c34)P09E_v+9#c?G=t}m-0n29rOb(R0 zCuW217`$G7I_EJA!84&x4}T5y4(oE1zH^4&0l1RNx@PkWbhZ~d}wa*0DPQf^4$yg;>*xDBH8KC z3GYPjhb@v#w5#oR(Yi8K-PxcvON{;_f?7~mOm*o`p4Y$^_9xt*ZsBm3=+fvOq_D8A zb56S_mBVZBH>CM=DLhYkPNp&|9`GVzw#gyfO#T}(T`7z17FzEHAH@fbQtiE`A zA5ne^?fqoPs^9Q7=Qw8zr`+iiR))ilk#M@Qeq%IF)%LvE7Rt^sNNX{6Poa!7tm0O} zKgc9^fT$xGtI}7cOJ7oObwgZLe{#wwzPlnB$$U^e^}{#aM26t`^6>Mre60}PXS)CM z6<*Q{x~g#WO6-^zhg>}34z7be7gp5=HZQk=;c5`;b&_lFvhUzMM#A}!uW{sGbyf4>d#SAM^R`eiNLGiA@rl=vmdEa-jlV#Z1Ofe8@-C=^H0vV5g%FWIJA}h ztUo>@CuJrctX|65xMyR+s`(D059n&OR12-dkp`mE;vD}^+Gmg zuM$mI-TUDAIs-k4ZGv!~QQjsF=i|`q)o7>XJu{d& z9JW^mGl#?W&S2(n*ghG|91eR=1~Z4l_RV1CaM*qs%p4BeKZBXWVFzR|b2#k43}z04 zh09eqtgk<$@Am0i1>B}n(K96KUkUp}it{P|4j+`!F$Z*JY_v_p21E2A)vs`&V*iL) zdK^9}C%XW1=I;TTQ)(Yf^lW1DGzfm!Pf!c8!+znvYf# z7c1x~emv+?V}d-v@I?@umpFVzF&^coG&Q_P^`)_;Y(A`z$Awx6Pw=TEza+ddtxw7> ziOD3A{0g84#o-2^$x8)*vY!0901$(wu}XeZfG!dAWC<>FX~eoad-rV zhot^njsExxnP)l*ZR4+OcTQfZ`qDn6P#>NFv)QAGuAmka=Gk_*5yP&feP{vw8#%h5 z7G&r>+|3OiyybgX0sEUdwxAYd*zBoIh<*xRSBanW0Ya)XdcpR43-Q0D_;xZ?Pz$ok znk=V#tAM=>Exe;f2Z9(%MqA;NbR0ppAMh@ch}E{AHe z5IOYBJC&?d6I9X|=GW}*#ra19;_zCR?rzt4O^5F4&{al5SwabS?a|ORfx3Jy8zrAn zqDj}*=U73FT3e^skBivAO+6kQq<1@`}c*Ru58rj1Pv|@2v6cnxz-p{vBTiuG%B_C`W#6S ziPHg;lE-k`u|)609ne0yP_>?gMsp8UEkP|v6=qI20|J?hbw|<;$or$nmZ+Kzv;Vmr>-R5jXoC~H%_k>*q%Q=78!uyb5I3}~mh z#L3^ImXA9n`4frGE>#+9(uWQtuZo3ga)Y+MV|%K0e0Qy!{GRkJU4MWo)%s`Y4nlm6F?FynRfeNWLc?{!WAuK`kf@QyT4K3rOD=((6JJ z)Plm9ASM3*Hh$g|c<4_4iQCTQ{0m2TgP(4<{{N*hIcitK%37MVXx(ViJEI9?jQbJR zjn>`C<%D>meU6TlU-m4Xj%NSC;o1xSII!zLVE!BrYaSe4fIS(M&B4$@0BhNm_Hl(A z{6INa4o@S3T2S(Dyt6AMruJVYv>blH?|k)7)A`%^`EQvR-# zC*9FU_Z{6J8HPWTA6J}}yyC|ztLo)+YiottCYq+B?7Xod{jtoRunXXgqCB6ovV68r zDCFchRt;4vFnggw-tg;CpzFnO|r zieNHSK|84ac!rJ8mSgANpoghO{%leQO{!PS@K^Oe707nzDsIScLg=hK8hq|4$hhq9{|O#&-0f ze&^qO&BZ)w=OdG6_Px?k-4d=4bqA&qE+@Ao<@~ksm_3K6_5BPP=&cbqr~5bg z1U=v&Q{J;_8w0xJ@Qye+h&ZXm5#ooheKR6s1OdH$2!fs&;124%IkVsBChBK1ra?+C zRN`AHGY$N)Dt8%QIETbqUAT0~XN7OGDzMH_rFJO(9@@>S=co(L1;5!1ibbd^LXRSR z5cur0ZCq1od~VGw`!@M54aTdC3qL1SuF@@KZ>Vam@fbYbBHCfRh+0jXx#2>opDK+O z@^4(kPjWsLu5ra^@3r#Yl!x9gFXkVPT%TvNyaqMpl*Yq3(wBtv))c>$Bafjt^H6I7 zm6_{!Q{b+~x*JmGeL^|f9LASO=08aFW|O2SE4L=QqD;Q7%9(vqj{O92@Q%vz$`7SB zn;WH8g6wVhBr_mkVNw0pJ z_<2tJluQ(9`<)7_CGQ3qF--C|R+CxeYT`I{-)yL{)2V*F2&)3_F&nU=<(mFZpRlBR znmruNl(>TV#Kdu26PK5E7sdTknA}s=FPBh?L3OV+1py2&jHDIi?F3*4POmk&%hg>o z2g3#A14D!i6GREgQMM>R^Z5B=8{jKcmT=Tp;)BoSdL-{W!T=ZAgu+Yme|tP=?gG_tge2 ztHn{wW98lbSIE^rx!$!$U%mM(37jne&yimwX3RpvoLSjd><+`*DYw$h!GsA7&3Dy> zn$5U$STC3`d*{s+%*vvYOeO>4yH{OU1s3!PA846o zzoPw4jONY49XEc9$D&S*N~Jx_+u?H06yllK;JbdNz{_AkoC@BnCH-l)y#WDLUg_OJ zzeZ?a0W&1s(yhD?9AGAXmg&u{za9<$JPQmPn0-uK5QixgSzt7sqXB!ZRidzz%0V_M zA8`5JN%;)W*IKQ~^Y3AwAdJ3YRM<|bBDVQW4HU0Xpt6A(PN=G;Up5DHft`}U%wcKz zzSLdN<+?o%)o=;zAB{xbCu!pQNe?ftEWDTSyFFa*e_HIUFQR!ypCYVmW<*?Y%!UWs zRkrZ0N)6410~I~|8`gW8t0J1-TH}#YbV@bp$FnpVmnx#F%>k?GCALVX;!5Sh-2>8Q z^RBn^EZq$KLiB0UELqS(EvF^U@DFB}J@c3#G9C^10oq!a1}(14_%qSRSM4E#>^6+G zKxECwuD;ooW1@vIz2C;%ZFkNj(}@cPE2a7dKUkRsRW-Z;UAL;Lc87oAsfHKGs$B~p zS?K0|pR+EAHf_3{ljd!zZJ!|zjcI=zcM7)2I)Uiv&oG9kgw^=^llIB#IDIyvZlG#@ ztdqSAwux9FNB2Oh`5V&b=&!1Y&T#8QRCpDkBp<~Ez;p(~h%>p?0j4-GjO!g>ii3Yb zCb`i8$MOjRtZQb39M0*W+~g?IRyubkdRyFEvevsyNgi}GQ#Jfmq;GM+35sWcTODAE z2?N~j0BIqTJKZfUL~@tAPv+wpyW0V#X0UvG)&ZuQFuH`9W5Y142G%6vpn3knxAsDvwht)ey0HW1ODPdTlxY|bRgpaa^C z0=}1ZgiW5bPGgbwp55 z3kn|+!RvB<+OZ$Uw9eTMN=_L}75cWjk)2EZto1Ds?Sx*XeQF_*x)NDei3n;zVYV`t z_N9H%<;d?o)q(JD>IP?WMgUYAf7X~aNo^b>ANnKfEvw1fh|5tBFnh;#0p94x!NmM6 zA>sPU6RAdSfhm11Gq+CvX^Q;Lt8$qx^9cGb)VwKwy>_?%{qScGPR0r9HlE+g`=0gi zTGvO$)0>;jvb35^0Vk`oI={35JUt*fL#*9a&ik=wJkp-ciNQuLr>Af~Nc`p?NrI&T zqY_HUmo7$H(%hqve$Qu$kpNj6aK z=Fx7+!(7}wt_Wv$LDw?qmPOkw7(Y*jzumT5;K$9iVUWBC+I%Ulyz~#tOW!UN@D84X zr~`~q!XJGmmHAZ+XQ^83))m!auELyuq%M?^s%7-yC;fvlUO&nDc3 zaxg;is}FQO*5y#V{2+}wmdanGWLX&%mQ5)YfBn$+7Sr;rMMsk`Q@*}<$doLLKZlrT zCxM^#vq!%?c?yg7BdV1_2%38p;2XL79Uo7dV?yi`&?F|Zn-+h28Sv0%q+sd zVQtCzb+v^!{7ud4pK_=3iIOGs1<`uVY57q5Y5}Ki_sl&aoVMd6{VPvTU{7yY@%?7e z@VXLh8A0-t%_Y@8d{HznOljJ#nT^rsd1O_PVB_xvX=IPvYismJ75CgU?y;B1+#K)^Y&e6N!(nG;FmpJpmBGy6uyzJBhr`awVCHbxNCq>9!_LlN<^ZPg zOmp|gkPCDFlI{u0`l>AKOKBMM`a+n$3;$(>@rJJ6g`cH}&~kZCjheXiH_Gn0^ITtQ z_pGZ+)3b8rFaZ)M3?}Ns;dy<~hELKLO%WfvmC3HFn6)*0AIQ~HqoDh@PFEIF9(qid zA|6UMmUI2EQQ;9DVhtp#(RsQW)yR|*5%XnfuD|sA8y_d1rN!e|iO`aDFp#yxnjnw8 zzma`xk#4LqNj3l?=LcRsrLmD{l)W*idvf={|Agdccpfnhs}d&;ef%~hP}*r2;G0b4 z2lq6&r@MQG+^e~JvfNYTwl+#S=VxVY4o~}n3}z08U6{el;joJ`m^mDFaRxJo!!F5S z=5W}h8O$6GyDWp5!(o?aFmpKUiVS8BhkZ~my?vtf&{rg{QcE!EiOrQ)2b}7&((Q}n z0?IWE(RSyl=j^wgh_EHX$z=1PEFE)rIv>tp<^aaJ@;Kte$!{>|r|^*Jl^KpXJl<6q z%p4B8I)jRW!OY>XYcrTR9Clp>Gl#>j&tT?o7~6&3 zCz-=xH)b$%IPBvY%p4B8DTA5AVK-+mb2#jl3}z08Ey-Z!aM-OG%p4A5SJ3%02Qc&- z2kThHunJ`OJO!&fZqM+{;c@TCVCDdZ4d*$)vejug2paa9HD#*vcM9~j8Mam(QC-`J zcwe=)xjrDPXf_J_s|wh~0PSogt)FcrrQ@T=|C+_0yVCfAzFGW>Y zcJ}*N9JVkN@5jU;;P>;%=4>uw`l9JLcUgxcGkWPkKlz)RYJdV^W9~Z?t!at?t<10W zQ_(+TOt>u2i{Y!Ke(b+wWQ>i>>Jc09(UZslYi3?vQn?KsN)ql|{2^TSl(+jA$)6ky znIRf4aPC7BbSMfi}W zMVyB?Q*L$MsG#Rv%$LnB(48?orZ3_uMiHADt z1Y*Tup?*;lb-@dFz+{K=`nsAM0qJ!G(dff{1LI)_<(Td4)moBK+>KtarED_nDf{6V zeg=Iu``*qJ-!Ag9(&jcVPDDx=qwn=n`S|?sXVLn-_R&M(;&{s`|RkzNL4sgP|z zw2dq6YhwrzeVwvvZbn6^r#q+2eP^D@eu27Jrb=xnG~Y>hxJpZ(tNCH8;!ZfvG!^Fv zgMPR^BB%w0kAQ|jSevb{9PeD=(Z=c{f?80x2E2s1sU5RV$Mkx11$;eaZHtkko~s{p z0Zpe#&A+i?JoZ#CKR#W@SNm-j+cwI$MVNqr1rkVgz~J1TIg5$kY~WKDXy>sy)!?1R zKV_b#N*Q=HkXeXfiyl4-pFZc%Ubbv>^(XUhRWH93$?D9W%h+LyW|ybzxy&&3m}0vh z#GNQV@3Bscy3w_cqYbTzgiZf!lX}8N)v=OQv2;93IREYUZS7}N)Qq+O6u0jxNce-2 z@RpLWpcWK92IuWh7Ld*p(gGm~YC+*zkeaJ9OZPl3h?A{AFu6#7y_5UnWFgSzDu`uJ zHuiov?o#Mc3AHb&)y2~)H|Cj@aJdC&u82Ld;g(a_b*V19-1-zOtZ+XyJ@(ze?M-Jn z?2#Wt{UHcu+XZ^Zu^{{8N+mW1c9meVb7mG8Jp*6ZPYo+YGvKe-o+6K%P^)r1YAMok z@EdQ9+j+WyeEVG3?+^N>@;>}&QdsdksGx6kPVrk~;yy>sUv#yfCH+rvzin|pv(j`0 zeXDf8GbU~^-TxGKsl~l#rRfU#R_T6sOx$9+|0(XX7WdwjrYq=MrTe`xaf|7`dECC} z=hTbuD{gaZ8UfcOe*{AS`)S^wj8KlwU+wNXGm8k8DCtj^bF||xMH1khd$--aeY{B-K=jMZsKECp|tK-!u{cs z0Bk&=%`*3T5U8zd%|ZTwJ(R)B;jqtTFmnLo?C5>Kva_SQ8P4bkDEiR(d=|$X9_O=# zIGZCCiz8qf=iw}lIh@WHGMG7lNiVLx{Rb+m!uhj%3VF+Lekh#6`LoeDJ=PaIC!BDL zBxVA$!yb0%RJYrqBGn+C`0m1!45N+EIZ&tU zsZ`@|t0INlg`q2Gf@D#qAMR@Ed`WLD4tFa|CrWDr$yxdo2-d=93AJ%U_x4`|FaHBC z|Mi*D`-q*NDcz0OnVvdfxO%}^#{ zJYyOnwpqD5N3xd8N`Bt6c*gWv63dJ|$0jL#oeRv8tPZ5{N1r&A)P}Yz@O*mCbK%4( zvn&(6QS$Srl;E`#RrnSJxMeDQoiBO;2i`AFWe5ckvalp}E+lboo`fGb@>8i?4pB@6 z)$M%BIHRa!u)pJw-_yl}z9>&R-VE5Ac0Wd5`Po&M$)Y?xWWw3iQR(>ETb9*ILFb2+ zkx{4rO34F&vNAm@Cq|iadUX^rKUoWrr*gh#Y_wMtN>Rk|WXe%eEZLePT*v$(EM<*T z&%m~sbG^V^U@?cc8Vx)AfNB+P6c|1K9PC{k{M;z;_)4-ZeeC@2BIjzdot&ugcujYE zIUm8kP<8Y%D!TJ1hQ;3^iT zyVFd4l1h!O$`7G7IV~CRW-^>5UGVO2j9U?8;0j=m+*fZiF|Q{jAf*0oiT>35TKekp zeiqlM4RAHtNxb#U!(b(v)Dw1=FD=`?-o%u&O3y9yJiQcL7WJO63o$nMnwuB*EbnLC zos#ZOb``Pl^VCsI8XtC(Z^EdIPbg%3m6Z2Y`W)KWfZ;PW50oNlz-?iYx{~D;HYIzP zCp&(5Kg--S*=5#?3~Si5quH@JixW~_R-h0Il_$B3g{CbpvK~(7#9tWP`Y7rcNgq%D z$8;}xgYN{s`V)LIKT2(XzC}29k3@$9XZ|({z8&#tK+!MKc%U#Qt{<^+6)n>^U~Q*= z%W1&7teNz0sf`~-F*Tq51>DF2%LP zyXrJcZ$gxAEbK3$-2+|y$)2N$c2CV<9iraJ<+9mhrL0=d9`+MmyE=9S%6;Xj6JXfV z>(EYn{d^5kwewFuQ5g;GNkZjhFDnq0{*-$27wq_8&|%G^9Bxt{c{4w)0W9vS!}_(G zx=OC);9l()wMDcyB+zo~!)Lb53D9}k0Ba*SX=@Ka_3EeUv$HepU!X8^zC8SA3fEjo zXWB=FSMALA&k29a^S_?z|JC_l&b%g%I4kM6*Jt{E>NYxJH*L|Z3NuR2mH+xI%jZp9 zWjjA#oD*#vZO9n)A~c%6L`1Tmord%{^gLCcVR=ly#i-Zug1@3>PdtJKJ}B^0L! zX}oNT@C8e&nozjMwg%*pBGq_0k2MYC zCy;I4$4rPC#Qha<>FItA4y&S6y(6V{xC>;PK=LHL&HWhNqS|0J$FeEYCxvC5;tUe5 z4(r!C#aiAe{zmB+JH=YggRdK3Qr|KK8_D#Zq9-T=<;&N0j`M5bl-~@e8magGjpXoh zDu>l!1Y7Yn^x=+$nfk`9)%Z~J1a&PTPlFid^2#e>Grhz?*wyfrQG9qBFDs4TrfIAx zqUF|F`jE!j`o^tUd`Lr3x5Xe0!(3kZ-$EL~9-Bspkb3kAY5e#7`iA7(C%m7?>(+{k zv+NAh5i|+*E_~>J>suafh46~EJX{78y$9W8G@&a!J@p+;f7b-k9ptnVhNEJd)yLi- zWZnA*Vbx9HZ6xouil?F6qv4wBS4-fUR_yw-b(`HY@uUjK7w@IyRc6+9PqB_AW$83X z$0tX=29Qdh4tXujUivCiJ#O+RqT=tN`#ul&U(p=!c|aO$;pl@+N0I45 z*prjmGQBHBPTFdEKMP?}Ev8{|jtY|+E)A1&RG3tQX_%ayFxkK8$dUehIzFUTS~fG+ z9l!bhpk-C670RpQ&f0i6Vr-6nr+k)7X_Ma#tWKvqSSfR4<8Hbd+nA^h2Dbh?=Q1>} z)*mwxkuEMp#@qqZW#@Q)Pdd#b=@8KwZq91N3B5&C!{6okzkJ8X5s0AfQt2edz z+ZraFY{K-0c3tKS)NyPs3F~-+i*{tOZ36`w|n4dSxZ|*8g!#T+_q;hq&5v(0$V3 zdDw$D`MaeW__6z?*Bf^6)99|H$kV-r-Fq@EX=;;lK(01rv*By78V~DtAo(KXxqtgf zJmEg{mUc!Zd={5&62`*{VXE?iB)&C6eliXQxDD9g;hB67MfM**ftNp7KA$4i(6e~s zVL6i%ktCZD<~|8GTc_qe8Fz2h%^qZx=ya2kGHJFDYXhtnpl-`zo4y>YQvErPPL*e1 zHlaUAHf9r{{lGXzf@Bk%%wO`<(}*&sEFwP$a@CM)o}f-U6cHW*p=JmulwWqaYi#76 z=l{dno50sql>h&y=iZ#VBq^i`NlSp1rR9)PD0`AZX<22bBD;WqfPiu!m#Pr%C4#Jm zO+0CL&mV@6R)5%W|#X@Bg3IE9cHUGxN+dpV_x( z1VJHsH_4mW&i!KL)ftJq@N#GuqVIz%#rH86B=h6v{QSWA`EBecIp>C0pmRS_4yxJn z9m`0n(W4VU(PbRd)~ZcYty8MYy9*TWtC@^_JLLl(MyA4XCqI0aD2FZs)97hrfTpWk2RQ>{+T7*c^ACwde2l>w;pD6M(DY+;5eQG8?;i~fs zVy8qZ{@MJ#N|{1mEMZUf?ZA?gH98iSM4)_#j>oJpZroDwRB-g?WaW)7#r#7n?PfN0 z_Hl+P%+ao5$8D`@GYx=gyU(z>v`y6tMuyEQ-ap{~n##L_?p{In6bTyC{<OQxx*!UUDlg92%p>m*(@QP|q;V9nNiPmyjc4)6U^a$*oijmgZQiR}6 z$zza)*51%Nu@JrvBQr{wKsEX(9?C;sdU=X-FHP#+?nl=lquola47~`mmhcVuSm<1$ zDiMk^=1NzaiU_*eKJG9OZql8>Zn5_|IMiN@$7btk6y`t?X3_r;JUWFyt;O&&T5el} zjBT}-@ZMet>a+3Qzd1}QWm9`mpQGW~GUfGT^Ts&{k(>GD=8cM12lCy#k%zxz%x0LU zB0)!Sna-8us0v?k^G?OPlJMa$OeURZew{>y-{3Q;;7mT3O(J;ANu!*Oz)e|8;Wx#J zW^Aq<`O+dMJNt{=IgiS6mGb3Uy_;iO?(VtT!Mj()Cz{8oD(LR(sPuV@H^(=Bd+@JQ zCOi(tb$b3$W1~J^quBkRoyC7UX8kE&_rd;#^7Z97U)Kkp{~}-i9_MR__kJeCX})d% z;s27aigzXX@*ne6@vbENf03^torSF;TzKq&=7T5#xJhNSv(zL{T9Q-dWAdb{kK3AK z@%5e?BqzkM*TDv&(ag0 z>e}X2Va4AGCwPl@qN(nj-|PLH^u3v-XR|atTBMT(x2ZgQ6;37IK5GFBjR$kh=Rc9N zb{aKuL{xJM>9O4rXV+vF8b8kkcq^OGHu4Dg0g{V#cT4vP%=PpBKcqtM_3xt$nuxP+cUJP+rAjjRRKI+AZ|0 zNgpr$!B67IjSRl}TG|vSZmHq-BRSjJ0KUw$idAT$BrSq7i*NR=IU!e6J#*Uc=xv-EvHweDLBpByxPd5In&;tR|NrFSV7tu3BFHjlae^p`GnF_rj9Y{Ejk9DzrvE}49Mb`XNDp;7G*S>S=jV^qdOb-4&nXbWiZXH6|_?OdE-u0 z)(TFdU`)DJ@b7V9ZLQ$H47Uf-6SR`_~o!8av=xM;V zLOHsFo~OVhwv3xw2GLZ$&=TE+(973WQp?eu6Fk{mzRNhGwl+Su{4sC#HJ*ZSPSgqr z6HR++O?JVIAa3HRbtf&{>d$XHf>SbWtV#}hw@_4bs;gA_jYo67S`%qUL^Y?nMc|I& z+FV&3s{Z$j&!`sa znx12Jmq^{BaICXqnjp3!5x@BQ787H&H!6eDU7#tw{#;nQuobsFTQPe-+}2lEi&W{# zGgkW~ntPC#@T=Pag6z$&KTJVI`_Lg?G_xO7b-zd=MuD$5_FLgB&s=uKT?9y_ezzn4HVe;S*lW|okpKFCAt_611;D} zJuKc%2wVE^!fN3+4SQ&u2baLwAO1bkMW4pl_fbFWMQGZ9S(5z*byI6GS8$6uo{Ew5l-eOh^`Q) z=fblUp0ziu?Jd?fu`zl$7jLwZ|4=KLfx((>d~ZPcw>x3m2+JPloA~22M_e%Ko5G|t ztnYvZ4bB){DNzPBk>xnYKNHRz3J}mSV8ZJ<-`yy`3jcK_!*>b0T6Sew+!wQ!FP44X zrbbS6#hux27e?Ii48l!Fg-iQ=ez<0~fPP9j=~Z|o?@!`b2>(JqQvb7Y=cJh0Oz}Ge zX{Wk0zGZ1F)Hf4C#;r6gvki{ywzqq!VS#$61IVgVX=aUin&^Ki(fu?i)p1c-ef-84 z8TUv#x`a((ta#je8kW4#mM~PE)|$@C{H~((4=d(@?XlY1oPNl0H2U4>Zi=O=wvE5w zBWcbT;##`~G)F`=r|`#kZS6k}7P*MpYHyQ>_HuXyqdU!Kokq;R=6G!@UN_@BB5FgQ z@V8`fg|}w~z_mmZ{zS}eS}|tz#1Ho(n@Zum_;36z$8?dH9xbM#np5}?ob326@80Nn_*rT z`-sX;5)hH|nD zsyT)CD{4E}I#Jbvjv>T((&im;g3FU$^dFuNy`zb2PF?Jk2pIl`OhtuPE55^PshIA< zI#0e_g==&*pZ3al*NQ2XWf_~Zs_z5f$&?#SlvKDekM+@J+y0^C&9*l0#M82Jv?)?d zLuU87-?7w7x9!c&^UzJ$*m(BCwTRI+o@bfCo{o$2MEe}#(b}OM%-6!Lablj}juGQb`{Z_C_XQEzncFRq zpTsZron+TISnEdJ$e>Ef-$sk{R#bIF^>VshhZflP0+eZH4SI(5swU@(nFWzr_V7K5$>VM5f(ccK_D1Y6PPF%BJM+^cENl!-x3DYWXn7zIGO^JW+r3UrxVxA6}4c7PVV`2Cbz}3&7gf( zv}yYeZo4Q(;s|$kQS0ujXsNzV>C1aBd}qMdy;tdnd*C6~qS}KKt9hbC>(Oo4YY5R0 zrDP7|_lhjb&|9mcUcxv>H&W~8#II~Rj8$eNyZ%_t>#{Z6sX@3e!ION@n0kHOS2rwm zWrjD8rWRRFZJ)|5#Hl3|C>Hg|h~AM5_p^|~QSZ;`+_3)QZeJs#`kMfuyFMp#oFv}# z&TbRMbH(hrIZn^0=@@#L0+YOJ93Dm_KFhg>=(iXiY1W|rnmD(FN6A{7NRt}mpuLwH(1bCCQGVEfi_?FC-?tOLW^m!( zNoZzpGzll291=yp|4#gv!TDK{(98gha-$?fWfG(OP=2xG;`LfyoQ5238WFnFtENzb z+?Rv<){d8~x{4jo6S}=Ertr>z%G4@WQVaEMR8sx=*8FfFOSb4363c5;`1Ja0#OCOw z=)gI|+)xU65*FI1Rbf`Ui2@e>l+FY~hX|h+;Q~8-p$Nc8}ja-I7B?r%KFj(8ELT{4J%E-djuMXc`>V;%%#PRA_kUR8DgGWF)RZ zsE&wgPBtM3*-V;SUr2!37m=`)H`kG;tzVmU<>+W>AEloud)ttg#APq&fQ$_YxScJcXz-aKJ^7|DL z9)e&) zo{@W^R*F*6Fxb@JAO0t;gi{h{M%QpNjr$%6cIQxXbOU*IHM$)~+V~c#P}25v&hPX_ zh-;R~^?u~)4r^(nrZbc`#^)qm)2M|V9U68um@Q*Vipz3(?XXH%743ln9y^MCJ=!=_ zW!EE%s$tZ9l_*!C^x~om!d{s5q3Y)~Pg&dKkkoydNCxCVF^;&Y>J zyW420;mSRMJ8fF#yr)>W!=`0xl3QK4ZxOC!hse_A8|~1!Mw=MixMP~(vyRDgAj}4| z#2u&G>O#_8+Okz{EiwED<6Ebdsi&@f#V*XTupo2X6_=E=Rvn^sgo?HP(H-OyV>uOW zboxRMPt$=r$s@gcA-(0g$W!aKwz5!POl#%W?j%%Qq2b%W`}@Ye*e0(4{UVq~lvWzRJ5 z*b8PBxHR3=ycHX$D^IZ-7IxM-ifT^bt6*d27V;<2-MSa^vmb&MV@DGq{q3CJW_thT zsC;$B@G$44k$Hb8UQ*b3o?B?auyq0Cj89$+2)Hc?FerN1IE{|@Va|7}0(mLmv;$?1UFtgDdDV`F&Qp!z$&M{x)6070bk09-pB<*HE zPH5GHW(H_Fhpbfg5uc9A^ZX*5q;$JX@lEh|`k&`oI?u(uNH6sha&p2NcWACbbPtZn z8aG)Mo`KkL+qbHBGVyJg@*3O|Yi<=dJdX&R7R^um){x)&l zhewN)h-tnFX^ZydWDVNJu^W1`c6V*Z!gP`w>hW62<0|9lsP~eVdMm)iLYloz_LlsV z^{I3|Iw5}&eHXbYE7RSJmCi!=Y5j0ZQa?zyN{^DE6t^)-mbh;JtH5d zCi!Rv0ED(mLNkN%)E`zD>PcEAR!#hv0YA)RFN6PN^Vp8WuNhn%(-N8)9IZ2X{Z#QK^%GXM&7OrJ2o@_%7*9x@XwE<;=z*@hv;WGR{M`6h9G(n zGY!>v;2At}+vVpta_!a9g!LC#8$G#{eI-qqsOFSQnY)=Cw=9=U(y~}VGHKfTKZGS)PZM4C3YJaKDD zTDGtTl(#E$p_96+u0y*dUrJd$rm>ZKTY@!Bjdd88O#ZtO4S@oxfl}Q2z)XK`eKu}I zkAFQ;$r`WwWlMv8p>ZT&@%}io*ZK^MjBfQ4T`0opBD93xkqBwux`&G*iDUf!Udw99 z{@#RzNG|YvB8{iuxEEvYuD-5r;!J)%fcCi;d2B3V2IPPy8MXE&sX1>D-hr^mwzT!l z+a>b4gq^K<`ikJEc&klk5k1_J;bCJ9LMQFZ&*Y>`9TC->;_QtvXfqvSTPTkiU)ade zottoaAcF870p{ADR@*<22u{Sj_vl~WF?s4>OY4xZ zV{Kppb|1@O$9*@;SHptxpz{cu5N?ogwdwJkWP8m?{Q7qMxcDQLZ>A$?9&{@!R#i7 zD2cbTOf&K0yxVI*2l8CdrUa<(pgeG|W~`elTYpp8vNwZ8ZRiv3N)aTFdX-1^j4zLe z*y$hD8Q!c=@vxWSa?j1BdaO^4oAq_o(AJ3gR0_%^tc;|6kb84%8q22Y6bhx{%oAM~L1br0YRd%rJalq8B{MifoLdCIG4y2(4NM#F3 z^_{F}8fK<>$5D4y%#9Bu%!q#G*yt_ah)>T5rt$sWw~MTP_*(=Dp8&1KdblSo_VdEn z&IgEUPVQZ2wNpDH=eCk_mXovo9tk$Augi2@wH(lmpzuj$gLAT&kZ$d9(k11p;Atea zNPO3c`R-zT^^F_qIHUGRGpf*-os;?nN&PD|exjOFxEu+HbzQ~!cV)@($`Zpw_g|l8 zY-Ac<$&_B&gAf@OBLm9+RWTUew+SGIyH$63WXuZ>tS#Eyt>m%2pju3uQuH)=)E`w; z_2Z*RFu1kZO&Npf&eD3P%L4b9J3}PwmKg+}8>=CHOmWMetA9>k%y!7gS=i@=ber*B zN?cW2-z~UGLk0f5qE;u;eF5O2n!Pb62iJ>&%PNwn=42H~b@-!hEVb15v^7*K;PgHXX z|KQl0Jb(1lVxVmD8-2OJuPCsMF+?>dtG+y}sPt^xR#>c*rX%|P-~v#xAsqJ4Q6g*RBONI6aE#(r1B{do)+P6 z5L!#_S^zViU|8YpVnErXAOl=F+q~yU=T5?G=ydSTotCvyR~| zdxiId`DMe>=JbiJqgW3ABzlXK)s2ebvsgP?Na}})*{Pw3o`Ytt?*2@mCzGmn|1VBA z{jy%E>Dw}SU{+G6e^=?Y1y51UDO{667d~&L$ohU;&tzWn z5PrvuA5>Q9h`gP_eMWk?MW7^yTMjNJ=INF%jy|FqljdEEM}*#cR7RIx1AYuos}KV2 z)I}Fj9Qzu)*_57(N%bYTcH>RSBsnzj+XWuzJEtNTIW8MTPi^F`#{YAU|11dcBL>>+ zidC@K!VA$xHz-!E&Ix#ef4gvemjQQi8{64nd$FrKyb>0(+-#rp2_SH3$Bk}ZeEJ=ZgpWQb83mcRIc zA8jA>tlHAQ6~CM%na@v)8zY+_i|9~2f9Yj>+R6jdu#|ZOds-nH0Rfu{SNi;=pTpU< z$Y$YT40|m%p~2MAq8lA-;k%?w3j*O>3Q}WkuC(>gDZ0`osySI{>ufQdrz(PHcD zd#YTxb@tH5V>QOdUISN180W)%HU?amACoa1GIuIve^!Nk!BrfUNy)mG_#1?jYxU#| z+iwCW14ql|x(J)rg{s#_zVA(#+6FdODb)8+t}nfUJYagG-kjZj(Mr)LVH5q8IL%Lg zcjjh`W|@=URKHnUc`~JC%dF)&fY!z|o^@NJWUWuE_e}AxM3TPsi+5g}U)u~}R$-cKF`E%ih6gI=ja?YE_V7{4qEuOI^Y z*3FaZVU+{I79zX^4B?BEQwUp%@UjRmIl@*V{9S~XAvEUYQanQ`eg&ryQOzl2=$ork z1v`iTKFQe+A3^^CC(u()ARa)7CsMBvFnrZQySB3EsR7!Tu=dtRwMctOOIga-kHA}m zpZ)L?FInlHa9j5j{=4hLosjODJjkQ}Tvz(O)65 zcjGh^<)o>-?WIE7*eF*XR#$nj8X&4U*={LAGN@ zyo14{5WYtFa1%beh2qC~Y&-fXq;}~(h5HiadeSCzcynk^-w&@EuOL$%sVR(47_Pq# zXP%yYgCDy+>8`oZ4Rw&>QuHdN{DQxd_O^cYp&<7UeDW-y9Lmvad>3fQ5gw;B-Nh{K zRBi-@9oQ@v8dTYI(z}NI*i1!Kb8<74H{sdtP81cp>AH@9V{HL~Y6KY6k3iB6&R4ZW zZxCPoNVAr){zKLeVy$!p!y>!&jyEB9P^Y(6B~z#9y2KJkQ%h0AY6~m#2dF1>$=LKW zErUuN^Nc@|wSAm^NpLIJIm<(Y8yab?9v?+Ces~YfuC;D@zJ8(NIa()^e*)R2l5x2% zcbzxvLXy$?;69lW9EeF2P~)SD?I36Hxyo6(Mtjx#>FLCOItElozFKMAU{p zmP(X?O=xbDa=@5((;SPn#KM#@h-ywww}LuxM6EG7UpBvfRMCNFr0R)Q# z!CR8}EhI*S|1fz`n0WG{&M;{|TI|gD;ljWs6gFjG>Xgn##?3oy>d;y$xQWBRh+8rz zZRmcOj}Wg!)0jFLRY-Rr$?YyOLRMv7bxO;iCcK5lW;u9frU;8_PKNNRQ&3ly#&b0F z>PW>CKijI^&2$#6ytcd6bNdQ2IEEqHzwppk=vj25Y>mxx5zbPC?~slWQOzlQ8{dsB za-P?nsOA*DBTrlAJgt*@64ji-f8&WU+zR>KD(81y`L)JNRCCHTMuq8%>LzG^ zF35TcvO+S5+R!I_S9}L@o@UF_yYeKeIfb0yQDehlySa_QoZmUA45FG-PKKddwQ}$w zwJi>J=5X;`%>8mN!7Fj%ata@nf${FioG+QXjkoLU+8n~^FTN!DCygn8NtAi}L)dG+ zi$vv&cngZR7{{B~TgJ(8P@ajH)&lc^|B}L&$NAT~xz?OMsB)#Z4TI<_$yo}Gf#h}+ zZagTix6U^JJ?o=;<1;`sMI8mx*;?&ih~L08wzd{qOoM#MUE=r=mWGS?RJ{ZQ*9HjyFc{n7A=&^^GM0AN2R$->uK-O$St`ddEnH#)4cXbFe0;6&Os9 zh-yxuPf1|WZ0npiTGgOd0g(|=&8e|X&V7O0t8y3BoWg<%)WV#nt>vjzoS2xRb+fs|sQS@kzbC zupyq@x)-Ac&c8CvOevaQb)#UIW15w4BgnDRsf{O9aMb7ak1JCa@9NIQ`rcjM6IZ$Y zW9j|a40cpM`ljfsq^-JqJqWFS^hGQ^rHJ7{wcC`c+phI;96k3;o#q&n5B;^bdu!3! zPhm}XXq|VboEXkSEDBIBcNuiP;aKBe4A+PJzlk8>KXt0(ulk`=rpLjrw%GbCzkUoo z4nyz{>8DsfRzE9(?bKySPfai^cS}vUm844g5ba$ZFFxDHe2#N`j&}@p$QZ~W$AEC+ z(aTvC$?{=%xLZF|*ywgp(*>^=h^lS5&I^w@UO8s{yBz1uDqi~<$=-g+TW5o0ExhV& zOZbl%cG1^W?z9d?s}RnIdvY>uV>|Fxm&f127cgj zPFdti9t#^f-=;!g1b4H617##n#V&B6-4@n{cUgO3xU}0{<0vP$&XFV{-Z`m=4nZbE zoH-{#YmUYs7w;8p;RgU43csT37WtnVwCd z53;sM*{t-aPl8vt1#-#G-L%>&v~jW9su*n(QFi)K+51*+ETRFG4%gxBFvKIS#$pk5 ze@;aC*B;#V{GLquzvK-;l?xUI@l)Ioea zZT@(w(}g~LZHfNl+IDytksyuj`6L@{J3y^XBh-kf<}_l0nf$eX>u^BALv6>F(3c`# zV+Xur^g_?%{0ExQPijKHqzV1*CiGXD&{vy2xjcI`p)YMh z|56irVMY`FP3TuQp}*CHzGU^u`Crn6{y-CYNAKi(wrxT`r3w9}CiI7!&`WDf9`AxC z^rM>4&uK!xtqFa#H7AdEnnT^lvtyzt)7l{;bLQ@6m*QUK9Fvo6z5CLf>TV$>Xgxq2JkrURq~zKKnPJ zU)zL!e-nCX-O2fH(u7`bLchHUy=A@0`7drlzpM%Up(gZ>*^~1>xC#BDCiDlJ&|BwB z&VQ>W^n;twZ)!sST@(6@^(T+_;3o8+G@-8+PR{3;CiJVD(C=+RpR&Q^{I_XBKcxx% zh9>j}o6t*rlgGPT6Z%O_=s#&f@0~k2|NWcLFK1ga1}xVV(_5xwmdJGfh}M4b%m z{iPS6rqMR$wTPF!rL({0=UQ-L*>fpNHacd)25R&;CvbRfkfq7ap#L6%OydlgY}{pa zuM^$|(Ju`v;>J!4*ptb`Pc@n7(quwZb7C!LPnOH3mBagR)S62rDxp$j;COg+l`yI6DwOu z=?*^(gZw35TU~Oi0NlMOkPKS~(2523mc;;)TOW%#WD5z}?a{k5?qWq>%!R91EU6h6 z!)NR&TfFvinm6_QM32yqy{XHbxp)4W+E4R7Ze_KrwRRw-4V?}328E{FQa@dVw!9)Z zC@F-t*4bWZyeF6GKO=>1ty5HUYV4A8e^BnW)+wqvxwXz+bDn-KPqx-6YC|8l*122G z(=X)7);dLP=woZ0rp;gxb6IxXP9)C(h%BIDu%kA9#Z!A^BHNN@sXVNdVzuSY%?ax$ zt~R1@U|@aaNXZ>h0f~bXB$Db_p|!nt3-reBxn%!R$+ikBsyW4ht=5)LtBa4--1ay@?XLR1 zjPT`QIS;6bD3(lr2FZB8lJR#iYArSP$VK&#qFPODgQ(^d2CODiYpraxtq4A#pgaJF zzJ!j}u%z|qJ#!qEi31NMR!2lNr?8Bt&Z$n2Sn`hc4hRB2x|IgS-umoZC8pStY{x1S z7LsOJaxBN%V?JXR`fbU%YD><87wKsNliA%>1^S5eJ{bcPO9zLZ4l*cF}w#q`R^pou{tvB{ZY7ihf~1T=JyPKbss?MU>LpK z$o>oX=RNDRjS{^J+H?%uIUPg454W?Sa~3V7|2RH$(7H*w80AhOoV98~@a=_N)>Ut% zBXMh4PVew3Y6qPo=Yi#FhYHXa`4#i2^&qV)spUS^+Dz`zT7%9pCS+ju(a-jq18)|j zVf;GOqcBQttq4KZ*Grdb>ZN0 zZvF9DxnniW${ssz%t2SXV{mN{(NI-a^$LD(v@RyM?#p@p^Ra}FQmB>RbNrbbCzcg) zBsrdj<3JZ4ec#O7u|VTdwXjHqQKy`edo< zeok3-dX~0<3293SzFS0fYpHB9L~DVMsgzS1lCr3Cpd%T-30N%|$FDHGHWNOzS$tTa z)v9c~N8)7rgr(yN8Y2TA?cW&Psrm3%Y7~wZtbRxX5MTFA)_T!afI}u*tG73@ogseF z+Qhbo8xWlQQG_SvEf}^$>p&mS&O>Zp7yGgk@sQI+t{u|Yc|DxD+~v|-gg&SSdNu*V3hk~R{!YSIF(!Kf1#dk#e^TL(vhaTWY=z&;g+E&1 zZ&9&XM+X}e=azo$aHxfd4oHPoccQO=$64^`{|JUcL|j$VI#7s+tLi&->MAz{c5UV; zxyrFZgi7%$*Y*2#Rv{?eL@k@5SJIawWqYMdhZCx{wWk-8#z}`&oncNP0uv%n3|^#t(}@@4DFMe zM+8fjH8ZD2AySM8Y{N#n1$93}`7c}q$2r6o-vxEI1eBFS$5SF#onlIc3TBC0C!Oal z4BblIjtQCpxZ&sRFwXCD*{E~q6cz0QNG(^8>ib9#0w|wW51%thbVr3&z&qFEcov#; z8f<{vlU`5pTw7Q2+Php^mxMoWO!&V4I=uP{GS)j^;kiR$0u)2CK6%5h=xv9){`_I3 zAeVf5>mmFDVeBkdZ9}5%tIg9lN8QM%8|&-RuJZI#3Z!lubWsjDm67|YFE0n6!Smfq5ZIFBkFOOM1Yy>5vMQZ1mpo6VK( zAi4%q5Q*A0aZ}IUKLrq<8?2ohCm5H#UEzHJylcm(9vU}vL^xh0V^%+hnz>xl0zaBT zJM-j3=2ZC)sme-&udv`)vCrv>>FaTzLE$j3H$RE9Xy=$ORC;PRATlyvOt{I5MOrS} zI$e0~`L2rZ@Odj`x`*mVUE1D4KeKBWiXQ!tcM<#x;fu=lLicgq(bmK?C$RHr6o;1- zn%}=07uTj$yd4O4G2v#ebwMY&hn|=2nQKLN&{(zx-KEC+C?v@Y_7wuw(BoVk5!IZ+ zHp&*aN>-TC2*;C2Hass;TEmx37W>h*_2vW)+jDKA+aLY3;$KlaQMti+<594;dhPgC zy^G*?srW@(!eD@cMT2HWoe}nJWON+POlh z8-h|ra68uzALbz1z@GAIhZvjO-RwEQ4c5qGCUE2oqe$%@bCgkMQ`>sldpgmhAvK&~ z0q5+32A*7Aw0NgrzD#-H#!9(M6t2lt`{Pt!+jR&wURVMQR}qq=QYZZf}U6Yv7l5b$;!~M13RU5C$Brg(9li?}1RemyexmaQfOL z%X);pmay@mlqxDs-X`KnTQt|tmA&@WlJ-z7GP>QBmaZjehnvCtV@XeSxt0m$bURIc z%u`gDyn?sNG_QQ8$y_y^=GPN$=wAAi5!IxjM`Thx8+t}2UF99xnHn>4s7woF(skaU z*W~&EnckJ@aG6S*Vmd;mwPiX|ro}RSP^KegI!dO?WjY$utPj(?_w;mkcdMu8Z`O~( zyJ$XYC_k-^9D|SS7MCh^a*In<*qNtW{dVTs=RkJkLxjq1blCBLXh)inXlFhn$Ksll z8K>*%bHd$pJ*}eYoRy~^j~V!6wNQ^_C4-i*1MeIw@3c@lgE4%ZnCqN{8AuMa;}e=0 zpe1^tm0UkmTVaz8dL=P(Kkg!`Ihr0myC)de9o_ApiPxGF*T!oq%Qq+;(P1Q#$6;nn z@lIUbCQC+? zSdSFdzCbMD5sa)`EvAyGNNX#**-5xC$Jgnux=DP8?kC&hxvvVmPs^%F@63v8Nz>V& z;*F<*ZWv=az9@l=qi6?i4rmNc3>N^4G8)weDwj7-U ze(jYDkDb2I%F_wd?;#6dtvU|f+XSG})vs}OrTZp2lPQt>SrD>ILdmVT zur6ky=wxYpl=wT#&WqjJuzaL`^n!{TNVw(dmT*n-HeemJrN&@38;|o=IC=a9<#7(? zn+5Y0@Q53One)PPwBTep`-Sn2vvQ8NjC0J&@LUSL$_T5Orz3VUPTWdm?iT1HqMDP< zXbO1e9q3iXuy^C;v19N z{pOL?j43wOXz^6aZc!exjyDVW2iJz+hDawNuM^cPwi1xS`AEvYjct)$*C0 zZK^Hn_0>>XZ7^R?YF!hrq8aoBLu)dKis|$zNuSU=e+}E8{fhX+dP&s#xX!$W$5R`p z(K1Fm(_vNn=ix-FgUXm{Yoml75lT0DUWo8+z!ieT`F1MvoegfZ~~gsUdRa8Ky7QEY~z`4%_8Ry0BQSq=KJDfI z5T}N@wLK{;ZH16JFn3S|xM&-0wASV1%AaLoeJ}j!PGu*;)Rw52bzy?Anh5(qz}zkK zzH;or#A5o2fX&0Xwf&v*44Ds<^XizwUOuMPTD#g%YurJvhHF5DaEJ(pim;~quEl2w z+jnXt(9kb&`$-1dqnt<>RL)8}wrwsG=}deZH^#i;=XRZOm?ek9;mXR$+W(PdK`gtL zbhISnkak;Rfl6igCAG?r)G@g+OLzDwretp9u$T%hfN(Pa#}~6b)#_v5+dXXlPyb zXk-D2pJ+2B)uY$#y@k(j!6#`4)p9bx3AdzRrFULbSPS7?epa30yWhCQDp*SvZy59w zw$aGiH!nI;33MBsYVq>E-K>@t(+wlymb{NR3a(L?F$5Ba5JM(wrwaD%)s;r)(9_o# z&Z3+WafP|+9@cYSX=RTRNmYWj(Av5a2^`)mB+|DJrHdM}_ieCn0kfW@yU$TvGtBZ_ zEV2V>OF}i3%{jP$JpbYXGGuyHd$)`cUemA3_jd16IDJQX5ks6n9_NN|^j(~)q%0zA z21Lhc4SRD8(~mp2ulqPHl&QUkxTyf#gwFv0uXH%>T|POM9n z(Waj@o$8G%1|hjFBwgL_oxh&PJ3QX)mUf{TmxdmmT9LJ6eKgu0ST1*QMJE$lbLF7+ z31aIk^&bvzj<2;u+={8zuT-5jsX798u7&l*GZMKpj1MK59vq2f6C9lOkW?L|VTCud z>+Cf*uk;+y9v=gl_gQyFWb7G`AbJrLoMe@*&T8#UN!Hr`S#fUVyq!sQ6`WlfI;u{x zR+f!Y$#`npNyfntzaCQQh zL6sJ-_3#x8i%})ydau0`l9O!uLB}1a!E;~Pc?wsMHd`nda&D2HguaMk@r}*<@--VeeR%r|W~xpfgB^5w_6chNrG|aBU{{ zyl9WA=n0F5tQt^JN3s9FhOn94t<=PJt)1?Q0N+#EtwN%LzaWA!6sBx84ZqSdHiCmeRnzw73lDFS1e(PoYWX#)dmAgJMzX!+JACX<3*!`Jt_UC1PD|4@Gfqf>Q*#B0t z=iGN5=YE*%`o#V}BD+4Z{Vdt_iS1X)u1{?LlI;4#_PfW~ACq05*!|^k_LePi--=J{ ze)u^1CFAV3$^KO4zp~X>`&Q%Z`^c_O%>T@B_OFk#|3db+GylE)W9>W3u20PGn6dT| zEgfeCytOoRmOSWV0ZK!c%AOX8($JN%zw}OA;7UU`$^NCx|AQFa%v2SmG@^CqECMFR zRwI6$1SnhK9#XNk2+NlFLn&v#U!>{316Otw;H5k7Q0&s%-O95sF=s@R-#qR zW4j9Tkcx3^w-WM9#@|ZBTbW&%KeWm~>R*{VG%vGT4(^iKl{rI4Wp>MvOH%uY))6v* z+A9Y3P%2=>z#h6S2~aVxhi*^pBbwwp1}D%Ms?#xy9VrrtS=A8z2}@J9PRM|y+p^eZ z-Rv`*h$p-#*JCf7`tPW%$?<1kV^YU~D;+Fcsff716&JW{q}U51 zk8TU%yi{W^G5--w1Z;(-HYE8u89a0s39fyGA~p0zVv1^#rgdoF!KO~1N}cXbOi8HO z3zAR=C#J;d&V(@ZN@7Z!mTaAbswbwz>DGiWG{Nby)Tyvd96k;;qV=g+42e!3_pv$W zNFCSO$-;mknyVVBKMkX6`zu;14BAFCTZ`u(fsG%2NdFgaM`^~yIAR)W2+?UwZQUC( z+C)Ew@vbAexlmVM5Y_QPU+U&EEyjx__;I{;)RctdD|5&3;;0S1q)m^+iv!1bUTkG~ zKY~~792en!Q;_W74^*>Gh+VGcjh$8l`46@1>> zJOxX8C0d_dS8S(Z!KV2ux*2ZwCig6caSGR0_|q`4ruQXzDu#90sEbQCk8IK2nTwB~bLAAal!7G)_&?{9!-~)p3Y&xT``?+XmhvUtAmr z_k=PynAmp4HivmegNRMJGv*Hgwk@{wbW#cJC^J;W#Xwv?2+Ea#>fmnarJ3T2Zf|Ghqw8wGVUaguZvWch|xxwr0ptjjnJPBF10u{OR6_735bbI(A14QQ_PPfx8$h0uIboYv=L_Lvj=sozl|fC5QE@v8`xn zp3}bsyVJ3!t4c?Zm}!;he1Z?SDG!lEpOOSRKq!k+=&C@t0TFaoD;?DdvARb|2iHrd zPGhh3RCqK(d@?!xcuv&iZML&Jo8mLuer}IsPE@w@)Ay)u&?nfL-|JPUf?@rb+|e~~ z3@NJA1}eyfsvw+Tt40^_DOu$wi_>;Ob^BiNyC~-OIq|csA@s!xeIWtEJ`$OQD|wd? zj^(wE0`Cn3`%`Xe7s=Zmn5xBzG)~(sI*=d*zi}o_Ua~cNU=nadRC6*GZD^_gWX|6~ zsXtN8$^5lXE0n{FiMVeXx}D9Crmf_igPD!Yj@l)0+HN3iD9yRik{GujpH>ntfkor2 zT!aTJ!cRjT5!IZ+xj+CWmny)eO6-OZ8fWK1y(~Y+*fqC-L5ihfCS5)R`Y@jqe@c?Raf+R;_IM{T~p< zpNTQPDFb&{W^0(OSq@nwqRzaYluxj{OjsVG-t165S@{a=eFKhKuokx;NhTPpE!Cx) z(E_uKS0#PnCmB@4O21g|VEvp^3TJ6@7w$s{AKQENTX0pi94^7;){>;lpA~?rxe%%5 z#CyQkcB9oT@~6VMUhXQ<@z~4o8pZ>eBS|&Tsdahk8GU ze;h7uJEBu*X+_kxdm zB*sZ(yIezCFktJWnN}c`6g&J9H4Nf#Q@C(gpt3;S)y!G81U{3S20c!&;9%QIpwH*% zO^q@~PP#EoS$DPU&$naDu6N{VDTBe;v{J4rSFmqLd+HXyeXDf^SNF8FWeYjtdxGul za)_GtsT$EbkwU6YwR`^aoZB7GOy_nd(sY;T^Mny@th3xKBfkDBgN}~VBrrdn!vu%*D*T0 zzF|&^BQR;BZ(^K?*Q3Jg&5ixLQdlyc(YFYa;gxZWzHJT@@%j#Q@cOQzGQ30(UPejq z`gJqBbf$#eq(rDn8WLPu<(Z!O<>>Xc8m_MJIqOO1SV~C zC&r0*Jtn+9{^BuzPw~olM&Bn$hF8Wh`hhu2#OsI9!RszXWq64oyo{3I_1hd?59JY& z@6n5Lh&+>b6_3%2bFM4H>vx71Hzv~Z^&?pL!-^)bZ*(_Chu4qINpS=wZS)h26Y=7r zUB|5N-M0V7Q@k>s(LDso@X9zw_nN~*yzYYzUiT|1!%GC=Wt0T3CvteTFU+-H@;%Be zkF*5!=3T{Ol=~g2>&ozY((w9B4zHiW!XH*NfqkO~Fgm<`W=@JDFlnO)F;2v5x$r8U z_}gPsyfU8A&k2&@m2r%IVGa}V`XzMmdPq?jULpuDqa=9!K8M$s@+IG+m*o&ykjG0r zMn9W#T^U|a8D5v?@LC27e^}83_KhCK=UcII1#U>h1aj!7JVeeE8`hG zN{|e%jAQg`bC`(NZ=i$MV~Wb~53U+{{Qz(9*oCc#Lu%BXwOF zUVk*axS5gG$KS%jA67JheWTxDba*{(PKqNiX`?4FPQ>dO;dMpfo9m@`Wjv!N36kNJ zag3Im!$iD(4;{RoQdEYQ2*S%K30{B7;dNOa5&0gyI)})Y@~+}BdQHxCWq3VncySvf z#p`KU_``}Ouy6DSj1I3qnv>!POxoxfj1%#CPI&D%`|%&8cx61JKM^FuE8`eFYYr3f zdJZ~x{aH~NULpuDqa=9!IfvIz@`%XyD7RJ867+E1RXj$ylajiw46nZ!UfkkH@%jra z{9#2C*f;tsMu*qm%t>(sCT;XQ#))|SRd}sCf8-A-UK!8m1%hOFWgMdy&0!*5FF^;d zmlc)aC4%rWN`lwla(F$TM?}6yx!sW>vhlXL-atG?xwnzJt_-i|4X>MWc>Ns~{;;A6 z>>Is;(c$%~IVq07q>Wy~I1#TGgxBFmJ@dm9uZ(B(IzckLGLF$3<}eYje?SMXHx-rP zC4%rWN`lvmIlRV{FZmw*d=8O)@_32ID0epgYrI}EyuOgb>z}ajhZRj=-{>uj4zGWi zli~>p1j+EqI7a_AhlzNtfDT^oDk{TE1mR_r1h2p6 z@H#S&hq|Mjyt438G=Y7iDG(f9zBwt5z@&`|5GLaF zs_^>eZ;#5_uZ(9@BuIu=#xZI!hlzLvinLfSDJsKD1mR_r1h3a}c#SDv@;&8Do;Z-#!#SxgaQ7guYc)cOK_WH`1Gt=^w z@r>FClHrwcjM~j%B3@IWgV!pG%J33Fco`+Z>mND1p2{O4-=mz+O%YjpQLgLN&n zSH>|~%^W7;)eRlIdK8u6C4%rWN`lv0IlQ*WBO>3UoUTpr+9&TS9;2KCOBK@LI>56h~mvM(bjnh}R0?wV-n6uT#7-p3!;)$?(cJMzhUfB3^T#gV*|s z%J33Fco`+Z>)mE}$@l1Ya)?}%$4fj$Iis1PxiY-GqSn8@m%}TBg+Hul0{ccAV03u( znUmrOOxkEJ#)){buGlf_rNTFFN%6{fMjH|&!z<$$%`=CIcx?n7yf#);hL;G!%P0w6 zK5-`Ng=5N>e2;Q+GezX9dA!79lyiQm>&oyd7+!bg@Iv7Vcqy8|zR@Na9bTK7li~@J3hrL;~8yEkPNSkW3+`iOvGzT=-{=LqB6Wh5MD+}@M_87b$1>S z`5xtjUW&*Qc~|im<(ypVx-z^1!;6yzY5T?fGVoF~fqf(PfnvN^*TzY41on*=X2|%cx61JtqGFhm2r%=F^7qGErbqU+bSxe2;R%B1L5O;@o&bJVx33 zPhD4rSDWF*u5^mmdtl)YE1JN*(JmMrUb~u;;s{LIXg7=#@oE=dr@qzlyA-dCXS6#( zGQ2X5(H`b75wAU=gV$b)%J33Fco`+ZYibU!fjlDeJ<2Y5ipVZ`SMeBSFFbW!8D6Ux zUhGV#c6_w#7g77j*f>%cluOst_$oD8a+$ka#GrZUhPVqVb z7XGlJ3G5pkh|%G7kU1%iz@&{1#yAnLPT{q2*J&LoUK!8m{RGMI$~Z=cn8QT84uuY0 zhbbz{-&>>l$rP`QXY@gWWO!v9qod4WB3?&B2d`rkmEk3V z@G?q*S5FSF<#|Npdz4+_6p?@DUBzRRz01^fWq3_Dyx4_I@%j)f{9#2C*f%;Bqr>Ys zb5b0IubOnnrOQT8rV*OlSbYk08>nc{UKEc{_b6WBL838TYn$ea{MVA4i4 zj1%!%LwK#_Z#F%}E8`iROppw(jAOLa946xRQRv|HF-2u~i6Fd;lHj#w4zD%0%k_Zr zJ<5(~ipb%4SMeBS?=p2=8D47{UhG1qczqle{;;A6>>Hhe(cyKfIVq07q>Y9#PQ+`b z@OtXCvolySp3!Lp$s96{QQaIS;?;l-UZ*Q6!%GC=Wt0T3SvkDU%OfJ+qwI*Lh+Lm{ z6^~K&E>qW);kCBm#V%xu*9a{9VMP2Av<$eb9BA;Uiz8?126U1l;+OqP^X?o~8c@ zmwqYl3eSOoi!87xqjM#IE>9-mbR=`O()hr}=boR|p)6c<9wF=|p$n6pZ8%@Ni}g>5 zqvgE_%6p?Ec|RwYwr}TiSH4Ht0Zr5PaNbosMwjPYSC;qdTiV%)O!Iye7XGlJ3G5qP zfYIgsh32F<0+Tkn2;;=O4~5IIbGQFmic7{bx|kqY-e(-6OUxn3`wXv7LkF)*6_w#7 zg77j*g4YH)yvDS}@;%B9Xo}a%dA!79l)cQ!t}`da z!EHdk(e->L;Jdz2l}6p?-NuHrGuUS{gLGQ3c&2VU$%rg(iG7XGlJ3G5r)jM3rs1#?myfk_+P zf^i~VJn&3?yz~plq~$B)8GVr;8D1I3=u74>5w9;p2d`TdmEk3V@G?q*7tcbcYg4D^ z5s~jvc0f}^F3P)#$0&Q5sq4z{+RX4`Co;wBE3oi~6-{8@=&KkVUSBgO#Sxga(QOzf z;N;;uf2_YuXaP^^8HGrZBaaPP}#SEaQ33gNAs5p;)UhZSLX z3~USb#w^+l5-wM#A$0C@70;jId0PleyXHFhg2XC>i;zINeCNT!Zk0O?RHr~5qoi{g z+o`>#`8RqWUK5>E`*wT5sX@;1+lW0VwF!>T0Vy9;&IQro3R>>T`8Q@|Q@>nu%o^8m zk~8`ae00V5yZjDpkn%eeeon8DDddScawi83BUQ(s62CV4IoK?f)HmzXH?3vGYBEUm zh2gDp3uUmy(;expNTWY2QuKYCrAT!rL`lou zrm^D>a8!BJTbu_e68`#?3Jyf$G{+xSj0K9VNb}#M$^A-1BdVUQctmY{{f=iOQ?_kIV4tjmM$bTcT#z zFWeI`hMs_fxnysN8h!Q-lhZ%agnn-m`ivbX=W}cm`khVa?K@4*XWu6D%bU=jZ9?B- z=gIk>(}ezqCiJ=QnVe6(3H^~K^clNM&gaY~^k0hEhMUlzYC_*}kIDI5*@XUP6Z-ypPR{4nCiE$LP4555CiJ_T(0lftoX;su=#Mm^ zFJ3Y^pNpE%9~n>Ay9j&Ht_-T}nz>f!i#njV>&58Y^6g@A&{yM%CHkRq3Sc*k z6~IP6qBSec+%POH`%x9U@)0XRDGjLGi9Pz! zxp?P!dzdXKh>ogAwWsd>REM|s;mQ4}il_U8TO)6GwO=!RKj0C8^9XMGFr&LkYtX~A z-SOP?>G-a2i?<7&x3O@()UVl%ud+SU(#}N|v{{A+@&+}^)cIEjY??d7ijD(`dJe2Q z&1rTYXVZJqzV)*llcbS$1Vk`_v;F^ zOBnFgc2JfTp>X^Kh4XC2=CuvvtB z8lNpEIi@bK;LOowqzC#F(4(Kjv9*5@-Wf#w0t-(XMZdIY22@ZS8s(^+5@d?AU?P0V z(L;EOE`?R45G}(@_=owK_uX_5#=*Gc%5R3LW$y|`0LjG`%_%WQK z-|`u>Tl5BdLRMu?{Pb8famBuUxvF4g=|*I!E__?1Mx9ecfG2x8gRag}E(1Hu{hKpM zL6fp_u(J|y5&L&C>3;V64GZNNRLjQK^ArJ(dIYCgsH0>BxT6&fRcZ`<9#lJvOkuc1 z8wJ&22&2adHpg9pE)Bd#uEAhdUXqxmi$@wpQ5ic^B$bf4!90~bB1Qe&QIB&eW-zF> z1=*}UveME~F?H$|q<^mbho?(G)Ka8D(c^wLH0Q?#;l=Pg2r#OOpA?11+5+{$q)P4J zkMug5TBm8{72R3ERgxB?PEhUFj{Kv#$omlg@~J=3>-;a_|CjtrQ2mMiPyTl$TeicJ z`0quR)cMf2qpZf|@d={uS-2D;3L*2AatBChDYODW%d8uXE?`_Ib(uVd*wsmgu#(-~ zzI+xxNy+`@Bqg_pDL!3R+#k&J_W!68b)r7b)cSMJaW2s8$o_=Tv4S#PR)vX`}L;kHAD#gkwWE$371m)=6ORs9}I zt6y@ZP>CwFEmtHsJ%!V}Ctae@9>uZJxV7o()AKfIAGguAE=}kauyQd6$B+8fE7#Qq z`n9LwR96jg%MrMLAz7FRSEX#)!!-4$<-s4;PfZh``X4aiSN+ei#J8iRLquMo*Z~g% zy1D31A$7O1oT^haF$E+@Uo5IdSU&p1a*iQWzABtrc; zw%oCh@lSYC8%(pP>}+lIMCZ-GxLfHi)}FgaX)$<`;0|WAm>LfVD7i()X38ppsvfS zEvDf;)rCe8AN>0M58=K~eoF_K8z1guc`A9L&uL^)aB9?sC0Fz!Qp8}U_UI*uya+ZZ zh=%q>WsX*s#Gnw}00(56LSw4+h0XD?GyDsBd`xAUL7N`8Yb)C{**H*zZCGeej=2HS z?|P`Q;=%mdqJ5bdg;8Svdu-p*xfh~W9DzBu{PO@}^r|SS`)kfUwZA^W{~MxQ=+Y4} zF6QE`v5NkILrlI|fbW#XF|`=I>G&M#XqIWQUzGFey+SAdKb^N!{^_*p6}@AW)c?Pohg^DBh;m#U`Hh+UK=JO_uwKQ$OyZj2tX__nFH+*JLMiOixC<^o zCR@=6sXGs!D8M>?clhg7k~IK7^7zuyCe6Z7ozM*LB@Nm?Eg(( z)%E$|_wf}4B%s=_b|P>iodHvX(6(G-u2|8^v&+?R1vYv?RkbQ-JUj7+#V_AJ_jt3n z_T-&)x$xV>;PeJKx&G|rG8vzf8Qe1qVf03&`bqt9Wl6H?);4X3dE1QJ^>tC5n?2;_ zjIoEOm87%jl^ivxR~DEtqv;s|*XJel9sckOih!XgafxKg2Z&4Na2Qr~d2rs;hO~Q! z;&&Ir(OCW(KLa~MbE}#sVx4gTV*}}U_QQLyO3A#F{rA{LS@)fCV=z4?J(ZDc-Imp} zpFpBKxi+O_+9!7$h6K0coM zKv{hudO|+XcVj-jiNzI%@P3SQtcUT#pJHCVka$p&fNlfj;ea*_9Lo+`T9Ly2;Srs| z$0nSKqfwUQ+gpAEpVEMqYXdjeiA6e^(D7P1LvO?u$a>`Z(_*$4{uAMk%6v*CTH-Ts zK4+&syTe-MQ<~9YC>Z-%O1m7MU1RaQk1+AvhnEz+b8qw(qVr*j<~|QT>q&b0S1a_U zY{(hATygHQV&A8=`g8ENJNeno4$2*{By-Z5+-6h1a#oYu{YqU`6wOIxYI z--(Rj1AP4GcD{@&(T`0C9)M>5Z#$YB#+90CCAsiXe7S0*htX`p#p`H6R3QPb29>4< zQ8lv}=u{q8Mn6Vym)(@nIC$B4u{y%q^Mg)~lIh&w8ELSj7P#ihmh`R4PUFdt=ykkS z`!$1fmDY%_i5Qr&7{6Q!e~z`=-m7!ySM#XJ`hBjoY%ylEjmT;LU3gbem{c(8YdHy}) z`Lgj;@kn^eTsLx3Zj7hG_`~`pJbUN&cvr!HZ!q@5y9s8Rbe+)_$=s97g`pp;?VZ>i zK8z1=l1FpxS!CJFdu$?g+qziK7+;HML8~@t<|QV~G?FFf163nHRGs(diR#DvgkktA zMM(N>jD4`TZX;Qj3p`D2mq_kHx;9yKYm+TWuo$;hyc&Mrt8!#gy9Z{A$lFTcA6k6f{;@(?#&0iWZi}%+jZ^y3~Er?GO!U}$D(J^I+$Hm36DTXS5s)Kiw*@E>rYWM zm~koZvU5qV82a>`W?1Nct@d`UC{U-Ft-*L7rOUh|6KL?$5|w1V`4GtHtKd z`$?{Xf7-ur3%8Jlq2-zrY6koQVeFAdl@a}Qc6t@HpPF~i!oI(yNg*e}(hq+__;}6M z`9GkEf5X!cA4~j`hhnO83~%dK^LFC(4z%!s+0~_C8Lb1irps1Pt9nK0PjG502XrYr zP*U2LYYs<8!rHc_DOrDj>J1Edtx8i8$3g%5IClJRYpJGnQxNrWsU zfuIBwY{McVXc7d%A}T5(D&hu$1_Xh|dxHy2M?{ukbAS=tPzj>rxS=A5EF!o8gNg_P zIsq3HL1%Py6qiwazu&3eZV1lz-uKT7-0rGVr%s(Zb?Ve!O}TNp^(v+TnKN_d8I*ZM zCfjj$cH#mM^X|M~fHTWLQPX&^Hy;Bf>j`O0eC-#@o22gFNsI63MAgky8RRJ zr0XKWQ-ev6uJfZ1L*Y^WRA$tjn8^QX@@*aj>Vzw?=!r&=7Zl=~3BLfOMwEut7>XR4 zbXNH3Rt~^asxN>Fm6m!|-0=hr-^JCg0bRq&1xEQNAehL53*9UNWS%p#Y&5{pV4f4U zBOie^?b9GYUMD4eHmvtI0ko_ekkhRKIO8Y7_E?2*RnVHIOG_O9lVZ^fq~}{jKz45% zyGsTY(FO(;5vwWCaC0MP-*EY4Gy2jL$LO^c!`lYn=6JXNNX-}FLP{KQb?1u=>v#mo z$R;mR#%>NSd6ZdPj%_gMiK`kZC_u%Ke=J`V%~9hUxl@ze;tovoQZP}Hf{~Dp9W0aX zQ{x(4Td9?PsOF$_?Pu+j6H_=Zit#}VJvsHKn_nS;HmZ2gD9~q}0IuA!!FP?7zOhpa zSSwuK<~m_J3bc=z^fv}Pp8aj;js)v3t!N^mVqkNYQc<`;E`yFhr`Hf zh?iM52x#F#minBn3av$jteDAGk{&@>@@9Ye!c4aG)Z-T-?QGp9RowK~ifQ2kzFvVY zl_8@l(4*$K!Qj`BLBN(GgRHx4WIyeO=T)DPeGu%zkw0DPk=*H6KZh9Kih&Z*o&+|8 z7TT=oHNR43obQg`1ddx2C9t79HknWf0%BgrrrMu@FcdPzXJB;mUtrF#aCC%n#d(le z`5g$3SU5Tni@!&iZ-YyP&{!T7(i$9OMy)n@6;_@EjA(&%GCURzOQ=s*NslBo48GW< za`(@;#Z2gvN+@2bIgmn={XlM=ZmdlP@oUMqD-l-Y?KpTH+La_#*D?_>feRP>vJSfd zdg=fvHN*S{WO1D#%w-Ip45V_M2}6l%JuTc=*H%r*ie1O}0pH{KC(tLte&(hgX~LBF z6$AI1wQaSEDrMuT|D0#wA8=C(2I?jU`Klv=nx+~0#qt#`!x$iChp!VTJIUz>*KPSx z+U>!F$pC49%wS03VgCe7y}(I8!S0k;7v6O6CD8OMxdVo+e_Ycn<4H*DV^3_<{)1ps1?kJ%u@Sv z%o$qS&g%0@)R9|3<2s~mOqdKoKyDoYz-RxE&IITWZsAmH;QRFCU$Tg$YlfTuA!Cvw z-DZH1IE^?WA|(J<7Q|6zLxC+{7H*#@s%=BE*MkpyURZr%eLVn8nq;rx=d^w8u-i{_VXpocvm`Eb3uo|!R@_(+KHn~&59?8eH@gP%wO z7fL{q7((fEK~hF!ev7u1Y*mnOi&HDvRYa;SZmx{LWp*Z_Q82o|LPL)`5G8NL*yBhR zt609GH_#0VD>FY!jkhs}cNq|HfoXDgLdh{h2HJ&JI0oY28*1!77G2?_(uaj=_^d8? zxCJ8#NdF_NOeRS3RY1NXRzC@axmWr~1uBICMLMeDMI>Gw#~(6wYOKv!thSG0&Xwhy zefypgyF1YJ9b1;}X+aL~?<8_<)5**NzI*2#58g(&UJ0EdJ zh#aXr6N&^hITbHnXr`Mgc){z^}9wbZ2)WYL)}Ul^)jp zV$_4H039j%=T<%{0=^!K9s!JqfmdQ4)IBCW7!QJ;Ea(}RJDXJ_Oue{Fk)g#e$T>{R_KLR3`}^7 zbo@rVOn4(zy+DGJ7TUaZwyZ3*&W8A6>~*szvxmNjA>W7}&HQ;?f3_QuL=KW+qg;%) zYqui7J+TQLT?;1)UDcH{olfc3IT>`uKS#&K$)eM2iKZUbK8+s3Izl@dfg1%zeT2?u z(>D;a-*h;~37#WBu!3+xxE{pxtX|;U>MiVZEX>rrv2q9Ss*)G5jFn@d@JH?f5hqot~eCR108Gwf-ft* z@QSn99pnrg`$6F!cL31uy~ANF)v%xLGWH)Z_BD?Oee8LX>JD#9<)!^bXo1;E{IbK! z9gncL-eV9hY4s?33%g0 z)xe9n<+}v$&{-^g>*^N79jD^9MQFun_zkNsxPi60hUtlvT4Z+}08f5qnQD(+$#rc6 zV0w$}N}6m8Lphv6Z-A7fMn|l3gi`yrqB3oO`KNOMXoL58e0y^~QH|!!56^#A4-SyhHV7< zfpL{Kth6MKnOwE`Os$rKLVG}@?+bT3xC_a>s(ajHUIKRlG!&EUZjn#S4fmiegC3)4 zW#ggJj7WZ~1z)}cdPS^E`n(ZYaL$aj$hhKcPuW?1Y^C_4J&v|0>DmTw*_wtg6{=kc z2KMbqWRx`W1qQDujg&Si<#xVE!KsfnQTg4f>bg5A%xaHKAS@UvGR%vZoqSb&^QD%H ztrZ((79dNB^MP$$fCp@?VB2D~#1@-Fp*I-x#?B#X|LG z61or%td(nbn4(35QnklGmBS{?HBxKTmVi{Vlx|UXbg=1WQ2>W-O!iAZzP}-#N;ljZ zB#lr%Lp5~*YpU9%L557`=r--IVWpD<39vtm@rV4W7E7V%A}s47@Mu^A@O10Z2yC(w z6CQ+n)eN-Mdf^1IgTBv8Mp(VY2i0M;l7!1#PW;oyPsvVfI|K8a ztTee3F!i^`;nTZn-e3BIrgp_0-aJ8`*tT1QcPVtyjc!s+&8A4SG^8Qu6b%GFnPq26 zx@^3n(u6g$U~$y3sfYj+So&_N-bKB*(e`hk%f+bXX(aF4fF7WEEBHWL#B5=wBX@qF zBF4J1ixGu!jS1YHP(i(dmG-ukc6vuw?E3Uh2J&spmu}{=%udH6RGO?wNu{aEGE@5l z;!Q-nLhLD4`V1X*_LD7{{&V-&bd+-*~VRfH~)0A z3(}P-NHsyxHUM(kQGl}aAO8~l8yEc&hKOpr0PfQidl^GTqaE?;nXX%%DL?B>d7dH9 zZg`q!;i1YD(Bz?@b)^0Xk@Pgp}1-dPj|0_0tmv#ke$2Nfl$dSjF4O@z+4F$@ zL`)rwixe8}b_ZG4RFhbq4A^Er02-5!hLKvyj>j>Q>KY_9^#3X;6a{mn$O_x3-Kj~6 z?O~v$mcG!)x+f7Y1@BAMDy+w?s#mGnSVVNds}vmuja1?aHcU#7D=rczWn0mQPQxJv zHdL^ruxiB+-9qOn65GrE4H`c|$X5vY3L)Q-GBNuCuTJWP8ateysbRD$@3C<+VXrvo@?d#o;12;3stto zJNq`eriA(uLo%{1HJM(4am-`(Ljj=+#<_xA?Oh;Eh8*2$%K180Osf(JWtQEG(5S3Z zWA}grwB8u+K7;jH_@Kn zq}Is2ybsa~3(elhrOK;Xo`yWUaD01&6$>#u3c|~_Q8BYc?RhduE$_bx?cF6 zoRJtzE^)pSLy$utW0->g(ABE0(~6cMRi@Qs?C-P$pmY&vbJqX&v1Fej3HWnjBXpbb z{r($0GT2A@2qUgPPezYS^&Klr7LJAQRP!>Zk`X@*@=z&Qg9Ol9078iXtZACr%q`{w z+J(|mKHa3#RAyVU9{KHI$H;5=YVx()5V`4F_hEh%245&jc^f z^_YBPS@MKCG673q>=ki3!=>AjKbvlg4Y97ASCU;fj2U&q#K|y}Khs#{3h4}>7!%H? z3d`unCSW`La_rr(+&D{d%_Bm})&9w3B zqZWIit@AR<*`DEO%WM!+E9f$}n~#O(YUoQ|x}KA6+HjSzqp#a63WQAzEGa*S3VQ6s zF3pKq+`6@w4J3~Cq^so-eA7MMyoJUy>Owh3H0Yjt2AZECFI zOxj^GgKr%|)G7RmsOq+7xy#*J3VK{RTIR}YylKt%wd=d3oZ1)Yy7s#GfBQ59RXjuz!gzr-6}+O)L^xKxMnct` zPIRk+6WJN&7$T`sGUITUwG1f4?}MaOe-7PHDb%GA+4Coj4u_}{5M?i7XnSR@!W>I- z`6|tPNv=+@W8H}mZ$4S}HkNAVCA4gn|5EL$X)o`!dy~ur@ZCJtfc{kEQEjpd z#$K_q-UtZ~nxmpVP*heAWcmtZI$g8_ORnavWESIHwXY__yqSJ@L4w8De&z2Cm_bqP z$?T?Oou@TceCKGFjZkB-?gj)aqE74q`#d*5^}$EQR6e@nFi@&!mdLF143sK2M|m3* ziaX|MkARhF%qO;TLY`ddoCA<6z!@NvWys)8wwcs)0R4Jv(&& z$b>@0ID`VgirqRdt(*-MKD1nTnQJI2Xb=E6#Rs6*LcrNE4})S8y8$w^jj=M6Flo}0 zSymo+vdTE=rv^NiLw>4)NH5K0!RxE#q^b>}>bPP>H(Cky&)pM?{2;1~?Y(|mIoV7v zXAM;3F9mtECsq1>N-BzGMDmng5g=c7Y~*MNZP2mNB5qHBO&w-Oy8*LQwRY)It2=$D z12SJ!sJ->6H(!)0V~iP6c5dUvE~#=F)({FaqRzv)=1YORd7h|zGY~Nlh33s&1E^j5Dx3j~xu@2fAk@eZPlBfZ~ViP!8j|hsElx zLow)g*P#Z*yFtk&bC*~AQMy=5A-7=9XSo3KIyRPb4}XB%uylpZfXD=c%KJeQhIDo@ zH`NiIh;=1WEpIInA_~u(Uj>kPHy#n|YI$CRr`1Ij8IcU@bb5@5C^NJyn8RQiSnny2 z#K00^6$)lJ;!v=z9!wm7p^qz^sbUr4sa9L152M{MPG>16k509dK(3RV133S5llBX% zwQ#}^&V&aOsM82*M3{0TgpD$^?&t*D3r*&QvbzqEW>R(`x|lmsbX9CN4({5z`6p0~ zsdai-)nbMS64aa<;G?o055`YrB5n}89YSel1pQFAyc%Nvt`PfSnOGf3N~$$78I0sq zevZ>dfu&hT=|Z3Xhb(kT&cbPax)2Z3HQZh5N-r8L+cPBFTEk^~rUW(^uk82Yl}jMk zolWFwHu7qC>#|t@L}WyjDcAKtk!f|&zo3T8_>g;lImbMQ@e;Tyfm_OIFg7e_Mb(&Jwvjd-vk{o@6d)s&BYg&^%*A1y=oj zkAXhVY_j3bBS*E9fOHq*$QGo+?kZAsgOODEw$^OK`6J?}P2%bdjBdVyIOakSPX_bk ziEgf7;35g+7JgYnz^x5(MnD|^v4$bnZM-8IV}TT!eUmuS)m7(b6#p1YJ_|gId9o!R zU<(=M84r)AqY}U0D}y|YHwFWL-tXljiB<8)%B9ET=>Nhb<>m1RoB05z~#sWt}g1;3ZZdPG)R zyiGdQo;h|KR8jrEB=5@NA<92F&js2E=r8?={Mcu~TvueldyFF+!Sw7^$=SUI#=xCb z4jH8Id5+N3?$v(W-JD#XzLje{^dT&E8?y%nh6X9XM zYc)8JsYb!UWG2Q;oIXZJj~!m?Iy}l`4nj&%1{~_Jn_SvqT^|c9_bFR)#*ev zu&TJ#>-oBikz5Uvo^Pre9_ywsO%*BV&MuE97|W;3z0X)u@bT0t2nOJx!&>Gjpu6Rw zEH=tt`m0&mf``1dGV?89@ti<6ub(3hqzYJf4<-%;>*2w~phTDy-=XippIS|JsK)t?A>#o5g?f z;pPaEdz$15%;kLHxEYhDzHid)o`_X(0(j8vUUbTGf^K4(vaQ1~bU6uEh~&Arqp4j2 z9l94hbC1XiAclchv^*byQR^9a(H&)>MXe{`LG|_(ExU}<4oP>qgfz_^6a}i5$5CcZ zY6K_vK?nn81P9{tON^5G) z_rpsr_reL20EA!QhhOQ36D9$$L0Q_>AbuaplM5Tt60_nPK|y3jD==Gy4dnKDh$k&y zG0#(}WqY^9Ix3E<1Tsig`nFWf>>BZw?X>anyTOgj?3Wti7N`OsvEq(xv~JL|`$f+Z zqrg$7o*F5(M#B}0H0j<+IEq*|!jCgEa%zCv!J_Hb7=Y5PUifrgx-}MV|8gv>`ZwwL zk}h)riE#+Y#*iAXg6=yJGov8G`VBorYdk=0a40noH(A{TcV1fA?Fi3JGvo9{GIX9^ zA^nKDluCUB9WXhtu#_3&fdcBIoIuD+Ps4$hP1q@!M@3?PA8!>)u8Yh-Tpm^M36VHp zihG^}$xB7@2_#=JfvQOoxJ$I)XaC#{n3DYxibRH76q$5C*%WPIVG84ESTD&p*P~9M z0&#BGft(+JoMmP_W|Uj-V?b1m)XbNGmKjxB0nP@zgr{Ofc3G+A8$e8*Y%G64oRzR) z*=4ig_HJb3!L*lHePNdsm2(lAE`pY+)O1(Arh#1AhdyH$EL<;J0D(j5wllL~J8FTl-DXW^|*bfdtynNf+Mk|q+?0_BjA zo1rGmCLq*hg>#w`2o(1`INPXBE2FYNnJ$G9=jx>FMaYcCpNEd9)6r^0Puc@j_s`Lm zeD0lBjmfL}p6+Tu`yhP2@l$vLip-Ix@_PQn=pM+UfHS<$s zwO-B4DnMh9s;XwR?2kamjjF1do)JM2sH&e-HPcnqe9fzx7SH-fW#oz+>LQO06?AV8 zPkvr3@j9z2rubE?za_`Y%E@eIqTP-qZbl?$74E{z$>iteQ){sA4>p50aCs0m%ej$| z#xSrTFT0E#znqMm?BJYI-f{VPjj$j<#m>pj$r7H^6nwYDRYWx7CiW}9~ zvgKqRiM#=ki{kN~HBr920zYa_fnp>N8O+N851k$g^XXp$vjhrGeiFr+PnjS5Tb3r4gsqk=|SJ>8V%(qfDyu?&z!B7p( zi$ER4R9F4#nd)egsYbm(A-mQ?nQHDx?b#g02VCvK?@>4=vg*OjKa3fqKg#t1F{p*2 z1Zclg{QVN~e?X*@S<>+z>7wq%8xMwydKvFP7rT$~UUX3|@vG@#?((Hikw2L|hy2Ox zAEUGX<^vyG_gmAn4sqVw9@e|z zMx{t&n%vDAa%~3h zTMC#!pCI5fQ|`SWp9XihL@addBf5PV^Q3m+oD_tiZH**z8Q_KP=g8E~AVK^!Kod0} zRv}A{l8B2z${~i``3{jY&z*DT;$i4#;!W5P-dFmf+*j(X#>*U-if-DG$Yz=s9Dt8m zT`{)t=eT?tr-8;2(%9nCcuCP%6QZ$|G$uoY5u0G^ETN?44sd^)S)C2x7|t+A2bC0D zwM}f#!1jP^0pM6AR>*yasd5;o7HP@7CpJTkNYqTvV~31+gWiz_ZiPWwvbkjnDDz%} z4DD>tS<1R7@vNCyD3pJLbWHk@5$ij+IU#yGVz|}o3+eTEX9F!DV6Bx2kSA3Kajcqs*s>dsnvqBeu93uCb83p2Fw<}}bZ_rk#I z=q^Z86Fm~yM#={k7KHu>mu?1x|U8Ds40$s+doIN|_L zfDx1DU>Mz+20|9@7~md?VvJ)rce;#a_!i3$D>ER5jkr~4akI)eK25hqz?~h4UYN&g#F$z=Vjy_%Jnw0hqJq2M9DK>Yg3`* z$#tPtNcvHhnKb}n!pYwmAeVV`smR>{G7k~evhq}X-Ei@QRi@HvI{WJJ9KL@h)2V`8g#{#EPt*wlK zv&E50wsKf-qEA=%p%o;)L+K$~_Ba3?KEiqXC-sE;ah^xa$0=Kzk+IPcZKjrnAD3n4 z;a9c*550+^t*F%u!>~opr{*7t{1dz;{tTs^OsE7|`v7xpBr}B)udpTIKz1jFVD{IVO6MSXM;7(TZC`YVz>4QDL2BnlVK)w!#y$Kp40Tw z?x)+g0x8w%-55FhdkS;rh4s?y+epCr6q1(KIp7)bYzg}sQRKrUK|HSMpi$PI6doo4 zO}8C9V}+T8S%uk=D2_^;Bv#ieC)KW_t*jwU^I8??@xeXSw}9SLpoeO3J8)n=cxRM7 z8EzYU53!|R$9CvUw(!qr?c++XMVa0m-Ns~HH?Ag8J3 zizwtw6&TGoUxF{WO&g-ycOYH!RYcV7DRj<)fc-v51(>`OP_LxDd_YfTOC_Buf$WO- zac)*&i8(+pao`q&r-exPWx_iodLWbh^T^Hc5zE^McrJ-xH-)+a!LaBrP=}y~szb(d z%7=A?`f@QMJq_6gl>pxk15MYC%!D(rBlP)pq|53pV5#(F+oSP2p-ZZOV=Kp@M5?qGade_bz@p=%~Mj-vC4^8;A!?g`{tjzBL+k zD&HIeVaX<7e0|M>T0;S>L0g;ZZmsJG%6hy8J@Wck=8Y(K=MRVpgGAzDkV2`9YA_W- zRVugDPv!0)6(1{PKU+|XbugsN1qg&;XEPXwv>SfNy!Hkisypr;grZHFrg0_E!b z8Z`1=BCSPWw>QB?LPA57n zYlskv-#j_Ko{wFEEcmGTA?&jGZ3?E>=dw6$KFj|o8Ku)|j6O+C4X9aDgM`p$gCHb4 z7vZvRDdbnvOWYc-Vopa)HQR(CL(I)AJIQ){r<90L>W;7w%g5JaS#fqpa>^Aq(J!-Z z@sXdVj5kL>G1Xc!ucTBgG7C%9$CRAAn8|qNXD+I46A*vSi<&3|tIi*Zq}zNcB|jmV zmrz^DI#9o@6j;z!O0@{gghMM4*nRd<<^y6CAZ1j3&+frqE&w>O3ue7QCOFJ~nZO8z z{|Vu8qg}ZByJsY;Xo(;PPIIay_1ZQBw=<{t@ zJJ*Ii0HDJMY}kEt-%EGMhP75UEK^$yKAsgDMnbS*Fi~Q|pj%qmWISM}Bn_K1tm`2T z(Ib7*{qURrz`&y73Zlh-sB=qCm3#DWN#)LE-hhOAf+ybSeHTfU@IsJ;>0)|fy67nI z`uPm3U#0>J%2XH)l_{mB#!_q-o~tL*hY;$@^g%cSnbPOWw6iPIM*wvAfJ~Rr{V?4j znYO1)xrg=u(t2KGNMMz$Fi{{r<{HQ~~%x)jXTtX7K|xk%D0 z%-k#WU#0G*+Y_`ZZo#ZLj;$bz1)1)KwNCKVd1DbYzuMlt>h1*eOG(o&E8cNV8@eJS z6CC!ZrlDb!U#Uxz354#aDALl7Po^1^wFoa%)+|llQ{akKWae%e74dOE8`STc4bw#C zD=>_Lj2=T=!#o85cT2I~mw2I`&inVC9}NuQQ3Z-! z|1Q+iTuHlwpLSC(ZC7(eI4b8onZoz@$OMiJLD0VDcB7U>OF559G4t;_NR~gYNb?Um z%$z0Z@F{?=3Y8Ib82vb3hY?%z^q9$o^tic}*3#Ewp&RJ2@Eg)&YM9dFASbRKOK~ba z_S%UT>*?nT#CG-bc{l_8q|evSbHN_<^CbWsKHy$S_X~7~^s^@rp`STg9JyO9c_*Qe zesZzz3FO?wyQ~rq=%=Km+awm!&o%HuHyBu!LPXsrNa^P)2I@9nNopYg~Qp3QW% zRG5)3mDTU)DHA-Fo(kPSPle-J44o(6ew^;C*ASx?v0)6?~c?ds_|I0HSU z&)3t7!5;N=6MzmMaBradWx7Lp+7F1((?(hZvRNy6C!tW=yBEds3VvmKSUyc0Nk_Ly zD5RsW!VBGCpxjr3f+R@k=qn7=ZN8L_ZY03wGu|YZ%0eA=jh8?<)2X24=QCNst-0oy zn(OKg`g~ov66{e| zwgBkx0rzIQ-=sUFE0+Kf{p_eV3Hg3m@=Zd}6|e6*1Oa8&;sHI8G;GqaIHZ$>?UHuT zvhJL^&{fDdgveObz0&?YG|J|?eC)tO^=)4R38)t7N#B+Zzi-Pxzf8z1+8==hG8INb zGNn|4zU_v3GTVkwS7v{OGmsg5zRZTZGJ6+5hY!f?ZMxs0J0!EKC^PnLn;_?}h|EX` z(@!1i-+ur-+EJ*b;+t?an(4ERsOI1}A}2o%aYS zaCQ=Xq(T>vO^B=+JKKq3Gpf`_-6lYFEWFMF15F&?jyPM1+*DFPRl0~2-SqG|S%l%M zt9&VsZZoaBMs=Er-P_2!%c@kjK2qJT1Jti>*TN&!Ey-4M6D@xsTTLeXa^{>r&BDfz zJR7prx=op7MvH<^`mtwN7GWNQJ-7Evo=`*8+Cp>f&F2E}RF^|@>B{bSZNYMx zdPY7QX&ef_$}+P41jJYwHvvVgyWvK*VB&GXE*5#Vr=_~LyQmEF_ za&_}wB6C6o5|BB~bRgk-jeF4(1xcz``$vyn@NqBKQRN!ds>XP0KISaQR^|-O27%YW zV^FBNy&I+K+JL{o8Q1{&d>ddvX=pe10O;@$uJ<<}5cJdJey7((PZ>F6E7=K>Z)?I< z3SA*&T?L7|!_bz%KwT$k0Xw_kf+`VPEFm4Cxf=%ib;PxW0t@t45(={FFsI5EQVws_ zlf&N;>dN5*I0HG*=gZ+1R}OUmI(&rXFkZdT`L)+_Nv{3!B%kiB0zU1P7?P)lbrWK8G>Xo zBFIpBvl~i}z#6n&4WxIkpPo$63C~1#C+I@y6*ZXN+=kL4@EG}<>8FQ1-mW-^zBEIf z9SHK*G&wyein|`h+}GC=fdzUZ0tx8}H6hTG&Gq!;Lxj3|vJcKcPw4aYLr>TU&}t9EZ!La}pduV_uE7txNwqQ@+osM)S~lrgi+q{Z zB7zZScTihVo$3V7R3PzO|#bMrsJ-g*4lENYgAyhielZns_ zdiu>o>g%__0{s?c3F$XAIGE#NAD4S*wn7gR^S}o#Gc&(M`qnIXVDdi(x&q8mfKPnD zT?Bv`Z(WUc^{@5n%V)rL>&vHb2K9wLzrM_L>&pQE9X`VKWs0gVnX-3mo75LZMt$MT z3hPUM{GP$D>{&ceKZLeTI@UMfQT4jZ8D`!s`qdOnLv!PuF(j7*5Yfc_G?x1j1(kvE zr83are*Dy@Rx_+Y<9JtCaq+=7FYzSx75YWV^!@%l1M8Qiz=E=rjD^aQ(hbUz>k*$b z-G3v~C>L)%0qe{M0XEDSS0Ms8_M9CO_+wb|b#I>GoDs|Mt$OA74KST`Vfe5wIp zaTdxZM%p4z&uB|}!T&Dugxf@Oyxt5KqYbO6?=KO5BlrvPwOE`Oh^Y^x;F~-kZZ^f5 zpWLbGuBD^QW2MjQ@!J|<&wDPg@wpY?*?&Mibe%KdG=D`6biNa=1D>G!hXFFoVM_Ns z{oYZpTz>+RTdqIC8I&u1C|5Sk1&QTux&8-0=Vv^^<@z|wwHS9;VY`L)o|G#ihwK!_ ztlBRiRF)41?3B>PM|^-~UJL%LN@UeJ0xyb^fo0sj3w`VIV%afmh9NZVj5v zD8CYFt0$>hPhjcM9ptLMqz{#T0hW+`K)gGQp!EREpL=*K2m!xt2&cfK_|_?sW-96$ zTQ^zaE3ow(l9jt8Ts-Foh80O(3bVX*BgwYPQ%_dvVi_zy3-J|Xxuevl;o;TsNn_=5 zNR7YHSef*Fz4q3Sc7|ksjCm?1cC2|Sp&8T*;Wkt+s3~e39OT0t2TL&p^Hj8>yXxs# zO2pSQ4bDK%==1e#HQ3{L%K*^P@d)eLa|o32+&Iwxo8*;|L-ylL1eD3DNfSrt;(~o( zh*mhMaFuc3i87+w`Hf{%D2QS@+!zc~t3Gro-1dJB*%Zd}Wlsh%A0@Crc0wv7JLX>5 z)@#7P?s~FW3>|dq;Dc}mvZ2qH%|q}|HV@x4eoDH9&SSvDEYqL)n)EoHN1CK#9IsFMOW?+O zFFe*0csNhu0f91h*-J{$1X)ip@M#9xBw5jiVK&*uI+i?1+KADcqZZIV#*t!LpZIEyDUQ1(pGk-$QgH5Wu4Kv*(u3*S9i zNqOItZayc(g!`8DIc(~2*n}ZUdj9O!^N7gVukbp>I7pelP<>`reVy{^^ZTLlI!1ja zUk%o0+)qoIb68;1hd?)_a6`ID?NjwyLL}>My%s5`dOgV7M`^x>YKV>6Z?HCs?&njv zxyM)>NDK9$i3byhz|`J9?rXae{tu8h!&-r~iz`(Dz5usjt;Ew>g@=1J&5HqaHJokq zNiX4LuEC>14o_&6Zm);KdJW^e zeDmL!Tr1~h2p9S~pygPJ#ofVNbVYshk&`6736GJ^75fC4=W=Nsiv%yPiHxmO{OU?+GmaVS^|4<-(Qsj{r_ zbiyeiiiUnQ9oBw~=vo|ay$s3no@9Z23>fv$^Pf@A&o~SpqVQb>l&A+7-LFA z19v#evlX7^PSwT1z6ABX_&Szzyce2x^J4^Ivp7~wK%KJjaP|t$rUr33Y{x`Zirf{5 z_D0d%C-{|D{vOQ_1?PnZahk@$8sc00s(!><_g()dW?e|7cmrSY-gjJW3a za6S>7J->^yUvMgiG(@Lad-8)gUgRH;Ks4*>7b5PXPX-HEcpEsqGb zCc$a#2$v<|VFxkjr9g#~>2(r#s)F~zZEy5j8=z73_9yo@@S()h5h`aN60cC_Jifd) z@6LV%y7ejZYW{Qqj`^n)9wlsNgJ}QXBW;w5bZ)YzG=I~fph@t z?!m;NU_CsTH~^y^=fph!JTqY8Dn&L82487r8eZ=HG*?eBPOk(Zt0jg&q4LHUi-RIu zkibAXy&ct>hOq1)jLxISU*o*^y%>KQlt#s;s(3o^yho=ua1;r-sKJX$u$wAQ7$xa; z9|RfJVhq4SJaf+BY$o@uw};(+9i=R?6o=5T-|%4KP_Q>Wm^eaddA!1oZUzog*n*eY z3#&AKKKkkQ#V}^NJpfO0D@pnLu?|2-f`%O{V+eKomD}J9`jzzgV|E-FmVRY9-VPrq zhzh#j0v3zO)19~BhdpeneT;VRbJ0f<3XSvLK)@sTm2JcWJt0Xa-+710q4I#JU4lo= zb^yGyBk#hU*n!7nLM6!TjU1bO@NnJ(%!^u#sEM5bIJ*d)^fx?@Gk+a?SvRjWE*)O$;W1fR7l*=5gEs_zItd9|-uC`SyIG+H3?lcQU z#ye6vHWRe=Gf0S8pTb$t?ICQr3D37OuHQeUQlK3tOfpU#3Hp~pHc&%{S{Tfyu-^1S zL7JZl*l$D7?q7}SWKR^sd=;GLxyY8U_v{nX-W(LY8zNQm6!ef{d$~;5CSQH`9rlKs z7V(#xtEJ;aREl4xknXh->i`l?e9qM4x;>O>Uc-k{2VbBQ29gYATonx>Z3kru_ zFJV;-`+-M>ys$+`bA*JAl;;id93{`uc$zWH+=Ofj=V&;DJ%l_a{?27%oJf0v=Yw#V z3HZ*N>a5V_&{?56E+}K>J7%3nad~yMB@`IrzBE}w|3YMT5LvcwgLnlY6SxtZzuh{I<(@$=yxzj5CkX zqw{zg68MsN-0S9Xi^|v5P`>stU;h9L5u0G^e94_}izI)P7is;2v_5oc{Z-N07NYf0 zK#Sl8X_5EagzJg&w8{H->HwHmo}Lc=Q{?FY!?6CF4z>o%!$EtJV6$zrL;?Satg+q% z^X(o?90F5qE82`Z5Qbw)Ovt>9hnX6Jd3j-er%Hrr z5@7%$B)(Ei@jjcAL7RU#;lywY_vzuLD$K9DPVRM2EI?ChEs{=}>RYF3qY&pS$R{uW zy8Q=GaND67a0cxVeSSN1IWo?+XC{CSA8^m6dzNy~rF)KY|B>#y=%x(azRdtij%Qdi z(E5BWWyAzR`*7X_av4X0XqzN$oTUJUntogW7v>iTFME_YIL*L7%>T1#y*4qXeIw=|iDH@9v4ZfU(bT<`5sNhPXs%V&zWQ3kj!S)-mrb zq-f=Jgoe0ruV7&2L(D8;8qJcJAxJUvAOm%qFU3r;$BfJ$sc4vvWCV|yDkSSyhHK%G z$`GE5yAOrIUr6Vf(~!=mX}2M>{|=R{tMh39d%rSPFWqKQ9K9Ef14(y&pVF!GcBIj* z;$)>aYxv9uGob1aGO254X=yzbtGZUAwZG7FkI~X@Qf{;n!hcY=M9)HXi#0&iEeR2o zaqE_7kE&Y}UByzR>xN4~d*QAIi@@D*k$rOAq&azA{FB&Erkq9n!qwZh@XCz*_{WyYgdn205 zsI2Zqt-oM4pkQ>Ri`5fY4duWmi%D{FvmCT>&caX31*?3iZU6n+r-kx*!yXd!^de9K1T0aGaHD9Q!a-OvE%IYiKHKFj+ON4c#W48mpZ zMAkzsT-V;GCtqzjR`DgMF?Deg64r= z2!V%Un#RRm83O+WS39`iRUvTCuYB-}A@J=1k<|p}J1_BNGkrB{bRjvmDM$Cr6?srW z{Y0sRr%8;ac7)Q}sJ%^3qHxu>kYq;^5tl{_l`QRA^!B~2Ny{O+iAZ}5FmRy7Phf;3 zAi0~wFtY@*sc0wx+5AStrRhltsAH-Lm4K*+y;MeVB49~MZhb=HYb9~YOy#aU6UWIG z0-Cc-6at?$6W9)N^Me|xxRDE-bwYyzRy0%wMBtMcX3j%>3uWLhzJz2q9TAsiBxS(e zRu|5|BcTj1hRQ&JvmS2UW-+S7xdTV}^+^mU`rdWCiUFk< zIDaHbsp3*%Q8{NaiSeu?PZFa@l)ez(HEc&-R2^`&AGRh|@y#z>z`7ZgvH(c5Lb{n? zvx2W1Ca*I?a2kKa;UC%(CJ|~2)mgrzZE)b~p|4AiAVj+{x~3L@@YacGWA(Rm1)7ZAzLDcql)%5ddm7BJ?6oWq9cUzZk$UKK;7g z3{Qoh#=KD%&jwfjK{*DMMYkgebldJIoI%@7pWk-31TnVVt?=dt+mhyW(@DR$<8c~S z|9=r(XXMbh`Dr9vR*X;-n$T60)KgeL63IZ6L<|pW0P^Q#!iClJEWQfEk@%hDSnEtD z8zE7B5)sVBs6=Q67{_{$E%tGYRwU8n(|rgeNIqZnDAsO@okqmaZN8kwbT<`jY__=r z%(`*iSTuv}*Xd>s@yuKmlZjQQVx7;*gUiV$)aJ9CRUV`%CSlffX2Gv8tc(2|N{os; zjB)%eJO!X3TX>Sz{Lg~)_zT%qvK_Lms&DpdNdBR*HDbzH+ERQE7}0)rjKOSrV+>|i z*ROqW)=jaXV>Y$@dCHCYM_%Sou&jT9ZI;3g)Xkx`DcdX|HcQX7%`8vzAxOGZ zdpRg^mYRH~%PE9QxA}A<&?)BAuM1cY`~X$UFh4-62}V$_i-06`SRCLDu%;eN90F5y z?@D~_#4xXfEyp6%NU-AUWp!s9ad>sEKjyynAw;)7#4~x$wjXx>0vN|_G2;yrV+`cS zt9wW4)xA%F=+?dca0YdcKELigho+Eq?=t`$KA1Ic&guySqVDBt*P?`fld@;z(Egm$ z5x_n1_@1Cv)&URHL7}fG%4jOS*1(3fU}E49(=QaXvd<6~+DwodM;~AyHtO;vPqmfq za|PxrGzD=`u*kJLY$HGo+s;sg>xCtjAxF+9j8-HJV6tF3FhmPccM08~UP%Fl>J>Ff)hh{+(sHYb6kKwj2lHKDB7$Kx zLrriSB2TxWzyCm(jFb%PespnywU?!y>Vd*@)fv)*-YGg6bnSoSM(Q29O$CV6)6gC zTq;caRrs6+*z>jJWtJtj)5!b*=ST0mPpJuP2?-|Y2>T00C_l&O6ElI3ekApYg=U~1 zlJTG@9F~OA4+)V>yZRydPu7niy8Qz)ZU2a;`3(0FeL;)r=?KDqlJK7!4(A$O3fE6o zA}VCSwf-*1V=D6~rWW5=D2DDiI6#1Yk%Yey?13mXPaz8K9pip)|4n*Aj0q*a|PhIuTFjBs_Gx zHQ`4hZSYE*jE6ap-Ab=rartd5^Ze*>SPJyIk5#XO;@q(XJd8(NMZuvB<{sQGQ=(V$4 zI;o2qtuxW(q&{{?>?8dGChXC#L7xSFs~9_T466m6a&5W!C~l?=?=SK2pGVJK@^~*$ z-AfN-y37)txzk))7fmWY(3nYv9CZTMIunH#==x>PZ^DwMI#3Yw1G6Eoz&K+Y7m(a`@=Q2`c9K57 z9~e;!)HW17)!`%DHvR_1gMCqFgfMJGe}j?HHezZ}RvFI1+dE4vbcK+0Aw-mXmYAdk z?3@7?T1#Tfh7USWwOk#r8SJ-XWCr$0U_m=12?beonA1}3(Zrm0s&xuPt=nDcEQOQy zjc~~a_iA9Yo1+^AX13&9DtN?dOH30t__r0?z_sSCz->(2LYTM*Fz+3aD7Z7(x(`09 z9iqq;+%CYd+Dpnz%&6mF~s1j!)BIKT- zaT1V!hE)cTe4$o3E#7+QlHlUK`6pN+S}^Y%o=S&%6}p4AVU;7kh1(%wiLN9LnqGa1 zd-brA{9w*4CiT+fhUYLI_qCFre8?xU-`$__4&vax+wFK^!yi3IBA;@DMlG6H^Aa{< z;Wl@QVQztnmn%!o%XxLXH(~{rJm8D>$6kx{_-Dv1khJ#cb+ zz_R2Bs|jSMnkgC47S1g|{l(Nw%`BwyV8oh%mu{a6TGn`$>Uc_#jS~tYEJya~&LbA4 zCsbWm<&8Rf7K<0Qt{dL?UgjY&x?WlPHunNV7U2YTo8tzaXDI-WfsugzfRJksd%zjk zL;C!2LnS=y+4RKQ!Ce(}_olm#a-U6iU%IJNZeGrTA7h9{+IcBhG?aQrqMJIIgz&W8Y(}_O1FnlmBnnL zR}1<#Blv2-3=5+kwaZDi^(F>NFvcm3G@d5ppJ72HG3ye9l%JREcP*?WbUl@V7PkB( zLAsRq+}4Rtg2Cys<6|AY_5hp0Q93p)g0XsIe6Mb@y&DLc{PRrmbyG+jnG<1tAK9<0N|dop;J*1rWHG0oofljD(wduRRPN?23fN`yGed~&=1=jg#c!0 zVrIS!oID-I>5;pTgJjv|RC(QHxQJRHOyEul9ulndWMU#n?7+cFL)u5B3$XJA|C z^KHuoZeMFWfDS&mk<`~Z8-cJPnc5EUfN6HL-HaTXbA$cVM&pO+Os#AQ9+-;|`nV(> zm|}a)GmuY?j$%$6Fw{k2s2&>bf`{80#K4;vsNxmi=6J$U&123O!iyvlrX{FKE(tfX zROgktc_FxUMs@>{QMuI{*r@Z)nB0* z)L#)&sQ$9FRQ;6@5sO=YMMA3ndh<`s>y`Bc#CFTN8qT1s>GR9_GO)+C;}!s&oAH4A zHo9-6JJfdc2O|1N5p5!beZ1tGghGAnOAt^tM3uLs(Zrbu42Yj}af7}*2`U`S@oh{6 z+k_PKV3!xD^f(D(7CIy%U2mbL@J@X;)CVV?UnXQ0V->>Y3`4s?-UHbRiI8k5ouCeG z#XbE1)J(#|+gd*u8BXNGTumlaf>b}meBG_17DuW6c!#p-jWqd(EBX-!8%`N>a){_P zK2bs?ND7T2(95Gi7(g#CT^I!V8YD@IaGkHusC!E zuijhrUpO8@sJ|*ehz@nY&^ocJ_>=baWU=RNT-G9IwObr zNm~){6neL4^fg;M@gY*_}ki4drlKFXKaI&L4?m^I0ZQxcNTF>D~|AIk;`&7hu&z(Vzu zrKxP7gb44h4HQ8p_hA+p{Der%9n$BDWUc@}fz`=7+7Hx`5Ez#)gxXB3_9pem{{#+P zeOdr#pilJq`ZNhyq&_VK(779rus%&dAZ%x$-0_8#QM4J141G!ii~OO7tUZa}SNL6w zj$;|Wa0|VXG_W-n*w&})JDdPsokj3MljNns4j?S?F&@r*h80Rgv7JIeP_0x<*EFeo z079-B2c zIp*p2l4zEk1PWh`g>1^n*JTzK+IWElx+tOx=^`~D$xht^Ktty_?`;r{KHz-_IO_Z- z;P*EK$DZSc=wRM$IHp{!>tr{@V#aI=i{rOL$>9$k70x+|he+6(LVG_6WX#K@1_XUd zjAtJvN~(E5QeTzh>b58o{u$Pls97gevi&fsJ8>@nuI7XGEI~|hs_#B<#wR?Mh8?dZ z26`M~$A@G8sj%}X0ETrnXjs?afgRss+gMZ@pN5rEH~ zC;})`3Bj9ijMEKsD1uVWMXZu&&+r+Ykl$;c_uJ79mVmJH44v`Iu=?yQr&E2S z6AK7zV4na)*6yFA1L(*Du>>X#z;JJ-`Gn*|WVM{mR(i1yYlUxa2jMmol=$L6eD+z` zZ99=R$uR$d_}GIBESM&&-pe<>V2ET+kMnvt?yuBnQBuiSJ-tZLN91RiI5y29wqfCJ z&tOh4Q@anSCyCu7@nQ~*wNfJ%X;IQuW)xeT+Lf!9krv&%7U5lX1s;l#ieYp%byE@E znpTQgkd$QC6TW6^;ka-!3(He#ic+x=ZBb&af_fLK?}duTtOgXzXc4Q#9GHf^X4FUQH4CX_DWFtOK>32w@%!-X@1HDuQ4`(KFVn?< zj1W!>U@|!0p{MLz5*I2ix43~YHnpgzL}4ox&49lz-UTl6D++wIE18F4g)CmD70^#OTrRAvfna z*ONle^Y9=*hr7Ilv0V>#Y!l5Ua^V%$98y^!5I)^Po#jDUXO&LnYk!2>qztVB?8A%c zRzA1pVHGx3!SjNK0$AUmPZo<*h+-;CBcfZEa0j2nuyi<$3AkTD&y2dgAW2%fjE1=q z;>02YIF6dD;MUE4h#-1uSU-U{dg9g%5Q1U-hd!6Tbg}8^xr4u4MBqNnJW#=jfl)xt zN;j0mrFzXrG)M!>6iU&^waz zplzX!Q)~H$%k>e>zM6L%Dd#ofTn(sv+YY;x>Es9QT!bqF+^gW^ZoK4k`?K&d0>r_V zWRe~t=;9nobWD;U(;nabborPiE<6FQ`4K-c=!ZeyUk3E3@ef8=N&VH0Kyv%5ufQ4f zSLs84l_gu?eX`Ns1mIEMZF~p1BkNFC0v97U*g{4QjrF+%;H{?#T_I$B0*;f{(@0;y z&ITr5=nz{vrgVhH@(ixu9}`&6ACrVa{W0b=kWX?szKSq=f(TojH;eN%K;3c_rz%H5 zNCddmEEsHVROQ&;+q7Yhq`iKfiL!st7b0i}*`!)GLR00FbTQp#a76BvmamSO(-23t zh~X3VIL8*NU{zI7%rS^p8kJkDq4%^Eo*oR*?KhZ#F|yHQGr1m1lQ+we2b9MnSeiiSD%q0G@K=W+8&or=J&=W_!Mxx0Yt5s>^v})|->a7if zYn*0@uNUA$ack)WZ4CYm#YeZ}c%BXX@d#)CNz*zWP2@sENQ4NGOf|j~StZG^l`8x1 zk7bnlpBuByq~Sz1fGUL z7MDUoOF^#Fe*JD&u@JgZN_i)cI|}YR zDPaq43h;U<0cK$sw53WL3G@_m(6BKRs!FaKHg23%T{66?WZZ-?V@j-e$*^%HRb$6j z-&T^Sj*l8QvO`KMg*kRYLhy!HRo_xoHLk?&=m7Wn68ki#L&|B%IKxVA7V0D7*4UEj z8>&iL0lQU6)wl^`tK!3|QSUmWv`CIJGF~;Tx+)HAFaYchDQ$lT0en{7G-247l4?sK zH%~?$QxI#3vX}Ar8kU9 zl#GvCqpPl~E{Ru-sESvOgJ~-1KjECJ>XPxpuDfyA$SN~&3fZkL85XZ989OSGfaFW8 zaeyK6b=KJN6Cj%oC1;NtHhfH#8+Cw+S^|4hZ6O*&alLiRxG~nS>k$uTu%x6f@;8=Y zqsEP};$ubf?Mf0=RV6o6SC6ka_0*A8hq0rsi(3h6M0E$GbLxm&#*7+w9merI+R?BGW6IQF$yezEf&(Ww~YV)E%1Jhr|{=m;8psr$rlxEoHC?%irpjomoqG;8COSH^Fg@+N-SQ#Vd|;N;Fz7vooY zO6RF(w(UIi(bGCl9dt(LsV#bUo_bH;&Qn*O+j(l*HJzvCUyJan&QsqW+j;6)M?Raj zPd_kiP|<;DJB~jvZ5MuzlpL7$aF+wq+Vwjyt@{P|RUMdiLCt|_*W7+!TJ)|1)1H~T zZ~9x0?3-Tq*uLpcJ+W_k|0nlNzh~9H>2JKUZ~Ez5_D%1#b>H-}@oThi-}H6g?wkJ1 zkNc*-^WN|oXO2EJW5d`(GxpweXvT_phi1HhU$46l&3J3^p&2!`hh_|Y5x?z+X0$(a zXvSGz9GY?9r$aODow$8wuUXq?UNU?8%wfy$Tfco~V#D^C+I!n){&H~p%&lK;pZOMk z=Y6w%=ElgoGq1~hcjg0cmdrZ;!Naq^ef02bbH(A=<*N?QKJmrFv!7ghc=nb}hiAXP z`S9$~ZylaJ=##^`?s&gw&b+#!IV(Ocn)B++ALs0`&zjruU%lsM{MdW$7r*wN`yZ{( z+>cZG%q`CAGj~*BpShXG_nG_n$$jQ#bm}wr?z8&L9p1gq+$#Kf{bkV~Ynr#2ckZDx z<_)-M%e+%=+cGa!vt?fK9b4wjyl2b2whwKYm-5J#d7B?c*orOlx~|+Z?}hbS=1qBd z%e-m$UA%tx{NAtbp1)@6?)mHS+xFMp^Z&Jb_xww~*ge1e``z5?7t}4@d2-$2>~?jFm!Dp@cv@NA;*JCB7N=ZNw>W~|1w-o=KYc^p;te;}Eza4K zSn^ozswFSxty=QSNvoE;-fq>B!56Jsa>~F}OFH29dey2WyKh*v*u%jWE*Z{yeT zt?Z?(c4jXvIheh4)0f#x`)S85{q>*2mt8#jhh?|j^TV%%${@a!Bb^Lbavwgo^`QTH7R=q!Q%!@OB?)y^O`tEBBX4kI$WkK!QhZfbY zUGQA(+J*RCx3YHaKi1c-J+h&8?a-~YYqP$oU3>hu@c&f1_RW-~Yim|dSXVT}SlImp=5GA%oZO8!Uy!@;?t!@*n_mw9O}QH*x8-gu zoRquq!dbZ+JLI+A)T5yFrs|VhZ@Tc*)|)Omz4fNnWvw?oeL?F@+b?dtsdixNO^@Ms z;SH@f4ZX4TrhnYtdehrePJAtzxbn44AH`q0wC=*!Z@RS0W_@s%&GWA8vbpOWT{fSE z-(37U&gimv^{g(N4=wJpId=)dmvz~^^rAo%6xH4-pCzWuSo3JIt0H{t9NW& zV(-}ce9exn&o0=pb>RIwwtnyo{4egm~vGv{ec5I#Ye#>nmK5n_~mQPx4 zTla0tZTB>3wXNv*R@)AhwA%I+eq&E=we6(RR@vlC=jqnZYcD=W{|L%-8`tL5<(tr0C@AluV@9)3+;8*>3&-%Lm?jOGc>_7c?pPzEk z?puz#X!jlXO~>!e=@WLJIW1$)#CaKe9Q@9opRwoWMHzcuyDwwU-yX==bL7d4Jv*O; z`-O}>pT3o`=lks$dzSA7{sTYk`LfHp4;FM=_rd1#*M0DQ|8*anf9bjpMqRb;gILwN z4_+O=?t{Y<*L_fFulwK}{JxyL?t|N=totDMvcq+Wp@-{U8hyC#W&Hkl#Pv5oT zv-iGfb6|DP??1otobNv`9{m01JFfcv^NWXn|M?*NPOkd?^T)@0|M?mVzsJA-{LW{; z|9tbt?>~Qk)AyhE`sRg$U4MGv;INF92gk=&9(<%^<-q}6Rvzqi*2;q)_FsAM(8Vhc zeudvBm#jQE`i7MUD{uNg>|J+26j%41O%xkoiNQh=SH+H~V6X%Wid~e5D2WtX?m{c+jq_tZEkt4sAKnYMQ**$6*cdD zuBbKejr+Nx-^QFP3JN?|RQqPF;{4bu{4vyuDV@Rsg(8`)sr+5PVIA?|nY4|l(7`=R^YZ*&(+mc;y7a(Zb=$>(cJN(y(B zl>EKBq$FT}NlAy3B_)5HE-Cr?`;wB&Kb4f6{-dO1>|Z4%s{17+en5A3@!pS~;=Pp` z@!qIl@m_A2c<&;xB|^N{cB*)8^x}t zKUdrJbbHNRPe;_+^>k^&T~ANEv+Jotn_W-)wcYh}08rOy*V7|zyPobGv+L=ayfi@w zUasiXEK~9R26MB5ZRTcmcA1+s-D_?ZaMIi?>1%T{;jFpYsUOVEqJPETubG?um2YmA zc-`D=8ZiB$RgJ}$tZMlEZdGGqfmMyi){Sb^ey33l3qZ7KRKu@*qZ%hWH>#2HZlfB$ zeHzs;b8b}Q!1v8-=6n)cvr9s3&6Y{AHCN1wt+^W5K0mhRf}OE79d^amY;q{J=HM)p zIU8H^^$W2z8(fO5dHVNeb%I@fsx$pkQ}e}_o0|JwX=*;Pu&Mdux2(-;H?uak0K`_- z=6)Tl%};i*HcxT1HuvpoZEn`j+T1+nj>X&O?^tyD>5j$4t9LAF{B_4--rsjDb_jPZ z?3>-SNCc(esccR{xz&)#`intyVw8rCR-DpxTgX_3wCB zs~_i6t^Q2lo5*VQr^ZyPUmTC^ZRh$qX7Tl#IGH#6EwOvUeaYP$_FCV)VV8~F8#)4g zQ@c0(CB1vYZ;y3v7;~X}!(BJJH#}O@z2UXT`2O`C4No*_WtG>ZmDN4_R#wOQwX$jx z(8_9DL@TR+s8&|NfZr#rtS(G#Wp!d&E2~@cTUli-Z)LUWi&(4P2V<@FpNqA!zYuHn zF7W!LSgSQxVy&JQ$66%|aaP;kh_lLQ7-zM{I?ig6O`O$2m;A<;J@Xs?284W=-#Bc1 ze&Z{u{Kn@a^Bdp!IKT0@#rSSXe&gD!^BX(w%x~YB!n*EO|Q>6$JG(=~lOPuDbTv99U1WxA$Uw(6SR-i|VRbWN?-q*}iPY+IXZ zePDg6b*r>g>x_z9r4S8&J~xdtl?>lICkClr*>1l{D`y0&`264^J&=K4D8q^BVh0n*SWW zyoGb~mNqLL-E5X`JZS>$$yH49&{^GPvkHe>JI(&87X5op`HcNm_r%v1SeS+_+ zpRuW9amJ>pO+d(B{EEg*G3X-LM%_>xRt;;G4QPY^F81 zVKczyhRyYMH*9_ke`NCu@L9woo27Fe*>wH%kch@J+k@fL51>)1AZ+r+jR1QglEwu!QfZPP?k(6+iFt6js_vfAa>&T98tgRFL+49sdbdvI2} zxxl><_;MxA$YM$+HntQgl zs^{5$Pz%rYx(=T0Gl481rJHAa?I_RoPeyyTk8bbUVOb~F4)q*dJN(eswL`!F*A9OV za_z8asB4GCK%T2>2j^M%Zh>ou+RI%#Sg%0&wRLQJZmwgyVtXCi$NTHp?mbw?w#%1w zY#o6bnRRTFPS>&ZxmCwD?Vmcf2cM#xnYr!60nIxO$@J{B&U{4Y2B%hZ={Uj6-pR|% z-qPR9{z0gjz4>%A`<+1Rm1g#fHk#RQ*koqE8L-@IX0JVHX8+bVX7-Oe^tNyQUT^!( zPQC44a{)qn+xv*U?bpWjw%?lA+kPidFR8b^u(7xOhSc8n?GN|1kLvB=APn?yXzA+V zU_Zjc;YzrN!@?+h7w6&d_C^nf&r&@cwgcv2FJIi;JaxX98V-~aGd!d$MNAmIgbAT zHJ|1N#?6m;vFQP3^;ctN+irwY0?`@Nvs{ObkXRD}iI{DAHE3c6YRQ_$_lh$-EL z8B@B~pE;#_%Xz@TDc$!Rn$o@Bu_@hqUzpN8>Ee{`^ME=xr*u!eGo}0b`%}6vONr?5 zMV~o6uGQGs^RJp4d)BD8vFFjo8+$f&*w{1BabwRQVEPz*|KY}-OU7^P*;=)+=bs@P zdrs1A?CE9h?4+yf>~y}dvr`irXQy|7KU+CFt?2FS6zbya)L@vi(=az@r#LTXrv*MJ zt8sR^J;1fkwo$Hq4tu!vIThmC=Zwy^&-zI0&vfnc(=69M?dH1n8NJZ8Pm4vaeOdwj zYh3$yoU-V5<($%`fm5`Lr(3kkMBvu@(Jm$K(JrbFqFvmz(Jqriqg{TQgYS}~U1l$i zcKK>^v`bD}v`f#zbpt-@v~2K^I+nw`*0UVGrj6zBC%r9)r}VQN{+5g7@ZEzfhaUhG zL-9Gpa=2ZDy48~e$Xs= zwoM-C(K~tMgFeY4Pxen9d2wL!Nb}LjBmWwoJW@UV*O94B2DyD#oZ;r;@ZtMG&F_!; z_Q(0|zy31c{monR-M8PL@1FHwzPsHU3*3h{T;Sfj{Q~#xoff$7>9WARufqcOLBQOB z3*4t=wec8uCVi~>YWi65TKd>N_tM91u|7EVr#1)2-e`Yt>`frw_Tbpjoez#3=y-5! zNWX()U4|VT+p5XQ@n*`C;~OJXh*L@Pse&?0CNOSFRMD9UXfOwUJaF=Ui({ndR1%h>DAlG)61rp zr`NlE@%I6qUVplJdM)3+#_PRZYrN{GukpH^vBs-M)*7!4r`LEb{C17k5@6GJYrOiJ zt@Y|*xz?+W)mpEnjn;Y%+&@Zn?e17rjfZ1ZR*%N2Ce-m%J?!YIO6u&Xng?X}^HfC) z@>E?L?y2&7-%~Zs-BV@m>8Z+zTCLg|zgjhW#%k5dS*umG)~!~3mbzLM|JiEQ;63=; z;nk|c8LL%YPpnqGc5=0!CI@?m zE)Mo~UJ~p*5J+AZ?A>f(b@aRB+0oC;yQ5!9a7Vvl zAS}6~Uji^4_}^lbS<%sN9Xz)ZLFfKT5~5BSA9Js@g&dO*#j^nkj+ zfEDQh_t&Hc_-;xM$WKcTsP0vjju=0uR$I`J<~jb=4|r_N(S2O z^a$Fw+aqY;K98Wf$322(W_tu}KI0LT)h;~f$9He(&WBorS?-)BYF%%M!+mav6Z~$8 z-v-?2T z=d`knT+!At@^7W4_BdY;#9NH4~!HF$V z9|4_CZi!lVZcEhO+$~YN^R`5dy16ClM@3rH-r8wVa~h;Yec3WCDz|l7RO0v5qdVWI z9=+gp_2@_cRF8fFm_Mx^9aYmTdePfv(RY9}d$Z^TJwE-sl*)aB2NyFH0E#8c6imRDD zaR+NGQ0q_pYB08exGwe=up78iEC{QBvA{P)cuEx8*7*M8;ev1sFmn|IS70&l6VPIW zAZUQyK<|-w8zQ#Tu{{eka8?MJxQ|Q(R`gZ~g+O=wHfSq+zKHEi;3>-N22{WZ{Jh#- zJUS8z>;XCfw{X9;1Maihf$diO_)#0c9|*$d4!{lUTj2NNEL$mr3BY!sYfFWY2z&>G z+9-r$KyzSuYlScrc#JXy*a{JX&tj z`D40dC{MY!7VT#P%a#3y|0jZ3phO6@)ZkBG40`*{?!tf&IV=TS0IKt^iN) z*~Lx}<^Wqd;VwSlJM4R5n~fJzHAI=89^yeAzy?qO!G8-v$pb;yhV6BrGq4|@qW~x1 z>3u;Mjaxp$w&4cGR6$6`4J>njF2F~?rPa8-0o!fZP61j1Zoqxq7jp_&1ynD@`2-df z2*QWJSs)UhTin38#?}nJQHbqgd>#jU18DXM!k0j!{rL4K!1oLE8_)pX)%+YhdvRWY ziP+x{Sm19lXyf{(3gHIefc>txPqwJBLYRW>25dh7>H#P4*%M{z0)Hhcgx=E>f)BRa zfj$We!8abiPXK%urx12vdmqTf_f7HlBy6>~y#LK_IM+4dQ*{+W4U`)WOo>$p#{tb$ zg|u!};l!!{k5i2Y4KQ^2gVLWt?45WWJw$Nn&2 zKA`TP5blkEua3nVRse4x%me)kI04&$D?kRyj0743Gl1z<`0-Pq5%Bw)@O?lBR0F&+xYp-~jfcfiBpe z)IuR_1FkejA7J~vQX!ZFr@8f{RfW>5-hi>2iHUjT-#|`qpS?sq3 zo;pG+*cRctcCHdLhSDby0wAkuRabmozkdW=0O~$LU6S!5(ItYA z3KRl+?;(Z&w!kNU;hqrSFYLSA$L$5cQGA|>tpo0}aPfza1E+EC!FWH!KHwto20qUP z+<>F_dpz(M=&nJW%!F3Y3W6F)2ljk}`T%u+ZRap10M&qv-y&WBPq2R<+jlQP$3SiL zOD49rE~0ONEr84S=)Vgn3(Ud(cR&+-|1EAUnU5F}xe7k)gu99wqx}G0A1yp;gxCjk z!hZKAxb+fnZi;h&tvR-ru-yRIE=CMqC5U53Rh3c!xKlSpc@!zk(kYjl^~s`+-s5Q(ziyL%D^&Zv=W^|Li!7bHIndA|T>J zjB~&)pc-)I1BK8F+lAPE04RYS$Dm1_Lg))Ue*)|We!*v3;12dTVB0thu>eQ`+<|H$ zVlI&Gjq?iF0b#%<75o%v3QPosd7-a?uO_08u>Bs0d|wbcj>30tg5U?dh0ossz1{Ip zJHFpGS`d=3y@$`sfsy#!G7z!lXB^8O@yHGF39xxzA^bB6F&W$AKz;0c0lR=z?h3&b zC<1zpMtgQZpK*v^4F%!njtXH3Py-kN6d^uu0_<%S!k0i4um>-p`x^)VS^`&lAm;Z3 zC$`Ig=G}1~yD5Y@Kwsc5N5oIy0KN|bUPGA>_+`cd|Fy(+32+Xmf$tCN1mO?(>R;Zd!(sH_ z3Ox9>9Q_G2#r}QZ81O#OaV0bc)LMmp$95&q7yFLm;Z{A6o7}~C1egQvz|=d?*lp+n z+iYMf_PqgX;KHARFc(Pr74-+Qf5G|2_A8vLIN&vWo(A*>hW#c8$v|!36v~X6i`bHk z;{%t0v-ms@coV3VA_xP4C%~6LBG40kb@B}Ijd9T5hv39^J+^K@9`>JpfPV0V?tuVc zCq7RA%mLL&)MKI`gd@h)Mm#?CjzSm&BmrhX_S?`B&>wgW`06c%5C`-D{;^gFQx%8@ zz*(RK2o~_fAutd)3?SqPe*m@cx3K_*ePMM!h2S^{^+%z{z)+wrFdf*A@2>-sf%Ag} zVHq$1XaT%a6L~RmoB1DMoCj*7-h+TVoS#4-4VX9qWr0<|4}d$$SpjixVeA2J0L|XU zd9=p&*dGR1V1Hv%^fk~A`;owQpdDiVqT_<_DnOI;Ta0jT4)fnU_f34uYt|9p{40DeG@5A+ULW4{*s=%^o#53~jP9);gzK>tV3t=R4a zoU#8m>N*?SxA55)+WQXWW&zgNZ(9Q0A`ZUO7J9`wd~YP?96$!}5AbLNd{gyASAw@9twe6yH6;FCqsGQwTo+K7$p4^AOBY1}TK;fEDl^zDq%wX25Rzt^EbG z@jPNKFdwM<9rBZ0#8aRx@KX-XJ+Kwuj|c7p6Y493G@t^9kE9V%m5Aosh?pi-G4mb)5+%}9@ z_e2olfiHn5eBb*Y-{p8Amjf(R&;+(WBW8@jb|^k)0W*PgjQhO-1@H;* z&Pnv$3Dgnz31|Q$XCpVyLVd9P7Kp=sFW^xoVktg1euS9$Cvw_W(6bF<9`G&j7CvhL zx7HZbfY*U(ZJaY1!8?72yq$PYxo?E zZ7M#G1MUD$@VQz@Mm_}6$0&qJK(+_;jcrS8zr#2uV!H<8hb!V1D(!> zPhooj$WKB{237(mXF<$3Y=M40JQJvn@15aSmP3%ceTsA67cm;>xHbU3?}NT5f_{;Q9Qy?I#r9onqk$Cc z-;PGifv=AOmI9yQb92BCSk?%A*b@219GnB-Z2%XGgdb;PjRhDD)CbPZLM#Oa1J!}! zNmx^U1AX2Ax(1d5_*qHeYv6NyKMn8z`ZmOR2T&jQ1E24O!&f8Vhu9X1$dQ45*iXfG zo{@;B*dF;9Z3b!sd+?ohC*lTh1gNzOzfT5i1ZM9>-LdV3?a@8ZBX9}(ld(Ox9(@AD z0NLv>o?)AW?Q7T$!*=mn5IH+f3#e7k>aMZbygR&=hLiIDF3Y*}ECuURv`n=*MXz*B#N;qFxu>c%0L@27P zSRkse6Ck*X4;qT6mI4L4%8QA3)aw1pis{g6VS=u*Vj^l5C@e*>zNJsS3;cpTPvnhS zsRcLev7Td3nW+IceA2=p=)oxsdSR0A1xNsFEaF2(ao{{3GKv=c zsv}P?Ep+zCB6~8G4H0S~2?cB_DqvLkiK-P81qD)&N*S3t@zRXS3X<}sR9=u&l~s8` zQcQiMMwQf&)ZkxvLGpCGub?tU@?s@2w@MC89vV}Xg3S9aR9=ug>+M>V9-6#n4+`3r zb_zDC_+a>4v0&-%U3pRZOaj z_50FJ?hgNFPkFQK$^{6+o(|aP&X~v|K zBx%N^mW$GiNilEKm(*rb%_wQcq?`rPj7dFgby0$okb>By7D>iz>=+}>n3S|wnlY(K zz^vVl2_r=CgH|RXCn-JK4b#tLL}V#OW%YuIqiH5aB`uI@DhijSnKBjOS6xl7Fli`J ziYY0mNQx=xXY892DopChkzz{Pv9*$LR8r1bDW;?w1(v8x_9hy80;QOeX1{jTQNqJ6rouA@>OCiW>kh{6BCMyf_>GCGX;#PYH{-VIaMuAo_@Tl#mT!LSG72K zbXQyhs8UCg7kgE;IC<`psum}2JyZ4KEUuebSF!Hol}=SHPM)}^;^G7F!&@r-TW{D3 zRG4rY#qG=Y$d`*7J=5VW31*_O%5*d4snxMqYEmW1V?#_eBhS5Lsu_7OyHsLQCCQVw znrcQK-JqF?M@vSj%!opyRtj{U3`|WB%!c= z!cca=E?wB@^@mJ15`{laHDVs$wuMR6BY#ga&4|4HvS~)->u0h`f6zGjc(M_Jaqrw=jzOIj1o=v%ma%{pM>JbvM<>=E6JEt65mmhu_5EJlVnV)8PG|hF;kCQ zXGzASBKDA+1m7k#ZLl|}iRJk0&6X@HdVaS;*=kC1FdWeoBcqzOOE(sUZ>1VDH5E%U zCN)`fmDFZZldUvkQqu@&#-t{#G-FcJVrj;trnAzFNlkxCHD+q6k2|0Bf-ucJNll%l z8Izhmf^lD_nX-?}uG!Lk9Q3x}vegw0lEHFGjA~oPk4zMH@gietJjI8M)LFuZjMUn~ zk;@4n^$y`fMrw}cLq_Ue!-tI2ex45*slP@yE+>HIU2XV~QFQ3Thm4}dY>+vXFZ9Z< zO0EQfiyQ)Dl-SRQNEFWTAY#!WUp^5th$6r-9z-k`_*p&?DgUv2B2v9w4?Oo#zGyx4_kgl@%Cj>6p2-e@c|YmqM#azL zK?A+Zr(tTZ)>CGqNb5u8(vZ^E%cUWm-;_&3D)0QB%)TLwhsmWOh3CknA$>Q(!(Oty zn8tP=xiqBh4RUEn+0A<4Ca9`N^W{rrDi~If2s{r7FB=-wyj327DBO`lz!co0x8x>} zcH^ZJkZMm!Cm_An?<2Vhq|^_j6OcyNOD7<87D^`|U3Td!xerK@QPK%Wi(g46AQjef z#+AgXsL&m&$Iq{WybrS~4a=p?j0&7C$6ORLq?tM3}!dSijm8`qH|wGgiQY zg#9RBQ&9njLHj=KR>FxAbIY{ft5Cfd^EQ5 zg5-@iDlbTW=QOC&LsLADtGpoj(y_`5lGiv6##0GpI|Yl{|DN&aV9?bR1EW`cDa}w6 zY7CKZMCNtFOgAJi+-SNXdF2Ds4arMghnn0*^4fi-8X#{q#83NZj@$B8vIq7F{!V~7)fm=-Hn!JOp2Q) z&6u=yTADGbtom36t&u65Vl7_}gF(n15q?nR^f~1&|dOne2O4^wr#gvq@K#D2pW~DS!rkXS< zrlgtArI?apvSDgJ1Tz@+L+JEoo2uMxcn)SgO*bqG$$3= zj+baoO6oB|qB*Il|3?zdNl~LFN;D@`b@P&FZcvs=qB*H+skdZvrm(MkB$|`TvVA3* zlhSvf%m~DmYU&%8DGcO$m zOnME8OPLGguAm&lm(myk(q0ucUN9B-N@~p_#pqW-P0=I!RZvqzu?u8qfo z$b(Dh{GE@Yk>9JJrU-TQRZttER>&*p5V{z5{8dm>bnBpf1+}J#_baF?O#4f}%FY;i zx`j$G!x2q4V>1|NH&j6 zH)DgldzgupBzIqFsu{U*ClNQ3S2WU&#IP-5p_Kj0-sh?-=Pus4AR5kt$f%Y_d={BfEuiNNRhS;Ag*QLJ61=HK#^|wJy0IwKijjC^ z78N3-85<(N6iG)WwX@%Plh9$LY}Hgr#)gzRR+2F(mi;W4gldyIec~h;lM*fBB^oo; zZI@Byv}&WV*6kAiw8W5i~oH9h~%R;bljrxt~SFz#ECswy%zs;k;G*(9Pc zSS|@u+YEUmq`F)3NJxDjPM6guq{0k&B&5bhGi23-RH>CmLh8IPkAzg}Hd9t}Xrj4A z9to+oc9N``ka{fU)URto`7PYJPMYBQGjZcs;oaeN}m_n4E2SP?4N{c~Fs@_wk@2Ip60&MRI<3 zE{AR>IS2EgB02BlK}B-D&4-G~xqS+Uz9KmX@Sq|&=Yq{}qaMid2RER;<|F<|r}*+dipS}c}LMEXA~ zpNQ1|`x4nTBJFSZlmih{{wGUi6B#Dr%VZOg>X$Faosd;i{mb_jyRWEZM(|wkFPj>b zzFjVbC{$l5s}@Y%AIYI0T_2D`L5i-oN=8FS%NjWpq~hapC`iB7t7SBVlq<@iAkBUw zkAkVS^%@xsA)Us`p&*4`21VDZDYWz*%U#x1c|b31XjJDoc?6;`O%4H5<__ruq{|`839e;j)P%ohYo}N5`VZ4PJBC9nQbLibW~77m2TklrQh~pzW~6}?rkargem2#N{Qu2ECbo^n4_8yo$oFTP zYDS)a2WH*NcIC=nQ{MV8Cb3eDjjC{!Pa+Coa!HtCK9xs8`uS2G390F}JQC8@+ec)b z9a7p*c_gH}2zex=!maX1NRvOvC1K-J^$b}ZOL}#bM?&hI0uslv1^E18N!fW_DolGz zGc_vrgj@l*}3exBTITWPOA3)K$GMT-6IkU!>Fc^wW2US|$0c|+&mM{~s;ca4(H%79 zTsbg>#;B|mo^*K0K0i99z+zr>q{?>LocfNG8qAB1)VqTh9Vz-YFFI1W;|WfEN6L@p zMMu%#7(Y4|AznMlsj(C_`tqWqNU|ApEk@!Ic;f>(6ZKajjX%#k5LYMJk7NFUV(lw0 zW{d=*zc!(`C>*JJai(PJQ&nUqr7o#zaZ+M~(^X_Ar7f>&aZ-}q>no_e^d#mN(+&;5&?y=f#wV7J1spE}mzC4}rTF^v#`Pr|oY zhb`@q6%{vnW@jm8qVR#~X3SF)Of@5qJ!YyId2aO_6T5^w*vV8g^5hg#&B&vVm}*9z zT`SkbwvmT>m~O^AeUYhVPH6zb|{X0QWmUiVA(=XQDQ9>6KYFk+$qnAfjy|5^p zsA^&6(Y4N3sT$|Cg~?~{R;@63YPSnjsx$d#c-0D%S01ifVe-W{zpqj? z=z395)e4i}eNnZ-=#7q-BpZuDfmCDWtt&1| zIx>0h@E;@@lQ;h(&6vD<_m7f}Oy2JOlO$vE{)RtGGA1>gkY-Hk`1lt|M<%tj|5cJP zspn^D#-yf{-!Kz53PUBZAA&7?Ctp7(jm^Ya8N4LFoO}5C{*Fn4d>W(TKITa$3ZL<# zW2(H&i;i?!{|cwRBjvjCq9ZLY=0!*9{)HDE>Ak@pocfL;zyw}&6cbkRqhnd!WnOd? zHyT{!)OQp~0zro#S-)Bw;VT3Br43T@X+H{bcP%5V*)8Fh-9eK18C>@*0O4 zv54U*pNL|`YWYMIC5q$|QGDo|C%ca*GR&4wL^0und?JblUGrr(jp9HG4p^5+k!Z`-dJ)Wenr>!PxI=*qb5Rhbn=>_UmugNLu2v|q@}%6cQq4)P zTcw(lO7BZGCvEn=A+hbG$URccNr!cdBp#iz^odfEx7UTY|iX_8sy?Fj6 z_p)_21tf#zk{DHZnje`c)W6B8W=x?Te8@1K9dg_#einFxzvmz!csnD6d!)!LuQ!Q->D?IFC8rg;Jx~+Nm0nn>BW@B7usp` zxq30^MpZp-R7PivAf4{M0$Ne{h(9fhD${t=QhfQAH!Ve)rX`&FmST<b)5-{p(X7s6E<|`61P>w>sXmcUL~-e$d?JcM zum4YWA5qM4kxxVsCQd#P#gk+5i70wBej>Y%C{}p!AYwVta`{9Q2hPhUBGo(mgXfVd zN=n%6U@p+RAFif^L;Ipodd?Omgo9$BJPM=of96Fc3ca3ksTEWIr#z@g|4jsi{Jx?H zu#5*4#eh}{4z;2vaF7QT#esUSai|qVg8e+GC>Ff;I)_?Oo{-6disC`fY8+}s5utu{ zh2U73oJS!Rgb2<6`$_94%x>8Gmlngc(qK}ysWAc+$fXbkdox+JV2Y2DLqSTL|=A?aLW&aKI$`h0$b6azl6;8sJ52$%Q~ zQhexP$*qPIEw1t-q}UNqms<@flH~Ctq_{G+9=94&l&M|6l9YnhH$yQu&|y|US7_Kw z;otXEg@LNV#nh@(86(Y)yeUPYbpx)oWYI>)lak`ik31zDS9wxW)bVS` zv6d8fzUN6vk!Q@C9BWCj=R3ZXY#m~d6~|gq{P~I}B}JgnMv98>HF1Z;g3%oIV`$~Q z*Y$UhRCupRRY;6c=hMdA$V9=m2`4fZX^!wAqZkv{luOMhy0}|&A)~lr{T3H8iYR$} z$S9U1zRjg(6h&sd!-b6E$H-=!$XMiPuH-^SG2;h5WE3qLv`|!hGv{c;2^J~J&QZRH zd4-RlRBUdH5G`ABpb-U?d>R%NHpr!+c<{Ge8j1uXZDjTh#enT{X-NI%tz_1QbnhjX zh7|v+TpH54b8DH6qS?uExiqBjV!1S=?8r8Xil6Ct{={WD+6F;|S0*bXFsl2Vwp@sy zZyrQU;Y;Kbk;ZSxCnA;iYbU#pNasuB6Oq!d$tNPM4{R^HX{7dT@`*_APk9iraeYh& z*-azOua{3ms<*LK2wf{$oO~|Y(yu6+48sZ^0V~hYsPcL82t;AK90I25ucZ@^nhT^8 zkcw+`l-!A=-qz9yNVP7~2}rHJ(g{eV3DOBjotxwkFjamjoq*K%n{)zFp_N@FbMP16 zv7s&}w{`?cg>&$#kQmkJ&5ukJ=I|n8sy)Dmj1+u_4;iVsQztGbfRwG{Lq;m!#)pg) ze}NAfso$zImp-FNFqRh?iwYa~kWqyAnGYF7iveA#6fKN*43?d($AhE_(V}7!W3<@E zk4zMP;YG%xMRj{F&7^2y&xeeng_aK)MT^aR$S7J|6ho$-&rLTZrCc%H zkW^vcO@AT3Y$s=T*{M)1_BPRe5Q3lKsUvo0{-koU?{Of+TgS>Gto&zes&&_o=+cah z@|z={L=>9zkXaKZ%T4k~NTTjNWz~e_+TuM~BqZHm<<#S3Ak72}%0hUb09?-uLB^ zkkmK#mQ@p40Qc%6i-bZzqrS38C>*qR)?d~tOMs(s(@ih}ffm{p%Mt%CFvn#rspdun z_v*)iMiiFGr(r5Cl1oE69^GGNqe#hT<ivVro?MpusXJaC5Fa z3Z~@W6FUz4I zl{yZW(GXJT4p87FzZJ{u<=>k62S(+j+s|eFvXN1h#jcW#Md8O05{;P>zaA;cm^8TG zO_DLGZ`1pdj7fJ3M@cd!#l^WxGA6BsjFx0fDjV-1$(Zytbc{q}rmXH`B^i^ZT6;<| zCN(wuKq1&wrl!)Da$ozf3PWUR6Qhz^OEndRkUH2 zjdE)Ks;EU_@T;L_G7NeZ)FjchuY#K7d+}9JleDcSz5)*+*^hb^)D#k?y$Wgy7sp=( zHH8v$uUF95w6N>^DyS(0MZOAZ3Qw0nU11`?-qO+^0m%nfQq_Vn^fXdQFcXDQrkk;l zG22u#3I~@=H6y7v^)|6>Bx65Q%}An|rkaubEPPC?BuOjLR5OyzZ>F2Ek+++#iIpUG zk2TedT=@+(mSrj$X-nVo%O2}1{VLcfVKOKN%A+tUWC1TKQP|0ciYe)99#o{RJRVe} zxTid*NQG_uIGjOJ<}e;qq}E^_RHWdIJg7+3r}$7YrRVXWBK23F#NiB5MCb~t?iIZyZYHW-GtL2l3!WFqBO!>|HWi^L1KT{qFsl7xV3F&-{ zMpko3;k)ILkhW_F$f^mcdVxF=(sPkq5~k#SfwG!I8r~$2gw)$7sFLxV-D4C4^%{Q~ z`QPLD8cxv`RB{O~D!f22m`kmgs&zc5NZY4*P?5qrhHz*g>3k^?=`L~+38 zW7$L$1?-|^6HyGXkCshD5y0*f*+iuO`Z2PJNc~|`WD}A06Q*(?V#=QqE1QUPuZ@#U zM5@0Mk4H4BCfd^XUwo5L<#18j(5Ui%i>-qK8sN^CeoCWR?b`X3MArY4e6W3Z~B3IWlTN`mB{KgMt)#85I30lUe1D*?G@Z2t(!57?nGl zC!Hwl;z!36eTf$xsr!u-PJKs8cjZM#s*mGEM-gBXFFJ|_r+Lv)WcZsG9Yu+j^EjPZ zS}vQ&i;kklTwZh(Ns2+&x3UmW*<8EXe7uH0E{QRUMDZgNg>$^fSOjUkfJ-weekAiD zqv%m*A(xs_>zjA2Ny?Z5DB9CPj^l<&4#8&Z7Zl`?5a>)YkiFqQXRC9^gLeaodGW&5wj?J!kWcIid5 z|H0UVB%-vjQPuU=$R-hmwsJ|BqMhWCkepp@RhI95N54tX1H8Z1P_scOC zg?rM?nM$44Nvu5SGfk>FDbsen#G{iY7f3ZHHQteGPC6X2L1N`ef$OE3llE$Flz4QS zPe)2MC%ye3)tr{ZKjRzH}_X-axQu3fJ92!Wf-pqrF6y7L}L#;^d^Y~D)@%AwfDvAQb zwsL47MT8rms&Eh;fmpy^nB`LDO=s@g^wWUy14_l_#z^4LgGLmhfylON?rGLhgP816H(J|#W-p;A96aiGc=qM6=%ZrX8LcJZF z8cUI394|VG5UY66QKTs5MMn{%<4#U}N3(*Nyyz%`Wb&e;NYZ0hC9{SX!$aA5LLw+C zoHbNVVT>Rfc~OZ%1|KRGIWF;_qNq{AgNh0Cblk2;g0;aC6F z;V5Db`Qkrn9Yxj8{;R`L?l)iBKGYp-i7#gE>%XC=;c)C#z0gI@6r4vw$d?cNKqMq|X$$da^Y_@a)icC4u z2`JWB9g^GxiXIcB6Hq)zl|#T3en&b1X}0@e$$da7oC5;fnpFNG4O5{S`Buftu{ofr zaIL3mG)9HiKf;j?uh`;8$J9HQ7aeIij~5*&+arTh-;vHY@uDNuKj1}2F`(yBPK~9A zFq;=0#fR_t(XnXp-Z4&%rPvYAi;f~moiFh)q&uFQQsY$vrC*%utY0lw<7yE5Eu|>D zz>{4i_Ah7M_#+Sv=RstQCR6wlio!acge;h8CLfVhvH7h2$>p+~oNlTr|K&g9zR_Qzkz#68N}OB@ zQP?7nf~n`M917CWJvkJls8;7>bSG(Rgd7S|S(F?K(%VKk6r{X7ITWNpt8Zm=Cyi;n z29_(V^Z8XX~v|r2H#0)GpTHhG-J}&3aQ3yocmRpF=?vBc}Z<1HTl8V zt}E@jT0Hp8g9 zsYXWC2;WOK76lKf#!NX|q#2WTnq8DsZBox#X~v|V>X#%PnG`f#nlWkU2WiHnBGqL{ z)g~R~Ni}9la{EEjkx5HmNi!xjh5v}Ow0vO<#Ji)|Z^qNh)BUio!I~(0s}%cJgR3ne z!gWv#lt*Dy+VP(_QHjFlpSe&m6>5IrKt-BN`IQ3|DfGc_9H>aIO|EdDBK3Ox!GVgj z?0l626)8LG8V4%U`I9^@R7~})u5+NG7|^bO0~JMt$v3ccQ@)&sVB9TxjNMX%E4We& zjp{!pk3bZDmP5dleqTBP>HCdh$$dbo?k1gpw5*a&U>JX;6Oe9Gr4x`^Pe~^rjoy(% zz?9kSrsUH|dh9QqfK-?S0=x3XhXwsS5Q>j4&n+HuH3N(=7-2uc1C_1#(m3=U=oHa@<>R%W2(t& z4ykvWJQ7lG)9SKnLh22WM?&iTMIH&Mx1X7;=8$@q$|E85-j+u~>P@ckT15+5FFtEf z_V{}R1TGbgzt105D4W2j;x}q?Argf?JcyW@{pAypqSwhMB2^d4Cn9CHt|hy(N!`Bk ziAdpVJP&T*1yX)G^#va z9)TzvlS9B%{X{wesrfx~$$da7j*?D5>OCNxfK>aJbOKVVgN5WiAeBy*PC)A1C5M2` zlW$5VAT@Tdl-viTLJbHixGp^gb6y=P%GUGBoBeJ9MFrQTt3qK^=2>1;qVOjlDyG&3 zbvZPUblaB)6)8A^2bE!l%!7(loyUWU^xd=`hi)gOkK{o`nxDsqimCq`4=RcSuh-|$ zSB8iHDuwlEf3?!tZHO{Z9i{Zs>XafrhpBZDYMq^;Y5uCYd9&B&El<0?Vw%2G-mV#i z3pZblOHjOh?Z_ea=jVUB{>6s8BTEYB?qh#`b68O3j;y(QqfnjJK&fcyqSmqRI=cJ# z2W1`!3sVOv{W6c}l)mZ^rMuy<*8PK25mc*Cl}@EZ8CD~WuNHMu4p%Ar2W4*6Gy7(4 z_0?oxnnG{2l6&Ay>@ti-oejdQLuaoEEIh{R0U?P z&pwLU;53Ws5K*fP&0e0lBTyAh6;ua>WbRN#hw4;5+K9~c?1Q&T?;U~JyX+MGUDT>T zQ4^t2>)->%CgIeLL4WGJ)fzDz&5F>5DBVyFMaW+?>M-p0Q~Rm?gX|OoT-0IyDsN4Y z27SaFhI&L5tf30Aj#39{*+~giO%7L!=pFK{Fj39A2fd?ZG?`n&R6eMUT8aJ@bt;Xh z4hDsxUYTk5)>m(9=;BaqxK8P#7Kw$?sO=Pk^e2ca1EMzSAeFaPr;65SL!O^B6^Jz8 z_3`nCIrh+G)GQ4B_pCl+uf{Ker(R9?{A%KwtBLq`7W){#_G&`>)%ee@#>HPvTyQlp z@oK^z=EVu=`0KUw)V!pnc{5XScCIEYygqGx-t2>{aQxD%@kg)5FK6d=Z1L(ZlttU7 z7p*(^g2UfTPGkPQB~DrN`GTT#+m*$8mldUMFWP)WS)8!Fc*WM6OO~;}7B87yG;dnb z`qj$fX`71IExEa5t5G4&W23SYvZg~My3EfbL$pEaN!ba^H=@;Iq)Hd93em7G2-K)W z{9Wk_>4@q{a2b^JQHN-tpx!u_Dx3nGNP}Oi*eO7nQfJXe`@%^Kd*LJo=d8(1$T>tJ z%h?S{B`9-_{#s?UuTC4FE+u`a_66ztlIA1TA-+uUOlJMH!J*-Z zwfZgyQ>uc(lxnnJ%|d}%gjx{&>=eV`Fr~yF9;R11e2W=ktnfudP)`omgzB}$Dy0d= z(X=|vBm@!mS3^{=Q+PZN0nw0dxCj|DcSQX04L6(%M3JC2TAi;ZL?x=3{t;f8kE??< znQ1t=bXve`JW+Ov;iW=?o;4a`@YN~}wPbN6h%xCK%yt-~CRnAfCG!Jgs6d?Z&tDan zm$aJ2g3|g|UQNi*M*=85O|SS=7C90QAb8+!80$9b!v#KXMsT3BPUXrD6dxAPSyeoH z)6MCtl*NbUbP0uVUR z%wSE{av$bOzB=qgho}RX!1Vp1GB_0mi^#BO7C5pGA<+0{C#Yb^qDnXmzs~|lc$mJA zaoY7F@>MB=GuOirLf{(OV675X%oQ}qGW5<6Y&dBww%92aD9Q>Y=@_h!AqKD@a)5;h zeJn`N*@w`OJ2y8eXSXp%9Lr6{K%YQ^x{}3`LkL4N@i`vfVz6hihQ|G)IiKeoRpx-3 zg&CB|$Vq3VUy4R{3U^mD6W)-yKg654f7V(SR5U?>to>?H8K{a1QDw2vq76d43{(b& z2L&N{V7q07o~%6~c8U+&L)AVSKa8nLF)9@QB8%|T1hJ1uU061w@`DVS3$n}t2~e1b z%tJ4Wp30E$Fqqq78yYx?ZP>^6^q-)o{N$N=J69B>#^>At-Nt%C%#w z5u=b=awA$pLc(ZQUpqJ_?`SeR(6qe<&TWhH z*C!ROU-JTInbl;BJ|4QPx#5UV=z%CEVGP;XyKI%nIdlji7-51{0f=^pA=G>oeAJl8 zge${?v@9GNt6t_|>=Yr+A(PbJh&e2uaY6LZu>KCQRr+FB41tg09O)>!z1YV}WOJcv z4aNbTs6?L0vgI%>&VEQG$BP`mx(#R6N2LtX;&dVehA|&k=`grNXj#U=nl>q1rSnzk zke%U=VWHtjgIFoVre|%<{Jd18tmMFx-9t0C>Rk$nl+mleh?@9AykW}BbxL)JPCZEz zChE{+Rj4jAEev6`RI?Fr4K8^@Sw$ce10@a&1fK?giKq`@r-^Q`%>i9r)irIX0Ik3yqcKAf^gzz@JD1`uEdTo`}Tc&d+i*Jv2-Vl4AiN!SF#k1Ng^~z6R6MGFqW%A zF(@KiV`_+2(K*vb;v06t49T6b4KGQ-@X=1;^MY@_;FpNb5%5uccCJ5T%sDbY4>NjV z=9bKjhD4sFfaM&;c$%gua+V@Ke*v&O5WzJ)=UDC>W$rY5a}dcO;k}5lVqJJpcyM@# zuZjsc1j7#EwXfP2vDQb80Idy+LT_V2tWO{jU(`Vwov6{3!%wYLI5;bjq==>Few2gg z19&(DPE-3*Q$a*ZWQ*4hr97JoA`Cx^%}5V1jVM^3#$sceXGJJucs3Qhc60^`=BH23 z`*bHO*v(xX9ij@RWG{Qyv-pTz%#`%`Vg`a7vc}*S=85WH#qa@aP#ca`utdlZ0x7{W zM8|(m`;=IuVA&!@y;3pJPVpWiViPQk>X|!`;~@m$L+Pm>asxJ^u?2=wlfYiaS{U*; zgQ;P{hqy&KAsY_Mn*8+|fUxWX57ihlw-+aQNI;CaAM(VqrhEg-n(}QiCTbKyN=^A* zO!+YRiz`Uo!p=mG(lb0`PR4?Qags+F8>WFR(ehClBPULC?eZK!?*fj!Nn5Uoz_tBmx=7~atx zzKbsngR~keGy@8bEzVoHrf~Y)>lr)q;*QYtt>D0}yra`_UTK^l!~CWD|2&eMw|hq3 zv5f0WHnWAAxLJkk53l%V5CSPS_CS6C+HW0FyHqZr12IZ&k*G><8fGLg+bGze#+M2tu2%)q*|10u~K%502g%xW{gN?G10o1&7Mmr$crd*;pv9sJYfCH#Luwa{6$9TkI3^MyJ7s_Unv%h9(8qL8w$_P? zhcOeq^RT~!8B(pxt#*nJM`=W@4%$>1+GuPcYZ;4x%q8Dv%S^0Al=ft%8CrzzCR3aA z-1z=kyF|=7C$p3X*^O~#nZIRDe$xEBxJ}4k;I+?^7x<3e{)MzgAGctK1uMgf*0!sO zOZD^8Ei7k>--YRCLF%Vh<&d-969O<1eRfh<;-j)vPV$YSFSV35X>k_dG$=|w z;m>@6of>T!-bY!D-uuFXFzFE}7u#@wyQS%}zqAZIU2 zX>w;7k{^7LLGw@j?2^q_Q7QwePGef&g#X)-`y2A3AYToe2SZ`r>_R~17L53Tuna`b z9|c-)V)1^ET0|t)p#Zic!tv3dehS){@V6*PIe?|F{G?9{b{<9iHI#Z5j9FA{!Pdr( zE@fr(!PQXaS)^rU96rq45r$=PWr*5ai;)s)izqLSMiGIX;@wfSO&xPBeC2ag5`P~QWJ~`CDz>4N;;;-*rkTD4%E*th6?IGy~fu< z_|$PP1`kD7GI~k-yD@i3FJ89k#-80p3CsSy^xVTu>y1$WiAT7%G8~nPM3!QZHKyv% z1~DdUnxupqyP_-lFmr3Lz9-b^2(&D$%swO`8rtTOvlgCz7@j}VsIYXs!$WA#ryQkK zhig6Ms?I?BF10?YEI}Bi1uEvzNPjU|P(`V9NKNb%lS0BLJ@;sR03JMgwA)0tQ6oJ+ z=;bepp*=fw>SEu`t~37YLh^ZDz|O;cz^GonxDcWV8IK8r&Z4%S&(3fXo|pXp1HII@ z|KD}b;^<2~^Z#D=|2q2r5LBh0+Ib`!bV4vi!cdBPF*?#bGE{}@eQXiln=R8~62N9C zY@TVSaG)i1%1y4N@1TqYD>HPR5BW*nrWLs0SGbr>BlC9Yr-j|fh{jxIq)%bUh%9ia z@7awUo!G>2ADeb6J{qd_Me3^0XOPMu#qf>L255Ygf%+@?ooG&oEZDGIPHW}fnHi!X z{ZWTRDI<=rdo~K|r;@>jb@p(@2v?TAVI2muX*F8;{Qi)RV==Sq=%!NXuu6`3HJc?N z3o4Z%=~JOeYJFxzlfC}#Y#oWMv_DIVbjt7$Em9U-0n#roB0ch9H=3}nMplTT&$1o; zOwUf?>A_A4mNbKKRTfh?W~R~U?J~DAGySwqi@OCdi_6@Gh3sb(n5bbj8#6UF?PHht zUYyz@*BkOIZwlAX2tqX-aCK1|8j8FQD@Xb&VT#A@%6Z|O_n|!MYWx;s)})^qRG2}@rgs(@fz=MTVi$TuWw zI(iKk^57}Bcc$aBd6u1`NjVvYvV|fdXARbDFGguDt))8Fau zi8b7p(~%}DO5CsGhs)r&dBIN6*hxPgVm(ydi{u=Gt_fE6{{O#l?}IFbK5K5n^ya4u z4>G1CSlBVHylK5fB)3?4!-8dyR)wqgla#HTLql;HPSt9>-kkn5^?VtlEu*=$H;+euCcb?lxZOm7iq^hai@4%gw9CoFv-rublK zAj(d0L{S*GqTtxfyxHptGBPTx9+v*DPuq`6s8sga;grIyd-7(d(H(jD>ki_Ut-OpS zc}L>%w#>;(+MSoNC~wwW`ci-Y*9I2$494VX?jevCMC=Z4=*d& zxrv4#HcITJv!MUey7`Dv6sGd#?J77jD{uPd3LB)nc6c+*4bimxl+6VTmXZ}!GVkb` z>l@>*Z&-__L2 z;tU-F98JTpx`#i|WFG6E7@%VI+#U><7;1tL12Z#%q5Nmo5!vh2xC&yt#$39l z`XROq$Fjw8JG-|A!4(;THhZ}`1S_Z@R{3H`!Yz2q)xr9Js}%#Iu=L?(o#8GuN^UG+{3qzo?cLw4~9ZjP|xr24g(}^}{N#CYbF6v%51GRk$D4h6BU& z2O7XueeieIPIf;;2)l1Enq4ao!NR)Ady-lg?x)5*4!;CbQb%Tnb_H|hV_d$%a5t~AeYj^@F3d-bv( z?3wPV>8@x^^$1mo=(?&dqN@rCRZFERi4wZZNKJPKnE?cOiR_FFsLZahApr>lD$pGY zBtV4(NJt=oP=XM$D`DngyvAtxGJf@-OhCX|_F7){qy77T-`@M26B(IEH9cd`GF@Fo zWW+i9oU_l~-}V3fzjoJWBAQ7OVDf;*CvAqZRFoZ)inKmaDuYg8(}ww%AY|3>3(&zs zq{c>?$VGd+I*<21l^!qT>q+qkX^+hm_A6;O;FJo8@#?@m2xE1fr)v_mO2-me?Qb<| zt;T10ZA$VeKg%-_a5rHu5P?g3vL3#)bPIzl&Rc3DdRMaWlEnYNGQV$(wdt2$C0U~n z7FZ{I9z$gwJ_j&xgb4av4?{BW*-LM{bz$8{m(GB3{zw6LFr(`a8RCHOI)Je^4V$p( z!n!RN#y4Nwb_N-0-#>X_9B|m-3*$!&zwicMUVahyDVH4=asm9pI)eYN^L=@0lG)jH z6?EQFitYc4Y_2B}&P=iX=XMK<4YZ-c$15+NCY*m|Vr%8fuMb{(Y9iRN*LG~U`pV(T zmFJ(ovUl^f4M)MOetL4NG69&erImVR$9CDeU3OscdONPZbl8`Z2KaR1=#^s=l~3P0 ze09S+mW2qB$oC@Xb<<6YnggRCB{1caAXVVM6lV0~KznSo)z?tQ0O;9ReT<|T;I&=@ zPmrGhW6{3Oa#iZJHF9?65GHo{Y({DJ4;q}-#wk6zqM}`%`!1+9%|3*W?R7m^?5{ilEBJmCP1`S-#A%kJs|&`<$;!Mhwe!rcO>2Cv)q# zK;6b6O+@)Y8jhzcEu7$ibzM6lp)_Its*J%Ni~J5S8X>2Z#5WWpIVC-S@=6~PE}sx; zQgsiyDL~ics3vrC{LWW`X&WH&{OM|TA$z1Y>}ec8GcGL4vGEpQ$GKKdWpwg%AC>_b zi$3)9FexSn;8-fDXYzEVZ}LRn`5OCWamNf|1o zs)VQns)J>xz#p0YVE@=-LpweG(mpxeuZI#N@eU^`Uf=BIeLQrhUtse(trjf8VC z#PaxCSNEbxQrh?LKiq1si2}MZraQ!@1dZ?qcmKSnzul;ih2=#6RuSe!cjnbQx1ImB zfypS^@okxaC|dm5M=btS#`6zs5*w9PTxkZ}1nk9A{=-EW1vrP)I1CJdV3Mzi?NFER zSk3-Rf4M+BKACuWdfWDk`%mc={+_?n>7C=3-rO>^<)i$Ud4|Af+8aK%DHhrc*2kL5 zs61%`e5~LtjIC~G^Y7#J)++$6R@9c&F{Z(WN#f(OQf)I(@kOw@DZ7_D`Q!V+%d=1g zb4RX|oORn7dk1iu*28c=Ip;sQ|CZWvp*vA&LxkyiL2|C9dL~7|K)Gmfs7wiP2P^)5 zJP8am;GkT+9y8k5UD#~4Mu>6xTjp_Ph5#5?PdJMz7(Q&0U9s<=<|P!i?7A@ioaX53 zSM6n2$n#gO9C}^=_5*9R2(CS|n?Ldzma9)C4gQCBa@zwkLc}(kuh`bt zz9)y-^?%>-H*yB80B^p2t>H0!u>jCSW9n-exA|uHLILD^i~U^K>c1CmA8bV`!qXVl z?AG%Be%nUob#`E2^+12?vvNDx(fG8?I|l@ojgugmVQxRt-gR+c_`|Klyv zMz)y>ud&%Yna@;K}kE9Qy#%xbpC9~UefSg?EL0QU-?sKqW^roN4Wop8Qw zbTaq~5#=wpn*FKI0a5zyvc3S&REXo=MU|;%w_e=5X?pizP1iTm=`-~J$Ga++an_>8 z@a$J1=@<^Q67F*W*d8MKA1Z8Kv3S1An8CBV220B0;Xku*`w|Oa+gOSN2-l87Zqp#= z-2@_9PM}V9Sgu~sw*5i-Ac##)0&uTpKh77S74|iHs}wi)B$hhX z>%z2NRocVT;(f-EcuhIlT<)q#D=QN!Dlmo!NH0VduNkO?Kb;Iz-AAs_k{k=(q4tdg z|KsK5FZC9cSr>Sxye;ljpsRAJPxlRTcS#4jBy=cvKz+)iVZ19xw^72g;p*NEUH8?G z!@jCCcoQR|%Nv;c#5)@T+O}2^%nzQ8RtHA%D3Ju9a$}O11pLVY6g29e#y2R?T1^+% zKbp4S6$Cv?V8g{~S>ygq*rq3B^-6+HAZ8J<{4rtBCAS&R2#bW3X}T9ZY$kS6&gYL} zP(K+&FX-kv;+3-K~4R3I53c&^qrOmTTOIP|D1O0|OBHoV`WjcNUGZKR` z$OVMxkIXuZ8~&%Gi-UFdwdz-Y_jfA%UjSNkJ)$!I{^nw{4{nSTL}qCQZ_Lk)_4EI+ z{q^+)QO)1m`~6D#BWQ{5R~{ET!F~17rIp7W+}m23-M%0>afnCGN`Ja)4`(^~0w+4m zdujIVH2fUbO4)p!Xt3|4*>@Kpg;VVs7v%PE1Pk9h?syprGMoNq2jKBvFN{7+Z4;XRUA=MEi{yfphWW~QiPgJxxZOxH#qwav+vK?e^& zSUIszFp@yV^`+T@1=u4vtFBJN{FYQKL)=y1rm$0q(Y>enZ7i5eu@)350~eGmQJ&Io zk7H6Nb_*_`UoobS68xns)7 zf)*j^H`H8xb{A%2ALb#sKJr$8WZOfQ2aMzx=Z*|ivjq#=Eee}f5@k}6|2>WV<#+{H z65#jA6R@@TW5qJUC6Vg_+o|2MvIfeWK#@?sjB8#SZCn1zs&YM(HPYmwWUr0=Lvc@h z@2Gs=5^4g|0y>9`5*DtKwc46IK6%=q5uWGTEKvgIbxbhU`kpu_c zIC$l`y)$VruD${~X2Ooxw&CiowO0;oHzWDwiK|a;D8!KNd~~#TxZT%YRcVd&P>eo# z?A&;Bjqom%miHL91x4zkt&u)nt}Out?MM0SY!~M?;PBwd`K7L`qm7uw0y?0Y}0ukIn8XyH#IzaXL)_%CXss*@Tq)O`hTGU3tz z0<@#GF$GSY31O(eHrm4DBP2^0$#!pJkTBGMgEizk&-`*(lPfmymYs0HH}>7rJI)XT zQr+98!@h?<`Dowtx+7o+3{UWsHvGn8QyWiw^1+K~&liu>;<)qjz9VTE-`DCH3P?XRMS2sPdW&a z_-0h;Z?DBeeh7&uXiTtB{#RIlmK>KK70Rx! z9D{O4Zuge`S6<_{PWGM7gNq@{6t{jD&Wv4a;JF}f(L~~q?u&DX5#W+%lp+_%m*T6- zzb14Koe`1X#$bmSdid_2H-MOiQ`{y%&R1$Clu%&6C=~FW?T8jjUr@=81<_~x8IfWq zggc#cXLF}0GSUnC5<^5qNqF?)*-=T75%nONEd6zizp2eu`Yh1!aL`83ntz5o>5n3Z zyk!3hMO0NognOR!pD$PCmv(RO$E?lP4%L8brKVsQxP*=7y|{AfF(G815tQ z3N4k1uWD9BWK@0{zn$KDdg}DHqV>^fZge}oXo0w*%T10y?KC;g?&A5*?dz)#myHh| zTK7Z=XFJ^`ar$l+2T}ic$Nm@vBV$3*P$(mcYi7udXmcQ1{N!c@SWUZ!gh|qGW@Qu% zh;B9q9B$#_@m{dol06|aLW~V&SFjAzwc-oN?l+DsSg^n^ti3P}@y)TR522*P48Xd` z!3)>39AfR^J+s&WR}O5tw(c;y`0B5YM{b4Pr>!UvgW{R(R2+5~3O}0LP*~&7LXBaC z(AwB&U#&tBJ;XQ8w-6r?nkT&q5-4WWWBc}-p};n^H$yr-?$+Xa7_;~A;Pnj!EPyV? z!Mn-}$E~RNTmEvsy|Ae2%@)Y@J+*qIR0r5rKw`-fahJ&iSh%>>Ql>K)kp_wt$X%u( zmOjuE3L+|qa6yxC+n3eBlfb{!=WZ3EyI7^w2)mJB$JMiH!-+7)*=)fo=d-zz; z`zZJk(S+fk1$sPkFAq=dURDQ!C7`+@=Th&{(r*bXOq`rdWOvO@Y#oa{aNwcV$J*fD zP~8-!Gr<^SWLO8A1Cq?lzAHhwhiJ|LQ=rrm&e+YlhF6By7^$!z*vXG9sWn;+7#ndI zFlb0z^xo1&`-E2_-9wRc$N{QKvAc3Fdls0m_h>PMd@!RHZWM7%!VQo|1F9?@g3AU4 zoJkSb&mDfa--ypC)Q>%C5(EFJtl@vSR1Wjq@ z>#w8jz8K#@#C&Oi=Tey@u=AJ zt-G5`GdoEdWNG%hipoZHQTnAcvP;^f*?;!|E1Y~^tg$IrP;sE z?saCmB91C&)C_O{0)~Mdsam;rITAAd2{w#8o+o(gy$E0I{K%sO&=}ne*$AW^MCu%e zmXMAHw-#fb4MF`h!ET1ukzJ07muMBPjh=6zGId78H2XD{*F_6+H1kNAC-|{W#LrY_ z)5AuYdVPHQmEF_3-|)jY2BTI{Pb|&Ua{endjgWZ{i{z-Zq}d{ALX<(R`JN0 z*>bR=%A;S={Vv_k#6a#j?@Q(BX_$&YhXuM-9lKK!K`44h$Bd4@PC4ag$kHpU-&?M+{M2B zaINgAo5JoA*G>T=NS($?3tSUu!VC?pJJ_*5^NNgW53GqgP~#+B*3Ax;@}I>_NM*&b%*TlC@J?e(;PNf`^FP z5T#Il6&z42kkK|&Jl=1onmrjNqlAVGbfXHo=fq?2E%bo$hS+Bbg$05kQHv3wB$Yw1 zc$2393K=2oZTeM1$**Im@^Jo$`kooaeoyix#prB$>_XV@k?7G(z<|s4Be{#~-hwW$ zyiIxv^S*nnOf}mYmqmnh8bv561B^&YBbZB|e@0X+qAO>GRC%o3VGWjZoCyEDGI)y$ zR0;=CgGW$_0pw1^K>}F`-^7BEz$(e5^64m4z<|7=G$-)3rAs5MXFX51ln5+K_jsG3 z*>1rp5y6${M#%Fl?{EJ+?vj5Kbx>Ft5fBvDhN3dm2}M2A!@6ZA`2Wn01D4E6!FotX8a7hbi8W3CMTi| za~-6(Di>C5Wi|WPH@Ucud`%FNN8aJ_607h`(2`Z6lvpw&fKvg~e4KS#%aaRipW42O9FX5!sFo=aYrcs}Ls7)rvvbQOEX4~2)luf2>N;%ktn1!hs^BgXtu=1k(#zHMkHCvbKp@diuq6YWg6$+{%2^CP6E^ZV=T-j`+(z+kT+~^RetHjU| z4Tb)9Ql6niR7)aYJDz;SUXNRY&3690lIp*5qX$+yDp}MSq4_K7? zs3=+-&vwFi&Q7%6;UVqJesx!=W?xyP?l#su#YbewbXbXgUcqC(c&C*SyP$NjHD>FG za!+V^;sfT$Ep<3Kxx+N=XKZWmwb<66+yW&|VA5!+G_k8yvu`rp{><`m^j=gu2`)?0 z)bU)Au`oibFQ@#s@4XqgpGu1w@w1I z5g_CNOOX+0a7YV~v;#W4rWDtTfC{#!csL+C>i1%ah?i8l1Hx=dq7(!{FImyRV0(ZJ zN%p9R3h?ut=g8w4a6e4%ebVC?Q~OVf3U}KZv@e?4{${?tVshxx+O5=5gyIGcTVj;GqrxBIB{*ruoW5a;5!`b8u>IQ0*5I zPJ_Ue#7dGXH(I;|`lWCooL8=q+=tuD0j&)Wk&I-R@Xi%a)GG<3JW+A6i>)<6Bt;CQNB+jjiQ)6dK9 zFNizKZ(TXCm0wA29TYj#p`)QxBxS$W=D*^ts2^0JmTn*z;VcQKzfFd>lXAj~dmB!s zs?2$>RQfg7jM4{bXYZJdbXYrasv#X88SSTiP|S#VZx>QPq#s$0Do{6gY=fmj(3RCO zz?fPf3IO$T1tI8=r1_EwD^lyRM$Zk|vEemF%&f}H%?#y-xF}Plidc1{5$GAKVqdAq zW@}Z>Dg*ow(@vJ>M=~%Cm&Z>9`dwLt?_e%b%c8yn;yTyIwJHkq>TZ>qC$6iIYD>1P z3R)Nr;GR_#sw;tRff|@p0CRpKdvqcBF-n#J;9)i~DJ!Y9Tn-agtp&n`%@h!~no^WE zrW4ZzlWzZQB-Z*dV#cW6b8N1Xa7d|s`qC+h_S-j{y4{T&_kQPUIAwLq9W7bnNS+Lz&(>#(1M_B8SRSbCQq!r_YDz++++_$MS8O$o|aPqL`S9W^J+AOU>pC4|An2T+<^)^&H9dAn9VBt53&8! zk60OoU$hu5fP67l*lc&M3-*@Q!hb;Br~drT27o$qISj$y*=%Z{OLHomK5IdR$2DNy znMs*$P4N1bgxp)mgGH7c#r@Z;6o@+5iY+%K4Y6omOvtyPffcy*UREUVQcA50)!L&T zzmv^KV=Cam%7c~KQ(+1^T^i!2BeUk_r!U?jv6=+c&wOApZN3fkSiMu-a^wm=Bur%- zh~b$MQyOpclRjP`G_#BQk=anGep_5$$WXLqf{e3bDh=wHZKS?xa>HT2jVtybIg?m5+njk-I9d`>ne%CZN3tZ$fLHQHcLk;|axR|1DWrQk z&Mo$1h=~?15UIOLM`Jt1RLkhyDSFkxeTCtQY?a-|g9OLPnpi1i5(MlVDHr%aW3HuR z;7F>~P8Gv4Ad9?I;y1`0XwxEbaT4mfMJA#pGh}4?TpQN$bw&xkab)w+(9+_ON(C_ zv^%ls^vG;wdLZh_yJn?0V*08OL0nN{_kr9hC@HMlb=ksxyb?qRt?3AP)Q~Q5a}x!} z2?>)-?OAB>v%J5yLY;gRz8F@k(bVGyz%HfpA_PrCfawd{RbLwkMEot#2vxJesg3I{ zy*=S7>GG=^rnWsZHL*TLHP9c<6bes78aQ$g`AOpI{AkD2FZZOAykQVQkjuMi6GbEF z{X|cuK6*)7t54TE_>P_W^5wnTr#5c7xbrl9o|F1=l?Aax_v^ikseXBU1J`qH2Wg8` zTJd5BcTSz$ql@jy9#%=|xlPLNr^Y5_qDM!HW) z0$>!YN6(!hyRPoi8UYGGD)A`6OG=Pns1;>#Y}g)H*rGnNHjl|(Zl&peC%YTy{D~E+ z%kx;sy+v^^7R*PevRK9)8lR0hNkDHyd!qXQJh;*ntqu_wgn$t%4dbNZ_-a@o9)LyI zV#X9Vj?Hipv?+3fLchw*9Sh@TEFbaZPz6O#NChgA+RdKL7K?8XyFEN(axyHAXt$~! zN380=kP%uN;rpR!3=hDBLgWA$B4~054Y@=OBDcao15g23O&}^IPGu+_5^rV4?Mlb! zrbM*SsW7FK!t`-VlZX7C*f<@^luk%osTV3oV~otzs_iquBNEGYykE=x%dv~M!;r>d z8UIf2+2_o9E!B!@RdZzfo-huGdl3}*(<+7?Iw+Bh(ymw7hgL~WWu*4qp*IgqM#BvZ zdd5Z)!A>eY8>F zDRD(UW!H{;Ob0TtF1@tl+SWp#shGOnLF!n|#IL=y$$E@OC7j+~n3w`<`AJ$o&CG>g zIriSwUE4)u4##7m{nNGQw_bT=$EWX4IM4ZptG{}_D+|=_?6LaT8iMc0q>^e!Z@X?+ z%%11iUf##tEas}M_g%&Y}YI*QNftz1-ppzl<+QYOuIT`v?7i*LHeU1?%wu=0toOiy+*lrmwHK)N5d^AR zECZP%D*yqF09;#ENADyNCaXhnJrg_C>`pnrW!G1|ls7+(S33RcwbOfEo8EC`YWwRX zU#7Nio!+pm!>o`-Uoic~tNDRpya4oMBu<_F<)%+gZF1Wn*a##bsy2|Uv@zYj6eT-lVh793&9ZB|*i z4cq1Pa&jWgWf+Y0%43A38v`_DU7;p}{BgTq9=xBzcx4Jp|J)5GZS+oDQhCQc;%V%C?=L zqprQU2{od$$F-fHrQiwJadpdEVj0}ApMtI>L&LQ-y<^1MVbwM1u66B`;3U6-=~$B2?Xt$s;(uB|aKtw@6&_3x8+|t%CG}CPbc$N(qw)OQP%Ck?bor z2WV(m@MA0FS!7i;`_6*}?s$^16yuuV&kmN=J*&Kdd-cIU(QYv#ooe%AwS9#%I|NHL zyQMspBL3(m7J!Cy?B=+Yv1UP#V(fal;C;`1V)aJ4awhMNZoATY!_O`zThzk?w;;c8)!x9}9b?n%(BxpkOM<*a+oqT>ZqD3T~at zm^Xqo?rS&b_5ydLibwM1-r>MAPq_1+9DdKe<;}fspQE`q%hszJ)Gydv@Sw4J8rcJP zi?kwk)t;-jcjexalO03AA+W58N84AkA9#am{%dRV%BwW8?X|mjHG;fZpqBOMu^3x1J02g2vk8RzX zAq5tqtR+=P!Ysn71!>BAds{5j7;a0;Ki?mY#0AECsNCE8JAUg4GRsp-7s;=|8FhGV z?z6;MTZQWW{^#uJo#x#31u^aOfBRj%JDiO36YSD|YGmJ116KAK!+M2=-X1yZ$1%4q z-fw3fZFe+M!>L=HJPdrCe;eZzGnrg{iu$eGOUrG9?)F$kX*C7k)uH!TsTji>j?W7iCyu;#(XF2JQo_ufg-b_X^P>W!DwdC>Tamtd zuH#-`PST}xmz8-?(@j73Qp##9l7YW5Q~1Mjd4#8zL3J9gv1#rP5pZZTr1V82pp10b?^@r)PbAn9~D z)D`OfXNfX`^5&PqXjUy&s0VXI*ts)U28WU@K$ob0m38IXjceAt8Vtrnx(f?XSf&HG=j6BOt|X8_JRaxWKwF07aDctFdpR zn8)c}Vm_BtfEw(TJGyfq)CjRMDsH*B2e`-nwmMRv6F3asLQ4|*4VQ|tN(x82Rc&YV zG%0JCc!qDQOde93K&yz;^BC4Fij@K&R`4=cf>@|}3MLT`3ylH=w>AXTnu zKJU-m)J?z6&8fV0U5s14IrY)*3+r}R2(*O1BLrH=YKEXH%f5)noAEpb?AvGe10avC zJI@fqWu&6AF9cJKpTdt>_hyda>nK_3^nQ43uNn6O`-vV~-GUTPULC9j(jxR8_`s}0cIiRc(IDluCV?v2$!vVjoW=XSxz zbM7?IT!!izkR=M$Jq?_f5xH?iX>Uz!FI7J@GK$Bo@NP9bmxP|exlW8tP|6rjgUl0( zQ8GelUEPK^q#&S#b?F;}te0&v`L66T*>D5EjSv?rb-Yjo^hOJ%Ih`-BKEUYKVoY^5 zGDE!Jw2)KQt*LN8yG$L@XXco*|KXDhA9kv(kktU@>cTi-m@9+RmTK`{JzcT>Tav0m7*;a`A2z zL$Ro{8U=;sI%R;T+TGA#!2CZ8Ws7DpJ>fJ8SDN0G zCef&tn8+*liEb6f6os5~Lo;fH85)?!Y!5)UAPvx+8hmHEKuzW3+Lo6Q>o-cDDi|8(6m?*Hi-*UYpamz37JGnHw{(*tE z{ma)IvB1;r!NPkN{X$+Hc`b__rn+T|-xlcEZ@u2gZkC8B{IgHMzl$TUJ6Dlb{ktXm z?l0XEYyTpdb${901V`q^Z2szuNWFS*FVjH?_ZN4$A*G5qKW0&#b1dx+>pFogqfYGqsGr8?qK4zY^EV;zlyq_f4(A>UfwxFAP)ZHEI zD7jLM=$2U=r_ePgPb~b=qk@CTrS+`dOxGj((!$SR#%Fh&f7ViOYF-0VULM^14AyV< zhuzG@WC>E6slcydGI1$U{zUXKnzYr*ouhd2M(=?W5^FO-J1J)z7I-{W$b!Jtsd(f= zqN{!KREqnt=wdHB0|brVYQdz!3CC~fyw=o zdm1Y&kmj|SY%_WSj^R9-1m_aA0`uR%a1A_gjploEz! zojfC1)X<(-)pDd(1RJUh1YYpjf^7(b78x&mV?uJER38kjnuod10##4A0hS3Ip>g@h zQElT(GIno$c(5^fkhpeyph5^tE6#aD)rtToHny*>W=roT0c5CzM2Qmy5cpTIBbKTK zhj5Dl9uj{HOPVNDPA2M)+kXpOHY#?C)0Mq61D>F|%A7j5Q%rQD0FSIMa1N_afv?99 z0$RWR!uUIe=bIq2S&lO4N~++DO%2O&oE3qPCB;e#-Mg-g1BE+Ypn&m?#o{1$UgE3o z(fDw0p~}-`m{oaNPsE(oC0ptVq8P)V<|d%sf_MYr8pud^J5zb)-p9O>+iYpMYkU}qXa8xhbLcu0% z7+g|Ofa7F;w|S;lzzUb{xwC&BfJ1|_DxTd~8QifBlH0*$L~#{!XI_e}aD%s>7i!X; z)(44YoirjVGMNv`JO5W1{0iQG0W5%Y0%{=0_m*SPf%?F{Z>TDAqrV+T;+*|>mCs5X ziB3B}e2JdXRLXem*5_bGJe9d3x%k0ONT0}Thcc^!Tc%EJQwAs|x;sj^IMNeZ9+Iuh zdB;vYI2%b~V7Lj-kczrGuHZ^AFqiO~jEsMtxz@V)-s>V^Jo5zKqw8GhrObQBo%>Bn9lO_J&V2RbX z!$=QZ=%MsniL1C5PA05?ZhVP(Qf>x8VcnU+J;7E^w2>dWd9G)_*(Xc@MYi_OoS9LY zFI3ri8t~@gZoGLWW#i{zNc`WkXqYGiCs8B4kF2q@ok1?p*P$@FSek^LFq0!uM^3(_ z#w0CE#}VxQ4E%_5&4^v5_`F^Lk$CV3DwIeWmBhky33P~dVuu+euA|ff#UEMgv{;5< zlmrBZjO60S9L&GnZW$t0+>XCqLHu;fC~Muuzl1*TI3v!k_!eLn4va7nl~yPmR({ z7j-;OweqlGcu0&E*v2p~gMU=bev{}A0hJcG4?WRWu<`2S^`1SR`# zPj^_F6ya`jz5_ z0#iCQ@*Eat$f{t{4RPzDV=OT>ehz}e|1I<0L`qQ>l!!;+1kvF8f-CC^Wx!>M@}_fh z941G^^^mlZ6Ud;S2d*PnyxbPK5;+yibMV{q8Ls=gUHc}LU6_=-2pU=cv_&YFm$eIrAqgC26CwXCM!F8o89B7P!xIuk>X0F12 zyim2zvTR}rWbzJGOoNfIl6F_s?2o)a*`2Sh1~i>ED6LyC1V$3?aX1c1kb3^1Qp%4Q36y4A6I zY^uh^I5q~#E+EQ{Hzljq*vaW5-dynBLz+Vc;U=Yi5u}^#bqrCOIXdmM0#a< z`))ce<07Y!c5vxq7{c;295r=xOY-zPk@oXuN80x>mCcn94*(XOd@HNot$Y26#1X4; zma>@)cw5;7C#tIc@9CtRDJTW*5(e+=l zJP#*ZpC#@_dcLwT`YDj+SfK*5uTAgQECoKiGOTSD%zO3IcOk9YT*9#x%*Gi&_b>Z{ z&H{8-)op96O@D(1!NNcJOwjhBdJA3$JcDX>_xaC>WskHOg#FG~6cRm6iN-=OjM5rf-uP-^;ISvo7cfQ~NMTdH`s(cY%I`Xt)On>A*CV;j7 z&hndj>!nMFUeO_c{8+8GzKSIjk`U=Vg zX7w4(k0)BpK0eqQJ1#{_*R{&pjz&I=OF794;@rBozwoB_j6z)8m z=d0}Mi^sbV%M?(O)ofnihtZ=r3Xuee-HjS{X>B#24A<(qtvDY{gpTt0h$|{ihdTQH z$l})TAo<|(qZhBOm=9!~VW*{fY4U^{Ekj6zS!lBfubC^Xt=rBXMJ5!{VfewA%3K{B zm@r_86omy{bEv4c7aRD@(KQ77|Q2=CqWj;>lzQnWoTQ$nZzPEZ1R1lmRTNUQ|KA1RUA+$;2DU zfI?w;(_HWDof10P{E$2uKQ(=1+tk`E2`g~PdUt!H*OW!c?no&LI5~!?vNddrVF6-S zMN$o_z@-`EnO=SkIgENABngFZzCV?5-bLFB$AaQT%dPu*ktMc@9D5+jGtKz@ZUJ#4 zVMisRALCu*#k%wiQu5Ry=GAOr3@)o>ju{8ajBAGbl_^&-f4T#L&MIB(S*err8D7*i zILiZ#)ZjX*Va#H@g<)(}S|ww11==DSbC7}FIkkO5M;$L2?$8%|-P@_d?i}II?5zM2otD_=#+z%-ZnXI!k{0I_ zz7{pgRGZCSh11-V0fxU|W_XEL5mHYn9`42zZQ0(-W{O2LN_N&VtX5Jy`Z`B6?9Hq#)RbBi6&f8&~^s=n|30 zh6Eq8K!HH~Bw2xR`}SjFhUBh#E+x`TYZ5efm?D%hlE3dVWVYO|R%{)YQjIA&>bX~n z3BBZS?ogZRm_OXzF<`dTuai2xb-f6EZ^(8-eTWI^CL_LD~h2SUZHeHc5d!ctj_)Eh0U+Ky z3|rHPz>z{Gsk&~c4KxY^N;;EqOjr`KfzWb#+jfAfXpHGi?_c_87aWAEt5$D)ypwAeg z>Jhq{oOOSz4^wn?Yot8{JL57;m*&W7;#Ug)ExOO}B?JMb18VK%JOE)p5mp&V%$@bY z_6Q_n9Hj#QQ7A}wCkV^Q{UewHphyvN-@2a|CN=OqjS({WSV;iutkz4Vy=^+M4>yd( zJWNH893ny$i|@b1L*djAiso4M=V}V+E!NXgw|Iqdto*n%inFkE+Zb?1M)JGK2doK zlOnA1aMAN&6H%ZDuyj7C$Wr)YC(^k33W;H)+TPbHS9WYSzCdGnGOmp)hn^SD(}A@L z4y7o%sG!OnFc#d&j11t?8LtM4)OyF&SE=}*xd#2G64O4iC=JR>F|3;-YI@PjD^^Kcx|+kK#Hj`Q1l0@*?o}CY1=$`3T&ObeV=^r8sPBh7mi+ja$ASb z7Y71RYa{V*97>yQp$21X*PrxjRw8+ z>8VVf8g8zxpWBpN3BFrRsC4o}ZOQf=W8RA$2NNHtYx!t!@mc$5?ZAcYmi8lFp=GTG zzgM~0XX@tLDmU8`>O*|Qn`t-kQ)-Px#A=)pJtAW3WjHjE4kET6+rhSoeD>DnxT(AD z2iyrWfKGMiQT@0`U9~_%!@%oXdh*b3_RcZLf`S_h~X7t>Q}oAE7`{x@?#J01|SN{l5Rf?q0x zGGahtgRl7KT|8BnDDTbj7!OQ7dG?(?oX=j(Omaml1C2h^2f|{RP+Q82heS4M?8fjM z10Kmd`m8We9(~qd=;J1#X<1TTe&}hTCRfe+LuLM*?M8oZW&V=Ufn`k`pZSZ2n?v9q zrIzk0y25|@ARskJzPk+N7q85JB-CAez52E4SF;;;T=mJnF~?Sob7NJ6y?SF+^xTjY zzxzA6JU0n`V^!Q(6~A+1Rgg07Flzq8mld}wyRZz~iARI_5JylfhKgwhD6O#_+LytU z(r+Mu!e1W!FO^rl_~a)aoWNz9+Cy>hVW$|BllPT)ibeGO6pETWz+X7{86EuX$0qmD z=CD`QMb5+Lk$0+*^1`8gmDM>ppN~%KVg*QQEsEqIPT*k0g6tnZV7~L>IZW7#Y3v)t zQSSc945m4o8Vr0v3`4X#OpFMb@eK=MbH4yR`|dKnHw9Dz;Tr?kK(+SIW2~BACl3j# z%m*m>L=zXI*ui41X5Y9Mmb}Qh7VZRSmg3TW|D^kH+5DS$^?UsT^{G^#CI+)vDhx`; zyzMU`aGmiI7KEX$CGM{rb05CLJ@abSKq02s%a%=7wm_wQ$GKlc3NG@spw`yFpKYO9 z!^Qg(h*H~JFlW`GW?Iey49E{87A${on}3U?rupY92>YUIhnFnA`>y#h7OE`X?f2WgrGVrh3jjp%*>?sAR)Q?HK&6FS z2%*%L@r`Jh6mbcK+H5J<{{nN zC&h0zk!;gRcLjn?r|P%+?He%~iDi=?if54bsTxzm`KCWb{2%KEdGep!Ex;}jP$EYn z>nFyD3%9DyNMheta{caMB2$7k@>eRU$5+#ru``ZhoBh>nNu0+>$lqJ1v-IR!mWvu{ zs5Lx$fmesaAOa@e7~ysF5L^LJ z=ZyOrjlVqwn-{&SXL_v1XF5c&&p@Dz1TU?r>2S|*y*4t$x2jk#aV}P~{+Y@63+taV z?(EG48hwj|(pGrcFe#?D>6R@>h}64_W)l2=Q+< zR`A~t0%xD}iSL6Df!3`4N<@@L=EdKL@|lF~6x=5oO)#xZn5FQV!S1OA=ei8SQ1H7-Sxq$s z{_B{EcCv~+@t~B3NlT~Gn%Hyd!n)UJ5GlIVwd?%iokC1(sk_lnCE@euG10s`UM%Km z3Nk0qk}B#e>*DB+K!oAfNuVPWO$QKPZ$+Eq{)g5y>A<1AM!q6nT)_Y-=9UdaMBX^9 zuKxD2V1(F=+tRxKE_G5%#1>&d)QL|s=0}*;;>*@cD;OreK33H=;lDV)4;k^kay~A3 zQWaPjI)-v3h)xsWg=n&r??pCwSy-oml5$ANWRZ-rP;n4h)$IP5l4a3_`?frhJ#TK; zAdE)p12Sx#kJ4w|#220UqS!(r-M1v5jz|-tKan&8GGEpZwWUs=m$!ht8^*Y0eb#^8 z)8A$))=<{qx=;p=z;OXPc(<=b7duJb(DG1O*k3+-dFOs)6@WC5g-EKY{lDS^EffVR zI{flcV4Ux ztR7T?kqJ~5!`3urJln$q^fW?Rk@h9$hS{{N-YD8iN*X6?2`&O!3HGeSMNzWK$pwPV z^p`ny9dV%~un_?9VkjqP2wn(piYB&XYXt@yX!cSn5DTniVBz8D&7oG2DY9Y8EsRzs z@V~^7q*Z?#ncJqNpT;^UKT^hzUBn23R!knEYJRvOSR=pK=q#E-7r^fJ)snE-s2lJn z8EQo;E*_qHdSal>GaR`YbFuxFGoXvID@Q=aXw zTzO$D8L-_~cLJo`Te-S(E#%9XX;)7k=YI`$x#74a#W2RkNs+yL{ObC30mPFt31zFJ zL1tK15u-0-s?P50sjsT6VJ-K_6>C|3g?@NyX2fdl8IwyU`nbtsOyWRImYWqSW2LPb z?V}ydnD%?@j5i{gtK4@GyQt(v#dSBJbzz)8Lp3OY;M}Xw&s&HF_J3Mk0A`T2tggf& zl)asucV^=EEwL3urZVOe>KGSt=0IXF)C6-8l7)XO*2V4}gGEbR0+8{%S+T2}mCSx@ zjqBb=sH*cVM~2eVQw;S>5H(!!{AoYPQ*2x)if`51TE;#$%{^Mp{@l%uBqRIV!+q?a zl>jg%4~PMw?QJZSMKsCVTU!Z1LT!vyx~kd7j_+fmh_;WN$!0DWc`RH!j0LR5aDyyx zOI#4Ise^lg`YrUBR&LBhtQ^XjKIHt%JKmjs>(!aABXTx$TR3zoHBHaH6y3sgG-O~$ zfQcy{6}p?>`&ez6x^`pN(E)B4#0sA%7~D5T_(l?vw_a~a3`$H&EV}z>{a$lpP@LNL zE@Hawh87fY)@~^(f?ygJsUUgwo|QyP@CZ7DVZm_(2Dwr)b(mnzqI(C1=ow{rm@r{Z zVVKVq0ff~xAOealh(zCiWc$9m2Zko!KwMZim^kf-O{_WPBAd)Rqd-TLMl=DG2+8++8V30;AfQ}8Er=$0&sG9@{NC9!g^CJ@v`*a1eXt|^R7 zwe>!kG4vWBX_1S`^><&()hs#cBC z(dB_4cd4s(5HfidKKhZK+Q)>;UBphA@ty86V_Eau9-fRMRx9?Zs5k=zk0HeAou(M< zPw&+-(ps!9XPc-yVYJs}P!K#qX-mh$zlI${Fb+G-z5)ktpr2BF>29|6^p?Y@zfUGk z;o@C-PyQgLl7Ev-GB?96uRl1o=?R5-PrrZ(m4}kQDpdas6^#{uvE`f_!0sVhMM?rY z-IG~ol1PpE~DCdQ*Z6K{Nk&he1w%mOASHx zW{M=Nbzb^~2x7)joZ2?d8}ID*=n%hRV2iHBK|H;FVO?1;J$Uu##MOOAuWZK*D!7dD z1+Tuk@#+&#U)}Id!v3Z56v2qFpiZn6J~>LPB%mI6c+J>~{;b z(e`h{y2u69OWFD7b7|xetPYnD>&W^us;?veQNu?Sqo@oecL1%I!Az*I+BP8O)JS2% zJWd%&?SQ;)VUowC1GS9qXgPfSvy`z((Sy%;k*U+8?!714BnLP zZRWvDin)N+GqPNdcF#{BgByf8j19-@Ul^XRa&zaS-yGUSa!`zm2QFFIty)al5AG%w zzpNiRO*37>&EV;E&LIkBmnNL6m^hvIu(H%e zrEp%iD|2g#h(~T$e|cQ`(HJ4J02J+V%3K22E;H{Uyg5;3ycI*+Go-|iAV@Uv0>|4(E?n!Osii{0e7toff<@M2-&ww4Hc9bOtCB}+ye+o{@ z42FWp%QwNv|#vyDR(``NAG!~T==J~^`m!b}_8*a9967cd^`sXgyg3BVvz zN4E)W{J|@iU)*we?^_HNt{S3AmcFJx-zCE)PwhWLDO_P>iIlZj?h=7B?pfJ{qI#fR ziVvlHb_xrH%aHZ3A~T#NKK3{1AJ-?otyMTc=g!dnecxDpHJ%nG&s+RKtnTd7eNE`z z2WvQ2aq|9|JgFstmYNVz^r*zIV{gbq950W%T=brg>=4W*X(hfAhK}@j= zM5$mpR2K2T)B$paXTWfm!u;dZ2qTvdSsrpNA*}Eq<})6;l_;1IWWV&PN#VC+tnAI0 zRG>g(7Uyz2ySjIKB)6s_n2NDdsE zC=g{^#Ef3Tv$&%3uI||MJ>UP;Y$KaAcS{FG&+Y1GUAJR|i|C7@nTev z(BYTnaBU2mL;{VUL(oi4?O<(ejXH;s2pzNtT8p?_r4I;m-`S09)}gpM+tI1@g(;`j z;$-~G_6YC>xp92$ta))^q~G)t!qf~)O8JqtX3JYFjnx@9ge|^ikgoq@cLz9v(Px&2 z729@oXV#Vx8AE5WZY8B7EDjf(U%AJyco)=?&nw|KLUEX!#P|4DDENtwH)4KDu^B-( zzd>^6$9b;AdWEe`f@f{m0A_J&lfthpRJ#%KkUt)5f^x?g5hCZ@o_T5BARt-%V}*C0fWK9tzT(dj8T!+fippQR1slzhact zG0$Qnr8B0V+154HG3pw zK@k6(i&dRJi$FB2T_VRTNZ2T3sY~!E;Yor6&;9U%iiweG_Fr`daOV%AzvH zslt2Zf@<+LD`YssSP#ns@BQsPtUgQpx(X;`Qno%B4foKFGwaP|zJpCF*LH27{WX<* zCrNJPL=%-OCpKK&@Uj`}TlQaj5k|2NRLa$t4$IG1JmA3EvNiv3NQd0!@RX*UCRHBm zzeCM6STdAt4nv5g9+Mt6!*nXjz6l@c4i)A77&ZF7^kuJKg1s(Cg3H9-iZbRDxu)? z+fgB2&c9!lz)F%JzyZcoV(n2OYFW)z+}9i+gCW5MkR?w9_xH9DsoHFVxHJBvPn^;h zXd@y4AYH7Q_j*7VyaBo?yKILlwMH~rW9{*M2j2^zTr;`>a4nS~+$HPcDkadJ!!gO^A z^$y3Odn&15@CSKb_(t+SbxOXt?F=?X_mtGSS%@n(WFeO051cEC9D;o1`RA|f-F$7s z(JQYX?k4!>Vz;=qW5d-~4$sJHc{zC@5;U4p=^!ujORp( zNb<9uR)}aV#N<*MvF5A)Xcvv+vE!8UijpDF!Irk zE_Kqi=vUJdzEUc+W$anf1H$>*-WyfahLL*c$VE?&JJh(Nzd_uDShYC6tY1%F$T}+? z>c=w1J(e9?;gF=4zS(w!D3$Lpg{w9_F}3Y|yAU5Q|LS>^goj9TqO~7;a61IBc8<$e zFk%bF3QFo7g|!*r(#}1Fv7CHOBR;hUj!nh3mM?C$`bJ0ED2vFuCpALlxuy2IBc7NM z@7ac1H8M!R80FIJ?LE7Tq^3axS|fm@RPE76XldRZ1W2}KOB@8Qu+vW`Pe5wfRQf(448`q-X`OVQ?P`I@6*J$D)X57TX~ZpxCfOA{)spcco)Oq3y8cE50k$| zN@6Z()!N` zxMHxXLPQI1#3sEf#A7WZ$3aJK{2k;%_T@~NAgOl*}#vQ^m}U&*TSW+1rKtI2vw3L zs2L1HE%xH$+dZgF2#0DWXfij#iPuGC{ns5z2z}woDnJ|LiF|NjJ&il?M8pjeUiQ>h zj5(kVPnm)-w7guDCoYWtIx*Qr&18Kf*F9&+NgNe&l22PEbEnq$SW+?xVj3V>a1$Jv zxccGlEBp4^0t-PbD3I_=l#`4J$i#UUoe)r5n@B>wvPq;QLbX2inmI9hcYk{9y@H-; z5tXV#EmG6=I^EwO6}bynBq$7nS?RUI8F_BJrmUk5AR9T{9P1qug3CKK?4m)S_(=vD zm4CDLl{@~;+Lu`Yy#Oz;g=gZmey$gcGlc9)3tK@YC5-ZyY`q%N;`X=eLEP|meWA0Q zxt8+DV%d00>n$wrE*P)FN^b^am$(bww=mNQoD^d>5DGtaMKA}(w1aenLP-3hlTKQO z67&{164m~Qn9mxxi@fh+n0CEIf}A5U`9;5Io4)58RlRCOBTA@rW&-${^&b z^~Q#SK^U)RHmAZ^=1MhjrCPjXgP6r@hC{2_b6IDtk|{DrhQOyz_5{!_YD*4H)NX7% zJScZ}B0Sl5YtVZ>#>B*>12H3$&P~Z404D^$G^~$b7(9DAD^@~scz88$-`_+>$9#SF6aDi`(7`)0L7$Qq9|*()}ELnrrzjF>D$$`){*S3~kwH zWdMZ;%Qgj8QlpkNj?P=XkGNQ?wz3^qZM+SeYz;$ij?x=V$U1lE(5^#ZPQ-rWE?@$= zhjIB~+1Xv^&KQNNQyS(`I=7uL3_FN)!V%nwU-R6NYIZ&&k4CaeYS(8Ug#NgiPl zkW3B<`SY{Tyi7T#C3g4tkAoxNaQa7BrKoEZM!n*^h$-VV9A3bDOH(ntaVVxHYGwr3 z%AMSgHnL|ZdZD_QE-r<>lE|)lP58y#NQ@3_H9MEK9Fr@oBC3%Pq4tO8bb@=SV2?H- zFa=@XLvu6Kd5c^hge5dZsN4lh3|2W~-I21#+8FxR}PlW zDB$z^CjEABY9mZbZ@S2gAa&*TsEe4In7|4OLaF2W9ZvnhsUv5mKH41yDBM5CmG4_F zx>xjg!BC9e{`1TmfLWpr+veJi38m*8XJtsO2*k?mDLDGe)r5K6_S1Kdmg2Tyb;X3C zMRhgmr|*7v^;bs?*mZPAc+_OMg@mE!4qrHaWy?ufUEEn7OHMbF>WBXOEPDAdL`+ba z4W8id(ce!cMq@Q`zbV1jGn)7Kf)y?-W&|30d2E!F9;HS_D~|5ECZx}93}r{*y?P&B z*=U$@m=Ypj>?3`5;CV8o) zgHqxa%B2`5%FbiFd>eVGREkE}hEa6ecRh!5w1Wym(7UVna_M#Arq5owX~v)xRe6Xz z{!T29q##%`%Lx5OA_5Klpe{vB{RA=&IPF=D=d)3?`Z`jiIAY z&!`qZ8ZKNY^is#+Eo3hPn{?#ZoS6d!c;_e{gC(m<%r6vJ!9u5q5K_^R>881rcdOZd zligP%<4gimTwY`z5L7E1nFq>8IN^Z8D+lpETM=sIP7)Jgomvhxn6ABs5b7m#5@fr- za#yW|_>1lbCOtwXep_0ub%Oroy0V{?ZC)9iPD*D28m#1ORrDAiI(VenBt~jE`D!Iw z;I^nElrh7cwJ-$t3&r$P@4q&+@%>;)?mr1ZgB8NGH^Y5$_7iD`yL5KvXk@jzj+Rd_|x?>@1 z)W#ZfgEuIj8Q4Rvgz|^*6fiEg@+GIC0HaxM1;rH>G@F*EudL? zy<*=GEfM_!Tzs%L3=*0s1TW)frI!KbIe}I5s*NJi@}Ksqm4#njM>*IsB7kOa7MXBh z(^)}UK-Fy1EY8itT6!hCAaZf<@#)QLac^Rj)j66irn)3q=E>~d9|xX`0)Uw5?hRK@?$B8=mYNDT zBA`R%H+^U);C8D(*~wN;D{W?7KY|L=+c-!@1A5!ys=>OZd?T(2`S?I(*n(u8^F&)* z493E1+mP)S7DGo3D-`N- zkJRng*wpDCVRn){~9 z*Eah=SNBGATzl@bEBU31+L{4ko2SBa=g+3LbF_FWJeU18(zGjkznZ1lx5D6wh^q37 zk^Tj(+&hI@ z1Lsui>Ezb5r2dzkxZC5KQVAcvEqnRUv5Uu#x>4-5vyS~vV(TU;5n4F~)7W%C_X1%B z92a;WCj|&2&`*iMdZOeu-hBORt3C*N5$dbA;lkL#Nv16kY*A*TxDlk@#>qaK5gTA$ z23j|R*Q0*WfW;FD4%1mS>)l@A7B^p zDsg6Ht?`G|!5}vwC#x){Erop_M6FbEHT%bxUVq}^t{0>BbE^w?k?nGE^Cn0W$&6^1 z=(wpPZ>Hm{@+2Lk6veBjb=+47{nv*k-#WLiUQtyD9;0pqi=6*2Cjh+0ZVXF=SNMqE zY>S&6;AYuRMN`V-?6o#Eufvu5hRK#!vu{3FR{=wf*cGP7;N&UJlkx7)?e+B_XhT~d ze`xmXgLabA$2bWXg@+0!sSZN~{T7ZcV5<@f;@`>c3bWT?ZCqHtT@Dwn*?O?3$1c9` zhUN{^W#XynT|_@g=oajcZ-qe$sG)Z^T-^)E^xaKF1E!FE@>|ly17j-BcB?f$%k781MRdQs@YG@@3GL-d+2nzCEijj z(3HtF5tx(M6%L91v0x7ndOWTj8N zR#?YhUEFSoz&?2o@+h>TL8kEpNKZ;F+sjBj>!=26;j1+NN?Kw1mj^FX-n;4O^zNsp zp4vCH^WfCU6W&~9YTGkY6YI53zch99$*I>~f*zE^r?x-y$!QoupXS(4CSJd|^YkYl z8uj39TFtaaj>bRvCS**!4Zn##i6%;-DD$4&%|@fOf~qN%1PVpl${SHuN>5u=Jn7*A z2NCX@~DJR?2wG6cW?Lk1WgzSf=6p`?QySWQt^91h$C9i0XUpJ;4bbeF6+5ns% zF3tJ6_B|KI-?Q+8?Fk|dWgWt{ut)|;2=WuJ+0GDi*VM+tl)05Q$~UiW*nNeq@zVBk zr2N`56KY5fQQ)z?gxAITD*_vq*lWiMJjM!n^)jIBbHT6K|nPQ5kt)1}J{lNxzm zIK#>y)1;zXbaYQ`KGl#9m=e(DFgAuz|D4NjbKn&QRfyMii2|tXru7gw2;~f7jNc&n zvwjNLGbZfW7udBuZK^#G=6L7y31_F$dgO?-18mCs#>(L)< z5Ma;uJoM1wc}s4MuZ1sr>vFP)S^+2%s|O%EnqyY(S15dBB|s^|d|Ce$H=JqD!ot#} zASD2$LpNqCZ6^0Xq=h}%W+M`g3W0!u#)_3AhH@rJKx@klna2yn?@-vW4?p;mZtVe$ z+q>EvUZJakjqYWc5sGWk<;03PwOE%}R!}Jdy2rt((a)0R=oV`>gji!p-wtrCwj~SM z`X~V^+yUFZD`J{rvCA*NLeMlM2a3G`(S%;g{mH2(y4;l?I<@w+uyEU7pW3uDVFs|> z^<wD&Kqg8bSsBrp5O7*ZQV&& zF6|juY^XC!U~Ez6Nb!V6)31H)UJ)OsZfa+rCcZ**6U*bb!-P_kN&I9`Wnt2-dG|Cs zy0Ws_3rxN?b9$@Uf0sGb8v|j9Ny_=U-|L{bZ%%i3vlLzcZdVp*O@db90W5e+q8MY{ zBQ`&x?Tym+O83jcD0cK{Avi`VH_up-H*5XrXj^~Xx+@wKLHQ0)30%0Eoy?*$4|p7# zT@NFJK8l+vHTY~M{x0O`Z_}Rw$EL?ZF%rSSKahCmbT$R@AIryA0(>(uW;An7eQYbz z9}|MT#2Vdo2zxxWh)aw6TeD6Xp6nXIfV-?l}8 zikum?DtuD{vipGDIyS!95Z%fozR>=0B4yQG0!9JICa+a1p8+Ai%(4pXNC(N+gk2jZ$(di5bp6Uv7=_QB##;@B zc@mJR-K3}SwS+?=USQreq|)JG_1%JH0$O6)Dd)!i+hr zW=FFnX7OnnZZR6IfV)JJ&a43NT{256N}@Jh_Dko%^|Lt6yfR>2#+xxXP;=;K%mYF7 zsq|}6@Rgfe{zciY8-b;XP@R==6m3w~2-fGIRcAf)0z3;7fI---eB-NMyDJ^cddA2DY*B?mw9tqsosjI8>D zXZIMj#?R8wG4jl!B-lR5p}Z~a{CS&az)H45iaQM zudl|%B8))Mft*D*cH&ITTg|6F9K6YWJu7dmRvw8Q9LXTUHo}ASnbCo1VwjfIsnqSE zIOF)xY(V$qpsrt0Q#=thDu**Ul)ULBc2&NTxwHs7Wl3P*Fnfko*K5~Ihw+3zwbwDo zb^oSdsGzt=hNH-&oa;XyqS3M27mTg)UL1o6*@rEW9uXF(G*`7GoQ8mbN4^c@k3VoY zJ+6hO)%FF+jWs z3r>z+T);=-VUz+$iU zg8LjjWhVptcGcWG6Ti*-7UcxDimObO0>>tj`c3|JBj)Wv zl8cl@$bQmM7X3spEq7F^XlXJgPAlf)oSGdj)nY{Dm2vL?8^|!*O)Fdr(L{^;$S7GrCixW zi0oRDO8}`D7=RR_TOf$EXO^5)bS)YLeY`_jxkRRo7C}b2}Hp&Qs#p(|< zMi|NhLPSA&EB6{}1oJk333QK>r(v5FAB5ot1RnPz*>2#3_{)NddSyuk04>1p;tNPE z@?B#bw8QXANSK2mt`o>ZxWzhU5aW>l_2Z}eqi9c=P!EI@@wgxl6?m*>wIr{>7_j`T z3X({#W`kWKl${~WPO;s2il}XIoK6CTwr9IAPBj=Afi8|*_E14C z7tzQutXbfSGt97_>e~2zp{~FgBZ|8M5F&i4q8cm;cKbjdSPDx)&^ED8W6QRn-thAJ zDqb|>-bU3Z^;@GuFdCoTsMaSPF;nI~t{z7q^njupgfk_CN`N>s?C(f#By!_ zU?!#5tBFV}dJ1BanP9!DaT2J5upuCmSjko}sX0dWE!gesu`8K*SspO=Ub91eD=Odo z>Q}$f`|a=CKEJ2u8{eMKU*DX+YdU{o>>IU0uUKv4&v$ZVeyg%_ zWMt@jfAS|iFxoT+h`mvP^(V6pI@|YE2Z^_4`@J$hTA<&!{i`>g_Qt!tv65%qDxYQ3 z-`KY|q?C0eN0Q98kZ#E2k~+Mhfo@nAH*BdJmLv2oH|*rOU5fvAtc#l$Ljy7&s&f}7by@Co{Z?2jjC!2fZm^FD*t#vj;-~$Kp2Zy0b@nX_tzK1fIvh<`TWp2 zt0NfTk0mVl`~}g?Pas&vzN_Hg+p!TFe#Zi#oH{CA&mZNK=&s9I=ag;;@h>xf(bEnO zklbueDWS!G??GNQjs02yS`yY96@9;d>7yM}zuXhPPist(yT5mNd_(?|uPS~2dk-ud zr14W;+B52BSF`#PgbRPUcTL}S1bI_@9&v1t(~Ds<)8dslaDFMvjW z576l78d5g#<)?@I2k9B?5fq+D_xSbm&sqdJwkh-WLldCd67o5e{Zhtex51?O?bypS z?itW_WF0G`lc&W+Q_cSPBJC6D_yrns-&W6;SJI2}*QeKV^VGWC>V$amSbmtlG=Gme z=4+4D`sm_yhU~fCp#h8(TI#QhERq7$7o-HwJ6*J3q>Sck;oiGH&abck5F4-mR-bnAk!j6T(V)xoN8iQN_0b{7T|GF)S2sK0Gfv`i=q#UW6 z3K}0z`^nS4D~2au1zbjw!EQ)nQHDJX85FqH_Av476(onnFT=>Rsv-+L(6H{G9w;sB zK(+fen5{M(Fc~pYC|#ik)xGd}K@ET%f|lJQ9(2Q zp(O^CDG1nS<$j@$>%)|Tt@9aYx=X8qle8E} z{5w&|fL=DDPl~IWJwr+MOhHg$@I(YifrZ_E>f@)?ozt;Dr!io*!txKXr|{hf3VkpB zf6zmG3!Gc>!I9nG_E>ER_{F++3f%qwu=nQiHC^lfxGkoNA%>C~;)p3BJyPSX#*hda zLW9PXs(WN|GLnfuTK7c;${-18MCP zJOdv|F;}ruX(cPwQ_>_R!$Um_->e1f#`YED?^6KFWQ&2O$VO3>o1dR2$CRKjxeTA> z?di|R_QcC&$_Ev;1||m4UBVS>fY65k^1^i>)de^nr0vjiC@X+EC=$1wh!kYcvhuC5 z$|iH?NCJ4giGOwLqSEy3oJ54GkF7{7jY;PEm~t{r42RO4pBhgT?QP;S2rc2#(&bC< z99^nb)_7xdwGYds0V~|B{4L-sAecDsDpe?yrx<97B0vU*3J$2^185t7QQ@4Ll`!SA zNc{>uZBTSRB(w$33Pvzjxn3*zu`C=EFUa%ZJaCj=HjRos1R{Ufmr=H|QCF#cSbX#o zfZpDE)R3AR9zs~Sncl!xsgm{OktIAhRc%D%n>NFcaBrYJfno+u8?ObWFO}B=I1FAA z15O#WMmaT2iKXN1F#weq4mGozR+=)2DpdR683-rc1N#rw98Ed7K@Ng4Ciy@+g|-xg z!q#9!qkYc{HD1}2z(R%ct4xV0*x1<`qv?blE)wK>Pi*M2@Qt=q;$(trRD+%M7az#`BgI0221Cmm*8lXI2@7;no1Km)ev6Ka%!gfL$1aw29eKuY$ z`I+b&Ce;&^JJC#_8{rw~{o{Kh4Yhn5K3f#|iJK96iHheK=Yx-l-a_9i4zYuWsvN(nA2)Qjk6KhT@B_L}AR>V%(S^%1q(vG17)lyxX&n&f} zU+cv+O%>=+vItfIRTo8J0y5`;3^Scmxnxbn){M&7bu~*D)W`-=PBjtEvfFAMW26>b zio(|**s4>PRK_2yNLX5t00A7NsAzHp1aMBz)fdE4HE$$xsEH0$P6twmWTyk+Q`Hx- z$~%nk5Yr%dCb$gIS~w$9gp)xvT`@(CWe+e{=ruEmjMpkarSfFe1uNS$R@eRcFpSv{hqlvz$khDA++W_1kd^3QU2AT@# z4%h`K5nR;k0qiy5avp?qeq8>c`IN(5Tk!(GLopEicTVfVq&DQQT5t#HL;N8je3ilm zWcLJMOtn(i^3S5Ui3 zFE^Buc5UT$@uE2?Hak%`gF!yeYpjrG)S6Bu0l}OJWG-@)BBPFlSq$b_=`CUVGy1j~ z){oJt09W6l^3PZ~VXbW2s{w`F@+T}|1t*5z94oJ?w|Fp(vD!JkG{MGlTs#4XMdPf*r1tK7z?Cd zHRGB*a;CEx>Dyz%;grGt4^k^w(_BShMmDFMWSRkW4(#SysYF6SCcf&JET=4DZe~)h zGs}S{7ZI@w@U0)aj_lGFFO8*4GksTR)Lu}6P4x-79N%F_MIASkJ%?gO+~`metDOlP zIusF9fu|}Tq>|LQxuSNkM=&-ZcbdkSsEk9kxCv!P^W^6WNu)Wm(q_mRRx2QssJwK2 zY1Xz9UcN7TNlhgM`NqOjRO-ztYZ2FT9JabqPNt4E%BkBpeTW!4aXN~*w zO^Sfq)gMZsBq9HG+)=e)pp~8>o|ddn_P|_QQr`sG&}v0We!NXEiG^ylDv`55ne?1X z7SZixaeTm(wx~C_p53x$pBX(0Z%t_i?98LRjg_uc8W-L_GZUes@zRA%PpcW2qLQ9q ziOAIWL88Ep5Jm@f8=~htZBSG=Omlo>a}ZY`9725Uh?ejIC-@0CQP_CO`AAEGRXrOH zVW^6*7N{S{kto>spF0LFOh`)f39VA?71jW{H#0ayu}S3#s+HpEGEQ~1Vu<`Dlpmi7 zX-hUWa)OmoD-aw=hhvo&**dHlhy#f`3}fh`LQiGLc@o@SIwvt)Os}I2Z7Qm_yT$II0+|sC=@+dXxz@E05i!If^kGTG`Z?u*^xkO4nW}CB=4_|b@)vZ3HrpPhstGu%soFO3`}w|th!sw!{Cz68ZF;IOM-kDO zODuJ`4x840=)l}aavc-G2#qOEfvY*uSGBRyNT^(WL54$X@;&a_zWI| z8O6+mU`-e)1yr49{t&gUizlwDumm83645uL zBd6>!^n-Fm5s@TEs$66DFFg`HjB3z0H8piYCU`wqU0!LWyAo0ED;B=UeF~5(70yIb zB$eegp22(oUfy7S1Exc{PJFA0B<%_28!bBKq-AF^?=PZYvgO5pLR?hsLI6*Kqdzv! zFr7dA1{AB|cb2;Z-KW|LK}ZCg*hD!87dcbKuz#`B#0^ZFmwJ0R&>l*L;t&v>$`C(U zlVzsX5Qc%HQ-A{O=i#6>iE6!wn=*8n406G@^x8YTc=n^CN@h$%NOdqW68rAd5Fv!0=V(68kru>I{2vFo-z6Bmb z+2(4!1!rKSXP42ExI`u9L03yJAAE7O4Y453#Y<6KdF*_d6Q$Z5q}v3~#yU7iuu*3Z z2a^?lkX6BmIWYG5Fu?$V z0Z~Dkl|T#vii)MGB2&XFCe|~5Vh>@%1O`hKHic7(+riu>r+=BXTU+B~Z?oZga|{Y> z1_b*;l)|dvozhAxq*39z5J+9JZxjSI=C=sd(A0u`C1(VyO++~IMb$D)LDrE0!T zK|zL!T{I+09y?!r>M#=Bw1zRKu!zMdRvo|n?Pz4k1I&hEB(Mncs3MrEeb9?BNg?-1 zF6XsMlC20J)fgElJ*$dCn%V%~okjQ!iz+v7H=AO*|yJowLM2xkoA`x39p)jgGl!#wz%c<8;XbBR40B@!upa#nrP;-zJsk-)M44J1Q2QxjBlXR(@AkW@z}p*2vC+U($}g6M_%UsXx;9L>@^kJi6x1ci>WV_ z#sC{1OV&XQB}oGmcqe$!D^~qn-I=@~s8V+9v5ZR==odVsyeg>=cvfXFrsHhYGOD(S z0QnKT889FjhL!Bp{e%Fbdc~rKF=B93=bo9lWNID*J~ocV3&BXbpE7ej9);D8gYF-CLZn=z_<`TM!5CYC`x!T0bzRL=hN(sVRu&InO z++Vz@(hyZENt_fWkT|tVFsK+zYavt))d)qU8G!bvhA2~vOeLW|l7YZc4o?jzc0eLW z^Sjn&wUUoK!Dx=iG7#dBhL2em{4LQ-63UD+!`RO%F-k3PHOCtkn~CbAmA1;b9Pqu7 zFf^JA^}Qsgr5AB@|j$R41^rtT94K@b*N70vZFgXeQ@djqi9>cT9O9rh_n%_=!@z<`?yg88}XJmpS?|C{@{P0FNEwDH1hmW_n*WZ28{XI_q z-8}qzocF;q;@4>AcNW*|W00IYv?c#OzCAYQky&UsusXABY z@UV0+S}{0P6}xIrXRC}A{AvtSwQ*1^3wC2U7FBC^OurN%CDSiOERXjPnlc)d<3d*G zVNJ&zzbi3jyy2i`$6(*fk)Ey&YU5dh-)f8GbY#P#C~i2*BxWUOq1&JA|ME2HK3oURxd}Lc0(;FK+|;HK49)n{;$9!Ne-|cV9J&uF@41nu%Dwk zujW-3Xvk_lx`Lyzr7_$@QLZjsoA)2DR%5lv?2b=|^+G1Mw;MBG$*n3+0On{4MKa%( z2%@t^!RNqmo}>;Wx3Q$}abPZhKa^pIuj)ULchW=!VyGFLf5?~WZ6N>x2P>RMle|Na zyMoYyFYpqk=lb@u*38@4zAi2kxhcOcZ_=v7yIrXQUV`zF>?yNd5>9c+Vx17xOqTKtGq)^q5aI z$zzc-pggtSLcYT)>GB$an^5I4B%8pP&BMQ_aSpQ=8SsUPge8&5cacZJ zzoNRr1oLMQm0I!q@XsScfKylk0Be$xTgX1n!<}B;DgCRu%o%(!1`5VRofW_*J)pms zh>^%H1fNHMH&#a=(gc7r2}F8}Kgy&l^$5qaT6$P`!Xrtq4&2$aMztD8aA?m4nlx-K zE29F?<{;Dspc*xY4BE^IX=$?;{`ThJ0UTmHewbs~7R28zY zg%{3CW6g%uS}S<~1*ZdC188bYdi>+bAS|>Tgs?+Q*^%BD!eIcc!Q)SCQv8)6mjwPQ z8+DxuuV7nvDV;*RBangPHL-_IuBr$pBPC-~k5!GMv>u-i^wz`YQS;y+LB=|6pcLlC z=&-NJQ6<-)u%#M|xQ!3FHT8G|@eBdD3Bv=kIm=rQqrSsw#rm#S&o)tQieJDUgX;8z z>Cn1HOuX3?edS5mQG3L!i`sQJDwAkMR9ryvaBFNzS)mDd7o*~DN25-~e%=&5@6q(Z zzuWK!m6JlUU^3i}D^X;H)sK=RxDhtLW6iLMR8drC{(a8O%X&XC}WDC-)M@N0zw^1S=r=Pq`AzB zrP2aM5~d@j_UtfHH@v_FAQxZq#E?#$?+Ln+{QZEC&hM~4%E^I{rqqUz-3K7O0TMK+TvV8By0%CblQ<^{uc}C4Oa4q{mHDy- ztMQHu0GEznOP9kxl*gxWj3kQmFeGNdjfm;4)ReF#XXKcIeJE!~rHA}A`FZmxj;RMm zP?VeS*UbzM(6H#K)M}iL(!70mAc$$UTB*6n2V9X;I81lpu4u^nROZZ74q(SAKNYony!E?o2G-8^u+8?3t!0Nd zV5gz0GgHg6mIgdX*-H<)CU+$GvKX67G9FpsBU0@_Qd>GaQRBxWFW zooZ`v8W2h>k`;cv6yOYHWeng-cyz>YNOhS>iRkY#{wbD%P8vJY;b$VThbTR$9u5Ce z9tj^k;;q?4GEflC!i&Sdga?WUM(T-pU+6RCg92K_-w-v#%B-?1 z81)OsoMHK(=n=~c0=E#L0-orxw=e4)wroyFrSyda$~bUilxO6X=0bp@%8*FD`O$Dob=Zk*{KNLFm0D*SEK&BY~1tE55c~vY6WYBv23vK8F-sj zurSSQEnEy1i81=X06mhRu}Ku9hlB$Y&8xE!aD*wY1?f5-m7!!;mOZU-M2XDT5HL!C zoyZNmtFoFZ(5E(`w#vG;|o*MXtV}N5$NzCgWd03#ABtV61?< zg}D+8$>ctQ6=f)l;tlwtbkp{d*r@V7xj@#IL}$QZRJP+-={D@P2_;99k^D>k zpt!8kq&+lW#t<-qGkCHsfVV+g%Gx6(dCAx*N>bA44h*S_#!A(T zd4kR?B_+)Wk)XW-Tu^7W1V`vR8Qo|8Q7@ezTtb4s5GPQ9TG=v zsd_}*rU%WwFvb?8GI`|XsU-R;!$8ercCs}~ekv61<0PnrvB0WDekA#(2#i6es&_}w zASr$&BAE&d)cNY>&j;xu`Lb{+d;a-&eo`5Ul#%auY<4rURC-cMU<98^n9kRiamvtn zwE2?Oq?ML2f+{kD(1z5KxK>({`G?Ah6BeB$Y zOS7O;orwkokR!NWu{o=zG)yFUMneymiSJn7dpgdr|XGjjV@00rszAeJs2?Ph%8bG=NY)5Wkj8GdGNhL9{ z@RSeIN0PPDJU1Qf^O`g1Sj6zK3Wrr~?2wFJ5;>3{o5W^8@KH>E?9H-1K_FGqIzXDP z5AcPv3L6Rb-%uTxGlCS}NsbZ$@^pj)nS38PdU<^`!8;Iy%OCMQ=p#;;>iv=XY%hcx zhG^boc9sXdp6N=s-Gd7X*#y(Xm+*+9~jr@xZAxi^h zrK%ye-Aw<>qeEk)YK2>*fBm_Fm;tM5h;IddeVEaZs+IrsWuX=IQ!%Oh*T?2hX3k%I z=iCTaJr$RV(A9^9i!c)Y(RIp`{;sj-;hA+ZMiN{?M z%)$kjnmM&p1}==F@oJw0DpO$1QqmK1R4~45?6rTg&ytwa;QTJRWeFbvSEzEUrXzWzov&T579V8?QCs*Bo$}U1@^!Fs60h=C0*No*S?Wb8E-aEYmUjl$ zjwy|tM(#P-(nbV@>hKU`fYn&W446!A5z%%q*wXCeYngwL`xD97#2O{@4^j;Sz{q}y z0$sTixt94t#C(Byr3{n(?Zsdmfe{lYtQn)Tk0>5*Q|0kv#M4Vw&Q2PVz7?5k?k`?c zk(7-s^?pn?3*Z>TE^7}|#xAYMT|>!p#yl6>X*7;=Nre|oaWsi%2ZzCIfFpwUhq&aB zk)u4J(PKx7Ke9vlX$aG4rQw&iT;2z@c@fm+>_3^t*`zOvv=+ooFzK_6>N=`zOSWS% z4&?47bytKfO#NuEo zOZ1`?8QN(X%yScm1yZu@2v$(}$rUKe!t=39_AD;RUQ)7jW680j#J^^UE8mk13mTWm zz2vu{iIgTGuNpn&j-IkLpQ5L)>Sp=UI8Mq|x^vB|#!6GRF&6~Ud|8)lJApoyq#qW2 zTo#9XZuG8fSAypKV4|I@);-3sK;1hmO^OVQ2qxw;a-V^|OnwBs8l=D@qAh!py#2Kr z&g4ekeipyrv~8iY!_RC9E7%AcS#p1P`@sRFVJ!M^VzN>QqGdJ@{85xy9{*bBK!nnv zFzUK~KHOcDU}w@jt#qExRmNvVp$^e+PV1oLe`DSPo4_5kBIz5*CGwFAiZujMd;^%T zD@gMmr}d|(C~MJ;vqzALr`OmFpXfH>z0r1>NlyH~BiUy}_`^eey&(!`34U}q0Vr?0 zW}oDsOrUrtB7Os0#1XOXD7QxD5EJvAi3EHd6b@Q;tU%^ECaNw|S{v*P-e6uN&okaO zjO9RmD7^iiI$n+d@{kB-;D16R*l_VCA`uus*#A|lkyatV3$^qL^fmCkBHW{qj!C2P zGlN)Z5!Ov6GnlBRkHH|yGgd-p{jSDs7TUvm9uk_MNU zk7Vp(^islJ-ErJmK3yxukNH1YNm>}kn!`w&B6&iFx+QAjWFk!?+L4RV*iHz(&k2$ywDJsUrrRWqi zR=5I5^u3TEO&De&rkXd7pb6r1a^^9Ks0KIOj#`aVSk0BqY_nU2(`s^o@tP8Xq3c!S z3=~8LM9}T1b=9j-MC~ZqlMY!Vxb6)HN>+gG8{S05flrKM`^n=NC6H`Nuc?@YLJgJ( z91mo=e3lHXI3ZOoUTXCF5ki7LG;{VLWh-W%(X~gKtwIHMKyzQk@+FA2Ua}JO@(|$R--6tNiIv4 za%OaGW~-9$|AbtNxVVTtdKvR?5;Ya~jiL++c~zr~L{rQm%EP4xQ6q(zx?V9Aq5GYH ziS2+UNVz0v^$gH{o^Wq251VURzMmxLeG zfnIs`i~9f{qx41U@*cF-xgp33mM0mLrFtLI6TRobH47cNTlr^8$~LZ*&kzb8*Z(MT zmzH5micXjEgzfxe$+9?HQnGiKa*3i1b$3GqZFYVZY6+OC8vsSq?XW<=WDA3a6i5!luUrZ*S!A>41f0Auh2Ki-)Ieg_?(Sw}qb> z=XrAYMDU1ds30aOItu zUo}+cV=-0?t#~Ee!4@ic5V2s7Yo%Uey(6H4VDlC?m*+jrYF|d#9;%3OHJr((Ka=V zQaXy=K);&a))=y;*4pB1Na;u)xLAQ}!G)}bl4wQ=2BY4x2O=N@f;|pp0U=X-qDp;K ziEj~CGI#~PZ0aH3=vk-}0ITWJR3505JIOHpsE`92hN@-h0~m~ka2e1hL$#XsXThTb z&54vY;4#2w8qNZpa-m$PaM*%@90729B77mrNS1CqK)#Np*{B0a?iofe0taQ;vZbYI zyRi=|6!_rZ=O+ukA!-t*0FOz#wVP-tJF0x^COA+Ce1leq&xf^Jqq#dr(&6%WMT-%R za6AA!f!Zda_f4H0K+b>x2n0aD?JMm? zK<`1hA;pEl63(=EB(3x@n>cV~h5Il)fi8n_NLw@Afs(Ff0^$)w8CW#>_)D}L3Tqd- zg9e^fmA^vuBi02rm-G6lPGUu#&o0oYlA-Uqma^%I(hQm%uN1VT0WM^TgrL2v2@ zyER}4dRPKM`kC;uYBeL!NkwxHg98_A-{_s(p7F)uDdA%bgU$lO)lc@)idoN_XMS68 zACud#A7%#t6bg$Ruph$3X@;}(Dlq|>BNtpIM7PC|GxAN8r`1Xm90~9e!oV_O=^>o} za6G`L@QlbB;E$*$#xE1gogrm#A<`{~y+qY!Y%S&7N|sW_0A?fQ?nUk7v+?%g70j)i z%gYf_rWRWUY7MFu+dB%yN}`ne0ZJ1sU&hU1+2DZYl&!gU>w8g5F)f!Z2gWPDZv%~a+b0MZ6v*4i$V^eC+>Pj?}rSZYC# z4r>QRPKo`QR*qaN1sqSIei-cc)t0NV3D8ngePlh5uUtV?hCwR@JMtR=;>Eb`jm3k+ zOeG#sO`wi^&LIBaW#8De&CiPP*4H*~sknnqtOC_j0}Dq5Qud*OD!lC6=;P$ZwUkAM z=mkv_1GX?~r~|klw-6Ou@IC3AlnX{^8TyJ>nIkmK5txh{7`O!{nudfm8I{NYtDTz} ztSNFoWd68Z#bh-0Tr16HQib3vu%JnEC9hv7l5#@x^H2gZkO5mL;V}Ro4-yo{@ zi4#NpQTa~%h=@cGu;yf>P}N8j)R037uww&f6T=ZKFQO|)u-FHgQY=}3E~c6U<$F$) z9p8h}b;?G@ih9?p!mi7(*_0ms`1lft7dbM_WcMAaI*mjYCs?` z{|1B_cAHsnNwX3)5obWMU_!B&NTeNnRdjD`h)RyOG79Pz#QCg^P=6F0 z*CS=4=CyoakW|Pzt~80=A5Vw$RDg5gE}0)Z6Ri29R-o(o$L9k!h+YHBhHet$Ae+hl zD#b%9mDY9j_T?Uli6UPRVwcvc54Jtwm|&p^q{btvf#3y;RG^j&^9^xYGpyG@%{0At zfEXmBD}&J#YH$z8n~6|7pu4hkMW)}Vr#rtL+K#=>Q2^E>IW00>7xk1pZf&+Z%ft6Uy2%LhAmmATGAx4a2e`P< zpolCOB_HWRa_Z1P1!=~JaV8}KX^jvf(5uqxLOmk2*^`9}pg)M5OOrfG1Os@&3f%ds z@C!Z(T}%^+fDQS6Slk9cWsEqF%%D$zF+)rt$fCNHPPO`&%QeL4S%M~ry1a;%VCNKf zyo{h~HY^x~{7gS+d~$4v z%}7+WCmj_TcRoG{V^Q;na6>-?KtNfR94`R0HS?!|!ZZ@af-(ud4o5RnBne9(Zj5oN zr7d~1NTt=YeTM@Oj2DeSu&sw~CJ?tgVMDHULp5TkmJTI1>4PH3g&EpI=R+5g+nmM6 zKvzpHZ~4*jWD&uX-xNl{A3l_rXx~dNfgm!#&Iu!e=eQ!6ByYqbABsEskS(E#91$3T z6$Fq2SjKij!_~ut2@GK;yAp95;Y`$OOsW%0p3KXFUqE{7y&Wwoha&#PH!HQOUXly<=Pr{TM6Xi0MHylQCq(Uq{%)LY zxTa=X)motxdTV2V7%PYNu@1AquRC(unHV*&3GAhKFF|M8FpO zfin}4bPsKzdQ9z5UB$$pc$(46ODOxrQ6_OShJ-<`=U$M#s(rw8Ag)=`HVURG1Io;pKfnCmz5^98ODi_Y*YWYI^&(^kpcAzc zVOJi?tVm8oRsk!(nvEw-Ohmkoo)M2u))jC-RQ`I$BC@^iuY{?UW_%oJdtG;|OhWtw zM#8ln1aur_TNkWXeBCSpH(%IH;k11+*SE$G2qC484w9|V1T=Nz9RzAMyiH^JwK671 zUp5=^-cNO|2rg28;r2!kl*pn|cn3NN zg(abIlvpnQXr5rfzl?FejW&K0)$vpU1x7>1=uO% zOmUI@EhluE#{KXKRy-^}wfCR)B`*CLghAOHMayhAQbr2bL(Bp?NBd!@2r^)^6TwA@ zd-Y|qXrpWNB&;$_(k(m&Ri1UJoqtK%+0{LaMIfg=8gTI9DhwNHe z%291{q+`^(oGP$cM_>uEtO^zBFhe8OnuU%qhMKP!7v>;IgMl5@S@JmTAmSNR%iI{z z%)NZr#5st}4p5j-D6(d_grb$;0O!=lB4tAzp**OLe=22kcp8aGc0Jlxse-U}MRlFR z1nN3?&0z#1f++$s=tymW89XAxa26(_ugQPq*8FV(q^!O#ivfvSF@u~H`QjRo22#27! za@PQYTH%qtlwQk{W>vHVGL->1fI|XUO?fN}3d9EJh{ynKLSfgz30y4%hTmAOjEE!~ z7adV|=_#RAaK4lGQq`W0WPWQOc2Q935kRr2v8$?JR->c6k0~NsDu3Rc}yG1 zR-|q=FN|A2IY5Zsh0R` z{nB0)A3y@8zwES~58YU@hRc>L9hI*ZZWX)`_TmskK-k*G#UzNp3saJvhsPpgLU!6B z(-yaaup^1cN`aA+6&O(};(@=&-Kv#3xe$dGtOpscL{M1SwMk`^JIlUBrgT)x;^Pn7 z-PHG|E}rb-tU|fkxu^pcFqe(B#fkP<_z79o8xYFY7LRGOLWCK>y9Ga##g7pEk4DgQ`QTnU}

s0HCb|zhvuu4HkXyo61ZE5M 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%0A%Zp1 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

f@-- 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 D>RC3& diff --git a/.nuget/NuGet.targets b/.nuget/NuGet.targets deleted file mode 100644 index 3f8c37b2..00000000 --- a/.nuget/NuGet.targets +++ /dev/null @@ -1,144 +0,0 @@ - - - - $(MSBuildProjectDirectory)\..\ - - - false - - - false - - - true - - - false - - - - - - - - - - - $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) - - - - - $(SolutionDir).nuget - - - - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config - - - - $(MSBuildProjectDirectory)\packages.config - $(PackagesProjectConfig) - - - - - $(NuGetToolsPath)\NuGet.exe - @(PackageSource) - - "$(NuGetExePath)" - mono --runtime=v4.0.30319 "$(NuGetExePath)" - - $(TargetDir.Trim('\\')) - - -RequireConsent - -NonInteractive - - "$(SolutionDir) " - "$(SolutionDir)" - - - $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) - $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols - - - - RestorePackages; - $(BuildDependsOn); - - - - - $(BuildDependsOn); - BuildPackage; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/AssemblyAttributes.cs b/AssemblyAttributes.cs new file mode 100644 index 00000000..172fb628 --- /dev/null +++ b/AssemblyAttributes.cs @@ -0,0 +1,10 @@ +using System; +using System.Runtime.InteropServices; + +// Assembly-wide attributes shared by every project, linked in via +// Directory.Build.props. Everything else that used to live in +// GlobalAssemblyInfo.cs is now expressed as MSBuild properties and emitted by +// the SDK's generated assembly info. + +[assembly: ComVisible(false)] +[assembly: CLSCompliant(true)] diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..279f5d4b --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,43 @@ + + + + + + net10.0 + latest + disable + disable + false + + true + + + + + Nils Maier + SimpleDLNA + Copyright © 2012-2016 Nils Maier + en-US + 1.2.0 + 1.2.0.0 + 1.2.0.0 + 1.2 + + + + + true + $(MSBuildThisFileDirectory)sdlna.key.snk + + + + + + + + diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 00000000..e0acca5c --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,26 @@ + + + + + + true + true + + + + + + + + + + + + + + diff --git a/GlobalAssemblyInfo.cs b/GlobalAssemblyInfo.cs deleted file mode 100644 index f71fbd15..00000000 --- a/GlobalAssemblyInfo.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; - -#if DEBUG -[assembly: AssemblyConfiguration("Debug")] -#else -[assembly: AssemblyConfiguration("Release")] -#endif - -[assembly: AssemblyCompany("Nils Maier")] -[assembly: AssemblyProduct("SimpleDLNA")] -[assembly: AssemblyCopyright("Copyright © 2012-2016 Nils Maier")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.2.*")] -[assembly: AssemblyInformationalVersion("1.2")] -[assembly: NeutralResourcesLanguage("en-US")] -[assembly: CLSCompliant(true)] diff --git a/fsserver/Properties/AssemblyInfo.cs b/fsserver/Properties/AssemblyInfo.cs deleted file mode 100644 index 1b1f278c..00000000 --- a/fsserver/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("File Server class library")] -[assembly: AssemblyDescription("")] -[assembly: Guid("0c898974-f4a3-4aa9-a096-5cd8a3bdd9d5")] diff --git a/fsserver/fsserver.csproj b/fsserver/fsserver.csproj index 09bde4e6..9f2509e2 100644 --- a/fsserver/fsserver.csproj +++ b/fsserver/fsserver.csproj @@ -1,128 +1,19 @@ - - + + - Debug - AnyCPU - 8.0.30703 - 2.0 - {50E06B21-E11A-42F0-81E2-0911E771E861} - Library - Properties NMaier.SimpleDlna.FileMediaServer SimpleDlna.FileMediaServer - v4.5.1 - 512 - - - ..\ - true - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AnyCPU - false - ..\sdlna.ruleset - true - false - - - true - - - sdlna.key.snk - - - - ..\packages\log4net.2.0.5\lib\net45-full\log4net.dll - True - - - ..\packages\taglib.2.1.0.0\lib\policy.2.0.taglib-sharp.dll - True - - - - - - - - - ..\packages\taglib.2.1.0.0\lib\taglib-sharp.dll - True - - - - - Properties\GlobalAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - + - - {232A96F6-A2BF-44C8-B623-6E411F6296F2} - server - - - {EF29F98A-B8B6-4591-BA29-E71BCC308E98} - thumbs - - - {A8960A7A-887C-40D7-9632-002E94BFC830} - util - + + + - - + + + - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file + + diff --git a/fsserver/packages.config b/fsserver/packages.config deleted file mode 100644 index d909ebee..00000000 --- a/fsserver/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/fsserver/sdlna.key.snk b/fsserver/sdlna.key.snk deleted file mode 100644 index 7e30ff02411640e5807b8ad0cd32d48cb745a656..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098wMZfhN->^Nl!3Q5v`Qf>P>)O;|H|uoq zuPj4V8M{Ea1kspx>7m=~Ae!YB7=t~Qz7(eePd3*)*b-~%a=s#O%-qg-@GPL*z6kU% z_rZ(=MtAVlNt1D>hD!9B=erFs`79ybW%gd3zM6N_Iz>{qvKFQq3-ak6OzAl8eiW^5 zOmPO^+X<^b0=H&n5wTcZ@h~o%(e5cR`ANyM%ct%9+9zyuRGC)FvaweMtNrl97Qn?s zamy#uD|T9Fa{c1Xe}>8%>_pA#h$%?caA9j1AF}orjgSmyI)uGpHuDJnF1OsUd=E1f zk2K3S76+h```Oc3U-Wme{HL>gKQqG%c4rE&?-jpk?Bd~E{~Iw+B~Ie<1%V#pR@X6h zUL0C=sJ5rU`+_8=T9L8`X>Kum>Bx}^(cTRDci3P0&#SZP`)nVOm(7?_n}f*+*Mp7U zmFRHUQ!6(|%D+=Co!{Q0Z~W}FwtXwCa7kH`hx=NoeGPF&^xO(LADYK>4*RHvW)k>x z|D7R^sunBQ6`EaX1o|FX8_=_^$?&Ia*X5JrY%JL}CCd})RcW>S)I30*%)=lme~(fB zxem@c$eEzgW0%I70=#Mmb6fA5FbAk;x{*bL8hUCD9;m6A>$BHKjd@@%*%&I!(*-hm zqlVmC - - - - - - - - - - - \ No newline at end of file diff --git a/sdlna.sln b/sdlna.sln deleted file mode 100644 index 710aa9eb..00000000 --- a/sdlna.sln +++ /dev/null @@ -1,77 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sdlna", "sdlna\sdlna.csproj", "{C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "server", "server\server.csproj", "{232A96F6-A2BF-44C8-B623-6E411F6296F2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fsserver", "fsserver\fsserver.csproj", "{50E06B21-E11A-42F0-81E2-0911E771E861}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "thumbs", "thumbs\thumbs.csproj", "{EF29F98A-B8B6-4591-BA29-E71BCC308E98}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "util", "util\util.csproj", "{A8960A7A-887C-40D7-9632-002E94BFC830}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleDLNA", "SimpleDLNA\SimpleDLNA.csproj", "{9BAEFB29-C818-446B-9BB5-014E6A0CBB49}" -EndProject -Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "setup", "setup\setup.vdproj", "{3C78015C-E0A0-45BD-BE00-FEF8D1477DAE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Global", "Global", "{4710D7C1-4ADC-4D3E-BD48-3295B7573B2A}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - .gitignore = .gitignore - GlobalAssemblyInfo.cs = GlobalAssemblyInfo.cs - NgenInstaller.cs = NgenInstaller.cs - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NMaier.Windows.Forms", "NMaier.Windows.Forms\NMaier.Windows.Forms.csproj", "{56667283-EBCD-4D63-BF61-FF319CB28A0B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{31165120-9D0D-417E-A332-93CD63DDA779}" - ProjectSection(SolutionItems) = preProject - .nuget\NuGet.Config = .nuget\NuGet.Config - .nuget\NuGet.exe = .nuget\NuGet.exe - .nuget\NuGet.targets = .nuget\NuGet.targets - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}.Release|Any CPU.Build.0 = Release|Any CPU - {232A96F6-A2BF-44C8-B623-6E411F6296F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {232A96F6-A2BF-44C8-B623-6E411F6296F2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {232A96F6-A2BF-44C8-B623-6E411F6296F2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {232A96F6-A2BF-44C8-B623-6E411F6296F2}.Release|Any CPU.Build.0 = Release|Any CPU - {50E06B21-E11A-42F0-81E2-0911E771E861}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {50E06B21-E11A-42F0-81E2-0911E771E861}.Debug|Any CPU.Build.0 = Debug|Any CPU - {50E06B21-E11A-42F0-81E2-0911E771E861}.Release|Any CPU.ActiveCfg = Release|Any CPU - {50E06B21-E11A-42F0-81E2-0911E771E861}.Release|Any CPU.Build.0 = Release|Any CPU - {EF29F98A-B8B6-4591-BA29-E71BCC308E98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EF29F98A-B8B6-4591-BA29-E71BCC308E98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EF29F98A-B8B6-4591-BA29-E71BCC308E98}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EF29F98A-B8B6-4591-BA29-E71BCC308E98}.Release|Any CPU.Build.0 = Release|Any CPU - {A8960A7A-887C-40D7-9632-002E94BFC830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A8960A7A-887C-40D7-9632-002E94BFC830}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A8960A7A-887C-40D7-9632-002E94BFC830}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A8960A7A-887C-40D7-9632-002E94BFC830}.Release|Any CPU.Build.0 = Release|Any CPU - {9BAEFB29-C818-446B-9BB5-014E6A0CBB49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9BAEFB29-C818-446B-9BB5-014E6A0CBB49}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9BAEFB29-C818-446B-9BB5-014E6A0CBB49}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9BAEFB29-C818-446B-9BB5-014E6A0CBB49}.Release|Any CPU.Build.0 = Release|Any CPU - {3C78015C-E0A0-45BD-BE00-FEF8D1477DAE}.Debug|Any CPU.ActiveCfg = Debug - {3C78015C-E0A0-45BD-BE00-FEF8D1477DAE}.Release|Any CPU.ActiveCfg = Release - {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/sdlna.slnx b/sdlna.slnx new file mode 100644 index 00000000..16f63873 --- /dev/null +++ b/sdlna.slnx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sdlna/Properties/AssemblyInfo.cs b/sdlna/Properties/AssemblyInfo.cs deleted file mode 100644 index 69e2e4ea..00000000 --- a/sdlna/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("sdlna - SimpleDLNA Server")] -[assembly: AssemblyDescription("A simple, zero-config DLNA server from command line")] -[assembly: Guid("1138accb-e668-4818-ae0f-93c716907f8b")] diff --git a/sdlna/app.config b/sdlna/app.config deleted file mode 100644 index 37fee690..00000000 --- a/sdlna/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/sdlna/packages.config b/sdlna/packages.config deleted file mode 100644 index b59b9327..00000000 --- a/sdlna/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/sdlna/sdlna.csproj b/sdlna/sdlna.csproj index 5b1ea40c..98066a2e 100644 --- a/sdlna/sdlna.csproj +++ b/sdlna/sdlna.csproj @@ -1,185 +1,32 @@ - - + + - Debug - x86 - 8.0.30703 - 2.0 - {C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED} Exe - Properties NMaier.SimpleDlna sdlna - v4.5.1 - 512 - - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - ..\ - true - - - - - true - - - sdlna.key.snk - - - sdlna.ico - - - true - bin\Debug\ - DEBUG;TRACE - full - AnyCPU - bin\Debug\sdnla.exe.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - ..\sdlna.ruleset - false - - - D:\bin\ - TRACE - true - pdbonly - AnyCPU - bin\Release\sdnla.exe.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - ..\sdlna.ruleset - false - false - true - false + - - ..\packages\GetOptNet.1.2.0.0\lib\net35-Client\GetOptNet.dll - True - - - ..\packages\log4net.2.0.5\lib\net45-full\log4net.dll - True - - - - - - ..\packages\System.Data.SQLite.Core.1.0.103\lib\net451\System.Data.SQLite.dll - True - - - - - + + + - - Properties\GlobalAssemblyInfo.cs - - - NgenInstaller.cs - Component - - - - - - - - True + + + + + + + True + True Resources.resx - - - - - {50E06B21-E11A-42F0-81E2-0911E771E861} - fsserver - - - {232A96F6-A2BF-44C8-B623-6E411F6296F2} - server - - - {A8960A7A-887C-40D7-9632-002E94BFC830} - util - - - - - - - - - - - False - Microsoft .NET Framework 4 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - - - - - - + ResXFileCodeGenerator Resources.Designer.cs - Designer - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - \ No newline at end of file + + diff --git a/sdlna/sdlna.key.snk b/sdlna/sdlna.key.snk deleted file mode 100644 index 7e30ff02411640e5807b8ad0cd32d48cb745a656..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098wMZfhN->^Nl!3Q5v`Qf>P>)O;|H|uoq zuPj4V8M{Ea1kspx>7m=~Ae!YB7=t~Qz7(eePd3*)*b-~%a=s#O%-qg-@GPL*z6kU% z_rZ(=MtAVlNt1D>hD!9B=erFs`79ybW%gd3zM6N_Iz>{qvKFQq3-ak6OzAl8eiW^5 zOmPO^+X<^b0=H&n5wTcZ@h~o%(e5cR`ANyM%ct%9+9zyuRGC)FvaweMtNrl97Qn?s zamy#uD|T9Fa{c1Xe}>8%>_pA#h$%?caA9j1AF}orjgSmyI)uGpHuDJnF1OsUd=E1f zk2K3S76+h```Oc3U-Wme{HL>gKQqG%c4rE&?-jpk?Bd~E{~Iw+B~Ie<1%V#pR@X6h zUL0C=sJ5rU`+_8=T9L8`X>Kum>Bx}^(cTRDci3P0&#SZP`)nVOm(7?_n}f*+*Mp7U zmFRHUQ!6(|%D+=Co!{Q0Z~W}FwtXwCa7kH`hx=NoeGPF&^xO(LADYK>4*RHvW)k>x z|D7R^sunBQ6`EaX1o|FX8_=_^$?&Ia*X5JrY%JL}CCd})RcW>S)I30*%)=lme~(fB zxem@c$eEzgW0%I70=#Mmb6fA5FbAk;x{*bL8hUCD9;m6A>$BHKjd@@%*%&I!(*-hm zqlVmC - - - \ No newline at end of file diff --git a/server/sdlna.key.snk b/server/sdlna.key.snk deleted file mode 100644 index 7e30ff02411640e5807b8ad0cd32d48cb745a656..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098wMZfhN->^Nl!3Q5v`Qf>P>)O;|H|uoq zuPj4V8M{Ea1kspx>7m=~Ae!YB7=t~Qz7(eePd3*)*b-~%a=s#O%-qg-@GPL*z6kU% z_rZ(=MtAVlNt1D>hD!9B=erFs`79ybW%gd3zM6N_Iz>{qvKFQq3-ak6OzAl8eiW^5 zOmPO^+X<^b0=H&n5wTcZ@h~o%(e5cR`ANyM%ct%9+9zyuRGC)FvaweMtNrl97Qn?s zamy#uD|T9Fa{c1Xe}>8%>_pA#h$%?caA9j1AF}orjgSmyI)uGpHuDJnF1OsUd=E1f zk2K3S76+h```Oc3U-Wme{HL>gKQqG%c4rE&?-jpk?Bd~E{~Iw+B~Ie<1%V#pR@X6h zUL0C=sJ5rU`+_8=T9L8`X>Kum>Bx}^(cTRDci3P0&#SZP`)nVOm(7?_n}f*+*Mp7U zmFRHUQ!6(|%D+=Co!{Q0Z~W}FwtXwCa7kH`hx=NoeGPF&^xO(LADYK>4*RHvW)k>x z|D7R^sunBQ6`EaX1o|FX8_=_^$?&Ia*X5JrY%JL}CCd})RcW>S)I30*%)=lme~(fB zxem@c$eEzgW0%I70=#Mmb6fA5FbAk;x{*bL8hUCD9;m6A>$BHKjd@@%*%&I!(*-hm zqlVmC - + + - Debug - AnyCPU - 8.0.30703 - 2.0 - {232A96F6-A2BF-44C8-B623-6E411F6296F2} - Library - Properties NMaier.SimpleDlna.Server SimpleDlna.Server - v4.5.1 - 512 - - - ..\ - true - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - ..\sdlna.ruleset - false - false - - - true - - - sdlna.key.snk - - + - - ..\packages\log4net.2.0.5\lib\net45-full\log4net.dll - True - - - - - - - - - + + - - Properties\GlobalAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True + + + + + True + True Resources.resx - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ResXFileCodeGenerator Resources.Designer.cs - Designer - - - - - - - - - - - - - - - - - - - - - - {A8960A7A-887C-40D7-9632-002E94BFC830} - util - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file + + diff --git a/thumbs/Properties/AssemblyInfo.cs b/thumbs/Properties/AssemblyInfo.cs deleted file mode 100644 index 33eb9ffa..00000000 --- a/thumbs/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; -using System.Resources; - -[assembly: AssemblyTitle("Thumbnails class Library")] -[assembly: AssemblyDescription("")] -[assembly: Guid("30c07387-4349-48c5-8464-1875bf2a80ed")] \ No newline at end of file diff --git a/thumbs/packages.config b/thumbs/packages.config deleted file mode 100644 index adec12e2..00000000 --- a/thumbs/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/thumbs/sdlna.key.snk b/thumbs/sdlna.key.snk deleted file mode 100644 index 7e30ff02411640e5807b8ad0cd32d48cb745a656..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098wMZfhN->^Nl!3Q5v`Qf>P>)O;|H|uoq zuPj4V8M{Ea1kspx>7m=~Ae!YB7=t~Qz7(eePd3*)*b-~%a=s#O%-qg-@GPL*z6kU% z_rZ(=MtAVlNt1D>hD!9B=erFs`79ybW%gd3zM6N_Iz>{qvKFQq3-ak6OzAl8eiW^5 zOmPO^+X<^b0=H&n5wTcZ@h~o%(e5cR`ANyM%ct%9+9zyuRGC)FvaweMtNrl97Qn?s zamy#uD|T9Fa{c1Xe}>8%>_pA#h$%?caA9j1AF}orjgSmyI)uGpHuDJnF1OsUd=E1f zk2K3S76+h```Oc3U-Wme{HL>gKQqG%c4rE&?-jpk?Bd~E{~Iw+B~Ie<1%V#pR@X6h zUL0C=sJ5rU`+_8=T9L8`X>Kum>Bx}^(cTRDci3P0&#SZP`)nVOm(7?_n}f*+*Mp7U zmFRHUQ!6(|%D+=Co!{Q0Z~W}FwtXwCa7kH`hx=NoeGPF&^xO(LADYK>4*RHvW)k>x z|D7R^sunBQ6`EaX1o|FX8_=_^$?&Ia*X5JrY%JL}CCd})RcW>S)I30*%)=lme~(fB zxem@c$eEzgW0%I70=#Mmb6fA5FbAk;x{*bL8hUCD9;m6A>$BHKjd@@%*%&I!(*-hm zqlVmC - + + - Debug - AnyCPU - 8.0.30703 - 2.0 - {EF29F98A-B8B6-4591-BA29-E71BCC308E98} - Library - Properties NMaier.SimpleDlna.Thumbnails SimpleDlna.Thumbnails - v4.5.1 - 512 - - - ..\ - true - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - ..\sdlna.ruleset - false - - - true - - - sdlna.key.snk - - - - ..\packages\log4net.2.0.5\lib\net45-full\log4net.dll - True - - - - - - - - - - - - Properties\GlobalAssemblyInfo.cs - - - - - - - - - - - + - - {232A96F6-A2BF-44C8-B623-6E411F6296F2} - server - - - {A8960A7A-887C-40D7-9632-002E94BFC830} - util - + + + + + - - + + - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file + + diff --git a/util/App.config b/util/App.config deleted file mode 100644 index d15344d1..00000000 --- a/util/App.config +++ /dev/null @@ -1,22 +0,0 @@ - - - -

- - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/util/Properties/AssemblyInfo.cs b/util/Properties/AssemblyInfo.cs deleted file mode 100644 index bb807739..00000000 --- a/util/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("Utilities class library")] -[assembly: AssemblyDescription("")] -[assembly: Guid("bbdcc8f8-c332-409a-ab56-742997ffb7fb")] diff --git a/util/packages.config b/util/packages.config deleted file mode 100644 index 8fa0fb80..00000000 --- a/util/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/util/sdlna.key.snk b/util/sdlna.key.snk deleted file mode 100644 index 7e30ff02411640e5807b8ad0cd32d48cb745a656..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098wMZfhN->^Nl!3Q5v`Qf>P>)O;|H|uoq zuPj4V8M{Ea1kspx>7m=~Ae!YB7=t~Qz7(eePd3*)*b-~%a=s#O%-qg-@GPL*z6kU% z_rZ(=MtAVlNt1D>hD!9B=erFs`79ybW%gd3zM6N_Iz>{qvKFQq3-ak6OzAl8eiW^5 zOmPO^+X<^b0=H&n5wTcZ@h~o%(e5cR`ANyM%ct%9+9zyuRGC)FvaweMtNrl97Qn?s zamy#uD|T9Fa{c1Xe}>8%>_pA#h$%?caA9j1AF}orjgSmyI)uGpHuDJnF1OsUd=E1f zk2K3S76+h```Oc3U-Wme{HL>gKQqG%c4rE&?-jpk?Bd~E{~Iw+B~Ie<1%V#pR@X6h zUL0C=sJ5rU`+_8=T9L8`X>Kum>Bx}^(cTRDci3P0&#SZP`)nVOm(7?_n}f*+*Mp7U zmFRHUQ!6(|%D+=Co!{Q0Z~W}FwtXwCa7kH`hx=NoeGPF&^xO(LADYK>4*RHvW)k>x z|D7R^sunBQ6`EaX1o|FX8_=_^$?&Ia*X5JrY%JL}CCd})RcW>S)I30*%)=lme~(fB zxem@c$eEzgW0%I70=#Mmb6fA5FbAk;x{*bL8hUCD9;m6A>$BHKjd@@%*%&I!(*-hm zqlVmC - + + - Debug - AnyCPU - 8.0.30703 - 2.0 - {A8960A7A-887C-40D7-9632-002E94BFC830} - Library - Properties NMaier.SimpleDlna.Utilities SimpleDlna.Utilities - v4.5.1 - 512 - - - ..\ - true - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - ..\sdlna.ruleset - false - - - true - - - sdlna.key.snk - - - - ..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.dll - True - - - ..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.SqlServer.dll - True - - - ..\packages\log4net.2.0.5\lib\net45-full\log4net.dll - True - - - ..\packages\Microsoft.IO.RecyclableMemoryStream.1.1.0.0\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll - - - - - - ..\packages\System.Data.SQLite.Core.1.0.103\lib\net451\System.Data.SQLite.dll - True - - - - - - - - Properties\GlobalAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - \ No newline at end of file + + From f5f708624e073880f3fe6ad40f6db3eb450ca382 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Sat, 12 Sep 2026 12:39:12 -0500 Subject: [PATCH 05/37] Migrate from System.Data.SQLite to Microsoft.Data.Sqlite System.Data.SQLite.Core does compile against net10.0, but it ships no native interop binary for osx-arm64. Verified on this machine: opening a connection throws DllNotFoundException: Unable to load shared library 'SQLite.Interop.dll' or one of its dependencies Microsoft.Data.Sqlite 10.0.12 bundles SQLitePCLRaw with natives for every platform this project cares about, and was verified working here (SQLite 3.53.3). The port is small because everything outside util/Sqlite.cs already talks to the database through the ADO.NET interfaces (IDbConnection, IDbCommand, IDbDataParameter) rather than provider types. util/Sqlite.cs Rewritten against SqliteConnection. Three behavioural notes: * Connection string. The old one was Uri=file:;Pooling=true;Synchronous=Off; journal mode=TRUNCATE;DefaultTimeout=5 Microsoft.Data.Sqlite does not accept "Synchronous" or "journal mode" as connection-string keywords, so those are now issued as PRAGMA synchronous=OFF; PRAGMA journal_mode=TRUNCATE; immediately after Open(). Same effect, different mechanism. * SetChunkSize(16MB) is gone. It mapped to SQLITE_FCNTL_CHUNK_SIZE and was a System.Data.SQLite extension with no counterpart here. It was a file-growth hint only; dropping it costs some fragmentation on large caches, nothing functional. * The Mono branch is gone. GetDatabaseConnectionMono reflection-loaded Mono.Data.Sqlite when running under Mono. On .NET 10 the Mono probe (Type.GetType("Mono.Runtime")) is always null, so the branch was dead. util/SystemInformation.cs Deleted. IsRunningOnMono() was its only member and Sqlite.cs was its only caller. Named parameters (fsserver/FileStore.cs, fsserver/Files/FileStoreVacuumer.cs) The old code bound parameters positionally with '?' placeholders. Verified that Microsoft.Data.Sqlite rejects this: InvalidOperationException: ParameterName must be set. The three affected statements now use named parameters (@key, @size, @time). The INSERT already used named parameters and is unchanged. While editing these, the parameters for the selectCover and insert commands are now created from their own command object. They were previously all created via select.CreateParameter(). That was harmless -- CreateParameter() returns a detached object either way -- but it read as a copy/paste slip. DBNull for absent covers (fsserver/FileStore.cs) `insertCover.Value = null` is rejected by Microsoft.Data.Sqlite, which requires an explicitly set value. Now binds DBNull.Value. util and server both compile clean with no warnings. thumbs is still blocked on System.Drawing, handled next. --- fsserver/FileStore.cs | 30 ++++++--- fsserver/Files/FileStoreVacuumer.cs | 3 +- util/Sqlite.cs | 100 +++++++++------------------- util/SystemInformation.cs | 15 ----- 4 files changed, 51 insertions(+), 97 deletions(-) delete mode 100644 util/SystemInformation.cs diff --git a/fsserver/FileStore.cs b/fsserver/FileStore.cs index cfe692bc..48b65b5f 100644 --- a/fsserver/FileStore.cs +++ b/fsserver/FileStore.cs @@ -62,41 +62,47 @@ internal FileStore(FileInfo storeFile) select = connection.CreateCommand(); select.CommandText = - "SELECT data FROM store WHERE key = ? AND size = ? AND time = ?"; + "SELECT data FROM store WHERE key = @key AND size = @size AND time = @time"; select.Parameters.Add(selectKey = select.CreateParameter()); + selectKey.ParameterName = "@key"; selectKey.DbType = DbType.String; select.Parameters.Add(selectSize = select.CreateParameter()); + selectSize.ParameterName = "@size"; selectSize.DbType = DbType.Int64; select.Parameters.Add(selectTime = select.CreateParameter()); + selectTime.ParameterName = "@time"; selectTime.DbType = DbType.Int64; selectCover = connection.CreateCommand(); selectCover.CommandText = - "SELECT cover FROM store WHERE key = ? AND size = ? AND time = ?"; - selectCover.Parameters.Add(selectCoverKey = select.CreateParameter()); + "SELECT cover FROM store WHERE key = @key AND size = @size AND time = @time"; + selectCover.Parameters.Add(selectCoverKey = selectCover.CreateParameter()); + selectCoverKey.ParameterName = "@key"; selectCoverKey.DbType = DbType.String; - selectCover.Parameters.Add(selectCoverSize = select.CreateParameter()); + selectCover.Parameters.Add(selectCoverSize = selectCover.CreateParameter()); + selectCoverSize.ParameterName = "@size"; selectCoverSize.DbType = DbType.Int64; - selectCover.Parameters.Add(selectCoverTime = select.CreateParameter()); + selectCover.Parameters.Add(selectCoverTime = selectCover.CreateParameter()); + selectCoverTime.ParameterName = "@time"; selectCoverTime.DbType = DbType.Int64; insert = connection.CreateCommand(); insert.CommandText = "INSERT OR REPLACE INTO store " + "VALUES(@key, @size, @time, @data, COALESCE(@cover, (SELECT cover FROM store WHERE key = @key)))"; - insert.Parameters.Add(insertKey = select.CreateParameter()); + insert.Parameters.Add(insertKey = insert.CreateParameter()); insertKey.DbType = DbType.String; insertKey.ParameterName = "@key"; - insert.Parameters.Add(insertSize = select.CreateParameter()); + insert.Parameters.Add(insertSize = insert.CreateParameter()); insertSize.DbType = DbType.Int64; insertSize.ParameterName = "@size"; - insert.Parameters.Add(insertTime = select.CreateParameter()); + insert.Parameters.Add(insertTime = insert.CreateParameter()); insertTime.DbType = DbType.Int64; insertTime.ParameterName = "@time"; - insert.Parameters.Add(insertData = select.CreateParameter()); + insert.Parameters.Add(insertData = insert.CreateParameter()); insertData.DbType = DbType.Binary; insertData.ParameterName = "@data"; - insert.Parameters.Add(insertCover = select.CreateParameter()); + insert.Parameters.Add(insertCover = insert.CreateParameter()); insertCover.DbType = DbType.Binary; insertCover.ParameterName = "@cover"; @@ -344,7 +350,9 @@ internal void MaybeStoreFile(BaseFile file) insertTime.Value = file.Item.LastWriteTimeUtc.Ticks; insertData.Value = s.ToArray(); - insertCover.Value = null; + // Microsoft.Data.Sqlite rejects an unset parameter value, so + // an absent cover has to be bound as DBNull rather than null. + insertCover.Value = DBNull.Value; if (cover != null) { insertCover.Value = c.ToArray(); } diff --git a/fsserver/Files/FileStoreVacuumer.cs b/fsserver/Files/FileStoreVacuumer.cs index a8438aea..cd5bb755 100644 --- a/fsserver/Files/FileStoreVacuumer.cs +++ b/fsserver/Files/FileStoreVacuumer.cs @@ -91,8 +91,9 @@ private void Vacuum(IDbConnection connection) using (var trans = connection.BeginTransaction()) { using (var q = connection.CreateCommand()) { q.Transaction = trans; - q.CommandText = "DELETE FROM store WHERE key = ?"; + q.CommandText = "DELETE FROM store WHERE key = @key"; var p = q.CreateParameter(); + p.ParameterName = "@key"; p.DbType = DbType.String; q.Parameters.Add(p); foreach (var f in gone) { diff --git a/util/Sqlite.cs b/util/Sqlite.cs index 6f93b111..7c0b058d 100644 --- a/util/Sqlite.cs +++ b/util/Sqlite.cs @@ -1,79 +1,19 @@ -using System; +using System; using System.Data; -using System.Data.SQLite; using System.IO; -using System.Reflection; using log4net; +using Microsoft.Data.Sqlite; namespace NMaier.SimpleDlna.Utilities { public static class Sqlite { - private const int GROW_SIZE = 1 << 24; - - private static Action clearPool; - - private static IDbConnection GetDatabaseConnectionMono(string cs) - { - Assembly monoSqlite; - try { - monoSqlite = Assembly.Load( - "Mono.Data.Sqlite, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"); - } - catch (Exception) { - monoSqlite = Assembly.Load( - "Mono.Data.Sqlite, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"); - } - var dbconn = monoSqlite.GetType( - "Mono.Data.Sqlite.SqliteConnection"); - var ctor = dbconn.GetConstructor(new[] {typeof (string)}); - if (ctor == null) { - throw new ArgumentException("No mono SQLite found"); - } - var rv = ctor.Invoke(new object[] {cs}) as IDbConnection; - if (rv == null) { - throw new ArgumentException("no connection"); - } - rv.Open(); - if (clearPool == null) { - var cp = dbconn.GetMethod("ClearPool"); - clearPool = conn => - { - cp?.Invoke(null, new object[] {conn}); - }; - } - return rv; - } - - private static IDbConnection GetDatabaseConnectionSDS(string cs) - { - var rv = new SQLiteConnection(cs); - if (rv == null) { - throw new ArgumentException("no connection"); - } - rv.Open(); - - try { - rv.SetChunkSize(GROW_SIZE); - } - catch (Exception ex) { - LogManager.GetLogger(typeof (Sqlite)).Error( - "Failed to sqlite control", ex); - } - - if (clearPool == null) { - clearPool = conn => - { - SQLiteConnection.ClearPool( - conn as SQLiteConnection); - }; - } - return rv; - } - public static void ClearPool(IDbConnection conn) { - clearPool?.Invoke(conn); + var sqlite = conn as SqliteConnection; + if (sqlite != null) { + SqliteConnection.ClearPool(sqlite); + } } public static IDbConnection GetDatabaseConnection(FileInfo database) @@ -87,12 +27,32 @@ public static IDbConnection GetDatabaseConnection(FileInfo database) nameof(database) ); } - var cs = $"Uri=file:{database.FullName};Pooling=true;Synchronous=Off;journal mode=TRUNCATE;DefaultTimeout=5"; - if (SystemInformation.IsRunningOnMono()) { - return GetDatabaseConnectionMono(cs); + var cs = new SqliteConnectionStringBuilder + { + DataSource = database.FullName, + Mode = SqliteOpenMode.ReadWriteCreate, + Pooling = true, + DefaultTimeout = 5 + }.ConnectionString; + + var rv = new SqliteConnection(cs); + rv.Open(); + try { + using (var pragma = rv.CreateCommand()) { + // System.Data.SQLite accepted "Synchronous" and "journal mode" as + // connection string keywords. Microsoft.Data.Sqlite does not, so + // they are applied as pragmas once the connection is open. + pragma.CommandText = + "PRAGMA synchronous=OFF; PRAGMA journal_mode=TRUNCATE;"; + pragma.ExecuteNonQuery(); + } } - return GetDatabaseConnectionSDS(cs); + catch (Exception ex) { + LogManager.GetLogger(typeof (Sqlite)).Error( + "Failed to configure sqlite connection", ex); + } + return rv; } } } diff --git a/util/SystemInformation.cs b/util/SystemInformation.cs deleted file mode 100644 index c0d024f8..00000000 --- a/util/SystemInformation.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace NMaier.SimpleDlna.Utilities -{ - public static class SystemInformation - { - /// - /// Returns true if applicaton is running under mono - /// - public static bool IsRunningOnMono() - { - return Type.GetType("Mono.Runtime") != null; - } - } -} From 4331644f6ae3774c15d8335cdca314350556acb3 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Sat, 12 Sep 2026 12:42:31 -0500 Subject: [PATCH 06/37] Port thumbnail generation from System.Drawing to SkiaSharp System.Drawing.Common is Windows-only from .NET 7 onward; the Unix compatibility switch that existed in .NET 6 was removed. Verified on this machine that constructing a Bitmap under .NET 10 on macOS throws TypeInitializationException: The type initializer for 'Windows.Win32.PInvokeGdiPlus' threw an exception so the thumbnailer could not run here at all. SkiaSharp 4.152.0 was chosen over ImageSharp: it is MIT licensed, which sits comfortably beside this project's BSD license, whereas ImageSharp 3.x moved to the Six Labors Split License. It also has verified osx-arm64 natives. thumbs/ThumbnailMaker.cs ResizeImage now takes and returns SKBitmap. The aspect-fit arithmetic is unchanged. Rendering maps across as: Bitmap + Graphics.FromImage -> SKBitmap + SKCanvas FillRectangle(Brushes.Black, ..) -> canvas.Clear(SKColors.Black) DrawImage(image, rect) -> canvas.DrawImage(img, rect, sampling) The old code picked InterpolationMode.High when enlarging and Bicubic otherwise. SkiaSharp 4.x removed SKFilterQuality entirely, so this is now expressed with SKSamplingOptions: Mitchell cubic when enlarging, linear with mipmaps when shrinking. SetResolution is gone. SKBitmap carries no DPI metadata, and DPI on a thumbnail is cosmetic. Added ResizeToJpeg, which folds the resize-then-encode sequence that both loaders were duplicating into one place. Added a floor of 1px on the computed size. A source with an extreme aspect ratio scales to zero on one axis, and a zero-sized bitmap is invalid; previously this threw and the thumbnailer was skipped. thumbs/ImageThumbnailLoader.cs Image.FromStream/FromFile -> SKBitmap.Decode. Decode signals failure by returning null rather than throwing, so an explicit null check now raises NotSupportedException to keep the "try the next loader" behaviour in ThumbnailMaker.GetThumbnailInternal intact. thumbs/VideoThumbnailLoader.cs Same decode swap, plus an explicit Seek(0) before decoding. StreamPump leaves the output stream positioned at the end of what it wrote, and SKBitmap.Decode reads from the current position. (FFmpeg.cs already did this rewind explicitly for the same reason.) JPEG quality is now specified explicitly as 85. GDI+ used its unspecified default; the encoders differ enough that no setting reproduces the old output byte for byte, so it is at least pinned and visible now. Verified end to end on macOS: an 800x600 source through ThumbnailMaker.GetThumbnail(file, 384, 216) produces a 288x216 JPEG -- correct aspect-preserving fit -- that decodes back cleanly and renders correctly. --- thumbs/ImageThumbnailLoader.cs | 32 +++++------- thumbs/ThumbnailMaker.cs | 90 +++++++++++++++++++++------------- thumbs/VideoThumbnailLoader.cs | 26 ++++------ 3 files changed, 78 insertions(+), 70 deletions(-) diff --git a/thumbs/ImageThumbnailLoader.cs b/thumbs/ImageThumbnailLoader.cs index e061fc5a..174c51ce 100644 --- a/thumbs/ImageThumbnailLoader.cs +++ b/thumbs/ImageThumbnailLoader.cs @@ -1,8 +1,7 @@ -using System; -using System.Drawing; -using System.Drawing.Imaging; +using System; using System.IO; using NMaier.SimpleDlna.Server; +using SkiaSharp; namespace NMaier.SimpleDlna.Thumbnails { @@ -13,35 +12,28 @@ internal sealed class ImageThumbnailLoader : IThumbnailLoader public MemoryStream GetThumbnail(object item, ref int width, ref int height) { - Image img; + SKBitmap img; var stream = item as Stream; if (stream != null) { - img = Image.FromStream(stream); + img = SKBitmap.Decode(stream); } else { var fi = item as FileInfo; if (fi != null) { - img = Image.FromFile(fi.FullName); + img = SKBitmap.Decode(fi.FullName); } else { throw new NotSupportedException(); } } + // Unlike Image.FromStream, SKBitmap.Decode reports failure by returning + // null rather than throwing. + if (img == null) { + throw new NotSupportedException("Not a supported image format"); + } using (img) { - using (var scaled = ThumbnailMaker.ResizeImage( - img, width, height, ThumbnailMakerBorder.Borderless)) { - width = scaled.Width; - height = scaled.Height; - var rv = new MemoryStream(); - try { - scaled.Save(rv, ImageFormat.Jpeg); - return rv; - } - catch (Exception) { - rv.Dispose(); - throw; - } - } + return ThumbnailMaker.ResizeToJpeg( + img, ref width, ref height, ThumbnailMakerBorder.Borderless); } } } diff --git a/thumbs/ThumbnailMaker.cs b/thumbs/ThumbnailMaker.cs index 31d2cd6f..528a3781 100644 --- a/thumbs/ThumbnailMaker.cs +++ b/thumbs/ThumbnailMaker.cs @@ -1,18 +1,18 @@ using System; using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; using System.IO; using System.Linq; using System.Reflection; -using log4net; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Utilities; +using SkiaSharp; namespace NMaier.SimpleDlna.Thumbnails { public sealed class ThumbnailMaker : Logging { + private const int JPEG_QUALITY = 85; + private static readonly LeastRecentlyUsedDictionary cache = new LeastRecentlyUsedDictionary(1 << 11); @@ -83,7 +83,7 @@ private byte[] GetThumbnailInternal(string key, object item, throw new ArgumentException("Not a supported resource"); } - internal static Image ResizeImage(Image image, int width, int height, + internal static SKBitmap ResizeImage(SKBitmap image, int width, int height, ThumbnailMakerBorder border) { var nw = (float)image.Width; @@ -97,38 +97,29 @@ internal static Image ResizeImage(Image image, int width, int height, nh = height; } - var result = new Bitmap( - border == ThumbnailMakerBorder.Bordered ? width : (int)nw, - border == ThumbnailMakerBorder.Bordered ? height : (int)nh - ); + // A source with an extreme aspect ratio can scale to zero on one axis, + // which is not a valid bitmap size. + var rw = border == ThumbnailMakerBorder.Bordered + ? width + : Math.Max((int)nw, 1); + var rh = border == ThumbnailMakerBorder.Bordered + ? height + : Math.Max((int)nh, 1); + + var result = new SKBitmap(rw, rh, SKColorType.Rgba8888, SKAlphaType.Premul); try { - try { - result.SetResolution(image.HorizontalResolution, image.VerticalResolution); - } - catch (Exception ex) { - LogManager.GetLogger(typeof (ThumbnailMaker)).Debug("Failed to set resolution", ex); - } - using (var graphics = Graphics.FromImage(result)) { - if (result.Width > image.Width && result.Height > image.Height) { - graphics.CompositingQuality = - CompositingQuality.HighQuality; - graphics.InterpolationMode = - InterpolationMode.High; + // Mitchell cubic when enlarging, cheap linear filtering when shrinking, + // matching the quality/speed split the GDI+ implementation used. + var sampling = rw > image.Width && rh > image.Height + ? new SKSamplingOptions(SKCubicResampler.Mitchell) + : new SKSamplingOptions(SKFilterMode.Linear, SKMipmapMode.Linear); + using (var canvas = new SKCanvas(result)) { + canvas.Clear(SKColors.Black); + using (var img = SKImage.FromBitmap(image)) { + var rect = SKRect.Create( + (rw - nw) / 2f, (rh - nh) / 2f, nw, nh); + canvas.DrawImage(img, rect, sampling); } - else { - graphics.CompositingQuality = - CompositingQuality.HighSpeed; - graphics.InterpolationMode = InterpolationMode.Bicubic; - } - var rect = new Rectangle( - (int)(result.Width - nw) / 2, - (int)(result.Height - nh) / 2, - (int)nw, (int)nh - ); - graphics.SmoothingMode = SmoothingMode.HighSpeed; - graphics.FillRectangle( - Brushes.Black, new Rectangle(0, 0, result.Width, result.Height)); - graphics.DrawImage(image, rect); } return result; } @@ -138,6 +129,37 @@ internal static Image ResizeImage(Image image, int width, int height, } } + /// + /// Scales to fit and encodes the result as + /// JPEG, reporting the dimensions actually produced. + /// + internal static MemoryStream ResizeToJpeg(SKBitmap image, ref int width, + ref int height, ThumbnailMakerBorder border) + { + using (var scaled = ResizeImage(image, width, height, border)) { + width = scaled.Width; + height = scaled.Height; + var rv = new MemoryStream(); + try { + using (var img = SKImage.FromBitmap(scaled)) { + using (var data = img.Encode( + SKEncodedImageFormat.Jpeg, JPEG_QUALITY)) { + if (data == null) { + throw new NotSupportedException( + "Failed to encode the thumbnail as JPEG"); + } + data.SaveTo(rv); + } + } + return rv; + } + catch (Exception) { + rv.Dispose(); + throw; + } + } + } + public IThumbnail GetThumbnail(FileSystemInfo file, int width, int height) { if (file == null) { diff --git a/thumbs/VideoThumbnailLoader.cs b/thumbs/VideoThumbnailLoader.cs index 96af61fe..43620c55 100644 --- a/thumbs/VideoThumbnailLoader.cs +++ b/thumbs/VideoThumbnailLoader.cs @@ -1,11 +1,10 @@ using System; using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; using System.IO; using System.Threading; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Utilities; +using SkiaSharp; namespace NMaier.SimpleDlna.Thumbnails { @@ -78,21 +77,16 @@ private static MemoryStream GetThumbnailFromProcess(Process p, throw new ArgumentException("ffmpeg did not produce a result"); } - using (var img = Image.FromStream(thumb)) { - using (var scaled = ThumbnailMaker.ResizeImage(img, width, height, - ThumbnailMakerBorder.Bordered)) { - width = scaled.Width; - height = scaled.Height; - var rv = new MemoryStream(); - try { - scaled.Save(rv, ImageFormat.Jpeg); - return rv; - } - catch (Exception) { - rv.Dispose(); - throw; - } + // The pump leaves the stream at the end of what it wrote, and + // SKBitmap.Decode reads from the current position. + thumb.Seek(0, SeekOrigin.Begin); + using (var img = SKBitmap.Decode(thumb)) { + if (img == null) { + throw new ArgumentException( + "ffmpeg did not produce a decodable image"); } + return ThumbnailMaker.ResizeToJpeg( + img, ref width, ref height, ThumbnailMakerBorder.Bordered); } } } From a145c27c965549c73e46ee1123a7aeb790461bfa Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Sat, 12 Sep 2026 12:48:09 -0500 Subject: [PATCH 07/37] Replace BinaryFormatter with an explicit binary cache format BinaryFormatter's implementation was removed from the runtime in .NET 9 and using it is now a build error (SYSLIB0011), not merely a warning. It was the encoder for the file store: the media metadata and cover art that fsserver caches in SQLite. The compat package (System.Runtime.Serialization.Formatters plus EnableUnsafeBinaryFormatterSerialization) does restore a working implementation and was verified to work here, but it reintroduces exactly the deserialization-gadget exposure the removal was meant to end. Since the cache is derived data that can always be rebuilt by rescanning, an explicit format is the better trade. New: fsserver/Files/MediaSerializer.cs A small BinaryReader/BinaryWriter format. Each blob starts with a format version byte; file blobs then carry a one-byte kind discriminator (audio/image/video) and the type's own fields in a fixed order. No CLR type or assembly name appears in the payload, which is what makes it inert on read. Helpers cover nullable strings/ints/longs, string arrays and byte arrays, each with an explicit presence flag so null and empty stay distinguishable. Per-type encoding AudioFile, ImageFile, VideoFile and Cover lose [Serializable], ISerializable, their SerializationInfo constructors and GetObjectData, and gain an internal Serialize(BinaryWriter) plus a (BinaryReader, DeserializeInfo) constructor. The field lists and their order are carried over unchanged, including AudioFile.description deliberately not being persisted. Two behavioural differences, both deliberate: * ImageFile round trips properly now. Its (SerializationInfo, StreamingContext) constructor -- the one BinaryFormatter actually called -- chained to the base constructor and read no fields at all, leaving initialized false. Cached image metadata was therefore discarded on load and re-read from taglib every time. The sibling constructor that did read the fields was unreachable. There is now one constructor and it reads them. * VideoFile records whether a Subtitle instance existed separately from its text. Previously a probed-but-empty Subtitle serialized to something that came back null, and VideoFile.Subtitle treats null as "not looked yet" and re-runs ffmpeg. Videos without subtitles were re-probed on every listing. server/Types/Subtitle.cs Added a public Text property so the video encoder can round-trip the subtitle without reflection, and dropped [Serializable]/[NonSerialized], which no longer mean anything. fsserver/FileStore.cs Uses MediaSerializer. The catch clauses now key on InvalidDataException and EndOfStreamException where they previously keyed on SerializationException, preserving "a bad cache entry is a debug-level miss, not a crash". CanSerialize replaces the [Serializable] type attribute check. Fixed alongside: the NotSupportedException handler around cover serialization said "Ignore and store null" but left the local cover reference set, so a throw part way through would persist a truncated cover blob. It now clears the local. SCHEMA bumped 0x20160618 -> 0x20260912. Existing caches are in the old format, and the existing schema-mismatch path deletes and recreates the database, so stale caches are discarded automatically on first run. Verified by round-tripping every type through the real serializer with populated and null-heavy field sets: values, nulls, Unicode, string arrays with null elements, and the probed-empty-subtitle case all survive exactly. Corrupt input (bad version byte, unknown kind, truncated payload) throws InvalidDataException or EndOfStreamException, which are precisely the types FileStore catches. Encoded sizes are compact: 52 bytes for a fully populated audio entry. The solution now builds. --- fsserver/FileStore.cs | 69 +++------- fsserver/Files/AudioFile.cs | 53 +++----- fsserver/Files/Cover.cs | 24 ++-- fsserver/Files/ImageFile.cs | 39 ++---- fsserver/Files/MediaSerializer.cs | 206 ++++++++++++++++++++++++++++++ fsserver/Files/VideoFile.cs | 77 +++++------ server/Types/Subtitle.cs | 13 +- 7 files changed, 306 insertions(+), 175 deletions(-) create mode 100644 fsserver/Files/MediaSerializer.cs diff --git a/fsserver/FileStore.cs b/fsserver/FileStore.cs index 48b65b5f..5c903051 100644 --- a/fsserver/FileStore.cs +++ b/fsserver/FileStore.cs @@ -1,11 +1,7 @@ -using System; +using System; using System.Data; using System.Data.Common; using System.IO; -using System.Reflection; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters; -using System.Runtime.Serialization.Formatters.Binary; using System.Threading; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Utilities; @@ -14,7 +10,7 @@ namespace NMaier.SimpleDlna.FileMediaServer { internal sealed class FileStore : Logging, IDisposable { - private const uint SCHEMA = 0x20160618; + private const uint SCHEMA = 0x20260912; private static readonly FileStoreVacuumer vacuumer = new FileStoreVacuumer(); @@ -234,20 +230,12 @@ internal Cover MaybeGetCover(BaseFile file) } try { using (var s = new MemoryStream(data)) { - var ctx = new StreamingContext( - StreamingContextStates.Persistence, - new DeserializeInfo(null, info, DlnaMime.ImageJPEG) - ); - var formatter = new BinaryFormatter(null, ctx) - { - TypeFormat = FormatterTypeStyle.TypesWhenNeeded, - AssemblyFormat = FormatterAssemblyStyle.Simple - }; - var rv = formatter.Deserialize(s) as Cover; - return rv; + return MediaSerializer.DeserializeCover( + s, new DeserializeInfo(null, info, DlnaMime.ImageJPEG)); } } - catch (SerializationException ex) { + catch (Exception ex) when ( + ex is InvalidDataException || ex is EndOfStreamException) { Debug("Failed to deserialize a cover", ex); return null; } @@ -286,28 +274,16 @@ internal BaseFile MaybeGetFile(FileServer server, FileInfo info, } try { using (var s = new MemoryStream(data)) { - var ctx = new StreamingContext( - StreamingContextStates.Persistence, - new DeserializeInfo(server, info, type)); - var formatter = new BinaryFormatter(null, ctx) - { - TypeFormat = FormatterTypeStyle.TypesWhenNeeded, - AssemblyFormat = FormatterAssemblyStyle.Simple - }; - var rv = formatter.Deserialize(s) as BaseFile; - if (rv == null) { - throw new SerializationException("Deserialized as null"); - } + var rv = MediaSerializer.DeserializeFile( + s, new DeserializeInfo(server, info, type)); rv.Item = info; return rv; } } - catch (Exception ex) { - if (ex is TargetInvocationException || ex is SerializationException) { - Debug("Failed to deserialize an item", ex); - return null; - } - throw; + catch (Exception ex) when ( + ex is InvalidDataException || ex is EndOfStreamException) { + Debug("Failed to deserialize an item", ex); + return null; } } @@ -316,31 +292,26 @@ internal void MaybeStoreFile(BaseFile file) if (connection == null) { return; } - if (!file.GetType().Attributes.HasFlag(TypeAttributes.Serializable)) { + if (!MediaSerializer.CanSerialize(file)) { return; } try { using (var s = StreamManager.GetStream()) { using (var c = StreamManager.GetStream()) { - var ctx = new StreamingContext( - StreamingContextStates.Persistence, - null - ); - var formatter = new BinaryFormatter(null, ctx) - { - TypeFormat = FormatterTypeStyle.TypesWhenNeeded, - AssemblyFormat = FormatterAssemblyStyle.Simple - }; - formatter.Serialize(s, file); + MediaSerializer.Serialize(s, file); Cover cover = null; try { cover = file.MaybeGetCover(); if (cover != null) { - formatter.Serialize(c, cover); + MediaSerializer.SerializeCover(c, cover); } } catch (NotSupportedException) { - // Ignore and store null. + // Ignore and store null. Clearing the local is what makes the + // "store null" actually happen: the insert below keys off it, + // and a throw part way through SerializeCover would otherwise + // persist a truncated cover blob. + cover = null; } lock (connection) { diff --git a/fsserver/Files/AudioFile.cs b/fsserver/Files/AudioFile.cs index 3095a1b1..f66ef896 100644 --- a/fsserver/Files/AudioFile.cs +++ b/fsserver/Files/AudioFile.cs @@ -1,15 +1,13 @@ using System; using System.IO; -using System.Runtime.Serialization; using NMaier.SimpleDlna.Server; using TagLib; using File = TagLib.File; namespace NMaier.SimpleDlna.FileMediaServer { - [Serializable] internal sealed class AudioFile - : BaseFile, IMediaAudioResource, ISerializable + : BaseFile, IMediaAudioResource { private static readonly TimeSpan emptyDuration = new TimeSpan(0); private string album; @@ -30,33 +28,22 @@ internal sealed class AudioFile private int? track; - private AudioFile(SerializationInfo info, DeserializeInfo di) + internal AudioFile(BinaryReader reader, DeserializeInfo di) : this(di.Server, di.Info, di.Type) { - album = info.GetString("al"); - artist = info.GetString("ar"); - genre = info.GetString("g"); - performer = info.GetString("p"); - title = info.GetString("ti"); - try { - track = info.GetInt32("tr"); - } - catch (Exception) { - // no op - } - var ts = info.GetInt64("d"); + album = reader.ReadNullableString(); + artist = reader.ReadNullableString(); + genre = reader.ReadNullableString(); + performer = reader.ReadNullableString(); + title = reader.ReadNullableString(); + track = reader.ReadNullableInt32(); + var ts = reader.ReadInt64(); if (ts > 0) { duration = new TimeSpan(ts); } initialized = true; } - private AudioFile(SerializationInfo info, StreamingContext ctx) - : - this(info, ctx.Context as DeserializeInfo) - { - } - internal AudioFile(FileServer server, FileInfo aFile, DlnaMime aType) : base(server, aFile, aType, DlnaMediaTypes.Audio) { @@ -184,19 +171,17 @@ public override int CompareTo(IMediaItem other) return base.CompareTo(other); } - public void GetObjectData(SerializationInfo info, StreamingContext ctx) + internal void Serialize(BinaryWriter writer) { - if (info == null) { - throw new ArgumentNullException(nameof(info)); - } - info.AddValue("al", album); - info.AddValue("ar", artist); - info.AddValue("g", genre); - info.AddValue("p", performer); - info.AddValue("ti", title); - info.AddValue("tr", track); - info.AddValue( - "d", duration.GetValueOrDefault(emptyDuration).Ticks); + // Note: description is deliberately not persisted, matching the + // original GetObjectData. It is recovered from the tag on demand. + writer.WriteNullable(album); + writer.WriteNullable(artist); + writer.WriteNullable(genre); + writer.WriteNullable(performer); + writer.WriteNullable(title); + writer.WriteNullable(track); + writer.Write(duration.GetValueOrDefault(emptyDuration).Ticks); } private void InitCover(Tag tag) diff --git a/fsserver/Files/Cover.cs b/fsserver/Files/Cover.cs index 6cf92bd8..2ca657eb 100644 --- a/fsserver/Files/Cover.cs +++ b/fsserver/Files/Cover.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Runtime.Serialization; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Server.Metadata; using NMaier.SimpleDlna.Thumbnails; @@ -8,9 +7,8 @@ namespace NMaier.SimpleDlna.FileMediaServer { - [Serializable] internal sealed class Cover - : Logging, IMediaCoverResource, IMetaInfo, ISerializable, IDisposable + : Logging, IMediaCoverResource, IMetaInfo, IDisposable { private static readonly ThumbnailMaker thumber = new ThumbnailMaker(); @@ -24,12 +22,11 @@ internal sealed class Cover private int width = 384; - private Cover(SerializationInfo info, StreamingContext ctx) + internal Cover(BinaryReader reader, DeserializeInfo di) { - bytes = info.GetValue("b", typeof (byte[])) as byte[]; - width = info.GetInt32("w"); - height = info.GetInt32("h"); - var di = ctx.Context as DeserializeInfo; + width = reader.ReadInt32(); + height = reader.ReadInt32(); + bytes = reader.ReadByteArray(); if (di != null) { file = di.Info; } @@ -141,17 +138,14 @@ public long? InfoSize } } - public void GetObjectData(SerializationInfo info, StreamingContext ctx) + internal void Serialize(BinaryWriter writer) { - if (info == null) { - throw new ArgumentNullException(nameof(info)); - } if (bytes == null) { throw new NotSupportedException("No cover loaded"); } - info.AddValue("b", bytes); - info.AddValue("w", width); - info.AddValue("h", height); + writer.Write(width); + writer.Write(height); + writer.WriteBytes(bytes); } internal event EventHandler OnCoverLazyLoaded; diff --git a/fsserver/Files/ImageFile.cs b/fsserver/Files/ImageFile.cs index 143e0794..f483adc9 100644 --- a/fsserver/Files/ImageFile.cs +++ b/fsserver/Files/ImageFile.cs @@ -1,15 +1,13 @@ using System; using System.IO; -using System.Runtime.Serialization; using NMaier.SimpleDlna.Server; using TagLib; using File = TagLib.File; namespace NMaier.SimpleDlna.FileMediaServer { - [Serializable] internal sealed class ImageFile : - BaseFile, IMediaImageResource, ISerializable + BaseFile, IMediaImageResource { private string creator; @@ -22,22 +20,14 @@ internal sealed class ImageFile : private int? width, height; - private ImageFile(SerializationInfo info, StreamingContext context) - : this(((DeserializeInfo)context.Context).Server, - ((DeserializeInfo)context.Context).Info, - ((DeserializeInfo)context.Context).Type) - { - } - - // ReSharper disable once UnusedMember.Local - private ImageFile(SerializationInfo info, DeserializeInfo di) + internal ImageFile(BinaryReader reader, DeserializeInfo di) : this(di.Server, di.Info, di.Type) { - creator = info.GetString("cr"); - description = info.GetString("d"); - title = info.GetString("t"); - width = info.GetInt32("w"); - height = info.GetInt32("h"); + creator = reader.ReadNullableString(); + description = reader.ReadNullableString(); + title = reader.ReadNullableString(); + width = reader.ReadNullableInt32(); + height = reader.ReadNullableInt32(); initialized = true; } @@ -110,17 +100,14 @@ public override string Title } } - public void GetObjectData(SerializationInfo info, StreamingContext ctx) + internal void Serialize(BinaryWriter writer) { - if (info == null) { - throw new ArgumentNullException(nameof(info)); - } MaybeInit(); - info.AddValue("cr", creator); - info.AddValue("d", description); - info.AddValue("t", title); - info.AddValue("w", width); - info.AddValue("h", height); + writer.WriteNullable(creator); + writer.WriteNullable(description); + writer.WriteNullable(title); + writer.WriteNullable(width); + writer.WriteNullable(height); } private void MaybeInit() diff --git a/fsserver/Files/MediaSerializer.cs b/fsserver/Files/MediaSerializer.cs new file mode 100644 index 00000000..5091fb85 --- /dev/null +++ b/fsserver/Files/MediaSerializer.cs @@ -0,0 +1,206 @@ +using System; +using System.IO; +using System.Text; + +namespace NMaier.SimpleDlna.FileMediaServer +{ + /// + /// Binary encoding for the entries held in the file store. + /// + /// + /// + /// Replaces BinaryFormatter, whose implementation was removed from the + /// runtime in .NET 9. The format is explicit and self-describing: each + /// type reads and writes its own fields in a fixed order, and no CLR + /// type or assembly identity is recorded in the blob. That is the point + /// -- BinaryFormatter blobs named their types, which is what made them + /// a deserialization gadget hazard. + /// + /// + /// Changing any payload layout requires bumping FileStore.SCHEMA, which + /// causes existing caches to be discarded and rebuilt. + /// + /// + internal static class MediaSerializer + { + private const byte FORMAT_VERSION = 1; + + private const byte KIND_AUDIO = 1; + + private const byte KIND_IMAGE = 2; + + private const byte KIND_VIDEO = 3; + + /// + /// Whether a file has a cacheable representation. Replaces the old + /// check for the [Serializable] type attribute. + /// + internal static bool CanSerialize(BaseFile file) + { + return file is AudioFile || file is ImageFile || file is VideoFile; + } + + internal static void Serialize(Stream stream, BaseFile file) + { + using (var writer = new BinaryWriter(stream, Encoding.UTF8, true)) { + writer.Write(FORMAT_VERSION); + + var audio = file as AudioFile; + if (audio != null) { + writer.Write(KIND_AUDIO); + audio.Serialize(writer); + return; + } + var image = file as ImageFile; + if (image != null) { + writer.Write(KIND_IMAGE); + image.Serialize(writer); + return; + } + var video = file as VideoFile; + if (video != null) { + writer.Write(KIND_VIDEO); + video.Serialize(writer); + return; + } + throw new NotSupportedException( + "Cannot serialize " + file.GetType()); + } + } + + internal static BaseFile DeserializeFile(Stream stream, + DeserializeInfo info) + { + using (var reader = new BinaryReader(stream, Encoding.UTF8, true)) { + CheckVersion(reader); + var kind = reader.ReadByte(); + switch (kind) { + case KIND_AUDIO: + return new AudioFile(reader, info); + case KIND_IMAGE: + return new ImageFile(reader, info); + case KIND_VIDEO: + return new VideoFile(reader, info); + default: + throw new InvalidDataException( + $"Unknown cache entry kind {kind}"); + } + } + } + + internal static void SerializeCover(Stream stream, Cover cover) + { + using (var writer = new BinaryWriter(stream, Encoding.UTF8, true)) { + writer.Write(FORMAT_VERSION); + cover.Serialize(writer); + } + } + + internal static Cover DeserializeCover(Stream stream, + DeserializeInfo info) + { + using (var reader = new BinaryReader(stream, Encoding.UTF8, true)) { + CheckVersion(reader); + return new Cover(reader, info); + } + } + + private static void CheckVersion(BinaryReader reader) + { + var version = reader.ReadByte(); + if (version != FORMAT_VERSION) { + throw new InvalidDataException( + $"Unsupported cache format version {version}"); + } + } + + internal static void WriteNullable(this BinaryWriter writer, string value) + { + writer.Write(value != null); + if (value != null) { + writer.Write(value); + } + } + + internal static string ReadNullableString(this BinaryReader reader) + { + return reader.ReadBoolean() ? reader.ReadString() : null; + } + + internal static void WriteNullable(this BinaryWriter writer, int? value) + { + writer.Write(value.HasValue); + if (value.HasValue) { + writer.Write(value.Value); + } + } + + internal static int? ReadNullableInt32(this BinaryReader reader) + { + return reader.ReadBoolean() ? reader.ReadInt32() : (int?)null; + } + + internal static void WriteNullable(this BinaryWriter writer, long? value) + { + writer.Write(value.HasValue); + if (value.HasValue) { + writer.Write(value.Value); + } + } + + internal static long? ReadNullableInt64(this BinaryReader reader) + { + return reader.ReadBoolean() ? reader.ReadInt64() : (long?)null; + } + + internal static void WriteStrings(this BinaryWriter writer, + string[] values) + { + if (values == null) { + writer.Write(-1); + return; + } + writer.Write(values.Length); + foreach (var value in values) { + writer.WriteNullable(value); + } + } + + internal static string[] ReadStrings(this BinaryReader reader) + { + var count = reader.ReadInt32(); + if (count < 0) { + return null; + } + var rv = new string[count]; + for (var i = 0; i < count; ++i) { + rv[i] = reader.ReadNullableString(); + } + return rv; + } + + internal static void WriteBytes(this BinaryWriter writer, byte[] value) + { + if (value == null) { + writer.Write(-1); + return; + } + writer.Write(value.Length); + writer.Write(value); + } + + internal static byte[] ReadByteArray(this BinaryReader reader) + { + var count = reader.ReadInt32(); + if (count < 0) { + return null; + } + var rv = reader.ReadBytes(count); + if (rv.Length != count) { + throw new EndOfStreamException( + "Truncated blob: expected " + count + " bytes, got " + rv.Length); + } + return rv; + } + } +} diff --git a/fsserver/Files/VideoFile.cs b/fsserver/Files/VideoFile.cs index 08a1cdb8..02fd7f25 100644 --- a/fsserver/Files/VideoFile.cs +++ b/fsserver/Files/VideoFile.cs @@ -1,16 +1,14 @@ using System; using System.Collections.Generic; using System.IO; -using System.Runtime.Serialization; using NMaier.SimpleDlna.Server; using TagLib; using File = TagLib.File; namespace NMaier.SimpleDlna.FileMediaServer { - [Serializable] internal sealed class VideoFile - : BaseFile, IMediaVideoResource, ISerializable, IBookmarkable + : BaseFile, IMediaVideoResource, IBookmarkable { private static readonly TimeSpan emptyDuration = new TimeSpan(0); private string[] actors; @@ -35,41 +33,26 @@ internal sealed class VideoFile private int? width; - private VideoFile(SerializationInfo info, StreamingContext ctx) - : this(info, ctx.Context as DeserializeInfo) - { - } - - private VideoFile(SerializationInfo info, DeserializeInfo di) + internal VideoFile(BinaryReader reader, DeserializeInfo di) : this(di.Server, di.Info, di.Type) { - actors = info.GetValue("a", typeof (string[])) as string[]; - description = info.GetString("de"); - director = info.GetString("di"); - genre = info.GetString("g"); - title = info.GetString("t"); - try { - width = info.GetInt32("w"); - height = info.GetInt32("h"); - } - catch (Exception) { - // ignored - } - var ts = info.GetInt64("du"); + actors = reader.ReadStrings(); + description = reader.ReadNullableString(); + director = reader.ReadNullableString(); + genre = reader.ReadNullableString(); + title = reader.ReadNullableString(); + width = reader.ReadNullableInt32(); + height = reader.ReadNullableInt32(); + bookmark = reader.ReadNullableInt64(); + var ts = reader.ReadInt64(); if (ts > 0) { duration = new TimeSpan(ts); } - try { - bookmark = info.GetInt64("b"); - } - catch (Exception) { - bookmark = 0; - } - try { - subTitle = info.GetValue("st", typeof (Subtitle)) as Subtitle; - } - catch (Exception) { - subTitle = null; + // The presence of the Subtitle instance is recorded separately from its + // text, so that "already looked, found none" survives a round trip and + // does not send us back to ffmpeg on every listing. + if (reader.ReadBoolean()) { + subTitle = new Subtitle(reader.ReadNullableString()); } initialized = true; } @@ -204,22 +187,22 @@ public override string Title } } - public void GetObjectData(SerializationInfo info, StreamingContext context) + internal void Serialize(BinaryWriter writer) { - if (info == null) { - throw new ArgumentNullException(nameof(info)); - } MaybeInit(); - info.AddValue("a", actors, typeof (string[])); - info.AddValue("de", description); - info.AddValue("di", director); - info.AddValue("g", genre); - info.AddValue("t", title); - info.AddValue("w", width); - info.AddValue("h", height); - info.AddValue("b", bookmark); - info.AddValue("du", duration.GetValueOrDefault(emptyDuration).Ticks); - info.AddValue("st", subTitle); + writer.WriteStrings(actors); + writer.WriteNullable(description); + writer.WriteNullable(director); + writer.WriteNullable(genre); + writer.WriteNullable(title); + writer.WriteNullable(width); + writer.WriteNullable(height); + writer.WriteNullable(bookmark); + writer.Write(duration.GetValueOrDefault(emptyDuration).Ticks); + writer.Write(subTitle != null); + if (subTitle != null) { + writer.WriteNullable(subTitle.Text); + } } private void MaybeInit() diff --git a/server/Types/Subtitle.cs b/server/Types/Subtitle.cs index 89e0af68..98222baa 100644 --- a/server/Types/Subtitle.cs +++ b/server/Types/Subtitle.cs @@ -7,13 +7,12 @@ namespace NMaier.SimpleDlna.Server { - [Serializable] public sealed class Subtitle : IMediaResource { - [NonSerialized] private static readonly ILog logger = + private static readonly ILog logger = LogManager.GetLogger(typeof (Subtitle)); - [NonSerialized] private static readonly string[] exts = + private static readonly string[] exts = { ".srt", ".SRT", ".ass", ".ASS", @@ -22,7 +21,7 @@ public sealed class Subtitle : IMediaResource ".vtt", ".VTT" }; - [NonSerialized] private byte[] encodedText; + private byte[] encodedText; private string text; @@ -42,6 +41,12 @@ public Subtitle(string text) public bool HasSubtitle => !string.IsNullOrWhiteSpace(text); + /// + /// The raw subtitle text, or null when none was found. Exposed so that + /// callers persisting a Subtitle can round-trip it without reflection. + /// + public string Text => text; + public DateTime InfoDate => DateTime.UtcNow; public long? InfoSize From 1341c4d470e686254290d6a7a1317c518221d8ba Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Sat, 12 Sep 2026 12:52:05 -0500 Subject: [PATCH 08/37] Fix .NET Core runtime incompatibilities and clear all build warnings Everything below compiled fine against .NET Framework but is either non-functional or removed on .NET 10. The solution now builds with zero warnings and zero errors. util/StreamPump.cs -- the important one Finish() dispatched the completion callback with callback?.BeginInvoke(this, result, callback.EndInvoke, null); Delegate.BeginInvoke/EndInvoke are not implemented on .NET. Verified: it throws PlatformNotSupportedException. Two call sites pass a non-null callback, and one of them is HttpClient's response writer, so every file served over HTTP would have failed at the point of completion. This is a runtime failure, which is why the compiler never flagged it. Replaced with an explicit ThreadPool.QueueUserWorkItem, preserving the original intent of not running the callback on the completing I/O thread. A throwing callback is now logged; previously EndInvoke would have rethrown it on a pool thread with nothing to catch it. Socket.UseOnlyOverlappedIO (HttpServer, HttpClient, SsdpHandler) Deprecated and inert on .NET. Verified the setter is a silent no-op and the property reads back false regardless. Removed rather than suppressed, since keeping it implies an effect it does not have. ProcessStartInfo.LoadUserProfile (FFmpeg, VideoThumbnailLoader; 4 sites) Windows-only (CA1416) and every site assigned false, which is already the default. Removed. Legacy exception serialization constructors (SYSLIB0051) HttpException, HttpStatusException and RepositoryLookupException each carried a (SerializationInfo, StreamingContext) constructor. These exist only to support formatter-based serialization, which went away with BinaryFormatter. Removed. [Serializable] is kept, being conventional and harmless on exception types. util/ProductInformation.cs -- Assembly.CodeBase (SYSLIB0012) .NET Framework only. Now uses Assembly.Location, falling back to Environment.ProcessPath (Location is empty under single-file publish) and then to the simple assembly name. util/HttpStream.cs -- short read (CA2022) The small-seek path did bufferedStream.Read(buf, 0, (int)off); discarding the return value. Stream.Read may legitimately return fewer bytes than requested, which would leave the stream short of the seek target and silently misalign every subsequent read. Now ReadExactly. The WebRequest.Create obsoletion (SYSLIB0014) in the same file is suppressed locally with a TODO rather than fixed: HttpWebRequest still works on .NET 10, and HttpStream turns out to be unreferenced by the rest of the solution now that the GUI is gone, so a rewrite here could not be verified by anything. Windows P/Invoke guards NaturalStringComparer probed shlwapi!StrCmpLogicalW and AddressToMacResolver called iphlpapi!SendARP, both relying on catching DllNotFoundException on non-Windows. The fallbacks were correct, so this was never a crash, just an exception thrown per probe and per address resolution. Both now short-circuit on OperatingSystem.IsWindows(). Verified: clean build with no diagnostics, the serializer round-trip suite still passes, and `sdlna --help` runs and prints its usage. --- server/Http/HttpClient.cs | 1 - server/Http/HttpServer.cs | 1 - server/Ssdp/SsdpHandler.cs | 1 - server/Types/HttpException.cs | 6 ------ server/Types/HttpStatusException.cs | 6 ------ thumbs/VideoThumbnailLoader.cs | 2 -- util/AddressToMacResolver.cs | 5 ++++- util/FFmpeg.cs | 2 -- util/HttpStream.cs | 10 +++++++++- util/NaturalStringComparer.cs | 6 ++++++ util/ProductInformation.cs | 16 +++++++++++++--- util/RepositoryLookupException.cs | 7 ------- util/StreamPump.cs | 19 ++++++++++++++++++- 13 files changed, 50 insertions(+), 32 deletions(-) diff --git a/server/Http/HttpClient.cs b/server/Http/HttpClient.cs index 4107c0d4..168e6af8 100644 --- a/server/Http/HttpClient.cs +++ b/server/Http/HttpClient.cs @@ -83,7 +83,6 @@ public HttpClient(HttpServer aOwner, TcpClient aClient) owner = aOwner; client = aClient; stream = client.GetStream(); - client.Client.UseOnlyOverlappedIO = true; RemoteEndpoint = client.Client.RemoteEndPoint as IPEndPoint; LocalEndPoint = client.Client.LocalEndPoint as IPEndPoint; diff --git a/server/Http/HttpServer.cs b/server/Http/HttpServer.cs index b18ba497..1ec8c46c 100644 --- a/server/Http/HttpServer.cs +++ b/server/Http/HttpServer.cs @@ -55,7 +55,6 @@ public HttpServer(int port) listener = new TcpListener(new IPEndPoint(IPAddress.Any, port)); listener.Server.Ttl = 32; - listener.Server.UseOnlyOverlappedIO = true; listener.Start(); RealPort = ((IPEndPoint)listener.LocalEndpoint).Port; diff --git a/server/Ssdp/SsdpHandler.cs b/server/Ssdp/SsdpHandler.cs index a9b8b7f7..d5a3344b 100644 --- a/server/Ssdp/SsdpHandler.cs +++ b/server/Ssdp/SsdpHandler.cs @@ -58,7 +58,6 @@ public SsdpHandler() queueTimer.Elapsed += ProcessQueue; - client.Client.UseOnlyOverlappedIO = true; client.Client.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, diff --git a/server/Types/HttpException.cs b/server/Types/HttpException.cs index cbf99395..ff8ccf59 100644 --- a/server/Types/HttpException.cs +++ b/server/Types/HttpException.cs @@ -1,16 +1,10 @@ using System; -using System.Runtime.Serialization; namespace NMaier.SimpleDlna.Server { [Serializable] public class HttpException : Exception { - protected HttpException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - public HttpException() { } diff --git a/server/Types/HttpStatusException.cs b/server/Types/HttpStatusException.cs index c05820f2..7204bea0 100644 --- a/server/Types/HttpStatusException.cs +++ b/server/Types/HttpStatusException.cs @@ -1,16 +1,10 @@ using System; -using System.Runtime.Serialization; namespace NMaier.SimpleDlna.Server { [Serializable] public sealed class HttpStatusException : HttpException { - private HttpStatusException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - public HttpStatusException() { } diff --git a/thumbs/VideoThumbnailLoader.cs b/thumbs/VideoThumbnailLoader.cs index 43620c55..3742cdd3 100644 --- a/thumbs/VideoThumbnailLoader.cs +++ b/thumbs/VideoThumbnailLoader.cs @@ -125,7 +125,6 @@ private static MemoryStream GetThumbnailInternal(Stream stream, sti.UseShellExecute = false; sti.FileName = FFmpeg.FFmpegExecutable; sti.Arguments = $"-v quiet -ss {pos} -i pipe: -an -frames:v 1 -f image2 pipe:"; - sti.LoadUserProfile = false; sti.RedirectStandardInput = true; sti.RedirectStandardOutput = true; p.Start(); @@ -152,7 +151,6 @@ private MemoryStream GetThumbnailInternal(FileInfo file, ref int width, sti.UseShellExecute = false; sti.FileName = FFmpeg.FFmpegExecutable; sti.Arguments = $"-v quiet -ss {best} -i \"{file.FullName}\" -an -frames:v 1 -f image2 pipe:"; - sti.LoadUserProfile = false; sti.RedirectStandardOutput = true; p.Start(); diff --git a/util/AddressToMacResolver.cs b/util/AddressToMacResolver.cs index 25e92827..76455d8a 100644 --- a/util/AddressToMacResolver.cs +++ b/util/AddressToMacResolver.cs @@ -43,7 +43,10 @@ public string Resolve(IPAddress ip) string mac = null; try { - if (SafeNativeMethods.SendARP(addr, 0, raw, ref length) == 0) { + // SendARP is iphlpapi.dll, Windows only. Elsewhere there is no MAC + // to report and callers already handle a null. + if (OperatingSystem.IsWindows() && + SafeNativeMethods.SendARP(addr, 0, raw, ref length) == 0) { mac = $"{raw[0]:X}:{raw[1]:X}:{raw[2]:X}:{raw[3]:X}:{raw[4]:X}:{raw[5]:X}"; } } diff --git a/util/FFmpeg.cs b/util/FFmpeg.cs index 6f7e14b3..33aca12f 100644 --- a/util/FFmpeg.cs +++ b/util/FFmpeg.cs @@ -155,7 +155,6 @@ private static IDictionary IdentifyInternalFromProcess( sti.UseShellExecute = false; sti.FileName = FFmpegExecutable; sti.Arguments = $"-i \"{file.FullName}\""; - sti.LoadUserProfile = false; sti.RedirectStandardError = true; p.Start(); IDictionary rv = new Dictionary(); @@ -254,7 +253,6 @@ public static string GetSubtitleSubrip(FileInfo file) sti.UseShellExecute = false; sti.FileName = FFmpegExecutable; sti.Arguments = $"-i \"{file.FullName}\" -map s:0 -f srt pipe:"; - sti.LoadUserProfile = false; sti.RedirectStandardOutput = true; p.Start(); diff --git a/util/HttpStream.cs b/util/HttpStream.cs index d60b5e89..26ddd3cd 100644 --- a/util/HttpStream.cs +++ b/util/HttpStream.cs @@ -179,7 +179,13 @@ protected void OpenAt(long offset, HttpMethod method) Close(); Dispose(); + // TODO: port to HttpClient. HttpWebRequest still functions on .NET 10, + // it is only obsoleted, and this class is currently unreferenced by the + // rest of the solution, so rewriting it here would be unverifiable + // churn. +#pragma warning disable SYSLIB0014 request = (HttpWebRequest)WebRequest.Create(uri); +#pragma warning restore SYSLIB0014 request.Method = method.ToString(); if (referrer != null) { request.Referer = referrer.ToString(); @@ -264,7 +270,9 @@ public override long Seek(long offset, SeekOrigin origin) else { if (response != null && off > 0 && off < SMALL_SEEK) { var buf = new byte[off]; - bufferedStream.Read(buf, 0, (int)off); + // A single Read may return fewer bytes than asked for, which would + // leave the stream short of the requested seek position. + bufferedStream.ReadExactly(buf, 0, (int)off); logger.DebugFormat("Did a small seek of {0}", off); } else { diff --git a/util/NaturalStringComparer.cs b/util/NaturalStringComparer.cs index 435e2580..69e49eb9 100644 --- a/util/NaturalStringComparer.cs +++ b/util/NaturalStringComparer.cs @@ -30,6 +30,12 @@ public NaturalStringComparer(bool stemBase) private static bool HasPlatformSupport() { + // StrCmpLogicalW lives in shlwapi.dll. Probing for it anywhere else just + // costs a DllNotFoundException, so short-circuit and use the managed + // natural sort below. + if (!OperatingSystem.IsWindows()) { + return false; + } try { return SafeNativeMethods.StrCmpLogicalW("a", "b") != 0; } diff --git a/util/ProductInformation.cs b/util/ProductInformation.cs index 5eeb09e4..947daf84 100644 --- a/util/ProductInformation.cs +++ b/util/ProductInformation.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Reflection; namespace NMaier.SimpleDlna.Utilities @@ -54,8 +55,17 @@ public static string Title return titleAttribute.Title; } } - return Path.GetFileNameWithoutExtension( - Assembly.GetExecutingAssembly().CodeBase); + // Assembly.CodeBase is .NET Framework only. Location is the modern + // equivalent, and is empty for assemblies loaded from a single-file + // bundle, hence the process path fallback. + var location = Assembly.GetExecutingAssembly().Location; + if (string.IsNullOrEmpty(location)) { + location = Environment.ProcessPath; + } + if (string.IsNullOrEmpty(location)) { + return Assembly.GetExecutingAssembly().GetName().Name; + } + return Path.GetFileNameWithoutExtension(location); } } } diff --git a/util/RepositoryLookupException.cs b/util/RepositoryLookupException.cs index 7cdb7d96..ab4c8973 100644 --- a/util/RepositoryLookupException.cs +++ b/util/RepositoryLookupException.cs @@ -1,17 +1,10 @@ using System; -using System.Runtime.Serialization; namespace NMaier.SimpleDlna.Utilities { [Serializable] public sealed class RepositoryLookupException : ArgumentException { - private RepositoryLookupException(SerializationInfo info, - StreamingContext context) - : base(info, context) - { - } - public RepositoryLookupException() { } diff --git a/util/StreamPump.cs b/util/StreamPump.cs index f28ded2e..45d49251 100644 --- a/util/StreamPump.cs +++ b/util/StreamPump.cs @@ -29,7 +29,24 @@ public void Dispose() private void Finish(StreamPumpResult result, StreamPumpCallback callback) { - callback?.BeginInvoke(this, result, callback.EndInvoke, null); + if (callback != null) { + // Delegate.BeginInvoke is not supported on .NET and throws + // PlatformNotSupportedException, so the callback is queued explicitly. + // Dispatching it off the completing I/O thread, as before, keeps a + // slow callback from stalling the pump. Unlike the old EndInvoke + // continuation, a throwing callback is logged rather than left to + // take down the process from a thread pool thread. + ThreadPool.QueueUserWorkItem(_ => + { + try { + callback(this, result); + } + catch (Exception ex) { + LogManager.GetLogger(typeof (StreamPump)).Error( + "Stream pump callback failed", ex); + } + }); + } try { sem.Release(); } From 1d252c982ad1952e134e0975278e97b4f3cf18ef Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Sat, 12 Sep 2026 12:55:33 -0500 Subject: [PATCH 09/37] Skip the Windows console icon setup on other platforms ProgramIcon sets the console window's icon through GetConsoleWindow, LoadImage and SendMessage (kernel32/user32). On macOS every startup logged a DllNotFoundException for kernel32.dll together with roughly twenty lines of dlopen probe output, since the loader reports every path it tried. Functionally harmless -- the constructor already caught and logged at debug level, and Dispose is guarded by the null window handle -- but it dominated the startup log. Now returns early unless running on Windows. Found by running the server end to end rather than by the compiler; the P/Invoke is perfectly legal to compile on any platform. --- sdlna/ProgramIcon.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sdlna/ProgramIcon.cs b/sdlna/ProgramIcon.cs index 2f680e78..491dc875 100644 --- a/sdlna/ProgramIcon.cs +++ b/sdlna/ProgramIcon.cs @@ -13,6 +13,12 @@ internal class ProgramIcon : Logging, IDisposable public ProgramIcon() { + // Setting the console window icon is a Windows console concept built on + // kernel32/user32. Attempting it elsewhere only produces a + // DllNotFoundException and a stack trace in the log on every startup. + if (!OperatingSystem.IsWindows()) { + return; + } try { window = SafeNativeMethods.GetConsoleWindow(); if (window == IntPtr.Zero) { From ffdf77cff9219be5a7e39b7d4d5290a41753d2b2 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Sat, 12 Sep 2026 12:55:57 -0500 Subject: [PATCH 10/37] Document the .NET 10 build and run steps The old instructions were implicit: open sdlna.sln in Visual Studio 2013. With the conversion to SDK-style projects the build is now a plain `dotnet build`, and the resulting server runs on Linux and macOS as well as Windows, so it is worth stating. Adds a build section, run examples for both `dotnet run` and a release build, a note that video thumbnailing needs ffmpeg on PATH (image and audio handling do not), and a table of the five remaining projects. --- Readme.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Readme.md b/Readme.md index 0806d10c..abcba1b5 100644 --- a/Readme.md +++ b/Readme.md @@ -4,3 +4,49 @@ A simple, zero-config DLNA media server, that you can just fire up and be done w See [the github page](http://nmaier.github.io/simpleDLNA/) for more details and downloads. + +Building +--- + +Requires the [.NET SDK 10.0](https://dotnet.microsoft.com/download) or newer. + +``` +dotnet build -c Release +``` + +Runs on Windows, Linux and macOS. + +Running +--- + +``` +dotnet run --project sdlna -- [OPTION]... DIRECTORY... +``` + +Or, from a release build: + +``` +dotnet sdlna/bin/Release/net10.0/sdlna.dll [OPTION]... DIRECTORY... +``` + +`sdlna --help` lists the options. A typical invocation, serving two +directories on a fixed port with an on-disk metadata cache: + +``` +dotnet sdlna.dll -p 8895 -c ~/.sdlna-cache.db ~/Music ~/Videos +``` + +Thumbnailing video files and reading their duration requires +[ffmpeg](https://ffmpeg.org/) on `PATH` (or pointed at by `FFMPEG_HOME`). +Image and audio handling have no external dependencies. + +Layout +--- + +| Project | Output | Role | +|------------|-------------------------------|-------------------------------------------------------------| +| `util` | `SimpleDlna.Utilities` | SQLite access, ffmpeg invocation, stream pumps, sorting | +| `server` | `SimpleDlna.Server` | HTTP and SSDP servers, UPnP/DLNA handlers, views, comparers | +| `thumbs` | `SimpleDlna.Thumbnails` | Thumbnail generation | +| `fsserver` | `SimpleDlna.FileMediaServer` | Filesystem media source and its metadata cache | +| `sdlna` | `sdlna` | Console entry point | From 4e8f5fec991d8c1cd5a8e100e7dd5ca2b6f01b7a Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 02:30:31 -0500 Subject: [PATCH 11/37] Pad resolved MAC octets to two digits so MAC restrictions can match AddressToMacResolver formatted each octet with {:X}, which drops the leading zero: a client at 01:AF:BC:00:0A:FF was reported as 1:AF:BC:0:A:FF. MacAuthorizer does an exact lookup against the configured entries, which IP.IsAcceptedMAC requires to be six two-digit groups, so any client whose MAC contains an octet below 0x10 could never be admitted -- roughly a third of all addresses. This is the same one-character fix proposed upstream in nmaier/simpleDLNA#68 by @cyclamenkde; credit for spotting it is theirs. It is included here because the configuration file added in the following commits makes MAC restrictions a first-class, per-server setting, and shipping that on top of a known matching bug would be misleading. Note that the MAC lookup itself (iphlpapi!SendARP) only exists on Windows. Elsewhere no MAC is resolved and MAC restrictions never match; that limitation predates the port and is documented rather than changed. Co-Authored-By: Claude Opus 5 --- util/AddressToMacResolver.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/util/AddressToMacResolver.cs b/util/AddressToMacResolver.cs index 76455d8a..d2157ada 100644 --- a/util/AddressToMacResolver.cs +++ b/util/AddressToMacResolver.cs @@ -47,7 +47,9 @@ public string Resolve(IPAddress ip) // to report and callers already handle a null. if (OperatingSystem.IsWindows() && SafeNativeMethods.SendARP(addr, 0, raw, ref length) == 0) { - mac = $"{raw[0]:X}:{raw[1]:X}:{raw[2]:X}:{raw[3]:X}:{raw[4]:X}:{raw[5]:X}"; + // X2, not X: MacAuthorizer compares against configured entries of + // the form 01:AF:BC:00:0A:FF, so every octet needs both digits. + mac = $"{raw[0]:X2}:{raw[1]:X2}:{raw[2]:X2}:{raw[3]:X2}:{raw[4]:X2}:{raw[5]:X2}"; } } catch (DllNotFoundException) { From badb0c3419361f4389b348c2c8e31beed67e318c Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 02:37:00 -0500 Subject: [PATCH 12/37] Run servers from a JSON configuration file when no folders are given Requested in review of this PR: with the GUI gone there was no way to keep a server setup between runs short of retyping every option. sdlna now reads ~/.sdlna/config.json (%USERPROFILE%\.sdlna\config.json on Windows) and, when started without folders, starts every server described there. Two modes, strictly separated sdlna ... Unchanged: serves exactly those folders using only the command-line options. The configuration file is not read at all. sdlna Starts the configured servers. Previously this served the current directory, because Options.Directories defaulted to "."; that implicit default is gone, and "sdlna ." does what plain "sdlna" used to. With no file, or a file with no servers, sdlna explains how to add one or how to serve folders directly, and exits 1. Per-server settings, like the old GUI Each server has its own folders, media types, sort order and direction, views, and restrictions, and all of them share one HTTP server. This is what the console could not previously express: --seperate mounts one server per folder but they share a single set of options and one global authorizer, so "video for the TV, audio for everyone" needed two processes. Restrictions are applied per server through FileServer.Authorizer, the mechanism the GUI used, rather than the global HttpAuthorizer that -i/-m/-u attach to the HTTP server. As before, MediaMount always admits loopback clients, so restrictions only constrain other machines. A folder that is missing at startup (an unmounted drive, say) is skipped with a warning; a server with no remaining folders is reported and the others still start. Process-wide settings "port" (default 0, any free port) and "cache" (default ~/.sdlna/cache.db; the value "none" turns caching off) live in the file. -p and -c on the command line override them. -p tracks whether it was given, so "-p 0" can override a configured port. Logging options and --no-rescanning apply in both modes. -t, -v, -s, -d, -n, -i, -m, -u and --seperate describe a single ad-hoc server. Given without folders they are now rejected with an explanation instead of being silently ignored. Reading and writing the file Read through Microsoft.Extensions.Configuration.Json and the configuration binder, written back with System.Text.Json (camelCase, indented, via a temporary file and a move so an interrupted write cannot truncate it). The .sdlna directory is marked hidden on Windows when created; the leading dot already hides it elsewhere. Two binder behaviours shaped the model, both verified empirically: collections are initialised empty, never with defaults, because the binder appends to an existing collection rather than replacing it; and "[]" and a missing key both bind to null, so an empty mediaTypes or folders list is caught by validation rather than defaulted. Hand-edited files are checked thoroughly. Comments and trailing commas are accepted. Unknown keys are rejected (ErrorOnUnknownConfiguration), so a typo is reported instead of ignored. Every problem is collected and reported at once -- missing folders or media types, unknown sort orders, views, media types, malformed MAC or IP addresses, duplicate names -- with a pointer to the command that opens the file. Binder and parser errors are reworded to name the offending key and position instead of internal type names: e.g. "unknown setting 'mediatype' in a server", "',' is an invalid start of a property name ... BytePositionInLine: 14". Verified against a hand-written file with three servers on one port: - a video-only server listed only the video, not the JPEG beside it - a server with the music view presented Albums/Genre/Performers - a server restricted to 10.9.9.9 answered 403 to this machine's LAN address while the unrestricted server answered 200; adding the LAN address to its list turned the 403 into a 200 - the configured port was used, -p overrode it, the default cache was created under ~/.sdlna, and "cache": "none" created none - "sdlna " used a random port, no cache and none of the configured servers - each malformed file above produced the error described The command to manage the file follows in the next commit. Co-Authored-By: Claude Opus 5 --- Directory.Packages.props | 4 +- sdlna/Configuration.cs | 558 +++++++++++++++++++++++++++++++++++++++ sdlna/Options.cs | 57 +++- sdlna/Program.cs | 152 ++++++++++- sdlna/sdlna.csproj | 4 +- 5 files changed, 769 insertions(+), 6 deletions(-) create mode 100644 sdlna/Configuration.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index e0acca5c..e9709148 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,4 +1,4 @@ - + + 2.0.0 + + false diff --git a/Directory.Packages.props b/Directory.Packages.props index e9709148..f8104692 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -20,7 +20,7 @@ - + diff --git a/sdlna/ProgramIcon.cs b/sdlna/ProgramIcon.cs index 491dc875..dccfd992 100644 --- a/sdlna/ProgramIcon.cs +++ b/sdlna/ProgramIcon.cs @@ -24,8 +24,14 @@ public ProgramIcon() if (window == IntPtr.Zero) { throw new Exception("Cannot get console window"); } + // IL3002: GetHINSTANCE returns -1 for a module with no file on disk, + // which is the case under single-file publish. LoadImage then fails, + // the catch below logs it at debug level and the console keeps its + // default icon. Purely cosmetic, so it is not worth special casing. +#pragma warning disable IL3002 var inst = Marshal.GetHINSTANCE( Assembly.GetEntryAssembly().GetModules()[0]); +#pragma warning restore IL3002 var iconLg = SafeNativeMethods.LoadImage(inst, "#32512", 1, 0, 0, 0x40); if (iconLg == IntPtr.Zero) { throw new Exception("Failed to load large icon"); diff --git a/thumbs/thumbs.csproj b/thumbs/thumbs.csproj index 60228e0a..90fc9b7b 100644 --- a/thumbs/thumbs.csproj +++ b/thumbs/thumbs.csproj @@ -1,4 +1,4 @@ - + NMaier.SimpleDlna.Thumbnails @@ -8,7 +8,7 @@ - + diff --git a/util/FFmpeg.cs b/util/FFmpeg.cs index 33aca12f..e7d5c240 100644 --- a/util/FFmpeg.cs +++ b/util/FFmpeg.cs @@ -4,7 +4,6 @@ using System.Drawing; using System.Globalization; using System.IO; -using System.Reflection; using System.Text.RegularExpressions; using log4net; @@ -55,9 +54,18 @@ private static string FindExecutable(string executable) executable += ".exe"; } var places = new List(); - var assemblyLoc = Assembly.GetExecutingAssembly().Location; - if (assemblyLoc != null) { - places.Add(new FileInfo(assemblyLoc).Directory); + // AppContext.BaseDirectory, not Assembly.Location: the latter is an + // empty (non-null) string in a single-file app, and FileInfo throws on + // an empty path. That threw inside this static initializer, taking the + // whole FFmpeg class down with a TypeInitializationException. + try { + var baseDirectory = AppContext.BaseDirectory; + if (!string.IsNullOrEmpty(baseDirectory)) { + places.Add(new DirectoryInfo(baseDirectory)); + } + } + catch (Exception) { + // ignored } try { var ffhome = Environment.GetEnvironmentVariable("FFMPEG_HOME"); diff --git a/util/ProductInformation.cs b/util/ProductInformation.cs index 947daf84..0b5a8617 100644 --- a/util/ProductInformation.cs +++ b/util/ProductInformation.cs @@ -57,8 +57,11 @@ public static string Title } // Assembly.CodeBase is .NET Framework only. Location is the modern // equivalent, and is empty for assemblies loaded from a single-file - // bundle, hence the process path fallback. + // bundle, hence the process path fallback. IL3000 flags the Location + // read; the empty case is exactly what the next line handles. +#pragma warning disable IL3000 var location = Assembly.GetExecutingAssembly().Location; +#pragma warning restore IL3000 if (string.IsNullOrEmpty(location)) { location = Environment.ProcessPath; } From 9a992efc173473ff0e2108b35c6b3ef0c7bc5235 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 11:10:57 -0500 Subject: [PATCH 17/37] Announce Matroska as video/x-matroska, keeping video/x-mkv for Samsung Every client was told that .mkv (and .matroska, .mk3d, .webm) files are video/x-mkv. The type Matroska documents, and that MiniDLNA and Universal Media Server both send, is video/x-matroska; clients that only recognise the latter may not list or play MKV files. nmaier/simpleDLNA#31 by Matthew1471 proposes exactly that one-line change to DlnaMaps, and this includes it. On its own, though, it risks a regression for Samsung TVs. MiniDLNA sends video/x-matroska generally but switches to video/x-mkv for Samsung clients, commenting that they expect that "[wrong]" type, and simpleDLNA -- which already advertises Samsung capabilities (sec:ProductCap) -- may well have chosen x-mkv for them. So: - video/x-matroska is the default, as in #31. - Clients whose User-Agent contains "SEC_HHP_" (Samsung TVs and players since 2010) or "SamsungWiselinkPro" (2008 Series A) keep video/x-mkv. These are the markers MiniDLNA matches Samsung clients on. Samsung therefore sees no change, and every other client gets the standard type. The MIME table reaches clients in three places, and all now go through DlnaMaps.MimeFor / ProtocolInfoFor so they cannot disagree: 1. The HTTP Content-Type of the file itself (ItemResponse). 2. protocolInfo on each item in Browse results (MediaMount_SOAP). 3. The ConnectionManager GetProtocolInfo source list, previously one precomputed string; there are now two, standard and Samsung. Browse results are cached (soapCache), keyed only by the request's SOAP parameters. That meant the first client to browse a folder decided the types everyone else was told, and testing showed exactly that: after a generic client browsed first, a Samsung client received a Content-Type of video/x-mkv but browse entries still saying video/x-matroska. The cache key now includes the client's MIME variant. Verified against a running server with an .mkv and an .mp4, as a generic client (VLC's User-Agent), a current Samsung TV ("SEC_HHP_[TV] Samsung Q70 Series") and a 2008 Samsung ("SamsungWiselinkPro"): browse protocolInfo Content-Type GetProtocolInfo generic, .mkv video/x-matroska video/x-matroska x-matroska only Samsung, .mkv video/x-mkv video/x-mkv x-mkv only any, .mp4 video/mp4 video/mp4 unchanged Browsing again as the generic client after the Samsung ones still yielded video/x-matroska, so the cache no longer leaks between them. Not verified on physical TVs; the Samsung behaviour relies on MiniDLNA's long-standing handling rather than a device test. Co-Authored-By: Claude Opus 5 --- server/Handlers/MediaMount_SOAP.cs | 15 +++--- server/Responses/ItemResponse.cs | 2 +- server/Types/DlnaMaps.cs | 73 ++++++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/server/Handlers/MediaMount_SOAP.cs b/server/Handlers/MediaMount_SOAP.cs index a1df36a5..5e2b6cde 100644 --- a/server/Handlers/MediaMount_SOAP.cs +++ b/server/Handlers/MediaMount_SOAP.cs @@ -82,7 +82,7 @@ private void AddCover(IRequest request, IMediaItem resource, res.SetAttribute("protocolInfo", string.Format( "http-get:*:{1}:DLNA.ORG_PN={0};DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS={2}", - c.PN, DlnaMaps.Mime[c.Type], DlnaMaps.DefaultStreaming + c.PN, DlnaMaps.MimeFor(c.Type, request.Headers), DlnaMaps.DefaultStreaming )); var width = c.MetaWidth; var height = c.MetaHeight; @@ -275,7 +275,7 @@ private void Browse_AddItem(IRequest request, XmlDocument result, res.SetAttribute("protocolInfo", string.Format( "http-get:*:{1}:DLNA.ORG_PN={0};DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS={2}", - resource.PN, DlnaMaps.Mime[resource.Type], DlnaMaps.DefaultStreaming + resource.PN, DlnaMaps.MimeFor(resource.Type, request.Headers), DlnaMaps.DefaultStreaming )); item.AppendChild(res); @@ -343,7 +343,10 @@ private static XmlElement CreateObjectClass(XmlDocument result, private IEnumerable> HandleBrowse( IRequest request, IHeaders sparams) { - var key = Prefix + sparams.HeaderBlock; + // Browse results embed per-client MIME types (see DlnaMaps.MimeFor), so + // a result built for one kind of client must not be served to another. + var key = Prefix + DlnaMaps.MimeVariant(request.Headers) + "\n" + + sparams.HeaderBlock; AttributeCollection rv; if (soapCache.TryGetValue(key, out rv)) { return rv; @@ -420,11 +423,11 @@ private static IHeaders HandleGetCurrentConnectionInfo() }; } - private static IHeaders HandleGetProtocolInfo() + private static IHeaders HandleGetProtocolInfo(IRequest request) { return new RawHeaders { - {"Source", DlnaMaps.ProtocolInfo}, + {"Source", DlnaMaps.ProtocolInfoFor(request.Headers)}, {"Sink", string.Empty} }; } @@ -539,7 +542,7 @@ private IResponse ProcessSoapRequest(IRequest request) result = HandleGetCurrentConnectionInfo(); break; case "GetProtocolInfo": - result = HandleGetProtocolInfo(); + result = HandleGetProtocolInfo(request); break; case "IsAuthorized": result = HandleIsAuthorized(); diff --git a/server/Responses/ItemResponse.cs b/server/Responses/ItemResponse.cs index 701ecb68..7427c124 100644 --- a/server/Responses/ItemResponse.cs +++ b/server/Responses/ItemResponse.cs @@ -22,7 +22,7 @@ public ItemResponse(string prefix, IRequest request, IMediaResource item, headers.Add("Last-Modified", meta.InfoDate.ToString("R")); } headers.Add("Accept-Ranges", "bytes"); - headers.Add("Content-Type", DlnaMaps.Mime[item.Type]); + headers.Add("Content-Type", DlnaMaps.MimeFor(item.Type, request.Headers)); if (request.Headers.ContainsKey("getcontentFeatures.dlna.org")) { try { headers.Add( diff --git a/server/Types/DlnaMaps.cs b/server/Types/DlnaMaps.cs index edb13d70..51b486c4 100644 --- a/server/Types/DlnaMaps.cs +++ b/server/Types/DlnaMaps.cs @@ -14,6 +14,21 @@ public static class DlnaMaps DlnaFlags.DlnaV15 ); + /// + /// The Matroska MIME type Samsung TVs expect instead of video/x-matroska. + /// + private const string SAMSUNG_MKV_MIME = "video/x-mkv"; + + /// + /// User-Agent fragments identifying Samsung TVs and players, matched the + /// way MiniDLNA does. "SEC_HHP_" covers most models since 2010; + /// "SamsungWiselinkPro" covers the 2008 Series A. + /// + private static readonly string[] samsungUserAgents = + { + "SEC_HHP_", "SamsungWiselinkPro" + }; + internal static readonly string DefaultInteractive = FlagsToString( DlnaFlags.InteractiveTransferMode | DlnaFlags.BackgroundTransferMode | @@ -101,7 +116,7 @@ public static class DlnaMaps {DlnaMime.VideoAVC, "video/mp4"}, {DlnaMime.VideoAVI, "video/avi"}, {DlnaMime.VideoFLV, "video/flv"}, - {DlnaMime.VideoMKV, "video/x-mkv"}, + {DlnaMime.VideoMKV, "video/x-matroska"}, {DlnaMime.VideoMPEG, "video/mpeg"}, {DlnaMime.VideoOGV, "video/ogg"}, {DlnaMime.VideoWMV, "video/x-ms-wmv"} @@ -289,7 +304,9 @@ public static class DlnaMaps public static readonly Dictionary MainPN = GenerateMainPN(); - public static readonly string ProtocolInfo = GenerateProtocolInfo(); + public static readonly string ProtocolInfo = GenerateProtocolInfo(t => Mime[t]); + + private static readonly string samsungProtocolInfo = GenerateProtocolInfo(SamsungMime); static DlnaMaps() { @@ -350,10 +367,10 @@ static DlnaMaps() DlnaMediaTypes.Audio); } - private static string GenerateProtocolInfo() + private static string GenerateProtocolInfo(Func mimeFor) { var pns = (from p in AllPN - let mime = Mime[p.Key] + let mime = mimeFor(p.Key) from pn in p.Value select string.Format("http-get:*:{1}:DLNA.ORG_PN={0};DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS={2}", pn, @@ -378,6 +395,54 @@ private static void InitMedia(string[][] k, DlnaMediaTypes t) } } + private static string SamsungMime(DlnaMime type) + { + return type == DlnaMime.VideoMKV ? SAMSUNG_MKV_MIME : Mime[type]; + } + + private static bool IsSamsung(IHeaders requestHeaders) + { + string userAgent; + return requestHeaders != null && + requestHeaders.TryGetValue("User-Agent", out userAgent) && + userAgent != null && + samsungUserAgents.Any( + s => userAgent.IndexOf(s, StringComparison.Ordinal) >= 0); + } + + /// + /// The MIME type to announce for to the client + /// that sent . + /// + /// + /// Matroska is announced as video/x-matroska, the type Matroska itself, + /// MiniDLNA and Universal Media Server use. Samsung TVs expect the + /// non-standard video/x-mkv instead, which every client was sent before, + /// so they keep getting it; MiniDLNA makes the same exception. + /// + internal static string MimeFor(DlnaMime type, IHeaders requestHeaders) + { + return IsSamsung(requestHeaders) ? SamsungMime(type) : Mime[type]; + } + + /// + /// Distinguishes clients that are announced different MIME types, for + /// anything that caches responses containing them. + /// + internal static string MimeVariant(IHeaders requestHeaders) + { + return IsSamsung(requestHeaders) ? "samsung" : "standard"; + } + + /// + /// The GetProtocolInfo source list for a client, consistent with the + /// types announces to it. + /// + internal static string ProtocolInfoFor(IHeaders requestHeaders) + { + return IsSamsung(requestHeaders) ? samsungProtocolInfo : ProtocolInfo; + } + internal static string FlagsToString(DlnaFlags flags) { return $"{(ulong)flags:X8}{0:D24}"; From a3b021e3c1be7284fd1a1c022259b40dcaf092fd Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 11:14:15 -0500 Subject: [PATCH 18/37] Serve the current directory when no servers are configured The previous behaviour -- refusing to start when run without folders and without saved servers -- contradicted the project's own "zero-config" promise and blocked the simplest use: running sdlna in a folder. That had been the long-standing behaviour, since Options.Directories defaulted to "."; the configuration file commit replaced it with guidance and exit 1. Now, when sdlna is run without folders: - servers configured -> they start, as before. - none configured -> the current directory is served exactly as (no file, or a file "sdlna ." would, with every command-line listing none) option applying, after a warning on stderr that shows the absolute path being served, says nothing has been saved, and gives the command to add a server. - file exists but is -> still an error, exit 1. Falling back would invalid silently hide a setup the user tried to make. Because the fallback is literally the ad-hoc mode, -t, -s, -d, -v, -n, -i, -m, -u and --seperate apply to it; they are only rejected when configured servers exist. That rejection message now says why ("each have their own settings") and offers both ways forward. The absolute path is printed rather than "." so it is obvious when sdlna was started from somewhere unexpected, such as a home directory. Updates the --help epilog and the readme's Quick start and "Two ways to run" sections, which described the refusal, including its note that "sdlna ." was needed for the old behaviour. Verified with an isolated HOME, running from a folder holding an image, an .mp4 and an .mkv: no file warning; served all three no file, -t video warning; served only the two videos file with "servers": [] warning naming the file; served all three file with a server no warning; the server's own settings applied file with a server, -t video rejected, exit 2 file with "port": "oops" error naming the key, exit 1; nothing served Co-Authored-By: Claude Opus 5 --- Readme.md | 28 +++++++++++++++--------- sdlna/Options.cs | 8 ++++--- sdlna/Program.cs | 55 +++++++++++++++++++++++++----------------------- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/Readme.md b/Readme.md index 88a2012c..9e8cdb4e 100644 --- a/Readme.md +++ b/Readme.md @@ -40,14 +40,22 @@ dotnet sdlna/bin/Release/net10.0/sdlna.dll [OPTION]... Quick start --- -Serve a folder once, with nothing saved: +With nothing set up, just run `sdlna` in a folder to serve it: ``` -sdlna ~/Videos +cd ~/Videos +sdlna +``` + +It warns that no servers are configured and serves the current directory. Or +name the folders to serve: + +``` +sdlna ~/Videos ~/Music ``` -Or set up a server that is remembered, then start it (and any others you add) -by running `sdlna` on its own: +Either way nothing is saved. To keep a setup, add a server. From then on, +running `sdlna` on its own starts it, along with any others you add: ``` sdlna --server add Videos ~/Videos @@ -64,15 +72,15 @@ Two ways to run the options on the command line. The configuration file is not read at all. **Without folders**, `sdlna` starts every server in the -[configuration file](#the-configuration-file). If there are none yet, it -explains how to add one and exits. - -> Earlier versions served the current directory when run without folders. To -> do that now, run `sdlna .` +[configuration file](#the-configuration-file). If no servers are configured, +because the file doesn't exist or lists none, it serves the current directory +instead, exactly as `sdlna .` would, and prints a warning explaining how to +save servers. A configuration file that exists but is invalid is reported as an +error rather than skipped. The options split accordingly. `sdlna --help` lists them all. -| Option | With folders | Without folders | +| Option | With folders, or no servers configured | Configured servers | |---|---|---| | `-p`, `--port` | HTTP port (default 0: any free port) | Overrides `port` from the file | | `-c`, `--cache` | Metadata cache file (default: none) | Overrides `cache` from the file | diff --git a/sdlna/Options.cs b/sdlna/Options.cs index ea64b885..aa2807bf 100644 --- a/sdlna/Options.cs +++ b/sdlna/Options.cs @@ -21,9 +21,11 @@ internal class Options : GetOpt "ignores the configuration file.\n" + "\n" + "Without folders, sdlna starts the servers saved in ~/.sdlna/config.json\n" + - "(%USERPROFILE%\\.sdlna\\config.json on Windows), and only -c, -p, -l,\n" + - "--log-file and --no-rescanning apply. Set up servers with\n" + - "'sdlna --server add '; see 'sdlna --server help'."; + "(%USERPROFILE%\\.sdlna\\config.json on Windows); only -c, -p, -l,\n" + + "--log-file and --no-rescanning then apply. If no servers are saved, it\n" + + "serves the current directory instead, as 'sdlna .' would. Save servers\n" + + "with 'sdlna --server add '; see 'sdlna --server help'."; + [Argument("cache", HelpVar = "file", HelpText = "Cache file to use for storing meta data (default: none)")] [ShortArgument('c')] public FileInfo CacheFile = null; [Argument("sort-descending", HelpText = "Sort order; see --list-sort-orders")] [ShortArgument('d')] [FlagArgument(true)] public bool DescendingOrder = false; diff --git a/sdlna/Program.cs b/sdlna/Program.cs index 582e3224..2635beaa 100644 --- a/sdlna/Program.cs +++ b/sdlna/Program.cs @@ -190,8 +190,18 @@ private static void Main(string[] args) return; } if (options.Directories.Length == 0) { - RunConfiguredServers(options); - return; + // An invalid file still stops here with an error (via + // ConfigurationException) rather than being silently bypassed. + var config = ConfigurationStore.Load(); + if (config != null && config.Servers.Count != 0) { + RunConfiguredServers(options, config); + return; + } + // Zero-config: nothing is saved, so serve the current directory + // exactly as "sdlna ." would, with every command-line option, and + // say how to save servers instead of refusing to start. + WarnServingCurrentDirectory(config != null); + options.Directories = new[] {new DirectoryInfo(".")}; } options.SetupLogging(); @@ -268,20 +278,20 @@ private static void Main(string[] args) #endif } - private static void PrintNoServersConfigured(bool fileExists) + private static void WarnServingCurrentDirectory(bool fileExists) { - Console.WriteLine( + Console.Error.WriteLine( fileExists - ? $"No media servers are configured in {ConfigurationStore.FilePath}." - : "No media servers are configured yet."); - Console.WriteLine(); - Console.WriteLine("Set one up. It is saved, and started every time you run sdlna:"); - Console.WriteLine(" sdlna --server add "); - Console.WriteLine(); - Console.WriteLine("Or serve folders just this once, without saving anything:"); - Console.WriteLine(" sdlna [...]"); - Console.WriteLine(); - Console.WriteLine("Run 'sdlna --server help' to manage servers, or 'sdlna --help' for all options."); + ? $"Warning: No servers are configured in {ConfigurationStore.FilePath}," + : "Warning: No servers are configured and no configuration file exists,"); + Console.Error.WriteLine("so serving the current directory:"); + Console.Error.WriteLine(" {0}", Path.GetFullPath(".")); + Console.Error.WriteLine(); + Console.Error.WriteLine( + "Nothing has been saved. To set up servers that 'sdlna' starts every time, add one with:"); + Console.Error.WriteLine(" sdlna --server add "); + Console.Error.WriteLine("See 'sdlna --server help' for more."); + Console.Error.WriteLine(); } private static void Run(HttpServer server) @@ -332,27 +342,20 @@ private static FileServer SetupFileServer(Options options, /// Only the process-wide options (port, cache, logging, rescanning) /// come from the command line here; everything else is per server. /// - private static void RunConfiguredServers(Options options) + private static void RunConfiguredServers(Options options, + SdlnaConfiguration config) { var given = options.GivenServerOptions().ToList(); if (given.Count != 0) { Console.Error.WriteLine( - "Error: these options only apply when folders are given on the command line: {0}", - string.Join(", ", given)); + "Error: {0} cannot be used with the servers configured in {1}, which each have their own settings.", + string.Join(", ", given), ConfigurationStore.FilePath); Console.Error.WriteLine( - "Configured servers take these settings from {0}; change them with 'sdlna --server config ...'.", - ConfigurationStore.FilePath); + "Change those with 'sdlna --server config ...', or give folders to serve them with these options instead."); Environment.ExitCode = 2; return; } - var config = ConfigurationStore.Load(); - if (config == null || config.Servers.Count == 0) { - PrintNoServersConfigured(config != null); - Environment.ExitCode = 1; - return; - } - options.SetupLogging(); var port = options.PortSpecified ? options.Port : config.Port; From ab0a7669b478a1d816b68008b3783275b067f816 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 12:32:23 -0500 Subject: [PATCH 19/37] Keep cached browse results from handing out another address's links Browse results contain absolute URLs for each item's file and cover, built from the local address the requesting client connected to: http://{request.LocalEndPoint.Address}:{port}/mm-1/file//res Those results are cached in soapCache, but the cache key did not include that address. Whichever client browsed a folder first therefore decided the host in every link that anyone else was given for it, until the cache happened to be cleared. This needs no unusual network setup. Any browse from the machine sdlna runs on -- a local VLC, say -- connects over loopback, so TVs on the network were then handed links to 127.0.0.1, which they cannot reach: they could list the folder but not play anything in it. Machines with several interfaces (a VPN, a second network card) hit the same thing between networks. Reproduced against the previous build by browsing first over loopback, then over this machine's LAN address: browsed via 127.0.0.1 -> links point to 127.0.0.1:9000 browsed via 192.168.20.38 -> links point to 127.0.0.1:9000 The cache key now includes the local endpoint, alongside the client's MIME variant added in 9a992ef. After the change, alternating the two repeatedly so that cache hits are exercised: browsed via 127.0.0.1 -> links point to 127.0.0.1:9000 browsed via 192.168.20.38 -> links point to 192.168.20.38:9000 browsed via 127.0.0.1 -> links point to 127.0.0.1:9000 browsed via 192.168.20.38 -> links point to 192.168.20.38:9000 and the file and cover links given to the LAN client, fetched from the LAN address, both returned 206 with data. The other places that build URLs from the local address -- the device description, subtitle links in ItemResponse, and redirects -- are produced per request and were never cached, so they needed no change. Co-Authored-By: Claude Opus 5 --- server/Handlers/MediaMount_SOAP.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/server/Handlers/MediaMount_SOAP.cs b/server/Handlers/MediaMount_SOAP.cs index 5e2b6cde..843e0c91 100644 --- a/server/Handlers/MediaMount_SOAP.cs +++ b/server/Handlers/MediaMount_SOAP.cs @@ -343,9 +343,13 @@ private static XmlElement CreateObjectClass(XmlDocument result, private IEnumerable> HandleBrowse( IRequest request, IHeaders sparams) { - // Browse results embed per-client MIME types (see DlnaMaps.MimeFor), so - // a result built for one kind of client must not be served to another. - var key = Prefix + DlnaMaps.MimeVariant(request.Headers) + "\n" + + // Browse results embed absolute URLs built from the local address the + // client connected to, and per-client MIME types (see DlnaMaps.MimeFor). + // A result built for one client must not be served to another that + // reached this machine through a different address -- loopback versus + // the LAN, or another network interface -- or that needs other types. + var key = Prefix + request.LocalEndPoint + "\n" + + DlnaMaps.MimeVariant(request.Headers) + "\n" + sparams.HeaderBlock; AttributeCollection rv; if (soapCache.TryGetValue(key, out rv)) { From ef8532179cfe4d72e7ec6f563e3b2a6d20473937 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 12:33:44 -0500 Subject: [PATCH 20/37] Tolerate a home directory that does not exist Environment.GetFolderPath returns an empty string, not the path, when the folder does not exist. Verified on .NET 10: HOME=/tmp/does-not-exist GetFolderPath(UserProfile) = "" GetFolderPath(UserProfile, DoNotVerify) = "/tmp/does-not-exist" A missing home directory is ordinary for exactly the places a media server runs unattended -- service accounts, containers, NAS packages -- and two things broke under it. util/FFmpeg.cs: video thumbnails and durations stopped working The static list of places to look for ffmpeg ended with new DirectoryInfo(GetFolderPath(UserProfile)), i.e. new DirectoryInfo(""). That throws inside FFmpeg's static initializer, so every later use of FFmpeg raised TypeInitializationException for the life of the process. Found while testing the previous commit, when a run under a nonexistent HOME returned 500 for every video cover: System.TypeInitializationException: The type initializer for 'NMaier.SimpleDlna.Utilities.FFmpeg' threw an exception. ---> System.ArgumentException: The value cannot be an empty string. at System.IO.DirectoryInfo..ctor(String path) at NMaier.SimpleDlna.Utilities.FFmpeg..cctor() Folders that resolve to an empty path are now skipped. One side effect: on Linux and macOS the Program Files folders also resolve to "", and Path.Combine("", "ffmpeg") had been producing a relative "ffmpeg" folder, so ./ffmpeg under the working directory was searched by accident. That is no longer searched. ffmpeg beside the executable, in FFMPEG_HOME, under the home directory and on PATH is still found. sdlna/Configuration.cs: the configuration moved to the working directory The home lookup behind ~/.sdlna had the same flaw, so the configuration path quietly became ".sdlna/config.json" relative to wherever sdlna was started, and "--server add" would have created .sdlna there. It now uses SpecialFolderOption.DoNotVerify. Verified with HOME pointing at a directory that does not exist: before after --server config path .sdlna/config.json /tmp/nohome-probe/.sdlna/config.json video cover request HTTP 500 HTTP 206 with data ffmpeg type initializer failed "Found ffmpeg at /opt/homebrew/bin/ffmpeg" --server add (would write to the cwd) created under that HOME; nothing in the cwd Co-Authored-By: Claude Opus 5 --- sdlna/Configuration.cs | 8 ++++++- util/FFmpeg.cs | 47 ++++++++++++++++++++++++++++++------------ 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/sdlna/Configuration.cs b/sdlna/Configuration.cs index 729fc11e..0f21f6ff 100644 --- a/sdlna/Configuration.cs +++ b/sdlna/Configuration.cs @@ -285,8 +285,14 @@ internal static class ConfigurationStore public const string CACHE_NONE = "none"; + // DoNotVerify: without it GetFolderPath returns "" when the home + // directory does not exist yet, which would silently turn the + // configuration path into ".sdlna/config.json" relative to wherever sdlna + // happens to be run. private static string HomeDirectory => - Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + Environment.GetFolderPath( + Environment.SpecialFolder.UserProfile, + Environment.SpecialFolderOption.DoNotVerify); public static string DirectoryPath => Path.Combine(HomeDirectory, ".sdlna"); diff --git a/util/FFmpeg.cs b/util/FFmpeg.cs index e7d5c240..e0845039 100644 --- a/util/FFmpeg.cs +++ b/util/FFmpeg.cs @@ -14,15 +14,7 @@ namespace NMaier.SimpleDlna.Utilities public static class FFmpeg { private static readonly DirectoryInfo[] specialLocations = - { - GetFFMpegFolder(Environment.SpecialFolder.CommonProgramFiles), - GetFFMpegFolder(Environment.SpecialFolder.CommonProgramFilesX86), - GetFFMpegFolder(Environment.SpecialFolder.ProgramFiles), - GetFFMpegFolder(Environment.SpecialFolder.ProgramFilesX86), - GetFFMpegFolder(Environment.SpecialFolder.UserProfile), - new DirectoryInfo(Environment.GetFolderPath( - Environment.SpecialFolder.UserProfile)) - }; + GetSpecialLocations(); private static readonly InfoCache infoCache = new InfoCache(500); @@ -39,11 +31,40 @@ public static class FFmpeg public static readonly string FFmpegExecutable = FindExecutable("ffmpeg"); - private static DirectoryInfo GetFFMpegFolder( - Environment.SpecialFolder folder) + /// + /// Conventional folders to look for ffmpeg in. + /// + /// + /// GetFolderPath returns an empty string for a folder that does not + /// exist on this system: the Program Files folders on Linux and macOS, + /// or a home directory that was never created, as is common for service + /// accounts and containers. Such folders are skipped. new + /// DirectoryInfo("") throws, and throwing in this static initializer + /// would disable FFmpeg -- and with it every video thumbnail and + /// duration -- for the life of the process. + /// + private static DirectoryInfo[] GetSpecialLocations() { - return new DirectoryInfo( - Path.Combine(Environment.GetFolderPath(folder), "ffmpeg")); + var rv = new List(); + var folders = new[] + { + Environment.SpecialFolder.CommonProgramFiles, + Environment.SpecialFolder.CommonProgramFilesX86, + Environment.SpecialFolder.ProgramFiles, + Environment.SpecialFolder.ProgramFilesX86, + Environment.SpecialFolder.UserProfile + }; + foreach (var folder in folders) { + var path = Environment.GetFolderPath(folder); + if (!string.IsNullOrEmpty(path)) { + rv.Add(new DirectoryInfo(Path.Combine(path, "ffmpeg"))); + } + } + var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + if (!string.IsNullOrEmpty(home)) { + rv.Add(new DirectoryInfo(home)); + } + return rv.ToArray(); } private static string FindExecutable(string executable) From 7914d57f2c5d68a7bbf2e49dd4d92a0dd741615a Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 12:35:28 -0500 Subject: [PATCH 21/37] Announce WebM as video/webm instead of as Matroska ".webm" sat in the Matroska extension list, so WebM files were announced exactly like MKV: video/x-matroska to most clients (video/x-mkv before 9a992ef) and video/x-mkv to Samsung. WebM has its own type, video/webm, which Universal Media Server also sends, and clients that recognise WebM by it -- including those that play VP8/VP9 but not arbitrary Matroska -- may not treat these files as playable otherwise. WebM now has its own DlnaMime.VideoWEBM, extension list and MIME entry. - The new enum member is appended rather than inserted alphabetically, so the numeric values of the existing public members do not change. - DLNA defines no profile for WebM. It keeps DLNA.ORG_PN=MATROSKA, which it was announced with all along: WebM is a restricted form of Matroska, and inventing a profile name would be a new untested value. - Samsung clients keep receiving video/x-mkv for WebM, as they always have, following the same no-regression rule as 9a992ef. - With Matroska and WebM now mapping to the same MIME and profile for Samsung, the GetProtocolInfo source list would have repeated that entry; it is de-duplicated. No cache rebuild is needed: the MIME type is derived from the extension each time, never stored in the file store. Verified with a VP9 .webm and an .mkv, before and after, as a generic and a Samsung client: before after generic, .webm video/x-matroska video/webm generic, .mkv video/x-matroska video/x-matroska Samsung, .webm video/x-mkv video/x-mkv Samsung, .mkv video/x-mkv video/x-mkv in browse protocolInfo, Content-Type and GetProtocolInfo alike. The WebM file still got a 3-second duration and an 8081-byte JPEG thumbnail. Both GetProtocolInfo lists contain no duplicates (87 and 86 entries, all unique), and the file is still classed as video. Co-Authored-By: Claude Opus 5 --- server/Types/DlnaMaps.cs | 40 ++++++++++++++++++++++++++++++++-------- server/Types/DlnaMime.cs | 6 +++++- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/server/Types/DlnaMaps.cs b/server/Types/DlnaMaps.cs index 51b486c4..910a5bfa 100644 --- a/server/Types/DlnaMaps.cs +++ b/server/Types/DlnaMaps.cs @@ -59,7 +59,7 @@ public static class DlnaMaps {"jpg", "jpe", "jpeg", "jif", "jfif"}; private static readonly string[] extMKV = - {"mkv", "matroska", "mk3d", "webm"}; + {"mkv", "matroska", "mk3d"}; private static readonly string[] extMP3 = {"mp3", "mp3p", "mp3x", "mp3a", "mpa"}; @@ -73,6 +73,9 @@ public static class DlnaMaps private static readonly string[] extOGV = {"ogm", "ogv"}; + private static readonly string[] extWEBM = + {"webm"}; + private static readonly string[] extPNG = {"png"}; @@ -119,6 +122,7 @@ public static class DlnaMaps {DlnaMime.VideoMKV, "video/x-matroska"}, {DlnaMime.VideoMPEG, "video/mpeg"}, {DlnaMime.VideoOGV, "video/ogg"}, + {DlnaMime.VideoWEBM, "video/webm"}, {DlnaMime.VideoWMV, "video/x-ms-wmv"} }; @@ -260,6 +264,15 @@ public static class DlnaMaps "MATROSKA" } }, + { + // There is no DLNA profile for WebM. It keeps the MATROSKA profile it + // was announced with while it shared Matroska's entry, since WebM is + // a restricted form of Matroska. + DlnaMime.VideoWEBM, new List + { + "MATROSKA" + } + }, { DlnaMime.VideoMPEG, new List { @@ -345,6 +358,8 @@ static DlnaMaps() new {t = DlnaMime.VideoOGV, e = extOGV}, new + {t = DlnaMime.VideoWEBM, e = extWEBM}, + new {t = DlnaMime.VideoWMV, e = extWMV} }; @@ -357,7 +372,7 @@ static DlnaMaps() } InitMedia( - new[] {ext3GPP, extAVI, extAVC, extFLV, extMKV, extMPEG, extOGV, extWMV}, + new[] {ext3GPP, extAVI, extAVC, extFLV, extMKV, extMPEG, extOGV, extWEBM, extWMV}, DlnaMediaTypes.Video); InitMedia( new[] {extJPEG, extPNG, extGIF}, @@ -374,7 +389,11 @@ private static string GenerateProtocolInfo(Func mimeFor) from pn in p.Value select string.Format("http-get:*:{1}:DLNA.ORG_PN={0};DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS={2}", pn, - mime, DefaultStreaming)).ToList(); + mime, DefaultStreaming)) + // Types that map to the same MIME and profile for a client, such as + // Matroska and WebM for Samsung, would otherwise be listed twice. + .Distinct() + .ToList(); return string.Join(",", pns); } @@ -397,7 +416,11 @@ private static void InitMedia(string[][] k, DlnaMediaTypes t) private static string SamsungMime(DlnaMime type) { - return type == DlnaMime.VideoMKV ? SAMSUNG_MKV_MIME : Mime[type]; + // WebM included: Samsung clients were always sent video/x-mkv for it + // while it shared Matroska's entry, so they keep receiving that. + return type == DlnaMime.VideoMKV || type == DlnaMime.VideoWEBM + ? SAMSUNG_MKV_MIME + : Mime[type]; } private static bool IsSamsung(IHeaders requestHeaders) @@ -415,10 +438,11 @@ private static bool IsSamsung(IHeaders requestHeaders) /// that sent . /// /// - /// Matroska is announced as video/x-matroska, the type Matroska itself, - /// MiniDLNA and Universal Media Server use. Samsung TVs expect the - /// non-standard video/x-mkv instead, which every client was sent before, - /// so they keep getting it; MiniDLNA makes the same exception. + /// Matroska is announced as video/x-matroska and WebM as video/webm, + /// the types MiniDLNA and Universal Media Server use. Samsung TVs expect + /// the non-standard video/x-mkv for Matroska instead, which every client + /// was sent before -- for WebM too -- so they keep getting it; MiniDLNA + /// makes the same exception. /// internal static string MimeFor(DlnaMime type, IHeaders requestHeaders) { diff --git a/server/Types/DlnaMime.cs b/server/Types/DlnaMime.cs index f784ab75..a404562c 100644 --- a/server/Types/DlnaMime.cs +++ b/server/Types/DlnaMime.cs @@ -19,6 +19,10 @@ public enum DlnaMime VideoMKV, VideoMPEG, VideoOGV, - VideoWMV + VideoWMV, + + // Appended rather than kept alphabetical, so the numeric values of the + // existing members do not change. + VideoWEBM } } From eade642d65c81706d18d7b81104e0ae66eec0fd4 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 13:05:04 -0500 Subject: [PATCH 22/37] Keep image thumbnails working when ffmpeg is not installed ThumbnailMaker discovers its loaders by reflection in a static initializer and constructs each one. VideoThumbnailLoader's constructor throws NotSupportedException("No ffmpeg available") when ffmpeg cannot be found, and nothing caught it, so the exception escaped the static initializer and made ThumbnailMaker itself unusable. On any machine without ffmpeg that disabled every thumbnail -- images and audio album art too, not just video -- although the readme says image and audio handling have no external dependencies. This predates the migration. Found while designing the test suite, and confirmed against a running server with ffmpeg removed from PATH. Requesting a JPEG's thumbnail returned HTTP 500: System.TypeInitializationException: The type initializer for 'NMaier.SimpleDlna.Thumbnails.ThumbnailMaker' threw an exception. ---> System.NotSupportedException: No ffmpeg available A loader whose constructor throws is now skipped and logged at info level. The same request then returned a 665-byte JPEG, with the log saying: INFO ThumbnailMaker - VideoThumbnailLoader is unavailable: No ffmpeg available BuildThumbnailers now takes the candidate types as a parameter (the static field passes the assembly's types, as before), so a test can check this without having to hide ffmpeg from the process. Co-Authored-By: Claude Opus 5 --- thumbs/ThumbnailMaker.cs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/thumbs/ThumbnailMaker.cs b/thumbs/ThumbnailMaker.cs index 528a3781..94aa57ce 100644 --- a/thumbs/ThumbnailMaker.cs +++ b/thumbs/ThumbnailMaker.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Reflection; +using log4net; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Utilities; using SkiaSharp; @@ -17,19 +18,37 @@ public sealed class ThumbnailMaker : Logging new LeastRecentlyUsedDictionary(1 << 11); private static readonly Dictionary> thumbers = - BuildThumbnailers(); + BuildThumbnailers(Assembly.GetExecutingAssembly().GetTypes()); - private static Dictionary> BuildThumbnailers() + /// + /// Instantiates every among + /// , grouped by the media types it handles. + /// + /// + /// A loader whose constructor throws is skipped. The video loader throws + /// when ffmpeg is not installed, and this runs in the static initializer: + /// letting that escape made ThumbnailMaker unusable, which took image + /// thumbnails and album art down with it on any machine without ffmpeg. + /// + internal static Dictionary> BuildThumbnailers( + IEnumerable candidates) { var types = Enum.GetValues(typeof (DlnaMediaTypes)); var buildThumbnailers = types.Cast().ToDictionary(i => i, i => new List()); - var a = Assembly.GetExecutingAssembly(); - foreach (var t in a.GetTypes()) { + foreach (var t in candidates) { if (t.GetInterface("IThumbnailLoader") == null) { continue; } var ctor = t.GetConstructor(new Type[] {}); - var thumber = ctor?.Invoke(new object[] {}) as IThumbnailLoader; + IThumbnailLoader thumber; + try { + thumber = ctor?.Invoke(new object[] {}) as IThumbnailLoader; + } + catch (TargetInvocationException ex) { + LogManager.GetLogger(typeof (ThumbnailMaker)).InfoFormat( + "{0} is unavailable: {1}", t.Name, ex.InnerException?.Message ?? ex.Message); + continue; + } if (thumber == null) { continue; } From 6e840f5ee7eeda4feb87cbe286dd2bf5fc71d977 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 13:15:30 -0500 Subject: [PATCH 23/37] Add a test project covering the migration's fixes Until now every behaviour in this PR was verified by hand: throwaway programs, curl and SOAP requests against a running server, and reverting fixes to watch things break. This turns that work into an xUnit test project, so it can be repeated by anyone and run in CI. Project setup tests/tests.csproj xunit.v3 4.0.1, referencing every project. xUnit v3 test projects are executables. global.json Opts "dotnet test" into Microsoft.Testing.Platform. Required: on the .NET 10 SDK the VSTest route errors out with "Testing with VSTest target is no longer supported by Microsoft.Testing.Platform on .NET 10 SDK and later". With the opt-in, xunit.v3 is the only package needed; xunit.runner.visualstudio and Microsoft.NET.Test.Sdk are for VSTest only. Directory.Build.props InternalsVisibleTo for SimpleDlna.Tests, with the full public key: every assembly is strong-named with sdlna.key.snk, and so is the test assembly. The test project does not get AssemblyAttributes.cs: it is not a public API, and CLSCompliant(true) would raise CS3016 on every [InlineData]. Two small internal seams, needed to test fixes that were otherwise reachable only through Windows APIs or a process-wide static initializer: - AddressToMacResolver.FormatMac, extracted from Resolve, which only produces a MAC through iphlpapi!SendARP. - FFmpeg.GetSpecialLocations, now internal, so a missing home directory can be tested without restarting the process. Tests (49) CacheSerializationTests Audio, image and video files and covers round trip through MediaSerializer, including nulls, Unicode and subtitles; corrupt input raises the exceptions FileStore treats as a cache miss. FileStoreTests SQLite storage survives reopening, is invalidated when a file changes, and replaces a database from another schema. StreamPumpTests Data is copied and the completion callback runs. MimeTypeTests Extension-to-type mapping; Matroska and WebM types for generic and Samsung clients; per-client GetProtocolInfo lists without duplicates. ViewTests filter, dimension, large and new behave as the readme and --list-views describe; documented views exist. ThumbnailTests Aspect-fit JPEG thumbnails, extreme aspect ratios, a loader that fails to construct, and video via ffmpeg (skipped when ffmpeg is absent). MacAddressTests Two-digit octets; normalisation and rejection of configured addresses. HomeDirectoryTests ffmpeg search locations with a missing home (Linux and macOS only). Tests that change process-wide state (console, HOME) run in a non-parallel collection. Checked that the regression tests detect their bugs, by reintroducing each bug alone and running the suite: MAC octets formatted with X MacAddressTests.ResolvedAddressesUseTwoDigitsPerOctet thumbnail loader exception uncaught ThumbnailTests.LoaderThatCannotBeCreatedIsSkippedWithoutAffectingOthers empty home path not skipped HomeDirectoryTests.FFmpegSearchLocationsTolerateAMissingHome WebM announced as Matroska MimeTypeTests.GenericClientsGetStandardTypes, ...ProtocolInfoMatchesTheTypesEachClientIsTold Samsung exception removed MimeTypeTests.SamsungClientsKeepVideoXMkvForMatroskaAndWebM StreamPump back on BeginInvoke the test host itself crashed with an unhandled PlatformNotSupportedException, as the server would With the fixes in place: 49 passed, 0 failed, 0 skipped (ffmpeg present). Co-Authored-By: Claude Opus 5 --- Directory.Build.props | 11 +- Directory.Packages.props | 1 + global.json | 5 + sdlna.slnx | 1 + tests/CacheSerializationTests.cs | 203 +++++++++++++++++++++++++++++++ tests/FileStoreTests.cs | 96 +++++++++++++++ tests/HomeDirectoryTests.cs | 48 ++++++++ tests/MacAddressTests.cs | 43 +++++++ tests/MimeTypeTests.cs | 79 ++++++++++++ tests/StreamPumpTests.cs | 53 ++++++++ tests/Support/Collections.cs | 25 ++++ tests/Support/Fields.cs | 28 +++++ tests/Support/TempDirectory.cs | 56 +++++++++ tests/Support/TestFileServer.cs | 17 +++ tests/Support/TestMedia.cs | 66 ++++++++++ tests/ThumbnailTests.cs | 102 ++++++++++++++++ tests/ViewTests.cs | 143 ++++++++++++++++++++++ tests/tests.csproj | 26 ++++ util/AddressToMacResolver.cs | 18 ++- util/FFmpeg.cs | 2 +- 20 files changed, 1016 insertions(+), 7 deletions(-) create mode 100644 global.json create mode 100644 tests/CacheSerializationTests.cs create mode 100644 tests/FileStoreTests.cs create mode 100644 tests/HomeDirectoryTests.cs create mode 100644 tests/MacAddressTests.cs create mode 100644 tests/MimeTypeTests.cs create mode 100644 tests/StreamPumpTests.cs create mode 100644 tests/Support/Collections.cs create mode 100644 tests/Support/Fields.cs create mode 100644 tests/Support/TempDirectory.cs create mode 100644 tests/Support/TestFileServer.cs create mode 100644 tests/Support/TestMedia.cs create mode 100644 tests/ThumbnailTests.cs create mode 100644 tests/ViewTests.cs create mode 100644 tests/tests.csproj diff --git a/Directory.Build.props b/Directory.Build.props index ee702dbd..542219aa 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -40,9 +40,16 @@ $(MSBuildThisFileDirectory)sdlna.key.snk - - + + + + + + diff --git a/Directory.Packages.props b/Directory.Packages.props index f8104692..283ea14f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,6 +23,7 @@ + diff --git a/global.json b/global.json new file mode 100644 index 00000000..3140116d --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "test": { + "runner": "Microsoft.Testing.Platform" + } +} diff --git a/sdlna.slnx b/sdlna.slnx index 16f63873..935e0f23 100644 --- a/sdlna.slnx +++ b/sdlna.slnx @@ -2,6 +2,7 @@ + diff --git a/tests/CacheSerializationTests.cs b/tests/CacheSerializationTests.cs new file mode 100644 index 00000000..933a48fa --- /dev/null +++ b/tests/CacheSerializationTests.cs @@ -0,0 +1,203 @@ +using System; +using System.IO; +using System.Linq; +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Tests.Support; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// The binary format that replaced BinaryFormatter for the file store. + /// + public sealed class CacheSerializationTests : IDisposable + { + private readonly TempDirectory temp = new TempDirectory(); + + private readonly FileServer server; + + public CacheSerializationTests() + { + server = TestFileServer.Create(temp.Info); + } + + public void Dispose() + { + server.Dispose(); + temp.Dispose(); + } + + private BaseFile RoundTrip(BaseFile file, DlnaMime type) + { + using (var stream = new MemoryStream()) { + MediaSerializer.Serialize(stream, file); + stream.Position = 0; + return MediaSerializer.DeserializeFile( + stream, new DeserializeInfo(server, file.Item, type)); + } + } + + [Fact] + public void AudioFileRoundTripsIncludingNullsAndUnicode() + { + var fi = temp.WriteFile("song.mp3"); + var audio = new AudioFile(server, fi, DlnaMime.AudioMP3) + .Set("album", "Album Ω") + .Set("artist", "Artist") + .Set("genre", null) + .Set("performer", "Performer") + .Set("title", "Title") + .Set("track", (int?)7) + .Set("duration", (TimeSpan?)TimeSpan.FromSeconds(212.5)) + .Set("initialized", true); + + var copy = Assert.IsType(RoundTrip(audio, DlnaMime.AudioMP3)); + + Assert.Equal("Album Ω", copy.MetaAlbum); + Assert.Equal("Artist", copy.MetaArtist); + Assert.Null(copy.MetaGenre); + Assert.Equal("Performer", copy.MetaPerformer); + Assert.Equal(7, copy.MetaTrack); + Assert.Equal(TimeSpan.FromSeconds(212.5), copy.MetaDuration); + } + + /// + /// Regression: the (SerializationInfo, StreamingContext) constructor that + /// BinaryFormatter called read no fields, so cached image metadata was + /// always discarded. + /// + [Fact] + public void ImageFileRoundTripsItsMetadata() + { + var fi = temp.WriteFile("photo.jpg"); + var image = new ImageFile(server, fi, DlnaMime.ImageJPEG) + .Set("creator", "Creator") + .Set("description", null) + .Set("title", "Photo") + .Set("width", (int?)1920) + .Set("height", (int?)1080) + .Set("initialized", true); + + var copy = Assert.IsType(RoundTrip(image, DlnaMime.ImageJPEG)); + + Assert.Equal("Creator", copy.MetaCreator); + Assert.Null(copy.MetaDescription); + Assert.Equal(1920, copy.MetaWidth); + Assert.Equal(1080, copy.MetaHeight); + } + + [Fact] + public void VideoFileRoundTripsIncludingSubtitleAndBookmark() + { + const string srt = "1\n00:00:01,000 --> 00:00:02,000\nhi\n"; + var fi = temp.WriteFile("movie.mkv"); + var video = new VideoFile(server, fi, DlnaMime.VideoMKV) + .Set("actors", new[] {"Ann", "Bob", null}) + .Set("description", "Desc") + .Set("director", "Dir") + .Set("genre", "Genre") + .Set("title", "Movie") + .Set("width", (int?)3840) + .Set("height", (int?)2160) + .Set("bookmark", (long?)1234) + .Set("duration", (TimeSpan?)TimeSpan.FromMinutes(97)) + .Set("subTitle", new Subtitle(srt)) + .Set("initialized", true); + + var copy = Assert.IsType(RoundTrip(video, DlnaMime.VideoMKV)); + + Assert.Equal(new[] {"Ann", "Bob", null}, copy.MetaActors.ToArray()); + Assert.Equal("Desc", copy.MetaDescription); + Assert.Equal("Dir", copy.MetaDirector); + Assert.Equal("Genre", copy.MetaGenre); + Assert.Equal(3840, copy.MetaWidth); + Assert.Equal(2160, copy.MetaHeight); + Assert.Equal(1234, copy.Bookmark); + Assert.Equal(TimeSpan.FromMinutes(97), copy.MetaDuration); + Assert.Equal(srt, copy.Subtitle.Text); + } + + /// + /// Regression: a probed-but-empty subtitle used to come back as null, + /// which VideoFile treats as "not looked yet", re-running ffmpeg on every + /// listing. + /// + [Fact] + public void ProbedEmptySubtitleSurvivesSoItIsNotProbedAgain() + { + var fi = temp.WriteFile("nosubs.mkv"); + var video = new VideoFile(server, fi, DlnaMime.VideoMKV) + .Set("subTitle", new Subtitle()) + .Set("initialized", true); + + var copy = RoundTrip(video, DlnaMime.VideoMKV); + + var subtitle = typeof (VideoFile) + .GetField("subTitle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic) + .GetValue(copy) as Subtitle; + Assert.NotNull(subtitle); + Assert.False(subtitle.HasSubtitle); + } + + [Fact] + public void CoverRoundTrips() + { + var fi = temp.WriteFile("cover.jpg"); + var payload = new byte[] {1, 2, 3, 250, 251, 252}; + var cover = new Cover(fi) + .Set("bytes", payload) + .Set("width", 384) + .Set("height", 216); + + Cover copy; + using (var stream = new MemoryStream()) { + MediaSerializer.SerializeCover(stream, cover); + stream.Position = 0; + copy = MediaSerializer.DeserializeCover( + stream, new DeserializeInfo(server, fi, DlnaMime.ImageJPEG)); + } + + Assert.Equal(384, copy.MetaWidth); + Assert.Equal(216, copy.MetaHeight); + using (var content = copy.CreateContentStream()) { + using (var buffer = new MemoryStream()) { + content.CopyTo(buffer); + Assert.Equal(payload, buffer.ToArray()); + } + } + } + + /// + /// FileStore treats these two exception types as "not cached" rather + /// than a crash, so corrupt input must produce exactly them. + /// + [Theory] + [InlineData("bad version", new byte[] {99, 1, 0}, typeof (InvalidDataException))] + [InlineData("unknown kind", new byte[] {1, 77}, typeof (InvalidDataException))] + [InlineData("truncated", new byte[] {1, 1, 1}, typeof (EndOfStreamException))] + public void CorruptInputRaisesTheExceptionsFileStoreCatches(string label, + byte[] blob, Type expected) + { + var fi = temp.WriteFile("corrupt.mp3"); + using (var stream = new MemoryStream(blob)) { + var ex = Record.Exception( + () => MediaSerializer.DeserializeFile( + stream, new DeserializeInfo(server, fi, DlnaMime.AudioMP3))); + Assert.True(ex != null && ex.GetType() == expected, + $"{label}: expected {expected.Name}, got {ex?.GetType().Name ?? "no exception"}"); + } + } + + [Fact] + public void AudioImageAndVideoFilesAreCacheable() + { + Assert.True(MediaSerializer.CanSerialize( + new AudioFile(server, temp.WriteFile("a.mp3"), DlnaMime.AudioMP3))); + Assert.True(MediaSerializer.CanSerialize( + new ImageFile(server, temp.WriteFile("a.jpg"), DlnaMime.ImageJPEG))); + Assert.True(MediaSerializer.CanSerialize( + new VideoFile(server, temp.WriteFile("a.mkv"), DlnaMime.VideoMKV))); + } + } +} diff --git a/tests/FileStoreTests.cs b/tests/FileStoreTests.cs new file mode 100644 index 00000000..49f0e872 --- /dev/null +++ b/tests/FileStoreTests.cs @@ -0,0 +1,96 @@ +using System; +using System.IO; +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Tests.Support; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// The SQLite-backed metadata cache: Microsoft.Data.Sqlite with named + /// parameters, DBNull for a missing cover, and the schema check. + /// + public sealed class FileStoreTests : IDisposable + { + private readonly TempDirectory temp = new TempDirectory(); + + private readonly FileServer server; + + public FileStoreTests() + { + server = TestFileServer.Create(temp.Info); + } + + public void Dispose() + { + server.Dispose(); + temp.Dispose(); + } + + [Fact] + public void StoredFileIsReadBackAfterReopeningTheDatabase() + { + var database = new FileInfo(temp.Combine("cache.db")); + var media = temp.WriteFile("movie.mkv", 1024); + var video = new VideoFile(server, media, DlnaMime.VideoMKV) + .Set("title", "Cached") + .Set("width", (int?)1280) + .Set("height", (int?)720) + .Set("subTitle", new Subtitle()) + .Set("initialized", true); + + using (var store = new FileStore(database)) { + // No cover has been generated, so this also exercises binding a + // missing cover as DBNull, which Microsoft.Data.Sqlite requires. + store.MaybeStoreFile(video); + Assert.False(store.HasCover(video)); + } + + using (var store = new FileStore(database)) { + var cached = Assert.IsType( + store.MaybeGetFile(server, media, DlnaMime.VideoMKV)); + Assert.Equal(1280, cached.MetaWidth); + Assert.Equal(720, cached.MetaHeight); + } + } + + [Fact] + public void ChangedFileIsNotServedFromTheCache() + { + var database = new FileInfo(temp.Combine("cache.db")); + var media = temp.WriteFile("clip.mkv", 1024); + var video = new VideoFile(server, media, DlnaMime.VideoMKV) + .Set("subTitle", new Subtitle()) + .Set("initialized", true); + + using (var store = new FileStore(database)) { + store.MaybeStoreFile(video); + } + + // The cache is keyed by path, size and modification time. + File.WriteAllBytes(media.FullName, new byte[2048]); + media.Refresh(); + + using (var store = new FileStore(database)) { + Assert.Null(store.MaybeGetFile(server, media, DlnaMime.VideoMKV)); + } + } + + [Fact] + public void DatabaseFromAnOlderSchemaIsReplaced() + { + var database = new FileInfo(temp.Combine("old.db")); + File.WriteAllText(database.FullName, "not a SQLite database from this version"); + + using (var store = new FileStore(database)) { + var media = temp.WriteFile("a.mkv"); + store.MaybeStoreFile( + new VideoFile(server, media, DlnaMime.VideoMKV) + .Set("subTitle", new Subtitle()) + .Set("initialized", true)); + Assert.NotNull(store.MaybeGetFile(server, media, DlnaMime.VideoMKV)); + } + } + } +} diff --git a/tests/HomeDirectoryTests.cs b/tests/HomeDirectoryTests.cs new file mode 100644 index 00000000..8d193886 --- /dev/null +++ b/tests/HomeDirectoryTests.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using System.Linq; +using NMaier.SimpleDlna.Tests.Support; +using NMaier.SimpleDlna.Utilities; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// Environment.GetFolderPath returns "" for a folder that does not exist. + /// These tests point HOME at a missing directory, which only redirects the + /// home folder on Linux and macOS. + /// + [Collection(ProcessStateCollection.NAME)] + public sealed class HomeDirectoryTests + { + private static void WithMissingHome(Action test) + { + Assert.SkipWhen(OperatingSystem.IsWindows(), "HOME does not redirect the profile folder on Windows"); + var original = Environment.GetEnvironmentVariable("HOME"); + var missing = Path.Combine(Path.GetTempPath(), "sdlna-tests", "missing-home-" + Guid.NewGuid().ToString("N")); + Environment.SetEnvironmentVariable("HOME", missing); + try { + Assert.Equal("", Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)); + test(missing); + } + finally { + Environment.SetEnvironmentVariable("HOME", original); + } + } + + /// + /// Regression: new DirectoryInfo("") threw inside FFmpeg's static + /// initializer, disabling video thumbnails and durations. + /// + [Fact] + public void FFmpegSearchLocationsTolerateAMissingHome() + { + WithMissingHome(missing => + { + var locations = FFmpeg.GetSpecialLocations(); + Assert.DoesNotContain(locations, l => string.IsNullOrEmpty(l.FullName)); + Assert.DoesNotContain(locations, l => l.FullName.StartsWith(missing, StringComparison.Ordinal)); + }); + } + } +} diff --git a/tests/MacAddressTests.cs b/tests/MacAddressTests.cs new file mode 100644 index 00000000..da9670bc --- /dev/null +++ b/tests/MacAddressTests.cs @@ -0,0 +1,43 @@ +using NMaier.SimpleDlna.Utilities; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + public sealed class MacAddressTests + { + /// + /// Regression: octets were formatted with {:X}, dropping leading zeros, + /// so addresses with any octet below 0x10 never matched a restriction. + /// + [Fact] + public void ResolvedAddressesUseTwoDigitsPerOctet() + { + var raw = new byte[] {0x01, 0xAF, 0xBC, 0x00, 0x0A, 0xFF}; + + var mac = AddressToMacResolver.FormatMac(raw); + + Assert.Equal("01:AF:BC:00:0A:FF", mac); + Assert.True(IP.IsAcceptedMAC(mac)); + } + + [Theory] + [InlineData("01:af:bc:00:0a:ff", "01:AF:BC:00:0A:FF")] + [InlineData("01-AF-BC-00-0A-FF", "01:AF:BC:00:0A:FF")] + public void ConfiguredAddressesAreNormalised(string input, string expected) + { + string mac; + Assert.True(ConfigurationValues.TryNormalizeMac(input, out mac)); + Assert.Equal(expected, mac); + } + + [Theory] + [InlineData("00:00:00:00")] + [InlineData("1:AF:BC:0:A:FF")] + [InlineData("xx01:AF:BC:00:0A:FFyy")] + public void MalformedAddressesAreRejected(string input) + { + string mac; + Assert.False(ConfigurationValues.TryNormalizeMac(input, out mac)); + } + } +} diff --git a/tests/MimeTypeTests.cs b/tests/MimeTypeTests.cs new file mode 100644 index 00000000..cf97e867 --- /dev/null +++ b/tests/MimeTypeTests.cs @@ -0,0 +1,79 @@ +using System.Linq; +using NMaier.SimpleDlna.Server; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// Which MIME types clients are told, including the Samsung exception. + /// + public sealed class MimeTypeTests + { + private const string GENERIC = "VLC/3.0.20 LibVLC/3.0.20"; + + private static RawHeaders Client(string userAgent) + { + return new RawHeaders {{"User-Agent", userAgent}}; + } + + [Theory] + [InlineData("MKV", DlnaMime.VideoMKV)] + [InlineData("MK3D", DlnaMime.VideoMKV)] + [InlineData("WEBM", DlnaMime.VideoWEBM)] + [InlineData("MP4", DlnaMime.VideoAVC)] + public void ExtensionsMapToTypes(string extension, DlnaMime expected) + { + Assert.Equal(expected, DlnaMaps.Ext2Dlna[extension]); + Assert.Equal(DlnaMediaTypes.Video, DlnaMaps.Ext2Media[extension]); + } + + [Theory] + [InlineData(DlnaMime.VideoMKV, "video/x-matroska")] + [InlineData(DlnaMime.VideoWEBM, "video/webm")] + [InlineData(DlnaMime.VideoAVC, "video/mp4")] + public void GenericClientsGetStandardTypes(DlnaMime type, string expected) + { + Assert.Equal(expected, DlnaMaps.MimeFor(type, Client(GENERIC))); + Assert.Equal(expected, DlnaMaps.MimeFor(type, null)); + } + + [Theory] + [InlineData("DLNADOC/1.50 SEC_HHP_[TV] Samsung Q70 Series (55)/1.0 UPnP/1.0")] + [InlineData("SamsungWiselinkPro/1.0")] + public void SamsungClientsKeepVideoXMkvForMatroskaAndWebM(string userAgent) + { + Assert.Equal("video/x-mkv", DlnaMaps.MimeFor(DlnaMime.VideoMKV, Client(userAgent))); + Assert.Equal("video/x-mkv", DlnaMaps.MimeFor(DlnaMime.VideoWEBM, Client(userAgent))); + Assert.Equal("video/mp4", DlnaMaps.MimeFor(DlnaMime.VideoAVC, Client(userAgent))); + } + + [Fact] + public void ProtocolInfoMatchesTheTypesEachClientIsTold() + { + var generic = DlnaMaps.ProtocolInfoFor(Client(GENERIC)).Split(','); + var samsung = DlnaMaps.ProtocolInfoFor(Client("SEC_HHP_[TV] Samsung")).Split(','); + + Assert.Contains(generic, e => e.Contains(":video/x-matroska:")); + Assert.Contains(generic, e => e.Contains(":video/webm:")); + Assert.DoesNotContain(generic, e => e.Contains(":video/x-mkv:")); + + Assert.Contains(samsung, e => e.Contains(":video/x-mkv:")); + Assert.DoesNotContain(samsung, e => e.Contains(":video/x-matroska:") || e.Contains(":video/webm:")); + + // Matroska and WebM share both MIME and profile for Samsung. + Assert.Equal(generic.Length, generic.Distinct().Count()); + Assert.Equal(samsung.Length, samsung.Distinct().Count()); + } + + [Fact] + public void VariantSeparatesClientsThatAreToldDifferentTypes() + { + Assert.NotEqual( + DlnaMaps.MimeVariant(Client(GENERIC)), + DlnaMaps.MimeVariant(Client("SEC_HHP_[TV] Samsung"))); + Assert.Equal( + DlnaMaps.MimeVariant(Client(GENERIC)), + DlnaMaps.MimeVariant(null)); + } + } +} diff --git a/tests/StreamPumpTests.cs b/tests/StreamPumpTests.cs new file mode 100644 index 00000000..7575234f --- /dev/null +++ b/tests/StreamPumpTests.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using System.Threading; +using NMaier.SimpleDlna.Utilities; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + public sealed class StreamPumpTests + { + /// + /// Regression: completion callbacks were dispatched with delegate + /// BeginInvoke, which throws PlatformNotSupportedException on .NET. The + /// HTTP server finishes every response through this callback. + /// + [Fact] + public void CopiesEverythingAndInvokesTheCompletionCallback() + { + var data = new byte[1 << 20]; + new Random(42).NextBytes(data); + var output = new MemoryStream(); + var done = new ManualResetEventSlim(); + var result = StreamPumpResult.Aborted; + + using (var input = new MemoryStream(data)) { + using (var pump = new StreamPump(input, output, 4096)) { + pump.Pump((p, r) => + { + result = r; + done.Set(); + }); + Assert.True( + done.Wait(TimeSpan.FromSeconds(10), TestContext.Current.CancellationToken), + "the completion callback never ran"); + } + } + + Assert.Equal(StreamPumpResult.Delivered, result); + Assert.Equal(data, output.ToArray()); + } + + [Fact] + public void ThrowingCallbackDoesNotStopThePumpFromFinishing() + { + using (var input = new MemoryStream(new byte[100])) { + using (var pump = new StreamPump(input, new MemoryStream(), 16)) { + pump.Pump((p, r) => throw new InvalidOperationException("callback failure")); + Assert.True(pump.Wait(10000)); + } + } + } + } +} diff --git a/tests/Support/Collections.cs b/tests/Support/Collections.cs new file mode 100644 index 00000000..14584631 --- /dev/null +++ b/tests/Support/Collections.cs @@ -0,0 +1,25 @@ +using Xunit; + +namespace NMaier.SimpleDlna.Tests.Support +{ + /// + /// Tests that change process-wide state, such as the console writers or + /// the HOME environment variable. They run one at a time, after the + /// parallel tests. + /// + [CollectionDefinition(NAME, DisableParallelization = true)] + public sealed class ProcessStateCollection + { + public const string NAME = "Process-wide state"; + } + + /// + /// Tests that start a real HTTP server. Each binds its own port, but the + /// SSDP responder shares UDP 1900, so they run one at a time. + /// + [CollectionDefinition(NAME, DisableParallelization = true)] + public sealed class HttpServerCollection + { + public const string NAME = "HTTP server"; + } +} diff --git a/tests/Support/Fields.cs b/tests/Support/Fields.cs new file mode 100644 index 00000000..33793758 --- /dev/null +++ b/tests/Support/Fields.cs @@ -0,0 +1,28 @@ +using System; +using System.Reflection; + +namespace NMaier.SimpleDlna.Tests.Support +{ + /// + /// Sets private fields. Media files normally fill their metadata from + /// taglib or ffmpeg; tests set it directly so they need neither real media + /// nor external tools. + /// + internal static class Fields + { + private const BindingFlags ALL = + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + + public static T Set(this T target, string field, object value) + { + for (var type = target.GetType(); type != null; type = type.BaseType) { + var info = type.GetField(field, ALL); + if (info != null) { + info.SetValue(target, value); + return target; + } + } + throw new MissingFieldException(target.GetType().Name, field); + } + } +} diff --git a/tests/Support/TempDirectory.cs b/tests/Support/TempDirectory.cs new file mode 100644 index 00000000..af5fdb68 --- /dev/null +++ b/tests/Support/TempDirectory.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; + +namespace NMaier.SimpleDlna.Tests.Support +{ + /// + /// A uniquely named scratch directory, deleted on dispose. + /// + internal sealed class TempDirectory : IDisposable + { + public TempDirectory() + { + Info = Directory.CreateDirectory( + System.IO.Path.Combine(System.IO.Path.GetTempPath(), "sdlna-tests", Guid.NewGuid().ToString("N"))); + } + + public DirectoryInfo Info { get; } + + public string Path => Info.FullName; + + public void Dispose() + { + try { + Info.Refresh(); + if (Info.Exists) { + Info.Delete(true); + } + } + catch (IOException) { + // A server under test may still hold a file open briefly; a stray + // temp directory is harmless. + } + catch (UnauthorizedAccessException) { + } + } + + public string Combine(params string[] parts) + { + var all = new string[parts.Length + 1]; + all[0] = Path; + parts.CopyTo(all, 1); + return System.IO.Path.Combine(all); + } + + /// + /// Writes a file with arbitrary content. The server classifies files by + /// extension, so this is enough to list and announce them. + /// + public FileInfo WriteFile(string name, int size = 64) + { + var path = Combine(name); + File.WriteAllBytes(path, new byte[size]); + return new FileInfo(path); + } + } +} diff --git a/tests/Support/TestFileServer.cs b/tests/Support/TestFileServer.cs new file mode 100644 index 00000000..5f3d6164 --- /dev/null +++ b/tests/Support/TestFileServer.cs @@ -0,0 +1,17 @@ +using System.IO; +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Server.Comparers; + +namespace NMaier.SimpleDlna.Tests.Support +{ + internal static class TestFileServer + { + public static FileServer Create(DirectoryInfo directory, + DlnaMediaTypes types = DlnaMediaTypes.All) + { + var ids = new Identifiers(ComparerRepository.Lookup("title"), false); + return new FileServer(types, ids, directory); + } + } +} diff --git a/tests/Support/TestMedia.cs b/tests/Support/TestMedia.cs new file mode 100644 index 00000000..93f0675b --- /dev/null +++ b/tests/Support/TestMedia.cs @@ -0,0 +1,66 @@ +using System; +using System.Diagnostics; +using System.IO; +using NMaier.SimpleDlna.Utilities; +using SkiaSharp; + +namespace NMaier.SimpleDlna.Tests.Support +{ + internal static class TestMedia + { + public static FileInfo WriteJpeg(string path, int width, int height) + { + using (var bitmap = new SKBitmap(width, height)) { + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.SeaGreen); + } + using (var image = SKImage.FromBitmap(bitmap)) { + using (var data = image.Encode(SKEncodedImageFormat.Jpeg, 90)) { + using (var file = File.Create(path)) { + data.SaveTo(file); + } + } + } + } + return new FileInfo(path); + } + + public static bool IsJpeg(byte[] data) + { + return data != null && data.Length > 3 && + data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF; + } + + public static bool HasFFmpeg => FFmpeg.FFmpegExecutable != null; + + /// + /// Generates a short H.264 video with ffmpeg. Callers must skip when + /// is false. + /// + public static FileInfo WriteVideo(string path, int seconds = 3) + { + var start = new ProcessStartInfo(FFmpeg.FFmpegExecutable) + { + UseShellExecute = false, + RedirectStandardError = true, + RedirectStandardOutput = true + }; + foreach (var arg in new[] + { + "-v", "error", "-y", "-f", "lavfi", + "-i", $"testsrc=duration={seconds}:size=320x240:rate=25", + "-c:v", "libx264", "-pix_fmt", "yuv420p", path + }) { + start.ArgumentList.Add(arg); + } + using (var process = Process.Start(start)) { + var error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + if (process.ExitCode != 0) { + throw new InvalidOperationException($"ffmpeg failed: {error}"); + } + } + return new FileInfo(path); + } + } +} diff --git a/tests/ThumbnailTests.cs b/tests/ThumbnailTests.cs new file mode 100644 index 00000000..45616622 --- /dev/null +++ b/tests/ThumbnailTests.cs @@ -0,0 +1,102 @@ +using System; +using System.IO; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Tests.Support; +using NMaier.SimpleDlna.Thumbnails; +using SkiaSharp; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + public sealed class ThumbnailTests : IDisposable + { + private readonly TempDirectory temp = new TempDirectory(); + + public void Dispose() + { + temp.Dispose(); + } + + [Fact] + public void ImageThumbnailKeepsTheAspectRatioAndIsAJpeg() + { + var source = TestMedia.WriteJpeg(temp.Combine("photo.jpg"), 800, 600); + + var thumbnail = new ThumbnailMaker().GetThumbnail(source, 384, 216); + + Assert.Equal(288, thumbnail.Width); + Assert.Equal(216, thumbnail.Height); + var data = thumbnail.GetData(); + Assert.True(TestMedia.IsJpeg(data)); + using (var decoded = SKBitmap.Decode(data)) { + Assert.Equal(288, decoded.Width); + Assert.Equal(216, decoded.Height); + } + } + + [Fact] + public void ExtremeAspectRatioDoesNotProduceAnEmptyBitmap() + { + var source = TestMedia.WriteJpeg(temp.Combine("strip.jpg"), 4000, 2); + + var thumbnail = new ThumbnailMaker().GetThumbnail(source, 384, 216); + + Assert.True(thumbnail.Height >= 1); + Assert.True(TestMedia.IsJpeg(thumbnail.GetData())); + } + + [Fact] + public void VideoThumbnailComesFromFFmpeg() + { + Assert.SkipUnless(TestMedia.HasFFmpeg, "ffmpeg is not installed"); + var video = TestMedia.WriteVideo(temp.Combine("clip.mp4")); + + var thumbnail = new ThumbnailMaker().GetThumbnail(video, 384, 216); + + // Video thumbnails are letterboxed to the requested size. + Assert.Equal(384, thumbnail.Width); + Assert.Equal(216, thumbnail.Height); + Assert.True(TestMedia.IsJpeg(thumbnail.GetData())); + } + + private sealed class UnavailableLoader : IThumbnailLoader + { + public UnavailableLoader() + { + throw new NotSupportedException("dependency missing"); + } + + public DlnaMediaTypes Handling => DlnaMediaTypes.Video; + + public MemoryStream GetThumbnail(object item, ref int width, ref int height) + { + throw new NotImplementedException(); + } + } + + private sealed class WorkingLoader : IThumbnailLoader + { + public DlnaMediaTypes Handling => DlnaMediaTypes.Image; + + public MemoryStream GetThumbnail(object item, ref int width, ref int height) + { + throw new NotImplementedException(); + } + } + + /// + /// Regression: the video loader throws without ffmpeg, and that used to + /// escape ThumbnailMaker's static initializer, disabling image thumbnails + /// and album art as well. + /// + [Fact] + public void LoaderThatCannotBeCreatedIsSkippedWithoutAffectingOthers() + { + var loaders = ThumbnailMaker.BuildThumbnailers( + new[] {typeof (UnavailableLoader), typeof (WorkingLoader)}); + + Assert.Empty(loaders[DlnaMediaTypes.Video]); + Assert.IsType(Assert.Single(loaders[DlnaMediaTypes.Image])); + } + } +} diff --git a/tests/ViewTests.cs b/tests/ViewTests.cs new file mode 100644 index 00000000..903d5351 --- /dev/null +++ b/tests/ViewTests.cs @@ -0,0 +1,143 @@ +using System; +using System.IO; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Server.Metadata; +using NMaier.SimpleDlna.Server.Views; +using NMaier.SimpleDlna.Utilities; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// The filtering views and their options, as documented in the readme and + /// by --list-views. + /// + public sealed class ViewTests + { + private sealed class Item : IMediaResource, IMetaResolution, IMetaInfo + { + public Item(string title, string path = null, int? width = null, + int? height = null, long? size = null, DateTime? date = null) + { + Title = title; + Path = path ?? "/media/" + title; + MetaWidth = width; + MetaHeight = height; + InfoSize = size; + InfoDate = date ?? DateTime.UtcNow; + } + + public DateTime InfoDate { get; } + + public long? InfoSize { get; } + + public int? MetaHeight { get; } + + public int? MetaWidth { get; } + + public string Id { get; set; } + + public string Path { get; } + + public IHeaders Properties => new RawHeaders(); + + public string Title { get; } + + public IMediaCoverResource Cover => null; + + public DlnaMediaTypes MediaType => DlnaMediaTypes.Image; + + public string PN => "JPEG_LRG"; + + public DlnaMime Type => DlnaMime.ImageJPEG; + + public int CompareTo(IMediaItem other) => string.CompareOrdinal(Title, other?.Title); + + public Stream CreateContentStream() => Stream.Null; + + public bool Equals(IMediaItem other) => Title == other?.Title; + + public string ToComparableTitle() => Title; + } + + private static IFilteredView Filter(string view) + { + return Assert.IsAssignableFrom(ViewRepository.Lookup(view)); + } + + [Fact] + public void FilterMatchesAnyWordAnywhereInTitleOrPathIgnoringCase() + { + var view = Filter("filter:beach,holiday"); + + Assert.True(view.Allowed(new Item("Sunny BEACH day"))); + Assert.True(view.Allowed(new Item("trip", "/photos/holiday/trip.jpg"))); + Assert.False(view.Allowed(new Item("mountains", "/photos/alps/mountains.jpg"))); + } + + [Fact] + public void FilterWordWithWildcardMustMatchTheWholeValue() + { + var view = Filter("filter:bea*"); + + Assert.True(view.Allowed(new Item("beach", "/x"))); + Assert.False(view.Allowed(new Item("the beach", "/x"))); + } + + [Fact] + public void DimensionMinIsTheShorterSideAndMaxTheLongerSide() + { + var landscape = new Item("big", width: 800, height: 600); + var small = new Item("small", width: 640, height: 480); + + Assert.True(Filter("dimension:min=600").Allowed(landscape)); + Assert.False(Filter("dimension:min=600").Allowed(small)); + + Assert.True(Filter("dimension:max=700").Allowed(small)); + Assert.False(Filter("dimension:max=700").Allowed(landscape)); + } + + [Fact] + public void DimensionHidesItemsWithoutAKnownSize() + { + Assert.False(Filter("dimension:min=1").Allowed(new Item("song"))); + } + + [Fact] + public void LargeTakesItsSizeInMegabytes() + { + const long megabyte = 1024 * 1024; + var view = Filter("large:size=10"); + + Assert.True(view.Allowed(new Item("big", size: 10 * megabyte))); + Assert.False(view.Allowed(new Item("small", size: 10 * megabyte - 1))); + } + + [Fact] + public void NewUsesTheGivenEarliestDate() + { + var view = Filter("new:date=2026-01-31"); + + Assert.True(view.Allowed(new Item("recent", date: new DateTime(2026, 2, 1)))); + Assert.False(view.Allowed(new Item("old", date: new DateTime(2025, 12, 1)))); + } + + [Theory] + [InlineData("bytitle")] + [InlineData("flatten")] + [InlineData("music")] + [InlineData("plain")] + [InlineData("series:no-cascade")] + [InlineData("sites")] + public void DocumentedViewsExist(string view) + { + Assert.NotNull(ViewRepository.Lookup(view)); + } + + [Fact] + public void UnknownViewIsReported() + { + Assert.Throws(() => ViewRepository.Lookup("musik")); + } + } +} diff --git a/tests/tests.csproj b/tests/tests.csproj new file mode 100644 index 00000000..b3f5efe8 --- /dev/null +++ b/tests/tests.csproj @@ -0,0 +1,26 @@ + + + + NMaier.SimpleDlna.Tests + SimpleDlna.Tests + + Exe + true + false + + + + + + + + + + + + + + + + diff --git a/util/AddressToMacResolver.cs b/util/AddressToMacResolver.cs index d2157ada..41f65e4c 100644 --- a/util/AddressToMacResolver.cs +++ b/util/AddressToMacResolver.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; @@ -23,6 +23,18 @@ public static bool IsAcceptedMac(string mac) return regMac.IsMatch(mac); } + /// + /// Formats a MAC address the way MAC restrictions are written. + /// + /// + /// X2, not X: MacAuthorizer compares against configured entries of the + /// form 01:AF:BC:00:0A:FF, so every octet needs both digits. + /// + internal static string FormatMac(byte[] raw) + { + return $"{raw[0]:X2}:{raw[1]:X2}:{raw[2]:X2}:{raw[3]:X2}:{raw[4]:X2}:{raw[5]:X2}"; + } + public string Resolve(IPAddress ip) { try { @@ -47,9 +59,7 @@ public string Resolve(IPAddress ip) // to report and callers already handle a null. if (OperatingSystem.IsWindows() && SafeNativeMethods.SendARP(addr, 0, raw, ref length) == 0) { - // X2, not X: MacAuthorizer compares against configured entries of - // the form 01:AF:BC:00:0A:FF, so every octet needs both digits. - mac = $"{raw[0]:X2}:{raw[1]:X2}:{raw[2]:X2}:{raw[3]:X2}:{raw[4]:X2}:{raw[5]:X2}"; + mac = FormatMac(raw); } } catch (DllNotFoundException) { diff --git a/util/FFmpeg.cs b/util/FFmpeg.cs index e0845039..5415a33c 100644 --- a/util/FFmpeg.cs +++ b/util/FFmpeg.cs @@ -43,7 +43,7 @@ public static class FFmpeg /// would disable FFmpeg -- and with it every video thumbnail and /// duration -- for the life of the process. /// - private static DirectoryInfo[] GetSpecialLocations() + internal static DirectoryInfo[] GetSpecialLocations() { var rv = new List(); var folders = new[] From 8e715c478d4cd55997c3a8d0596f55f9f832b772 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 13:19:50 -0500 Subject: [PATCH 24/37] Test the configuration file, server commands and startup decision Covers the configuration feature added in review, which had so far been checked only through manual runs against a scratch HOME. Two internal seams: - ConfigurationStore.HomeDirectoryOverride. Tests point the store at a scratch directory, so they never read or write the developer's real ~/.sdlna, and it works on Windows, where HOME does not redirect the profile folder. - Program.ChooseConfiguredServers, extracted from Main. It holds the no-folders decision -- run the configured servers, or warn and serve the current directory -- and takes the warning writer as a parameter, so it can be tested without starting a server. Main behaves as before. New tests (36, for 85 in total) ConfigurationTests No file; saved files are strict JSON and reload with the documented defaults; every validation problem is reported in one message; typos are named ("unknown setting 'mediatype' in a server"); wrong value types name the key; broken JSON gives a position; comments, trailing commas and spelling variants are accepted; cache default, "none" and "~"; the folder is hidden on Windows (skipped elsewhere); symlinked folders compare equal. ServerCommandTests add and remove, with their exit codes; each config option's changes and limits; the restriction grammar from the feature request, including switching verbs after "--"; malformed entries; the warning about MAC entries off Windows; nothing saved when any option fails; printing a setting; the editor setting; --edit running the editor and validating, including on a broken file (using "sh -c true" as the editor, so skipped on Windows). StartupTests No configuration, or one with no servers, serves the current directory with the right warning; configured servers are chosen silently; an invalid file is an error, not a fallback; per-server options are recognised and process-wide ones are not; "-p 0" still counts as given. HomeDirectoryTests The configuration path stays under a missing HOME. Console output and the home override are process-wide, so these join the non-parallel collection. Checked by breaking each behaviour alone and running the suite: saving before every option succeeds ServerCommandTests.NothingIsSavedWhenAnyOptionFails fallback not serving "." StartupTests.WithoutAConfigurationTheCurrentDirectoryIsServed, ...AConfigurationWithoutServersAlsoServesTheCurrentDirectory invalid file silently bypassed StartupTests.AnInvalidConfigurationIsAnErrorRatherThanAFallback verb unchangeable after "--" ServerCommandTests.RestrictionGroupsAreSeparatedByDoubleDash home lookup without DoNotVerify HomeDirectoryTests.ConfigurationStaysUnderAMissingHome unknown keys ignored ConfigurationTests.TypoInAKeyIsReportedByName (3 cases) symlinks not resolved ConfigurationTests.FoldersReachedThroughASymlinkAreTheSameFolder, ServerCommandTests.SameFolderThroughASymlinkIsNotAddedTwice -t not detected as per-server StartupTests.PerServerOptionsAreRecognisedAndProcessWideOnesAreNot With the code as committed: 84 passed, 1 skipped (the Windows-only hidden-folder test), 0 failed. Co-Authored-By: Claude Opus 5 --- sdlna/Configuration.cs | 7 + sdlna/Program.cs | 58 ++++-- tests/ConfigurationTests.cs | 153 ++++++++++++++ tests/HomeDirectoryTests.cs | 13 ++ tests/ServerCommandTests.cs | 298 +++++++++++++++++++++++++++ tests/StartupTests.cs | 97 +++++++++ tests/Support/ConfigurationHome.cs | 56 +++++ tests/Support/ServerCommandRunner.cs | 49 +++++ 8 files changed, 713 insertions(+), 18 deletions(-) create mode 100644 tests/ConfigurationTests.cs create mode 100644 tests/ServerCommandTests.cs create mode 100644 tests/StartupTests.cs create mode 100644 tests/Support/ConfigurationHome.cs create mode 100644 tests/Support/ServerCommandRunner.cs diff --git a/sdlna/Configuration.cs b/sdlna/Configuration.cs index 0f21f6ff..3f195cfb 100644 --- a/sdlna/Configuration.cs +++ b/sdlna/Configuration.cs @@ -285,11 +285,18 @@ internal static class ConfigurationStore public const string CACHE_NONE = "none"; + /// + /// Test seam: when set, used in place of the user's home directory, so + /// tests never read or write the real ~/.sdlna. + /// + internal static string HomeDirectoryOverride { get; set; } + // DoNotVerify: without it GetFolderPath returns "" when the home // directory does not exist yet, which would silently turn the // configuration path into ".sdlna/config.json" relative to wherever sdlna // happens to be run. private static string HomeDirectory => + HomeDirectoryOverride ?? Environment.GetFolderPath( Environment.SpecialFolder.UserProfile, Environment.SpecialFolderOption.DoNotVerify); diff --git a/sdlna/Program.cs b/sdlna/Program.cs index 2635beaa..fbaada09 100644 --- a/sdlna/Program.cs +++ b/sdlna/Program.cs @@ -190,18 +190,11 @@ private static void Main(string[] args) return; } if (options.Directories.Length == 0) { - // An invalid file still stops here with an error (via - // ConfigurationException) rather than being silently bypassed. - var config = ConfigurationStore.Load(); - if (config != null && config.Servers.Count != 0) { + var config = ChooseConfiguredServers(options, Console.Error); + if (config != null) { RunConfiguredServers(options, config); return; } - // Zero-config: nothing is saved, so serve the current directory - // exactly as "sdlna ." would, with every command-line option, and - // say how to save servers instead of refusing to start. - WarnServingCurrentDirectory(config != null); - options.Directories = new[] {new DirectoryInfo(".")}; } options.SetupLogging(); @@ -278,20 +271,49 @@ private static void Main(string[] args) #endif } - private static void WarnServingCurrentDirectory(bool fileExists) + /// + /// Decides what a run without folders does. + /// + /// + /// The configuration whose servers should start. When none are + /// configured, returns null after writing a warning and pointing + /// at the current directory, so the run + /// continues exactly as "sdlna ." would. + /// + /// + /// The configuration file is invalid. That is reported rather than + /// silently bypassed. + /// + internal static SdlnaConfiguration ChooseConfiguredServers(Options options, + TextWriter warnings) + { + var config = ConfigurationStore.Load(); + if (config != null && config.Servers.Count != 0) { + return config; + } + // Zero-config: nothing is saved, so serve the current directory with + // every command-line option, and say how to save servers instead of + // refusing to start. + WarnServingCurrentDirectory(config != null, warnings); + options.Directories = new[] {new DirectoryInfo(".")}; + return null; + } + + private static void WarnServingCurrentDirectory(bool fileExists, + TextWriter warnings) { - Console.Error.WriteLine( + warnings.WriteLine( fileExists ? $"Warning: No servers are configured in {ConfigurationStore.FilePath}," : "Warning: No servers are configured and no configuration file exists,"); - Console.Error.WriteLine("so serving the current directory:"); - Console.Error.WriteLine(" {0}", Path.GetFullPath(".")); - Console.Error.WriteLine(); - Console.Error.WriteLine( + warnings.WriteLine("so serving the current directory:"); + warnings.WriteLine(" {0}", Path.GetFullPath(".")); + warnings.WriteLine(); + warnings.WriteLine( "Nothing has been saved. To set up servers that 'sdlna' starts every time, add one with:"); - Console.Error.WriteLine(" sdlna --server add "); - Console.Error.WriteLine("See 'sdlna --server help' for more."); - Console.Error.WriteLine(); + warnings.WriteLine(" sdlna --server add "); + warnings.WriteLine("See 'sdlna --server help' for more."); + warnings.WriteLine(); } private static void Run(HttpServer server) diff --git a/tests/ConfigurationTests.cs b/tests/ConfigurationTests.cs new file mode 100644 index 00000000..b86f5b33 --- /dev/null +++ b/tests/ConfigurationTests.cs @@ -0,0 +1,153 @@ +using System; +using System.IO; +using System.Linq; +using NMaier.SimpleDlna.Tests.Support; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// Reading, validating and writing ~/.sdlna/config.json. + /// + [Collection(ProcessStateCollection.NAME)] + public sealed class ConfigurationTests : IDisposable + { + private readonly ConfigurationHome home = new ConfigurationHome(); + + public void Dispose() + { + home.Dispose(); + } + + private ConfigurationException LoadFails(string json) + { + home.WriteConfig(json); + return Assert.Throws(() => ConfigurationStore.Load()); + } + + [Fact] + public void NoFileMeansNoConfiguration() + { + Assert.Null(ConfigurationStore.Load()); + } + + [Fact] + public void SavedFileIsStrictJsonAndLoadsBackWithTheDocumentedDefaults() + { + var config = ConfigurationStore.CreateDefault(); + var server = ConfigurationStore.CreateServer("Movies"); + server.Folders.Add(home.Folder("movies")); + config.Servers.Add(server); + + ConfigurationStore.Save(config); + + using (var json = home.ReadConfig()) { + Assert.Equal(0, json.RootElement.GetProperty("port").GetInt32()); + Assert.Equal(ConfigurationStore.DefaultCachePath, json.RootElement.GetProperty("cache").GetString()); + } + var loaded = ConfigurationStore.Load(); + var copy = Assert.Single(loaded.Servers); + Assert.Equal("Movies", copy.Name); + Assert.Equal(new[] {"video", "audio", "images"}, copy.MediaTypes); + Assert.Equal("title", copy.SortOrder); + Assert.Equal("asc", copy.SortDirection); + Assert.Empty(copy.Views); + Assert.True(copy.Restrictions.IsEmpty); + } + + [Fact] + public void EveryProblemIsReportedTogether() + { + var ex = LoadFails(@"{ ""servers"": [ + { ""name"": ""A"", ""folders"": [], ""mediaTypes"": [], ""views"": [""musik""], ""sortOrder"": ""name"", + ""restrictions"": { ""macs"": [""00:00:00:00""], ""ips"": [""300.1.1.1""] } }, + { ""name"": ""a"", ""folders"": [""/x""], ""mediaTypes"": [""video""] } ] }"); + + Assert.Contains("has no folders", ex.Message); + Assert.Contains("has no mediaTypes", ex.Message); + Assert.Contains("unknown sortOrder \"name\"", ex.Message); + Assert.Contains("unknown view \"musik\"", ex.Message); + Assert.Contains("invalid MAC address \"00:00:00:00\"", ex.Message); + Assert.Contains("invalid IP address \"300.1.1.1\"", ex.Message); + Assert.Contains("defined more than once", ex.Message); + Assert.Contains("sdlna --server config --edit", ex.Message); + } + + [Theory] + [InlineData(@"{ ""prot"": 1 }", "unknown setting 'prot' in the top level")] + [InlineData(@"{ ""servers"": [ { ""name"": ""A"", ""folders"": [""/x""], ""mediatype"": [""video""] } ] }", + "unknown setting 'mediatype' in a server")] + [InlineData(@"{ ""servers"": [ { ""name"": ""A"", ""folders"": [""/x""], ""mediaTypes"": [""video""], ""restrictions"": { ""mac"": [] } } ] }", + "unknown setting 'mac' in a server's restrictions")] + public void TypoInAKeyIsReportedByName(string json, string expected) + { + Assert.Contains(expected, LoadFails(json).Message); + } + + [Fact] + public void WrongValueTypeNamesTheKey() + { + Assert.Contains("'Port'", LoadFails(@"{ ""port"": ""eighty"" }").Message); + } + + [Fact] + public void BrokenJsonReportsWhere() + { + var ex = LoadFails(@"{ ""port"": 8200,, }"); + Assert.Contains("is not valid JSON", ex.Message); + Assert.Contains("BytePositionInLine", ex.Message); + } + + [Fact] + public void CommentsTrailingCommasAndSpellingAreForgiven() + { + home.WriteConfig(@"{ + // hand-written + ""port"": 8911, + ""servers"": [ { ""name"": ""Music"", ""folders"": [""/x""], ""mediaTypes"": [""AUDIO"", ""image""], ""sortDirection"": ""DESC"", }, ], + }"); + + var server = Assert.Single(ConfigurationStore.Load().Servers); + + Assert.Equal(new[] {"audio", "images"}, server.MediaTypes); + Assert.Equal("desc", server.SortDirection); + Assert.Equal("title", server.SortOrder); + } + + [Fact] + public void CacheDefaultsToTheConfigurationFolderAndCanBeTurnedOff() + { + Assert.Equal(ConfigurationStore.DefaultCachePath, + ConfigurationStore.ResolveCache(new SdlnaConfiguration()).FullName); + Assert.Null(ConfigurationStore.ResolveCache(new SdlnaConfiguration {Cache = "none"})); + Assert.Equal(Path.Combine(home.Path, "media.db"), + ConfigurationStore.ResolveCache(new SdlnaConfiguration {Cache = "~/media.db"}).FullName); + } + + [Fact] + public void ConfigurationFolderIsCreatedHiddenOnWindows() + { + Assert.SkipUnless(OperatingSystem.IsWindows(), "the hidden attribute is Windows-specific"); + + ConfigurationStore.EnsureDirectory(); + + Assert.True(File.GetAttributes(ConfigurationStore.DirectoryPath).HasFlag(FileAttributes.Hidden)); + } + + [Fact] + public void FoldersReachedThroughASymlinkAreTheSameFolder() + { + var target = home.Folder("media"); + var link = Path.Combine(home.Path, "media-link"); + try { + Directory.CreateSymbolicLink(link, target); + } + catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { + Assert.Skip($"cannot create symbolic links here: {ex.Message}"); + } + + Assert.Equal(ConfigurationValues.CanonicalFolder(target), + ConfigurationValues.CanonicalFolder(link)); + } + } +} diff --git a/tests/HomeDirectoryTests.cs b/tests/HomeDirectoryTests.cs index 8d193886..382170b7 100644 --- a/tests/HomeDirectoryTests.cs +++ b/tests/HomeDirectoryTests.cs @@ -44,5 +44,18 @@ public void FFmpegSearchLocationsTolerateAMissingHome() Assert.DoesNotContain(locations, l => l.FullName.StartsWith(missing, StringComparison.Ordinal)); }); } + + /// + /// Regression: the configuration path became ".sdlna/config.json", + /// relative to wherever sdlna was run. + /// + [Fact] + public void ConfigurationStaysUnderAMissingHome() + { + WithMissingHome(missing => + { + Assert.Equal(Path.Combine(missing, ".sdlna", "config.json"), ConfigurationStore.FilePath); + }); + } } } diff --git a/tests/ServerCommandTests.cs b/tests/ServerCommandTests.cs new file mode 100644 index 00000000..c1f3f962 --- /dev/null +++ b/tests/ServerCommandTests.cs @@ -0,0 +1,298 @@ +using System; +using System.IO; +using System.Linq; +using NMaier.SimpleDlna.Tests.Support; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// "sdlna --server": exit codes are 0 on success, 1 for an invalid value + /// or conflict, and 2 for a malformed command line. + /// + [Collection(ProcessStateCollection.NAME)] + public sealed class ServerCommandTests : IDisposable + { + private readonly ConfigurationHome home = new ConfigurationHome(); + + private readonly string movies; + + public ServerCommandTests() + { + movies = home.Folder("movies"); + } + + public void Dispose() + { + home.Dispose(); + } + + private static CommandResult Run(params string[] args) + { + return ServerCommandRunner.Run(args); + } + + private static CommandResult Succeeds(params string[] args) + { + var result = Run(args); + Assert.True(result.ExitCode == 0, result.ToString()); + return result; + } + + private static void Fails(int exitCode, params string[] args) + { + var result = Run(args); + Assert.True(result.ExitCode == exitCode, $"expected exit {exitCode}; {result}"); + } + + private static ServerConfiguration Server(string name = "Movies") + { + return ConfigurationStore.Load().Servers.Single(s => s.Name == name); + } + + [Fact] + public void AddCreatesAServerWithTheDocumentedDefaults() + { + Succeeds("add", "Movies", movies); + + var server = Server(); + Assert.Equal(new[] {movies}, server.Folders); + Assert.Equal(new[] {"video", "audio", "images"}, server.MediaTypes); + Assert.Equal("title", server.SortOrder); + Assert.Equal("asc", server.SortDirection); + Assert.Empty(server.Views); + Assert.True(server.Restrictions.IsEmpty); + home.ReadConfig().Dispose(); + } + + [Fact] + public void AddRejectsBadInput() + { + Succeeds("add", "Movies", movies); + + Fails(1, "add", "movies", movies); // duplicate, ignoring case + Fails(1, "add", "Other", Path.Combine(home.Path, "nope")); // missing folder + Fails(2, "add", "Other"); // no folder + Fails(2, "add", "Other", movies, "--views", "add", "music"); // options belong to config + } + + [Fact] + public void RemoveDeletesTheServer() + { + Succeeds("add", "Movies", movies); + + Succeeds("remove", "MOVIES"); + + Assert.Empty(ConfigurationStore.Load().Servers); + Fails(1, "remove", "Movies"); + } + + [Fact] + public void MediaTypesAreSetAndUnsetButOneAlwaysRemains() + { + Succeeds("add", "Movies", movies); + + Succeeds("config", "Movies", "--media-types", "unset", "audio", "image"); + Assert.Equal(new[] {"video"}, Server().MediaTypes); + + Fails(1, "config", "Movies", "--media-types", "unset", "video"); + Fails(2, "config", "Movies", "--media-types", "set", "movies"); + + Succeeds("config", "Movies", "--media-types", "set", "images"); + Assert.Equal(new[] {"video", "images"}, Server().MediaTypes); + } + + [Fact] + public void SortOrderTakesAFieldAndAnOptionalDirection() + { + Succeeds("add", "Movies", movies); + + Succeeds("config", "Movies", "--sort-order", "date", "desc"); + Assert.Equal(("date", "desc"), (Server().SortOrder, Server().SortDirection)); + + Succeeds("config", "Movies", "--sort-order", "size"); + Assert.Equal(("size", "asc"), (Server().SortOrder, Server().SortDirection)); + + Fails(2, "config", "Movies", "--sort-order", "name"); + Fails(2, "config", "Movies", "--sort-order", "date", "sideways"); + } + + [Fact] + public void FoldersAreAddedAndRemovedButOneAlwaysRemains() + { + var music = home.Folder("music"); + Succeeds("add", "Movies", movies); + + Succeeds("config", "Movies", "--folders", "add", music); + Assert.Equal(new[] {movies, music}, Server().Folders); + + Succeeds("config", "Movies", "--folders", "remove", movies); + Assert.Equal(new[] {music}, Server().Folders); + + Fails(1, "config", "Movies", "--folders", "remove", music); + Fails(1, "config", "Movies", "--folders", "remove", movies); + Fails(1, "config", "Movies", "--folders", "add", Path.Combine(home.Path, "nope")); + } + + [Fact] + public void SameFolderThroughASymlinkIsNotAddedTwice() + { + var link = Path.Combine(home.Path, "movies-link"); + try { + Directory.CreateSymbolicLink(link, movies); + } + catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { + Assert.Skip($"cannot create symbolic links here: {ex.Message}"); + } + Succeeds("add", "Movies", movies); + + var result = Succeeds("config", "Movies", "--folders", "add", link); + + Assert.Contains("is the same folder as", result.Output); + Assert.Single(Server().Folders); + } + + [Fact] + public void ViewsAreAddedInOrderAndRemovedByValueOrName() + { + Succeeds("add", "Movies", movies); + + Succeeds("config", "Movies", "--views", "add", "new", "large:size=1000", "series:no-cascade"); + Assert.Equal(new[] {"new", "large:size=1000", "series:no-cascade"}, Server().Views); + + Succeeds("config", "Movies", "--views", "remove", "large"); + Assert.Equal(new[] {"new", "series:no-cascade"}, Server().Views); + + Fails(1, "config", "Movies", "--views", "add", "musik"); + Fails(1, "config", "Movies", "--views", "remove", "bytitle"); + Fails(2, "config", "Movies", "--views", "add"); + } + + /// + /// The grammar from the feature request: "--" ends a group, after which + /// another kind may follow, or the verb may change. + /// + [Fact] + public void RestrictionGroupsAreSeparatedByDoubleDash() + { + Succeeds("add", "Movies", movies); + + Succeeds("config", "Movies", "--restrictions", "add", + "--mac", "00:00:00:00:00:00", "11-11-11-11-11-11", "--", + "--ip", "192.168.1.2", "192.168.1.3", "--", + "--user-agent", "Mozilla/Whatever"); + var r = Server().Restrictions; + Assert.Equal(new[] {"00:00:00:00:00:00", "11:11:11:11:11:11"}, r.Macs); + Assert.Equal(new[] {"192.168.1.2", "192.168.1.3"}, r.Ips); + Assert.Equal(new[] {"Mozilla/Whatever"}, r.UserAgents); + + Succeeds("config", "Movies", "--restrictions", + "remove", "--ip", "192.168.1.3", "--", + "add", "--ip", "10.0.0.1", "--", + "remove", "--mac", "11:11:11:11:11:11"); + r = Server().Restrictions; + Assert.Equal(new[] {"00:00:00:00:00:00"}, r.Macs); + Assert.Equal(new[] {"192.168.1.2", "10.0.0.1"}, r.Ips); + } + + [Fact] + public void RestrictionsRejectMalformedEntries() + { + Succeeds("add", "Movies", movies); + + Fails(1, "config", "Movies", "--restrictions", "add", "--mac", "00:00:00:00"); + Fails(1, "config", "Movies", "--restrictions", "add", "--ip", "300.1.1.1"); + Fails(1, "config", "Movies", "--restrictions", "remove", "--ip", "8.8.8.8"); + Fails(2, "config", "Movies", "--restrictions", "add", "192.168.1.9"); + Fails(2, "config", "Movies", "--restrictions", "add", "--ip"); + Fails(2, "config", "Movies", "--restrictions", "--ip", "192.168.1.9"); + } + + [Fact] + public void MacRestrictionWarnsWhereMacsCannotBeLookedUp() + { + Succeeds("add", "Movies", movies); + + var result = Succeeds("config", "Movies", "--restrictions", "add", "--mac", "01:AF:BC:00:0A:FF"); + + Assert.Equal(!OperatingSystem.IsWindows(), result.Output.Contains("only be looked up when sdlna runs on Windows")); + } + + [Fact] + public void NothingIsSavedWhenAnyOptionFails() + { + Succeeds("add", "Movies", movies); + var before = home.ConfigBytes(); + + Fails(2, "config", "Movies", "--views", "add", "music", "--sort-order", "bogus"); + + Assert.Equal(before, home.ConfigBytes()); + } + + [Fact] + public void OptionWithoutValuesPrintsTheCurrentSetting() + { + Succeeds("add", "Movies", movies); + Succeeds("config", "Movies", "--views", "add", "music"); + + var result = Succeeds("config", "Movies", "--views"); + + Assert.Contains("Views of \"Movies\"", result.Output); + Assert.Contains("music", result.Output); + } + + [Fact] + public void OptionsThatChangeAServerNeedItsName() + { + Fails(2, "config", "--views", "add", "music"); + Fails(1, "config", "Nope", "--views"); + Fails(2, "bogus"); + } + + [Fact] + public void EditorIsSetShownAndReset() + { + Succeeds("config", "--editor", "code", "--wait"); + Assert.Equal("code --wait", ConfigurationStore.Load().Editor); + + Assert.Contains("code --wait", Succeeds("config", "--editor").Output); + + Succeeds("config", "--editor", "default"); + Assert.Null(ConfigurationStore.Load().Editor); + } + + private static void SkipUnlessPosixShell() + { + Assert.SkipWhen(OperatingSystem.IsWindows(), "uses /bin/sh as a stand-in editor"); + } + + [Fact] + public void EditOpensTheEditorAndValidatesTheResult() + { + SkipUnlessPosixShell(); + Succeeds("add", "Movies", movies); + Succeeds("config", "--editor", "sh -c true"); + + var result = Succeeds("config", "--edit"); + + Assert.Contains("is valid (1 server)", result.Output); + } + + [Fact] + public void EditStillOpensABrokenFile() + { + SkipUnlessPosixShell(); + Succeeds("add", "Movies", movies); + File.WriteAllText(home.ConfigPath, "{ broken"); + + Fails(1, "config", "Movies", "--views"); + + // The editor here changes nothing, so the file is still reported invalid + // afterwards -- but it was opened, which is the point. + var result = Run("config", "--edit", "--editor", "sh -c true"); + Assert.Contains("Warning:", result.Error); + Assert.Contains("is not valid JSON", result.Error); + Assert.Equal(1, result.ExitCode); + } + } +} diff --git a/tests/StartupTests.cs b/tests/StartupTests.cs new file mode 100644 index 00000000..c1ddd02e --- /dev/null +++ b/tests/StartupTests.cs @@ -0,0 +1,97 @@ +using System; +using System.IO; +using System.Linq; +using NMaier.SimpleDlna.Tests.Support; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// What "sdlna" does when run without folders. + /// + [Collection(ProcessStateCollection.NAME)] + public sealed class StartupTests : IDisposable + { + private readonly ConfigurationHome home = new ConfigurationHome(); + + public void Dispose() + { + home.Dispose(); + } + + private static Options Parse(params string[] args) + { + var options = new Options(); + options.Parse(args); + return options; + } + + [Fact] + public void WithoutAConfigurationTheCurrentDirectoryIsServed() + { + var options = Parse(); + var warnings = new StringWriter(); + + var config = Program.ChooseConfiguredServers(options, warnings); + + Assert.Null(config); + var directory = Assert.Single(options.Directories); + Assert.Equal(Path.GetFullPath("."), Path.TrimEndingDirectorySeparator(directory.FullName)); + Assert.Contains("No servers are configured and no configuration file exists", warnings.ToString()); + Assert.Contains("sdlna --server add ", warnings.ToString()); + } + + [Fact] + public void AConfigurationWithoutServersAlsoServesTheCurrentDirectory() + { + home.WriteConfig(@"{ ""port"": 0, ""servers"": [] }"); + var options = Parse(); + var warnings = new StringWriter(); + + Assert.Null(Program.ChooseConfiguredServers(options, warnings)); + + Assert.Single(options.Directories); + Assert.Contains($"No servers are configured in {home.ConfigPath}", warnings.ToString()); + } + + [Fact] + public void ConfiguredServersAreChosenWithoutAWarning() + { + home.WriteConfig($@"{{ ""servers"": [ {{ ""name"": ""Movies"", ""folders"": [""{home.Folder("movies").Replace("\\", "\\\\")}""], ""mediaTypes"": [""video""] }} ] }}"); + var options = Parse(); + var warnings = new StringWriter(); + + var config = Program.ChooseConfiguredServers(options, warnings); + + Assert.Equal("Movies", Assert.Single(config.Servers).Name); + Assert.Empty(options.Directories); + Assert.Equal("", warnings.ToString()); + } + + [Fact] + public void AnInvalidConfigurationIsAnErrorRatherThanAFallback() + { + home.WriteConfig(@"{ ""port"": ""oops"" }"); + var options = Parse(); + + Assert.Throws( + () => Program.ChooseConfiguredServers(options, new StringWriter())); + Assert.Empty(options.Directories); + } + + [Fact] + public void PerServerOptionsAreRecognisedAndProcessWideOnesAreNot() + { + Assert.Equal(new[] {"-t", "-v", "-d", "-i"}, + Parse("-t", "video", "-v", "music", "-d", "-i", "127.0.0.1").GivenServerOptions().ToArray()); + Assert.Empty(Parse("-p", "8200", "-l", "DEBUG", "--no-rescanning").GivenServerOptions()); + } + + [Fact] + public void ExplicitPortZeroStillCountsAsGiven() + { + Assert.True(Parse("-p", "0").PortSpecified); + Assert.False(Parse().PortSpecified); + } + } +} diff --git a/tests/Support/ConfigurationHome.cs b/tests/Support/ConfigurationHome.cs new file mode 100644 index 00000000..9f0f4d8b --- /dev/null +++ b/tests/Support/ConfigurationHome.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using System.Text.Json; + +namespace NMaier.SimpleDlna.Tests.Support +{ + /// + /// Points the configuration store at a scratch home directory for the + /// lifetime of a test, so the real ~/.sdlna is never touched. Use only + /// from tests in . + /// + internal sealed class ConfigurationHome : IDisposable + { + private readonly TempDirectory home = new TempDirectory(); + + public ConfigurationHome() + { + ConfigurationStore.HomeDirectoryOverride = home.Path; + } + + public string Path => home.Path; + + public string ConfigPath => ConfigurationStore.FilePath; + + public void Dispose() + { + ConfigurationStore.HomeDirectoryOverride = null; + home.Dispose(); + } + + public void WriteConfig(string json) + { + Directory.CreateDirectory(ConfigurationStore.DirectoryPath); + File.WriteAllText(ConfigPath, json); + } + + public JsonDocument ReadConfig() + { + // Parsed with default options: strict JSON, no comments or trailing commas. + return JsonDocument.Parse(File.ReadAllText(ConfigPath)); + } + + public byte[] ConfigBytes() + { + return File.ReadAllBytes(ConfigPath); + } + + /// + /// A media folder inside the scratch home. + /// + public string Folder(string name) + { + return Directory.CreateDirectory(System.IO.Path.Combine(home.Path, name)).FullName; + } + } +} diff --git a/tests/Support/ServerCommandRunner.cs b/tests/Support/ServerCommandRunner.cs new file mode 100644 index 00000000..e7225b63 --- /dev/null +++ b/tests/Support/ServerCommandRunner.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; + +namespace NMaier.SimpleDlna.Tests.Support +{ + internal sealed class CommandResult + { + public string Error; + + public int ExitCode; + + public string Output; + + public override string ToString() + { + return $"exit {ExitCode}\n--- stdout:\n{Output}\n--- stderr:\n{Error}"; + } + } + + /// + /// Runs "sdlna --server ..." in-process with the console captured. Use + /// only from tests in . + /// + internal static class ServerCommandRunner + { + public static CommandResult Run(params string[] args) + { + var originalOut = Console.Out; + var originalError = Console.Error; + var output = new StringWriter(); + var error = new StringWriter(); + Console.SetOut(output); + Console.SetError(error); + try { + var exitCode = ServerCommand.Run(args); + return new CommandResult + { + ExitCode = exitCode, + Output = output.ToString(), + Error = error.ToString() + }; + } + finally { + Console.SetOut(originalOut); + Console.SetError(originalError); + } + } + } +} From 9ef260b486fd802045a9dd06d153e40d94a069a5 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 13:37:37 -0500 Subject: [PATCH 25/37] Test the HTTP server end to end, as a TV talks to it The earlier tests exercise the pieces; these start the real HttpServer on a free port, mount FileServers over scratch folders and send the UPnP SOAP requests a renderer sends (ContentDirectory Browse, ConnectionManager GetProtocolInfo, plain and ranged GETs), choosing both the User-Agent and the local address each request connects through. What is covered (tests/HttpServerTests.cs): - Browse lists files with their UPnP classes (movie, musicTrack, photo), and a server's media types limit what it lists. - Files are streamed byte for byte. Every response passes through StreamPump, whose completion callback used Delegate.BeginInvoke, which throws on .NET. - Matroska and WebM types are client dependent everywhere they appear: the DIDL protocolInfo, the Content-Type of the file response and the GetProtocolInfo source list agree, for a generic client and for a Samsung one, and browsing as one client and then the other does not replay the first client's types from the browse cache. - Browse links use the address each client connected to. The browse cache used to ignore it, so a local browse sent network clients to 127.0.0.1. This uses a non-loopback address of the machine, or 127.0.0.2 on Linux where all of 127/8 is local, and is skipped when neither is available. - Restrictions refuse other machines but always admit this one (skipped without a non-loopback address). - A server set up from the configuration file (Program.SetupConfiguredServer, now internal for this) applies its own media types and restrictions, and skips a folder that does not exist instead of failing. - Image thumbnails are served; video duration and thumbnail come from ffmpeg (skipped when ffmpeg is not installed). Each of those regressions was reintroduced by hand to confirm the tests catch it: the browse cache key without the local endpoint or without the MIME variant, no Samsung MIME exception, a GetProtocolInfo that ignores the client, loopback no longer always admitted, the BeginInvoke callback, and a configured missing folder no longer skipped. All seven fail the suite. Support code: - tests/Support/DlnaClient.cs: a minimal UPnP client built on System.Net.Http. Browse returns the status, the parsed items and the raw DIDL; LinkHosts reads element text only, since namespace declarations in attributes are URIs too. The timeout is 10 seconds: the server is local, so a hung response should fail promptly rather than stall the run. - tests/Support/DlnaTestServer.cs: one HttpServer shared by the collection through a collection fixture. Mount prefixes come from a process-wide counter, so a mount's prefix is found through the index page and the friendly name in each description.xml. Tests unmount and dispose their FileServers afterwards. Production change, test only in effect: HttpServer gains an internal HttpServer(int port, bool announce) constructor; the public constructors pass true and behave exactly as before. With announce false no SsdpHandler is created. Without it the tests: - announced throwaway "test-" media servers to every TV and player on the developer's network, - needed UDP port 1900, and - spent about 3 seconds per server on dispose while SSDP drained its queue of byebye datagrams (each sent several times, 25-75 ms apart, for every mount, address and device type). The suite went from 28 seconds to about 3.5 seconds: 94 tests, 93 passed and one skipped on macOS (the Windows hidden-folder test). Co-Authored-By: Claude Opus 5 --- sdlna/Program.cs | 2 +- server/Http/HttpServer.cs | 21 ++- tests/HttpServerTests.cs | 222 ++++++++++++++++++++++++++++++++ tests/Support/Collections.cs | 6 +- tests/Support/DlnaClient.cs | 146 +++++++++++++++++++++ tests/Support/DlnaTestServer.cs | 101 +++++++++++++++ 6 files changed, 490 insertions(+), 8 deletions(-) create mode 100644 tests/HttpServerTests.cs create mode 100644 tests/Support/DlnaClient.cs create mode 100644 tests/Support/DlnaTestServer.cs diff --git a/sdlna/Program.cs b/sdlna/Program.cs index fbaada09..1fbca5cd 100644 --- a/sdlna/Program.cs +++ b/sdlna/Program.cs @@ -419,7 +419,7 @@ private static void RunConfiguredServers(Options options, } } - private static FileServer SetupConfiguredServer(ServerConfiguration config, + internal static FileServer SetupConfiguredServer(ServerConfiguration config, FileInfo cacheFile, bool rescanning, HttpServer httpServer) { // A folder may be on a drive that is not mounted right now; serve the diff --git a/server/Http/HttpServer.cs b/server/Http/HttpServer.cs index 1ec8c46c..88de5043 100644 --- a/server/Http/HttpServer.cs +++ b/server/Http/HttpServer.cs @@ -40,6 +40,17 @@ public HttpServer() } public HttpServer(int port) + : this(port, true) + { + } + + /// The TCP port, or 0 for any free port. + /// + /// Whether to run SSDP, which announces mounts to the network and answers + /// discovery. Only tests turn it off: without it nothing finds the server, + /// but it no longer needs UDP 1900 or drains byebye datagrams on dispose. + /// + internal HttpServer(int port, bool announce) { prefixes.TryAdd( "/favicon.ico", @@ -61,7 +72,9 @@ public HttpServer(int port) NoticeFormat( "Running HTTP Server: {0} on port {1}", Signature, RealPort); - ssdpServer = new SsdpHandler(); + if (announce) { + ssdpServer = new SsdpHandler(); + } timeouter.Elapsed += TimeouterCallback; timeouter.Enabled = true; @@ -89,7 +102,7 @@ public void Dispose() foreach (var s in servers.Values.ToList()) { UnregisterMediaServer(s); } - ssdpServer.Dispose(); + ssdpServer?.Dispose(); timeouter.Dispose(); listener.Stop(); foreach (var c in clients.ToList()) { @@ -264,7 +277,7 @@ public void RegisterMediaServer(IMediaServer server) mount.AddDeviceGuid(deviceGuid, address); var uri = new Uri($"http://{address}:{end.Port}{mount.DescriptorURI}"); lock (list) { - ssdpServer.RegisterNotification(deviceGuid, uri, address); + ssdpServer?.RegisterNotification(deviceGuid, uri, address); } NoticeFormat("New mount at: {0}", uri); } @@ -284,7 +297,7 @@ public void UnregisterMediaServer(IMediaServer server) if (devicesForServers.TryGetValue(server.UUID, out list)) { lock (list) { foreach (var deviceGuid in list) { - ssdpServer.UnregisterNotification(deviceGuid); + ssdpServer?.UnregisterNotification(deviceGuid); } } devicesForServers.TryRemove(server.UUID, out list); diff --git a/tests/HttpServerTests.cs b/tests/HttpServerTests.cs new file mode 100644 index 00000000..304ec9bc --- /dev/null +++ b/tests/HttpServerTests.cs @@ -0,0 +1,222 @@ +using System; +using System.IO; +using System.Linq; +using System.Net; +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Tests.Support; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// End to end: a real HTTP server on a free port, a file server over a + /// scratch folder, and UPnP requests sent the way a TV sends them. + /// + [Collection(HttpServerCollection.NAME)] + public sealed class HttpServerTests : IDisposable + { + private readonly TempDirectory media = new TempDirectory(); + + private readonly DlnaTestServer server; + + public HttpServerTests(DlnaTestServer server) + { + this.server = server; + } + + public void Dispose() + { + server.UnmountAll(); + media.Dispose(); + } + + private string Mount(DlnaMediaTypes types = DlnaMediaTypes.All) + { + return server.Mount(TestFileServer.Create(media.Info, types)); + } + + private static string RequireNonLoopbackAddress() + { + var address = DlnaTestServer.NonLoopbackAddress(); + Assert.SkipWhen(address == null, "this machine has no non-loopback IPv4 address"); + return address; + } + + [Fact] + public void BrowseListsFilesWithTheirUpnpClasses() + { + media.WriteFile("film.mkv"); + media.WriteFile("song.mp3"); + TestMedia.WriteJpeg(media.Combine("photo.jpg"), 64, 48); + var prefix = Mount(); + + var (status, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + + Assert.Equal(HttpStatusCode.OK, status); + Assert.Equal("object.item.videoItem.movie", items.Single(i => i.Title == "film").Class); + Assert.Equal("object.item.audioItem.musicTrack", items.Single(i => i.Title == "song").Class); + Assert.Equal("object.item.imageItem.photo", items.Single(i => i.Title == "photo").Class); + } + + [Fact] + public void MediaTypesLimitWhatIsListed() + { + media.WriteFile("film.mkv"); + media.WriteFile("song.mp3"); + var prefix = Mount(DlnaMediaTypes.Video); + + var (_, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + + Assert.Equal("film", Assert.Single(items).Title); + } + + /// + /// Regression: StreamPump's completion callback used delegate + /// BeginInvoke, so every HTTP response failed when it finished. + /// + [Fact] + public void FilesAreStreamedByteForByte() + { + var content = new byte[256 * 1024]; + new Random(7).NextBytes(content); + File.WriteAllBytes(media.Combine("film.mkv"), content); + var prefix = Mount(); + + var (_, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + + Assert.Equal(content, DlnaClient.GetBytes(Assert.Single(items).Url)); + } + + /// + /// The MIME type reaches clients three ways, which must agree; and the + /// browse cache must not hand one client's types to another. + /// + [Fact] + public void MatroskaAndWebMTypesDependOnTheClientEverywhere() + { + media.WriteFile("film.mkv"); + media.WriteFile("web.webm"); + media.WriteFile("clip.mp4"); + var prefix = Mount(); + + void Expect(string userAgent, string mkv, string webm) + { + var (_, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix, userAgent); + foreach (var (title, expected) in new[] {("film", mkv), ("web", webm), ("clip", "video/mp4")}) { + var item = items.Single(i => i.Title == title); + Assert.Equal(expected, item.MimeType); + using (var response = DlnaClient.Get(item.Url, userAgent, true)) { + Assert.Equal(expected, response.Content.Headers.ContentType?.MediaType); + } + } + var source = DlnaClient.GetProtocolInfo(server.Port, prefix, userAgent); + Assert.Contains(source, e => e.Contains($":{mkv}:")); + Assert.Contains(source, e => e.Contains($":{webm}:")); + } + + Expect(DlnaClient.GENERIC, "video/x-matroska", "video/webm"); + Expect(DlnaClient.SAMSUNG, "video/x-mkv", "video/x-mkv"); + Expect(DlnaClient.GENERIC, "video/x-matroska", "video/webm"); + } + + /// + /// Regression: browse results embed links built from the address the + /// client connected to, and the cache ignored that address, so a local + /// browse sent network clients to 127.0.0.1. + /// + [Fact] + public void LinksUseTheAddressEachClientConnectedTo() + { + var other = DlnaTestServer.NonLoopbackAddress(); + if (other == null && OperatingSystem.IsLinux()) { + // All of 127.0.0.0/8 is local on Linux, and a different local address + // is all this needs. + other = "127.0.0.2"; + } + Assert.SkipWhen(other == null, "no second local address to connect through"); + media.WriteFile("film.mkv"); + var prefix = Mount(); + + foreach (var host in new[] {"127.0.0.1", other, "127.0.0.1", other}) { + var (_, _, didl) = DlnaClient.Browse(host, server.Port, prefix); + Assert.Equal(new[] {$"{host}:{server.Port}"}, DlnaClient.LinkHosts(didl)); + } + } + + [Fact] + public void RestrictionsRefuseOtherMachinesButAlwaysAdmitThisOne() + { + var address = RequireNonLoopbackAddress(); + media.WriteFile("film.mkv"); + var fileServer = TestFileServer.Create(media.Info); + var authorizer = new HttpAuthorizer(); + authorizer.AddMethod(new IPAddressAuthorizer(new[] {"10.255.255.1"})); + fileServer.Authorizer = authorizer; + var prefix = server.Mount(fileServer); + + Assert.Equal(HttpStatusCode.Forbidden, DlnaClient.Browse(address, server.Port, prefix).Status); + Assert.Equal(HttpStatusCode.OK, DlnaClient.Browse("127.0.0.1", server.Port, prefix).Status); + } + + [Fact] + public void ConfiguredServerAppliesItsOwnSettings() + { + media.WriteFile("film.mkv"); + media.WriteFile("song.mp3"); + var config = new ServerConfiguration + { + Name = "Configured", + SortOrder = "title", + SortDirection = "asc" + }; + config.Folders.Add(media.Path); + config.Folders.Add(media.Combine("unmounted-drive")); + config.MediaTypes.Add("video"); + config.Restrictions.Ips.Add("10.255.255.1"); + + var fileServer = Program.SetupConfiguredServer(config, null, false, server.Http); + var prefix = server.Mount(fileServer, true); + + // The missing folder was skipped rather than failing the server. + var (status, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + Assert.Equal(HttpStatusCode.OK, status); + Assert.Equal("film", Assert.Single(items).Title); + + var address = DlnaTestServer.NonLoopbackAddress(); + if (address != null) { + Assert.Equal(HttpStatusCode.Forbidden, DlnaClient.Browse(address, server.Port, prefix).Status); + } + } + + /// + /// Works without ffmpeg since image thumbnails no longer depend on the + /// video loader constructing successfully. + /// + [Fact] + public void ImageThumbnailIsServed() + { + TestMedia.WriteJpeg(media.Combine("photo.jpg"), 800, 600); + var prefix = Mount(); + + var (_, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + + Assert.True(TestMedia.IsJpeg(DlnaClient.GetBytes(Assert.Single(items).CoverUrl))); + } + + [Fact] + public void VideoDurationAndThumbnailComeFromFFmpeg() + { + Assert.SkipUnless(TestMedia.HasFFmpeg, "ffmpeg is not installed"); + TestMedia.WriteVideo(media.Combine("clip.mp4"), 3); + var prefix = Mount(); + + var (_, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + + var item = Assert.Single(items); + var duration = TimeSpan.Parse(item.Duration); + Assert.InRange(duration.TotalSeconds, 2.5, 3.5); + Assert.True(TestMedia.IsJpeg(DlnaClient.GetBytes(item.CoverUrl))); + } + } +} diff --git a/tests/Support/Collections.cs b/tests/Support/Collections.cs index 14584631..fdda32a3 100644 --- a/tests/Support/Collections.cs +++ b/tests/Support/Collections.cs @@ -14,11 +14,11 @@ public sealed class ProcessStateCollection } /// - /// Tests that start a real HTTP server. Each binds its own port, but the - /// SSDP responder shares UDP 1900, so they run one at a time. + /// Tests that talk to the real HTTP server. They share one server (see + /// DlnaTestServer) and run one at a time, so no test sees another's mounts. /// [CollectionDefinition(NAME, DisableParallelization = true)] - public sealed class HttpServerCollection + public sealed class HttpServerCollection : ICollectionFixture { public const string NAME = "HTTP server"; } diff --git a/tests/Support/DlnaClient.cs b/tests/Support/DlnaClient.cs new file mode 100644 index 00000000..a5f88639 --- /dev/null +++ b/tests/Support/DlnaClient.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Xml.Linq; +using Http = System.Net.Http; + +namespace NMaier.SimpleDlna.Tests.Support +{ + internal sealed class BrowsedItem + { + public string Class; + + public string CoverUrl; + + public string Duration; + + public string MimeType; + + public string Title; + + public string Url; + } + + /// + /// A minimal UPnP client: enough SOAP to browse and query a server the way + /// a TV does, from a chosen local address and with a chosen User-Agent. + /// + internal static class DlnaClient + { + public const string GENERIC = "VLC/3.0.20 LibVLC/3.0.20"; + + public const string SAMSUNG = "DLNADOC/1.50 SEC_HHP_[TV] Samsung Q70 Series (55)/1.0 UPnP/1.0"; + + /// + /// The server is local and answers at once, so a short timeout turns a + /// hung response into a prompt failure. + /// + private static readonly Http.HttpClient http = new Http.HttpClient + { + Timeout = TimeSpan.FromSeconds(10) + }; + + private static CancellationToken Cancellation => Xunit.TestContext.Current.CancellationToken; + + public static Http.HttpResponseMessage Get(string url, string userAgent = GENERIC, + bool firstByteOnly = false) + { + var request = new Http.HttpRequestMessage(Http.HttpMethod.Get, url); + request.Headers.TryAddWithoutValidation("User-Agent", userAgent); + if (firstByteOnly) { + request.Headers.TryAddWithoutValidation("Range", "bytes=0-0"); + } + return http.Send(request, Cancellation); + } + + public static byte[] GetBytes(string url, string userAgent = GENERIC) + { + using (var response = Get(url, userAgent)) { + response.EnsureSuccessStatusCode(); + return response.Content.ReadAsByteArrayAsync(Cancellation).GetAwaiter().GetResult(); + } + } + + private static Http.HttpResponseMessage Soap(string host, int port, string prefix, + string service, string action, string body, string userAgent) + { + var envelope = + "" + + "" + + $"{body}"; + var request = new Http.HttpRequestMessage(Http.HttpMethod.Post, $"http://{host}:{port}{prefix}control") + { + Content = new Http.StringContent(envelope, Encoding.UTF8) + }; + request.Content.Headers.Remove("Content-Type"); + request.Content.Headers.TryAddWithoutValidation("Content-Type", "text/xml; charset=\"utf-8\""); + request.Headers.TryAddWithoutValidation("SOAPACTION", $"\"urn:schemas-upnp-org:service:{service}:1#{action}\""); + request.Headers.TryAddWithoutValidation("User-Agent", userAgent); + return http.Send(request, Cancellation); + } + + /// + /// Browses the root of a mount. Returns the HTTP status and, on success, + /// the items. + /// + public static (HttpStatusCode Status, List Items, string Didl) Browse( + string host, int port, string prefix, string userAgent = GENERIC) + { + using (var response = Soap(host, port, prefix, "ContentDirectory", "Browse", + "0BrowseDirectChildren*" + + "0100", + userAgent)) { + if (!response.IsSuccessStatusCode) { + return (response.StatusCode, null, null); + } + var envelope = XDocument.Parse(response.Content.ReadAsStringAsync(Cancellation).GetAwaiter().GetResult()); + var didl = envelope.Descendants().First(e => e.Name.LocalName == "Result").Value; + var items = XDocument.Parse(didl).Descendants() + .Where(e => e.Name.LocalName == "item") + .Select(item => + { + var res = item.Elements().First(e => e.Name.LocalName == "res" && !e.Value.Contains("/cover/")); + return new BrowsedItem + { + Title = item.Elements().First(e => e.Name.LocalName == "title").Value, + Class = item.Elements().First(e => e.Name.LocalName == "class").Value, + Url = res.Value, + MimeType = res.Attribute("protocolInfo")?.Value.Split(':')[2], + Duration = res.Attribute("duration")?.Value, + CoverUrl = item.Descendants().Select(e => e.Value).FirstOrDefault(v => v.Contains("/cover/")) + }; + }) + .ToList(); + return (HttpStatusCode.OK, items, didl); + } + } + + public static string[] GetProtocolInfo(int port, string prefix, string userAgent) + { + using (var response = Soap("127.0.0.1", port, prefix, "ConnectionManager", "GetProtocolInfo", "", userAgent)) { + response.EnsureSuccessStatusCode(); + var envelope = XDocument.Parse(response.Content.ReadAsStringAsync(Cancellation).GetAwaiter().GetResult()); + return envelope.Descendants().First(e => e.Name.LocalName == "Source").Value.Split(','); + } + } + + /// + /// The host:port parts of every link in a browse result (res and cover + /// elements). Attributes are ignored: namespace declarations are URIs too. + /// + public static string[] LinkHosts(string didl) + { + return XDocument.Parse(didl).Descendants() + .Where(e => !e.HasElements) + .Select(e => Regex.Match(e.Value.Trim(), @"^https?://([^/]+)/")) + .Where(m => m.Success) + .Select(m => m.Groups[1].Value) + .Distinct() + .ToArray(); + } + } +} diff --git a/tests/Support/DlnaTestServer.cs b/tests/Support/DlnaTestServer.cs new file mode 100644 index 00000000..0aa4cfd2 --- /dev/null +++ b/tests/Support/DlnaTestServer.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Text.RegularExpressions; +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.Server; + +namespace NMaier.SimpleDlna.Tests.Support +{ + /// + /// A real HttpServer on a free port, shared by the HTTP server collection: + /// tests mount their own file servers on it and unmount them after. SSDP + /// is off, so test servers are never announced to TVs on the network. + /// + public sealed class DlnaTestServer : IDisposable + { + private readonly List mounted = new List(); + + public DlnaTestServer() + { + Http = new HttpServer(0, false); + } + + public HttpServer Http { get; } + + public int Port => Http.RealPort; + + public void Dispose() + { + UnmountAll(); + Http.Dispose(); + } + + /// + /// Registers a file server and returns its mount prefix ("/mm-N/"). + /// Prefixes come from a process-wide counter, so they are discovered from + /// the server's index page and each mount's device description. + /// + /// The file server to host. + /// + /// Whether Load() was already called. It must not be called twice: each + /// call subscribes the rescan handlers again. + /// + public string Mount(FileServer fileServer, bool loaded = false) + { + var name = "test-" + Guid.NewGuid().ToString("N"); + fileServer.FriendlyName = name; + if (!loaded) { + fileServer.Rescanning = false; + fileServer.Load(); + } + Http.RegisterMediaServer(fileServer); + mounted.Add(fileServer); + + var index = DlnaClient.GetBytes($"http://127.0.0.1:{Port}/"); + foreach (Match m in Regex.Matches(System.Text.Encoding.UTF8.GetString(index), "href=\"(/mm-\\d+/)\"")) { + var prefix = m.Groups[1].Value; + var description = System.Text.Encoding.UTF8.GetString( + DlnaClient.GetBytes($"http://127.0.0.1:{Port}{prefix}description.xml")); + if (description.Contains(name)) { + return prefix; + } + } + throw new InvalidOperationException($"mount for {name} not found"); + } + + /// + /// Unregisters and disposes every file server mounted so far. + /// + public void UnmountAll() + { + foreach (var fileServer in mounted) { + Http.UnregisterMediaServer(fileServer); + fileServer.Dispose(); + } + mounted.Clear(); + } + + /// + /// An IPv4 address of this machine other than loopback, or null. The + /// server always admits loopback clients, so restrictions can only be + /// observed through such an address. + /// + public static string NonLoopbackAddress() + { + return NetworkInterface.GetAllNetworkInterfaces() + .Where(n => n.OperationalStatus == OperationalStatus.Up && + n.NetworkInterfaceType != NetworkInterfaceType.Loopback) + .SelectMany(n => n.GetIPProperties().UnicastAddresses) + .Select(a => a.Address) + .Where(a => a.AddressFamily == AddressFamily.InterNetwork && + !IPAddress.IsLoopback(a) && + !a.ToString().StartsWith("169.254.", StringComparison.Ordinal)) + .Select(a => a.ToString()) + .FirstOrDefault(); + } + } +} From f8609764158e1dc8ef5c16d5ce8878067cf83a3a Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 13:40:58 -0500 Subject: [PATCH 26/37] Document and test the music view that audio-only servers get FileServer.Load has always given a server the music view when it serves only audio and has no views of its own: if (types == DlnaMediaTypes.Audio) { lock (ids) { if (!ids.HasViews) { ids.AddView("music"); } } } Nothing said so. The readme described a new server as having no views, and views as something you add, so a configured server with "mediaTypes": ["audio"] and "views": [] browsing as Albums/Artists/Folders rather than as its folders looked like a bug. The same happens with sdlna -t audio . Readme.md: the per-server table's views row and the Views section now say that an audio-only server without views gets music, for configured servers and the command line alike, and that any view of its own replaces it. tests/ViewTests.cs: AudioOnlyServersWithoutViewsGetTheMusicView loads a FileServer over a folder holding an untagged MP3, once serving audio only and once serving audio and video, and compares their root folders: Albums and Folders (the music view; the empty Artists, Performers and Genre folders are pruned) against the plain "album" folder. Removing the AddView call makes it fail. Co-Authored-By: Claude Opus 5 --- Readme.md | 6 +++++- tests/ViewTests.cs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 9e8cdb4e..e083514b 100644 --- a/Readme.md +++ b/Readme.md @@ -159,7 +159,7 @@ It is created by the first `sdlna --server add`. A complete example: | `mediaTypes` | Any of `video`, `audio`, `images`; at least one. | all three | | `sortOrder` | `title`, `date` (file date) or `size`. | `title` | | `sortDirection` | `asc` or `desc`. | `asc` | -| `views` | [Views](#views), applied in order. | none | +| `views` | [Views](#views), applied in order. A server with no views that serves only audio gets `music`. | none | | `restrictions` | [Restrictions](#restrictions): `macs`, `ips`, `userAgents`. | none | ### Adding and removing servers @@ -334,6 +334,10 @@ and the same for a configured server: sdlna --server config TV --views add new series ``` +**A server that serves only audio and has no views gets the `music` view**, +whether it is configured (`"mediaTypes": ["audio"]`) or run as +`sdlna -t audio `. Giving it any view of its own replaces `music`. + `sdlna --list-views` prints this summary. Restrictions diff --git a/tests/ViewTests.cs b/tests/ViewTests.cs index 903d5351..c7cd25ea 100644 --- a/tests/ViewTests.cs +++ b/tests/ViewTests.cs @@ -1,8 +1,10 @@ using System; using System.IO; +using System.Linq; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Server.Metadata; using NMaier.SimpleDlna.Server.Views; +using NMaier.SimpleDlna.Tests.Support; using NMaier.SimpleDlna.Utilities; using Xunit; @@ -139,5 +141,33 @@ public void UnknownViewIsReported() { Assert.Throws(() => ViewRepository.Lookup("musik")); } + + private static string[] RootFolders(DirectoryInfo directory, DlnaMediaTypes types) + { + using (var server = TestFileServer.Create(directory, types)) { + server.Rescanning = false; + server.Load(); + var root = (IMediaFolder)server.GetItem(Identifiers.GENERAL_ROOT); + return root.ChildFolders.Select(f => f.Title).ToArray(); + } + } + + /// + /// FileServer.Load gives a server that serves only audio, and has no + /// views, the music view. Any view of its own replaces it. + /// + [Fact] + public void AudioOnlyServersWithoutViewsGetTheMusicView() + { + using (var media = new TempDirectory()) { + Directory.CreateDirectory(media.Combine("album")); + media.WriteFile(Path.Combine("album", "song.mp3")); + + // The file has no tags, so the empty Artists, Performers and Genre + // folders are pruned; "Unspecified album" still fills Albums. + Assert.Equal(new[] {"Albums", "Folders"}, RootFolders(media.Info, DlnaMediaTypes.Audio).OrderBy(t => t, StringComparer.Ordinal)); + Assert.Equal(new[] {"album"}, RootFolders(media.Info, DlnaMediaTypes.Audio | DlnaMediaTypes.Video)); + } + } } } From f5dbe7c91d6c2c7cd62e55aee91cec83256055f0 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 13:55:30 -0500 Subject: [PATCH 27/37] Add AGENTS.md, a guide for developers and coding agents With the GUI gone, the configuration file added and a test suite in place, there is a lot of knowledge about this code base that lives only in commit messages. AGENTS.md collects it for anyone about to change the code, whether a person or an AI coding agent (which read AGENTS.md by convention). It covers: - Commands: build, test (whole suite, one class, one method), run from source, try --server against a scratch HOME without touching your own configuration, and publish a release-style single-file binary. - Layout: the six projects, their assemblies, dependencies and roles; the shared Directory.Build.props and Directory.Packages.props; how a request flows from Main through HttpServer, MediaMount, the SOAP handlers and StreamPump; and where file types, views, the metadata cache and the configuration file are decided. - Code style as practised in the repository (two-space indentation, brace placement, block namespaces, explicit usings, no nullable annotations, field and constant naming, Logging base class, why-comments), and that the readme and help text change together with behaviour. - Tests: xUnit v3 on Microsoft.Testing.Platform, InternalsVisibleTo through the strong-name key, the two serial collections and what belongs in each, dynamic skips instead of silent passes, the Support helpers, and checking that a regression test fails with its fix reverted. - Traps, each of which broke something during the .NET 10 migration or after it: - reflection-discovered views, comparers and thumbnail loaders, which rule out trimming and hide types whose constructors throw; - Delegate.BeginInvoke throwing on .NET; - Assembly.Location being empty in single-file executables; - Environment.GetFolderPath returning "" for missing folders; - bundled native libraries needing a writable HOME to start at all; - Windows-only MAC lookup, hidden folder and console icon; - SkiaSharp's per-platform native asset packages; - the browse cache key needing every request property a response depends on (local endpoint, MIME variant); - the Samsung MIME exception and the three places a type must agree; - loopback clients always being admitted, and restrictions being alternatives; - the implicit music view for audio-only servers; - bumping FileStore.SCHEMA when a cached payload changes, appending to DlnaMime, and Microsoft.Data.Sqlite's named parameters and DBNull; - the configuration binder appending to collections and binding [] to null, strict unknown keys, atomic writes, and HomeDirectoryOverride. - A short checklist for before committing. Every file, type and member the guide names was checked against the code, and every command in it was run. Readme.md gains a Testing section (dotnet test, what the suite does and what it skips), the tests project in the layout table, and a link to AGENTS.md. Co-Authored-By: Claude Opus 5 --- AGENTS.md | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Readme.md | 18 ++++ 2 files changed, 298 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..832b63a1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,280 @@ +AGENTS.md +=== + +Guidance for anyone changing SimpleDLNA, human or AI agent. +[Readme.md](Readme.md) documents the program for its users. This file +documents the code: how to build and test it, how it fits together, and the +traps that have already cost someone a debugging session. + +Commands +--- + +Requires the .NET SDK 10.0. `global.json` only selects the test runner, not +an SDK version. + +```bash +dotnet build +``` + +Builds `sdlna.slnx`: the five projects and the tests. It should finish with +zero warnings; keep it that way. + +```bash +dotnet test +``` + +Runs the whole suite in a few seconds. To run part of it: + +```bash +dotnet test --filter-class NMaier.SimpleDlna.Tests.HttpServerTests +``` + +```bash +dotnet test --filter-method NMaier.SimpleDlna.Tests.ViewTests.UnknownViewIsReported +``` + +To run the program from source: + +```bash +dotnet run --project sdlna -- -l DEBUG ~/Videos +``` + +`sdlna --server ...` reads and writes `~/.sdlna/config.json`. To try it +without touching your own configuration on Linux or macOS, build first and +point `HOME` at a scratch folder. Run the built `sdlna.dll` rather than +`dotnet run`, which would restore every package into that folder: + +```bash +HOME=$(mktemp -d) dotnet sdlna/bin/Debug/net10.0/sdlna.dll --server add Test ~/Videos +``` + +To produce a release-style binary: + +```bash +dotnet publish sdlna/sdlna.csproj -c Release -r osx-arm64 --self-contained -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=false -p:PublishTrimmed=false +``` + +Both of the last two properties matter; see [Traps](#traps). + +Layout +--- + +| Project | Assembly | Depends on | Role | +|------------|------------------------------|------------------------------|------| +| `util` | `SimpleDlna.Utilities` | - | Logging base class, SQLite helpers, ffmpeg discovery and invocation, `StreamPump`, MAC lookup, natural sorting, `Repository` | +| `server` | `SimpleDlna.Server` | util | HTTP server, SSDP, UPnP/DLNA handlers, MIME and profile maps, views, comparers | +| `thumbs` | `SimpleDlna.Thumbnails` | util, server | Thumbnails: images through SkiaSharp, video through ffmpeg | +| `fsserver` | `SimpleDlna.FileMediaServer` | util, server, thumbs | `FileServer`: scans folders into media items, reads tags with TagLibSharp, caches metadata in SQLite | +| `sdlna` | `sdlna` | util, server, fsserver | Console entry point, command-line options, configuration file, `--server` commands | +| `tests` | `SimpleDlna.Tests` | all of the above | xUnit v3 test suite | + +Shared build settings live at the root: `Directory.Build.props` (target +framework, version, strong naming, `InternalsVisibleTo` for the tests) and +`Directory.Packages.props` (every package version, through Central Package +Management; `PackageReference` items in projects carry no `Version`). + +### How a request flows + +1. `sdlna/Program.cs` `Main` hands `--server ...` to `ServerCommand.Run`, + which edits the configuration file and exits. Otherwise it parses + `Options`. With folders it builds one ad-hoc `FileServer`; without, + `ChooseConfiguredServers` either returns the configuration file's servers + (one `FileServer` each) or falls back to serving the current directory. +2. Every `FileServer` is registered with a single `HttpServer` + (`server/Http`), which mounts it at `/mm-N/` as a `MediaMount` + (`server/Handlers`). `SsdpHandler` announces each mount over UDP multicast + on port 1900, which is how TVs discover it. +3. A client fetches `/mm-N/description.xml`, then posts SOAP to + `/mm-N/control` (`MediaMount_SOAP.cs`: ContentDirectory `Browse`, + ConnectionManager `GetProtocolInfo`, and so on). Browse results are DIDL + documents with absolute links to `/mm-N/file//res` and + `/mm-N/cover//...`. +4. File responses are copied to the socket by `util/StreamPump.cs`. A browser + pointed at `/` gets an HTML index (`IndexHandler`, `MediaMount_HTML.cs`). + +### Where things are decided + +- **File types.** `server/Types/DlnaMaps.cs` maps extensions to `DlnaMime` + values, and those to MIME types, DLNA profile names (PN) and the + GetProtocolInfo list. `fsserver/Files/BaseFile.GetFile` picks `AudioFile`, + `ImageFile` or `VideoFile` from the media type. +- **Views** (`server/Views`) rebuild or filter the folder tree. `Identifiers` + (`server/Types`) applies them in order when the tree is loaded. +- **Metadata cache.** `fsserver/FileStore.cs` keeps each file's metadata and + cover in SQLite, encoded by `fsserver/Files/MediaSerializer.cs`. +- **Configuration file.** `sdlna/Configuration.cs` holds the model, + validation and loading/saving; `sdlna/ServerCommand.cs` the `--server` + commands. + +Code style +--- + +Match the surrounding code rather than modernising it in passing. + +- Two-space indentation, LF line endings for `.cs` (`.editorconfig`). Project + and solution files are CRLF (`.gitattributes`). Many `.cs` files start with + a UTF-8 BOM; leave existing BOMs alone. +- Braces: types and members open on their own line; `if`, `foreach`, + `using` and friends open on the same line, and `else` starts a new line + after the closing brace. +- Block-scoped namespaces, explicit `using` directives (implicit usings are + off), no nullable reference types, `var` for locals, `typeof (T)` with a + space. +- Private fields are camelCase without an underscore; constants are + UPPER_SNAKE_CASE. +- Classes that log derive from `NMaier.SimpleDlna.Utilities.Logging` and call + `Debug`, `InfoFormat`, `Warn` and so on. log4net is configured once, in + `sdlna/Options.cs`. +- Comments explain why, especially for workarounds. Existing ones often name + the failure they prevent; keep that habit. +- User-facing behaviour is documented in `Readme.md`, and in the help text + (`sdlna --help`, `sdlna --server help`, `sdlna --list-views`). Change both + together. + +Tests +--- + +The suite uses xUnit v3 on Microsoft.Testing.Platform (selected in +`global.json`). The test project is an executable; `dotnet test` builds and +runs it. + +- **Internal access.** The shipped assemblies grant `InternalsVisibleTo` to + `SimpleDlna.Tests` with the public key of `sdlna.key.snk`, which signs the + tests too. Prefer testing through `internal` members over reflection; making + a private method `internal` for a test is fine. +- **Collections.** Most tests run in parallel. Tests that change process-wide + state (the console writers, environment variables such as `HOME`, + `ConfigurationStore.HomeDirectoryOverride`) belong in + `[Collection(ProcessStateCollection.NAME)]`. Tests that talk to the HTTP + server belong in `[Collection(HttpServerCollection.NAME)]` and receive the + shared `DlnaTestServer` through their constructor. +- **Skips, not silent passes.** When a test cannot run on a machine (no + ffmpeg, no non-loopback address, a Windows-only behaviour), skip it with + `Assert.Skip`, `Assert.SkipWhen` or `Assert.SkipUnless` and a reason, so it + shows as skipped. +- **Cancellation.** Pass `TestContext.Current.CancellationToken` to async + APIs (xUnit analyzer rule xUnit1051). +- **Helpers** in `tests/Support`: + - `TempDirectory` creates and deletes a scratch folder. + - `TestMedia` writes real JPEGs (SkiaSharp) and, when ffmpeg is installed, + short videos. + - `TestFileServer.Create` builds a `FileServer` over a folder. + - `ConfigurationHome` redirects the configuration file to a scratch folder + and reads back what was written. + - `ServerCommandRunner` runs `--server` commands and captures their output + and exit code. + - `DlnaTestServer` and `DlnaClient` host file servers on a real + `HttpServer` and talk to it with SOAP, choosing the User-Agent and the + local address each request connects through. +- **Regression tests name their bug.** Each one's summary says what used to + go wrong. When adding one, check that it fails with the fix reverted before + relying on it. + +`DlnaTestServer` uses the internal `HttpServer(port, announce: false)` +constructor. With SSDP off, tests never announce `test-` servers to +real TVs on the network, need no UDP port 1900, and shut down instantly +rather than after SSDP's byebye datagrams drain. + +Traps +--- + +Each of these has broken something before. + +### Runtime and platform + +- **Reflection discovers views, comparers and thumbnail loaders.** + `Repository` (`util/Repository.cs`) instantiates every type in the + interface's assembly that implements `IView` or `IItemComparer` and has a + public parameterless constructor; `ThumbnailMaker` does the same for + `IThumbnailLoader`. Adding one needs no registration. It also means + **trimming must stay off**: the trimmer cannot see these types are used. + A constructor that throws hides that type: `Repository` silently, + `ThumbnailMaker` with an Info log line (the video loader throws when ffmpeg + is missing, which used to disable image thumbnails too). +- **`Delegate.BeginInvoke` throws `PlatformNotSupportedException` on + .NET.** It compiles without a warning. Use `ThreadPool.QueueUserWorkItem` + or tasks. +- **`Assembly.Location` is `""` in a single-file executable.** Use + `AppContext.BaseDirectory` for the program's folder. +- **`Environment.GetFolderPath` returns `""` for a folder that doesn't + exist**, such as the home folder of a service account. Pass + `Environment.SpecialFolderOption.DoNotVerify` when you need the path, and + skip empty results when searching (`FFmpeg.GetSpecialLocations`). +- **Single-file bundles and native libraries.** With + `IncludeNativeLibrariesForSelfExtract=true`, the host extracts SkiaSharp + and SQLite into `$HOME/.net` before `Main` runs, and refuses to start at all + when `HOME` is missing or read-only. Publish them beside the executable + instead. +- **Windows-only features.** Looking up a client's MAC address + (`util/AddressToMacResolver.cs`) only works on Windows, so MAC restrictions + never match elsewhere. The `.sdlna` folder's hidden attribute and the + console icon are Windows-only too. Guard such code with + `OperatingSystem.IsWindows()`. +- **SkiaSharp's native library comes from per-platform packages.** The main + package brings Windows and macOS; Linux needs + `SkiaSharp.NativeAssets.Linux.NoDependencies`, the variant that doesn't + require fontconfig. Image thumbnails failing on one OS only usually means a + missing asset package. + +### Protocol + +- **The browse cache key must include everything a response depends on.** + `MediaMount_SOAP.cs` caches SOAP responses under a key built from the + prefix, `request.LocalEndPoint`, `DlnaMaps.MimeVariant(request.Headers)` + and the request parameters. The endpoint is there because DIDL links embed + the address the client connected to; without it, a browse from + `127.0.0.1` sent network clients to localhost. The MIME variant is there + because Samsung clients get different types. If you make a response depend + on anything else about the request, add it to the key. +- **Samsung gets `video/x-mkv`.** Clients whose User-Agent contains + `SEC_HHP_` or `SamsungWiselinkPro` are sent `video/x-mkv` for Matroska and + WebM; everyone else gets `video/x-matroska` and `video/webm`. The type + appears in three places, which must agree: DIDL `protocolInfo`, the file + response's `Content-Type`, and the GetProtocolInfo list. Go through + `DlnaMaps.MimeFor` and `DlnaMaps.ProtocolInfoFor` instead of reading + `DlnaMaps.Mime` directly. +- **Loopback clients are always admitted**, by `HttpServer.AuthorizeClient` + and by `MediaMount.HandleRequest`, whatever the restrictions. Restrictions + can only be observed from another address. +- **Restrictions are alternatives.** A client matching any entry of any kind + (IP, MAC, User-Agent) is admitted. User-Agent entries must match the whole + header exactly, including case. +- **Audio-only servers get the `music` view.** `FileServer.Load` adds it when + the server serves only audio and has no views. + +### Persistence + +- **Changing a cached payload means bumping `FileStore.SCHEMA`.** + `MediaSerializer` replaced `BinaryFormatter` (removed from .NET 9) with an + explicit field-by-field format. Change what `AudioFile`, `ImageFile` or + `VideoFile` write or read, and old caches will misparse unless the schema + number changes, which makes existing caches be discarded and rebuilt. +- **`DlnaMime` values are persisted.** Append new members at the end of the + enum; never reorder or insert. +- **Microsoft.Data.Sqlite** requires named parameters (`@key`) and rejects a + parameter whose value is `null`; bind `DBNull.Value`. + +### Configuration file + +- **The configuration binder appends to collections** that already hold + items instead of replacing them, so the model's collections start empty + and `ConfigurationStore.Normalize` fills in defaults after binding. An + empty JSON array (`[]`) binds to `null`, not to an empty list, which + `Normalize` also handles. +- Unknown keys are errors (`ErrorOnUnknownConfiguration`), so renaming a key + breaks existing files. Add new keys; don't rename old ones. +- Writes are atomic (a temporary file, then a move) so a crash never leaves a + half-written configuration, and `--edit` keeps working on an invalid file. + Keep both properties. +- `ConfigurationStore.HomeDirectoryOverride` redirects the file's location + for tests. Use it (through `ConfigurationHome`) rather than changing `HOME`. + +Before you commit +--- + +- `dotnet build` with no warnings, and `dotnet test` passing. +- New behaviour has a test; a bug fix has a regression test that fails + without the fix. +- `Readme.md` and the command help describe any user-visible change. +- Cached payload changed? `FileStore.SCHEMA` bumped. +- New response dependency? Added to the browse cache key. diff --git a/Readme.md b/Readme.md index e083514b..7c144c1d 100644 --- a/Readme.md +++ b/Readme.md @@ -16,6 +16,7 @@ See [the github page](http://nmaier.github.io/simpleDLNA/) for more details and - [Views](#views) - [Restrictions](#restrictions) - [Thumbnails and ffmpeg](#thumbnails-and-ffmpeg) +- [Testing](#testing) - [Project layout](#project-layout) Building @@ -386,6 +387,19 @@ Thumbnailing video files and reading their duration requires [ffmpeg](https://ffmpeg.org/) on `PATH`, in `FFMPEG_HOME`, or beside the `sdlna` executable. Image and audio handling have no external dependencies. +Testing +--- + +``` +dotnet test +``` + +Runs the test suite, which takes a few seconds. Besides unit tests, it starts +real servers on free ports and browses them the way TVs do, from the same +machine. The test servers are never announced on your network. Tests that need +ffmpeg, or a network address other than loopback, are reported as skipped +when those aren't available. + Project layout --- @@ -396,3 +410,7 @@ Project layout | `thumbs` | `SimpleDlna.Thumbnails` | Thumbnail generation | | `fsserver` | `SimpleDlna.FileMediaServer` | Filesystem media source and its metadata cache | | `sdlna` | `sdlna` | Console entry point and configuration file | +| `tests` | `SimpleDlna.Tests` | Test suite | + +[AGENTS.md](AGENTS.md) explains how the code and tests fit together, the +conventions to follow and the pitfalls to avoid when changing them. From 7ec83d2a7cfeb9966b8fbfc9b149c997a05d70e9 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Mon, 14 Sep 2026 16:02:46 -0500 Subject: [PATCH 28/37] Say "Connection: close" when the server is going to close the connection Every HTTP response carried "Connection: keep-alive", set by default in ResponseHeaders. But HttpClient only keeps a connection open when the request itself said "Connection: keep-alive"; otherwise it closes it once the response is written. This predates the migration. HTTP/1.1 connections persist unless one side says "close", so a client that doesn't ask for keep-alive, yet is told the connection stays open, reuses it. The server then closes it without reading the next request. Whether that request is lost depends on timing: the close happens in the response pump's completion callback on the thread pool, and if the client sends before it lands, the request fails. .NET's HttpClient reports HttpRequestException: An error occurred while sending the request. ---> HttpIOException: The response ended prematurely. (ResponseEnded) and does not retry it. Found by the first run of the test suite in CI. On the 2-vCPU Linux runner, with ffmpeg generating thumbnails in the background, HttpServerTests.VideoDurationAndThumbnailComeFromFFmpeg failed that way on the browse request that followed the description.xml fetch. It passed on macOS and Windows, and could not be reproduced locally even with the thread pool starved or every core busy: the close usually wins the race. Reproduced deterministically instead, two ways: - A minimal server that answers with "Connection: keep-alive" and closes 300 ms later: .NET's HttpClient fails the next POST on that connection with exactly the error above. - sdlna itself with a 300 ms sleep before HttpClient.Close(): all 10 HTTP server tests failed with ResponseEnded. With this fix and the same sleep, all 10 passed. The fix - HttpClient.SendResponse decides once whether the connection will be kept (the request asked for keep-alive) and writes "Connection: keep-alive" or "Connection: close" to match. The pump callback uses the same decision, so the header and the behaviour cannot disagree. - The header is written while building the header block instead of being set on response.Headers, because StaticHandler hands the same response object, such as the favicon or an error page, to every client; changing it per request would race between clients. Any Connection header a handler sets is replaced. - ResponseHeaders no longer defaults Connection to keep-alive. Clients that ask for keep-alive are unaffected. Clients that don't were already getting a new connection for every request; now they are told so, instead of occasionally losing a request. Test: HttpServerTests.ConnectionHeaderSaysWhetherTheConnectionStaysOpen opens a raw socket, sends a request asking for keep-alive (expects "keep-alive"), then one without on the same connection (expects "close", then end of stream). It failed before the fix with "keep-alive" where "close" was expected. DlnaClient.RawGet sends a request over an open stream and reads the headers and exactly Content-Length body bytes. dotnet build: zero warnings. dotnet test, Debug and Release: 96 tests, 95 passed, 1 skipped (the Windows-only hidden-folder test), 0 failed. Co-Authored-By: Claude Opus 5 --- server/Http/HttpClient.cs | 20 ++++++++++++++++---- server/Http/ResponseHeaders.cs | 3 ++- tests/HttpServerTests.cs | 29 +++++++++++++++++++++++++++++ tests/Support/DlnaClient.cs | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 5 deletions(-) diff --git a/server/Http/HttpClient.cs b/server/Http/HttpClient.cs index 168e6af8..3fb23d2c 100644 --- a/server/Http/HttpClient.cs +++ b/server/Http/HttpClient.cs @@ -313,6 +313,14 @@ private void SendResponse() var statusCode = response.Status; var responseBody = ProcessRanges(response, ref statusCode); var responseStream = new ConcatenatedStream(); + // The connection is only kept when the client asked for it, and the + // Connection header must say which. HTTP/1.1 clients otherwise assume + // it persists, reuse it, and lose the request they send before it is + // closed. Written here rather than set on response.Headers, because + // static and error responses are shared between clients. + string conn; + var keepAlive = Headers.TryGetValue("connection", out conn) && + conn.ToUpperInvariant() == "KEEP-ALIVE"; try { var headerBlock = new StringBuilder(); headerBlock.AppendFormat( @@ -320,7 +328,13 @@ private void SendResponse() (uint)statusCode, HttpPhrases.Phrases[statusCode] ); - headerBlock.Append(response.Headers.HeaderBlock); + foreach (var h in response.Headers) { + if (!string.Equals(h.Key, "Connection", StringComparison.OrdinalIgnoreCase)) { + headerBlock.AppendFormat("{0}: {1}\r\n", h.Key, h.Value); + } + } + headerBlock.AppendFormat( + "Connection: {0}\r\n", keepAlive ? "keep-alive" : "close"); headerBlock.Append(CRLF); var headerStream = new MemoryStream( @@ -340,9 +354,7 @@ private void SendResponse() if (result == StreamPumpResult.Delivered) { DebugFormat("{0} - Done writing response", this); - string conn; - if (Headers.TryGetValue("connection", out conn) && - conn.ToUpperInvariant() == "KEEP-ALIVE") { + if (keepAlive) { ReadNext(); return; } diff --git a/server/Http/ResponseHeaders.cs b/server/Http/ResponseHeaders.cs index 83e5fd75..3a1319d8 100644 --- a/server/Http/ResponseHeaders.cs +++ b/server/Http/ResponseHeaders.cs @@ -13,7 +13,8 @@ public ResponseHeaders(bool noCache) { this["Server"] = HttpServer.Signature; this["Date"] = DateTime.Now.ToString("R"); - this["Connection"] = "keep-alive"; + // No Connection header: HttpClient.SendResponse writes it, since only + // the connection knows whether it will be kept open. if (noCache) { this["Cache-Control"] = "no-cache"; } diff --git a/tests/HttpServerTests.cs b/tests/HttpServerTests.cs index 304ec9bc..ddc54c54 100644 --- a/tests/HttpServerTests.cs +++ b/tests/HttpServerTests.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using System.Net; +using System.Net.Sockets; using NMaier.SimpleDlna.FileMediaServer; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Tests.Support; @@ -144,6 +145,34 @@ public void LinksUseTheAddressEachClientConnectedTo() } } + /// + /// Regression: every response said "Connection: keep-alive", yet the + /// server closes the connection after answering unless the request asked + /// to keep it open. HTTP/1.1 clients believe the header and reuse the + /// connection, so a request sent before the close landed was lost: "The + /// response ended prematurely". It took a busy machine to hit, but CI + /// did. + /// + [Fact] + public void ConnectionHeaderSaysWhetherTheConnectionStaysOpen() + { + media.WriteFile("film.mkv"); + var prefix = Mount(); + + using (var client = new TcpClient("127.0.0.1", server.Port)) { + var stream = client.GetStream(); + stream.ReadTimeout = 10000; + + var kept = DlnaClient.RawGet(stream, prefix + "description.xml", "Connection: keep-alive\r\n"); + Assert.Equal("keep-alive", kept["CONNECTION"]); + + // Still open, as announced; without asking again, it is closed. + var closed = DlnaClient.RawGet(stream, prefix + "description.xml"); + Assert.Equal("close", closed["CONNECTION"]); + Assert.Equal(-1, stream.ReadByte()); + } + } + [Fact] public void RestrictionsRefuseOtherMachinesButAlwaysAdmitThisOne() { diff --git a/tests/Support/DlnaClient.cs b/tests/Support/DlnaClient.cs index a5f88639..74146910 100644 --- a/tests/Support/DlnaClient.cs +++ b/tests/Support/DlnaClient.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Text; @@ -128,6 +129,38 @@ public static string[] GetProtocolInfo(int port, string prefix, string userAgent } } + /// + /// Sends a GET over an already open connection, the way HttpClient reuses + /// one, and reads the whole response. Returns its headers, with names + /// in upper case. + /// + public static Dictionary RawGet(Stream stream, string path, + string extraHeaders = "") + { + var request = Encoding.ASCII.GetBytes( + $"GET {path} HTTP/1.1\r\nHost: 127.0.0.1\r\nUser-Agent: {GENERIC}\r\n{extraHeaders}\r\n"); + stream.Write(request, 0, request.Length); + + var head = new StringBuilder(); + while (!head.ToString().EndsWith("\r\n\r\n", StringComparison.Ordinal)) { + var b = stream.ReadByte(); + if (b < 0) { + throw new EndOfStreamException("connection closed before the response headers ended"); + } + head.Append((char)b); + } + var headers = head.ToString() + .Split("\r\n", StringSplitOptions.RemoveEmptyEntries) + .Skip(1) + .Select(l => l.Split(':', 2)) + .ToDictionary(h => h[0].Trim().ToUpperInvariant(), h => h[1].Trim()); + string length; + if (headers.TryGetValue("CONTENT-LENGTH", out length)) { + stream.ReadExactly(new byte[long.Parse(length)]); + } + return headers; + } + /// /// The host:port parts of every link in a browse result (res and cover /// elements). Attributes are ignored: namespace declarations are URIs too. From e65fb9d4918ae7c9deb88d41bb383adaffd32295 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Wed, 16 Sep 2026 19:25:07 -0500 Subject: [PATCH 29/37] Generate thumbnails with ImageSharp instead of SkiaSharp SkiaSharp wraps Google's native Skia library, which has to ship as a separate file beside the executable: libSkiaSharp.so, .dylib or .dll, about 9 MB. Its packages contain no static build for desktop platforms, so it cannot be linked into the single-file executable. ImageSharp is written entirely in C#, so it compiles into the executable itself. Version choice - SixLabors.ImageSharp 3.1.12, the current 3.x release. - ImageSharp 4.x (4.1.2) was tried and rejected: its package adds a build step that fails Release builds with "No Six Labors license found" unless a license key is configured. That would break CI and every contributor's release build. Directory.Packages.props says so next to the version. - 3.1 is under the Six Labors Split License, which grants Apache 2.0 to software under an open-source license, as this project is. 2.1.13 is plain Apache 2.0 but an older, slower build for .NET. - The stb_image ports (StbImageSharp, Unlicense or MIT) were rejected: they are compiled as unsafe pointer code, so decoding damaged or hostile files is no safer than native code. - NuGet's audit reports no vulnerabilities for 3.1.12. It has no package dependencies. Behaviour kept - The same fit rule: scale down to fit within the requested size keeping the aspect ratio, never enlarge, and never produce a zero-sized side. Images are borderless; video frames are letterboxed on black. This is now ThumbnailMaker.FitWithin. - Transparent areas become black. JPEG has no alpha channel, and Skia drew onto a black canvas; ImageSharp would otherwise encode whatever colour the transparent pixels hold, so the image is drawn onto an opaque black canvas too. - JPEG quality 85. - Damaged or unknown data is reported as NotSupportedException, and the video loader still turns an undecodable ffmpeg frame into ArgumentException. Changes - Only the first frame of animated images is decoded (MaxFrames = 1), since only that frame is shown. - Resizing uses ImageSharp's bicubic resampler throughout, where Skia used Mitchell when enlarging and mipmapped linear when shrinking. - Thumbnails are decoded at the size they are shown. LoadImage reads the image header first, computes the fitted size, and passes it as DecoderOptions.TargetSize, which makes the JPEG decoder work at a reduced scale. Measured on a 12 MP JPEG to a 288x216 thumbnail (Release, Apple silicon): ImageSharp 205 ms with a full decode, 77 ms with TargetSize; SkiaSharp 74 ms. TargetSize also enlarges images smaller than the target (a 100x50 JPEG came back 400x200), so it is only set when shrinking. The final resize uses the size computed from the original dimensions, so thumbnail sizes don't depend on the decoder's rounding. Streams that can't seek are decoded in full. Tests - The helpers write test images with ImageSharp. - New in ThumbnailTests: - SmallImagesAreNotEnlarged - TransparencyBecomesBlack: a half-transparent PNG whose transparent pixels are white underneath - AnimatedGifShowsItsFirstFrame - DamagedImageIsReportedAsUnsupported - The aspect-ratio test now also checks the thumbnail's colour. - Checked against their bugs: a white canvas fails TransparencyBecomesBlack, and scaling small images up fails SmallImagesAreNotEnlarged. - The HTTP tests serve image thumbnails and ffmpeg video thumbnails, which now decode through ImageSharp. AGENTS.md: ImageSharp in the layout and test helpers; the SkiaSharp native-asset trap is replaced by why ImageSharp stays on 3.1 and how TargetSize is used. dotnet build: zero warnings. dotnet test: 100 tests, 99 passed, 1 skipped (the Windows-only hidden-folder test). Co-Authored-By: Claude Opus 5 --- AGENTS.md | 23 +++--- Directory.Packages.props | 6 +- tests/Support/TestMedia.cs | 57 +++++++++++-- tests/ThumbnailTests.cs | 72 +++++++++++++++- tests/tests.csproj | 2 +- thumbs/ImageThumbnailLoader.cs | 22 ++--- thumbs/ThumbnailMaker.cs | 147 ++++++++++++++++++++++++--------- thumbs/VideoThumbnailLoader.cs | 19 +++-- thumbs/thumbs.csproj | 4 +- 9 files changed, 262 insertions(+), 90 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 832b63a1..f4afe832 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -63,7 +63,7 @@ Layout |------------|------------------------------|------------------------------|------| | `util` | `SimpleDlna.Utilities` | - | Logging base class, SQLite helpers, ffmpeg discovery and invocation, `StreamPump`, MAC lookup, natural sorting, `Repository` | | `server` | `SimpleDlna.Server` | util | HTTP server, SSDP, UPnP/DLNA handlers, MIME and profile maps, views, comparers | -| `thumbs` | `SimpleDlna.Thumbnails` | util, server | Thumbnails: images through SkiaSharp, video through ffmpeg | +| `thumbs` | `SimpleDlna.Thumbnails` | util, server | Thumbnails: images through ImageSharp, video through ffmpeg | | `fsserver` | `SimpleDlna.FileMediaServer` | util, server, thumbs | `FileServer`: scans folders into media items, reads tags with TagLibSharp, caches metadata in SQLite | | `sdlna` | `sdlna` | util, server, fsserver | Console entry point, command-line options, configuration file, `--server` commands | | `tests` | `SimpleDlna.Tests` | all of the above | xUnit v3 test suite | @@ -156,8 +156,8 @@ runs it. APIs (xUnit analyzer rule xUnit1051). - **Helpers** in `tests/Support`: - `TempDirectory` creates and deletes a scratch folder. - - `TestMedia` writes real JPEGs (SkiaSharp) and, when ffmpeg is installed, - short videos. + - `TestMedia` writes real JPEGs, transparent PNGs and animated GIFs + (ImageSharp) and, when ffmpeg is installed, short videos. - `TestFileServer.Create` builds a `FileServer` over a folder. - `ConfigurationHome` redirects the configuration file to a scratch folder and reads back what was written. @@ -201,8 +201,8 @@ Each of these has broken something before. `Environment.SpecialFolderOption.DoNotVerify` when you need the path, and skip empty results when searching (`FFmpeg.GetSpecialLocations`). - **Single-file bundles and native libraries.** With - `IncludeNativeLibrariesForSelfExtract=true`, the host extracts SkiaSharp - and SQLite into `$HOME/.net` before `Main` runs, and refuses to start at all + `IncludeNativeLibrariesForSelfExtract=true`, the host extracts SQLite + into `$HOME/.net` before `Main` runs, and refuses to start at all when `HOME` is missing or read-only. Publish them beside the executable instead. - **Windows-only features.** Looking up a client's MAC address @@ -210,11 +210,14 @@ Each of these has broken something before. never match elsewhere. The `.sdlna` folder's hidden attribute and the console icon are Windows-only too. Guard such code with `OperatingSystem.IsWindows()`. -- **SkiaSharp's native library comes from per-platform packages.** The main - package brings Windows and macOS; Linux needs - `SkiaSharp.NativeAssets.Linux.NoDependencies`, the variant that doesn't - require fontconfig. Image thumbnails failing on one OS only usually means a - missing asset package. +- **ImageSharp stays on 3.1.** ImageSharp 4 fails Release builds unless a + Six Labors license key is configured. 3.1 is under the Six Labors Split + License, which grants Apache 2.0 to open-source projects like this one. +- **Thumbnails decode at the size they are shown.** `ThumbnailMaker.LoadImage` + reads the image's size first and passes the fitted size as + `DecoderOptions.TargetSize`, so JPEGs decode at a reduced scale (about + three times faster for a 12 MP photo). `TargetSize` also enlarges smaller + images, so it is only set when shrinking. ### Protocol diff --git a/Directory.Packages.props b/Directory.Packages.props index 283ea14f..5dc55e7a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -19,9 +19,9 @@ - - - + + diff --git a/tests/Support/TestMedia.cs b/tests/Support/TestMedia.cs index 93f0675b..34f2f76c 100644 --- a/tests/Support/TestMedia.cs +++ b/tests/Support/TestMedia.cs @@ -2,29 +2,68 @@ using System.Diagnostics; using System.IO; using NMaier.SimpleDlna.Utilities; -using SkiaSharp; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.PixelFormats; namespace NMaier.SimpleDlna.Tests.Support { internal static class TestMedia { + public static readonly Rgb24 SeaGreen = new Rgb24(46, 139, 87); + public static FileInfo WriteJpeg(string path, int width, int height) { - using (var bitmap = new SKBitmap(width, height)) { - using (var canvas = new SKCanvas(bitmap)) { - canvas.Clear(SKColors.SeaGreen); - } - using (var image = SKImage.FromBitmap(bitmap)) { - using (var data = image.Encode(SKEncodedImageFormat.Jpeg, 90)) { - using (var file = File.Create(path)) { - data.SaveTo(file); + using (var image = new Image(width, height, SeaGreen)) { + image.SaveAsJpeg(path, new JpegEncoder {Quality = 90}); + } + return new FileInfo(path); + } + + /// + /// A PNG whose left half is opaque white and right half fully + /// transparent (but white underneath). + /// + public static FileInfo WriteHalfTransparentPng(string path, int width, int height) + { + using (var image = new Image(width, height, new Rgba32(255, 255, 255, 255))) { + image.ProcessPixelRows(rows => + { + for (var y = 0; y < rows.Height; y++) { + var row = rows.GetRowSpan(y); + for (var x = width / 2; x < width; x++) { + row[x] = new Rgba32(255, 255, 255, 0); } } + }); + image.SaveAsPng(path); + } + return new FileInfo(path); + } + + /// + /// An animated GIF: one frame of each colour, in order. + /// + public static FileInfo WriteAnimatedGif(string path, int width, int height, + params Rgba32[] colours) + { + using (var image = new Image(width, height, colours[0])) { + foreach (var colour in colours.AsSpan(1)) { + using (var frame = new Image(width, height, colour)) { + image.Frames.AddFrame(frame.Frames.RootFrame); + } } + image.SaveAsGif(path, new GifEncoder()); } return new FileInfo(path); } + public static Image Decode(byte[] data) + { + return Image.Load(data); + } + public static bool IsJpeg(byte[] data) { return data != null && data.Length > 3 && diff --git a/tests/ThumbnailTests.cs b/tests/ThumbnailTests.cs index 45616622..db0e6d7c 100644 --- a/tests/ThumbnailTests.cs +++ b/tests/ThumbnailTests.cs @@ -3,7 +3,7 @@ using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Tests.Support; using NMaier.SimpleDlna.Thumbnails; -using SkiaSharp; +using SixLabors.ImageSharp.PixelFormats; using Xunit; namespace NMaier.SimpleDlna.Tests @@ -28,12 +28,80 @@ public void ImageThumbnailKeepsTheAspectRatioAndIsAJpeg() Assert.Equal(216, thumbnail.Height); var data = thumbnail.GetData(); Assert.True(TestMedia.IsJpeg(data)); - using (var decoded = SKBitmap.Decode(data)) { + using (var decoded = TestMedia.Decode(data)) { Assert.Equal(288, decoded.Width); Assert.Equal(216, decoded.Height); + AssertClose(TestMedia.SeaGreen, decoded[144, 108]); } } + private static void AssertClose(Rgb24 expected, Rgb24 actual) + { + // JPEG is lossy; a few steps either way is the same colour. + Assert.True( + Math.Abs(expected.R - actual.R) <= 12 && + Math.Abs(expected.G - actual.G) <= 12 && + Math.Abs(expected.B - actual.B) <= 12, + $"expected about {expected}, got {actual}"); + } + + [Fact] + public void SmallImagesAreNotEnlarged() + { + var source = TestMedia.WriteJpeg(temp.Combine("icon.jpg"), 100, 50); + + var thumbnail = new ThumbnailMaker().GetThumbnail(source, 384, 216); + + Assert.Equal(100, thumbnail.Width); + Assert.Equal(50, thumbnail.Height); + using (var decoded = TestMedia.Decode(thumbnail.GetData())) { + Assert.Equal(100, decoded.Width); + } + } + + /// + /// JPEG has no alpha channel, so transparent areas are flattened onto + /// black, as the Skia and GDI+ implementations did, whatever colour the + /// transparent pixels hold. + /// + [Fact] + public void TransparencyBecomesBlack() + { + var source = TestMedia.WriteHalfTransparentPng(temp.Combine("logo.png"), 200, 100); + + var thumbnail = new ThumbnailMaker().GetThumbnail(source, 100, 100); + + using (var decoded = TestMedia.Decode(thumbnail.GetData())) { + Assert.Equal(100, decoded.Width); + Assert.Equal(50, decoded.Height); + AssertClose(new Rgb24(255, 255, 255), decoded[10, 25]); + AssertClose(new Rgb24(0, 0, 0), decoded[90, 25]); + } + } + + [Fact] + public void AnimatedGifShowsItsFirstFrame() + { + var source = TestMedia.WriteAnimatedGif( + temp.Combine("anim.gif"), 64, 64, + new Rgba32(255, 0, 0), new Rgba32(0, 0, 255)); + + var thumbnail = new ThumbnailMaker().GetThumbnail(source, 32, 32); + + using (var decoded = TestMedia.Decode(thumbnail.GetData())) { + AssertClose(new Rgb24(255, 0, 0), decoded[16, 16]); + } + } + + [Fact] + public void DamagedImageIsReportedAsUnsupported() + { + var source = temp.WriteFile("broken.jpg", 512); + + Assert.Throws( + () => new ThumbnailMaker().GetThumbnail(source, 384, 216)); + } + [Fact] public void ExtremeAspectRatioDoesNotProduceAnEmptyBitmap() { diff --git a/tests/tests.csproj b/tests/tests.csproj index b3f5efe8..8b65a3d1 100644 --- a/tests/tests.csproj +++ b/tests/tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/thumbs/ImageThumbnailLoader.cs b/thumbs/ImageThumbnailLoader.cs index 174c51ce..a5dd0b81 100644 --- a/thumbs/ImageThumbnailLoader.cs +++ b/thumbs/ImageThumbnailLoader.cs @@ -1,7 +1,7 @@ using System; using System.IO; using NMaier.SimpleDlna.Server; -using SkiaSharp; +using SixLabors.ImageSharp; namespace NMaier.SimpleDlna.Thumbnails { @@ -12,28 +12,24 @@ internal sealed class ImageThumbnailLoader : IThumbnailLoader public MemoryStream GetThumbnail(object item, ref int width, ref int height) { - SKBitmap img; + Image img; + Size fit; var stream = item as Stream; if (stream != null) { - img = SKBitmap.Decode(stream); + img = ThumbnailMaker.LoadImage(stream, width, height, out fit); } else { var fi = item as FileInfo; - if (fi != null) { - img = SKBitmap.Decode(fi.FullName); - } - else { + if (fi == null) { throw new NotSupportedException(); } - } - // Unlike Image.FromStream, SKBitmap.Decode reports failure by returning - // null rather than throwing. - if (img == null) { - throw new NotSupportedException("Not a supported image format"); + using (var file = fi.OpenRead()) { + img = ThumbnailMaker.LoadImage(file, width, height, out fit); + } } using (img) { return ThumbnailMaker.ResizeToJpeg( - img, ref width, ref height, ThumbnailMakerBorder.Borderless); + img, fit, ref width, ref height, ThumbnailMakerBorder.Borderless); } } } diff --git a/thumbs/ThumbnailMaker.cs b/thumbs/ThumbnailMaker.cs index 94aa57ce..39828276 100644 --- a/thumbs/ThumbnailMaker.cs +++ b/thumbs/ThumbnailMaker.cs @@ -6,7 +6,11 @@ using log4net; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Utilities; -using SkiaSharp; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; namespace NMaier.SimpleDlna.Thumbnails { @@ -14,6 +18,20 @@ public sealed class ThumbnailMaker : Logging { private const int JPEG_QUALITY = 85; + private static readonly JpegEncoder jpegEncoder = new JpegEncoder + { + Quality = JPEG_QUALITY + }; + + /// + /// Only the first frame of an animated image is ever shown, so the rest + /// are not decoded. + /// + private static readonly DecoderOptions decoderOptions = new DecoderOptions + { + MaxFrames = 1 + }; + private static readonly LeastRecentlyUsedDictionary cache = new LeastRecentlyUsedDictionary(1 << 11); @@ -102,11 +120,17 @@ private byte[] GetThumbnailInternal(string key, object item, throw new ArgumentException("Not a supported resource"); } - internal static SKBitmap ResizeImage(SKBitmap image, int width, int height, - ThumbnailMakerBorder border) + /// + /// The size a by + /// image is shown at to fit within + /// by , keeping its + /// aspect ratio and never enlarging it. + /// + internal static Size FitWithin(int sourceWidth, int sourceHeight, + int width, int height) { - var nw = (float)image.Width; - var nh = (float)image.Height; + var nw = (float)sourceWidth; + var nh = (float)sourceHeight; if (nw > width) { nh = width * nh / nw; nw = width; @@ -115,29 +139,78 @@ internal static SKBitmap ResizeImage(SKBitmap image, int width, int height, nw = height * nw / nh; nh = height; } - // A source with an extreme aspect ratio can scale to zero on one axis, - // which is not a valid bitmap size. - var rw = border == ThumbnailMakerBorder.Bordered - ? width - : Math.Max((int)nw, 1); - var rh = border == ThumbnailMakerBorder.Bordered - ? height - : Math.Max((int)nh, 1); - - var result = new SKBitmap(rw, rh, SKColorType.Rgba8888, SKAlphaType.Premul); + // which is not a valid image size. + return new Size(Math.Max((int)nw, 1), Math.Max((int)nh, 1)); + } + + /// + /// Decodes the first frame of an image, in any format ImageSharp reads, + /// for a thumbnail of at most by + /// . + /// + /// + /// The size to show the image at; see . + /// + /// + /// The data is not an image, or is damaged. + /// + internal static Image LoadImage(Stream stream, int width, int height, + out Size fit) + { try { - // Mitchell cubic when enlarging, cheap linear filtering when shrinking, - // matching the quality/speed split the GDI+ implementation used. - var sampling = rw > image.Width && rh > image.Height - ? new SKSamplingOptions(SKCubicResampler.Mitchell) - : new SKSamplingOptions(SKFilterMode.Linear, SKMipmapMode.Linear); - using (var canvas = new SKCanvas(result)) { - canvas.Clear(SKColors.Black); - using (var img = SKImage.FromBitmap(image)) { - var rect = SKRect.Create( - (rw - nw) / 2f, (rh - nh) / 2f, nw, nh); - canvas.DrawImage(img, rect, sampling); + if (!stream.CanSeek) { + var whole = Image.Load(decoderOptions, stream); + fit = FitWithin(whole.Width, whole.Height, width, height); + return whole; + } + var start = stream.Position; + var info = Image.Identify(decoderOptions, stream); + stream.Position = start; + fit = FitWithin(info.Width, info.Height, width, height); + var options = decoderOptions; + if (fit.Width < info.Width || fit.Height < info.Height) { + // JPEGs are then decoded at a reduced scale, which makes a photo's + // thumbnail several times faster. TargetSize would also enlarge a + // smaller image, hence only when shrinking. + options = new DecoderOptions + { + MaxFrames = decoderOptions.MaxFrames, + TargetSize = fit + }; + } + return Image.Load(options, stream); + } + catch (Exception ex) when ( + ex is ImageFormatException || ex is InvalidImageContentException) { + throw new NotSupportedException("Not a supported image", ex); + } + } + + /// + /// Scales to and + /// flattens it onto black. Bordered results are letterboxed to exactly + /// by . + /// + internal static Image ResizeImage(Image image, Size fit, int width, + int height, ThumbnailMakerBorder border) + { + var rw = border == ThumbnailMakerBorder.Bordered ? width : fit.Width; + var rh = border == ThumbnailMakerBorder.Bordered ? height : fit.Height; + var at = new Point((rw - fit.Width) / 2, (rh - fit.Height) / 2); + + // Drawing onto an opaque black canvas, rather than encoding the scaled + // image directly, gives transparent areas a defined colour: JPEG has no + // alpha channel. + var result = new Image(rw, rh, new Rgb24(0, 0, 0)); + try { + if (image.Size == fit) { + result.Mutate(c => c.DrawImage(image, at, 1f)); + } + else { + using (var scaled = image.Clone( + c => c.Resize(fit.Width, fit.Height, KnownResamplers.Bicubic))) { + result.Mutate(c => c.DrawImage(scaled, at, 1f)); } } return result; @@ -149,27 +222,19 @@ internal static SKBitmap ResizeImage(SKBitmap image, int width, int height, } /// - /// Scales to fit and encodes the result as - /// JPEG, reporting the dimensions actually produced. + /// Scales to and + /// encodes the result as JPEG, reporting the dimensions actually + /// produced. /// - internal static MemoryStream ResizeToJpeg(SKBitmap image, ref int width, - ref int height, ThumbnailMakerBorder border) + internal static MemoryStream ResizeToJpeg(Image image, Size fit, + ref int width, ref int height, ThumbnailMakerBorder border) { - using (var scaled = ResizeImage(image, width, height, border)) { + using (var scaled = ResizeImage(image, fit, width, height, border)) { width = scaled.Width; height = scaled.Height; var rv = new MemoryStream(); try { - using (var img = SKImage.FromBitmap(scaled)) { - using (var data = img.Encode( - SKEncodedImageFormat.Jpeg, JPEG_QUALITY)) { - if (data == null) { - throw new NotSupportedException( - "Failed to encode the thumbnail as JPEG"); - } - data.SaveTo(rv); - } - } + scaled.SaveAsJpeg(rv, jpegEncoder); return rv; } catch (Exception) { diff --git a/thumbs/VideoThumbnailLoader.cs b/thumbs/VideoThumbnailLoader.cs index 3742cdd3..1b52dac0 100644 --- a/thumbs/VideoThumbnailLoader.cs +++ b/thumbs/VideoThumbnailLoader.cs @@ -4,7 +4,7 @@ using System.Threading; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Utilities; -using SkiaSharp; +using SixLabors.ImageSharp; namespace NMaier.SimpleDlna.Thumbnails { @@ -78,15 +78,18 @@ private static MemoryStream GetThumbnailFromProcess(Process p, } // The pump leaves the stream at the end of what it wrote, and - // SKBitmap.Decode reads from the current position. + // decoding reads from the current position. thumb.Seek(0, SeekOrigin.Begin); - using (var img = SKBitmap.Decode(thumb)) { - if (img == null) { - throw new ArgumentException( - "ffmpeg did not produce a decodable image"); + try { + Size fit; + using (var img = ThumbnailMaker.LoadImage(thumb, width, height, out fit)) { + return ThumbnailMaker.ResizeToJpeg( + img, fit, ref width, ref height, ThumbnailMakerBorder.Bordered); } - return ThumbnailMaker.ResizeToJpeg( - img, ref width, ref height, ThumbnailMakerBorder.Bordered); + } + catch (NotSupportedException ex) { + throw new ArgumentException( + "ffmpeg did not produce a decodable image", ex); } } } diff --git a/thumbs/thumbs.csproj b/thumbs/thumbs.csproj index 90fc9b7b..d837f0dc 100644 --- a/thumbs/thumbs.csproj +++ b/thumbs/thumbs.csproj @@ -7,9 +7,7 @@ - - - + From 28ea5124f6d7f24427a4b47bedce7b6f388981f8 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Wed, 16 Sep 2026 19:36:49 -0500 Subject: [PATCH 30/37] Keep the metadata cache in LiteDB instead of SQLite Microsoft.Data.Sqlite is C#, but the SQLite engine behind it is native: SQLitePCLRaw adds libe_sqlite3.so, .dylib or e_sqlite3.dll beside the executable. Its package has no static build for desktop platforms (only for WebAssembly), and no maintained SQLite engine is written in C#. LiteDB is an embedded database written entirely in C# (MIT, 5.0.21, no known advisories), so with ImageSharp the release is now one executable. The cache is a key/value table, so the port is direct: FileStore keeps the same methods (MaybeGetFile, MaybeGetCover, HasCover, MaybeStoreFile) and entries are still valid only for the file's path, size and modification time. Caches from earlier releases are not migrated: they are discarded and rebuilt, as a schema change always did. LiteDB needs more care than SQLite; each point below was found by probing LiteDB 5.0.21 before writing the store: - Two processes, one file. LiteDB's direct mode must not have two engines on a file, yet a second process could open the file and write to it while the first had it open. Two sdlna processes with the same cache would corrupt it. A lock file beside the database (cache.db.lock, taken with FileShare.None, deleted on close) keeps a second process out; it logs "The cache ... is not available; running without it" and serves normally, as FileServer already did when a cache could not open. - One process, one file. Configured servers share a cache file, so FileStores on the same file share one reference-counted LiteDatabase. - Collation. LiteDB stores the culture it compares with in the file, defaulting to the current one (es-CO/IgnoreCase here). Such a file could not be opened under invariant globalization, common in containers ("Only the invariant culture is supported"), and ids differing only in case collided. The database is created with "/Ordinal" instead. - Key length. LiteDB index keys are limited to 1023 bytes, which a deep path can exceed, so documents are keyed by the SHA-256 of the path, and the stored path is compared on read. - Other versions. The schema number is now LiteDB's UserVersion (0x20260916). A file that is not this version's database throws LiteException ("File is not a valid LiteDB database format"), including the SQLite caches of 2.1.x and earlier; it is deleted, along with LiteDB's -log file and SQLite's -journal, -wal and -shm files, and recreated. A file that is locked or read-only is never deleted: those errors propagate and the server runs without a cache. Fixed on the way - A changed file kept its old cover. The SQL insert took the previous cover whenever a file was stored without one (COALESCE), regardless of the file's size and time. Metadata is often stored before the cover loads, so after a file changed, its stale cover was stored with the new size and time, and HasCover then stopped it ever being regenerated. The stored cover is now kept only for the same version of the file. - Caches were never closed at exit. HttpServer.Dispose only unregisters its media servers, so no FileServer or FileStore was disposed. Program now disposes the file servers it created, in both run modes. Without that, LiteDB's log was not checkpointed and the lock file remained. - A cache inside a served folder only ignored changes to the database file. FileServer now also ignores LiteDB's log and the lock file, via FileStore.IsStoreFile, so they don't trigger rescans. The periodic vacuumer keeps its job of removing entries for files that no longer exist (FileStore.PurgeMissingFiles), once per database file. LiteDB reuses freed pages, so there is no VACUUM step. util/Sqlite.cs and its code-analysis suppressions are removed. Tests (FileStoreTests, 13; two skip on macOS) - kept: read back after reopening; a changed file is not served - new: - covers are stored and read back - storing again without the cover keeps it - a changed file does not keep its old cover - a 2.1.x SQLite cache is replaced - a database from another schema is replaced - stores on one file share one database, and the lock file goes when the last one closes - a cache held by another process is left untouched and raises IOException - long paths are stored (skipped where the file system can't hold them, like macOS) - paths differing only in case are separate (skipped on case-insensitive file systems; run here on a case-sensitive APFS disk image) - purging removes deleted files - the cache's own files don't count as media changes - Each was checked against its bug, by reintroducing it alone: no lock, the stale cover kept, the cover never kept, the raw path as id with the default collation, the schema ignored, the database not shared, and the purge doing nothing. All seven failed the suite. The lock test takes the lock through the same FileStore.LockCache the store uses; with a stricter mode of its own, the no-lock mutation had passed. End to end, with a single-file osx-arm64 publish (the output directory holds only the sdlna executable) and HOME pointing at a directory that doesn't exist: 1. The 2.1.3 release wrote a SQLite cache for a JPEG, a PNG, an MP4 and an MP3. 2. The new build logged "Recreating the cache database", served the same titles, durations and JPEG covers, and cached 4 entries with 3 covers (the MP3 has no art). After Ctrl+C only cache.db remained. 3. A restart reused it, without recreating it. 4. With a second process on the same cache, the second warned and still served everything; the lock file existed only while they ran. 5. DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 opened the same cache. 6. Two configured servers sharing ~/.sdlna/cache.db both stored into it (5 entries), and shut down cleanly. 7. No error or fatal log lines in any run, and HOME was never created. Docs: the readme notes that only one process can use a cache file; AGENTS.md describes the LiteDB store and its traps, and the rule that the release has no native libraries. dotnet build: zero warnings. dotnet test: 110 tests, 107 passed, 3 skipped on macOS (the Windows hidden-folder test and the two file-system-dependent store tests). Co-Authored-By: Claude Opus 5 --- AGENTS.md | 47 ++- Directory.Packages.props | 2 +- Readme.md | 8 +- fsserver/FileServer.cs | 5 +- fsserver/FileStore.cs | 543 ++++++++++++++++------------ fsserver/Files/FileStoreVacuumer.cs | 119 ++---- fsserver/GlobalSuppressions.cs | 4 - fsserver/fsserver.csproj | 1 + sdlna/Program.cs | 24 ++ tests/FileStoreTests.cs | 266 ++++++++++++-- util/GlobalSuppressions.cs | 2 - util/Sqlite.cs | 58 --- util/util.csproj | 1 - 13 files changed, 655 insertions(+), 425 deletions(-) delete mode 100644 util/Sqlite.cs diff --git a/AGENTS.md b/AGENTS.md index f4afe832..5611f47c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -51,20 +51,22 @@ HOME=$(mktemp -d) dotnet sdlna/bin/Debug/net10.0/sdlna.dll --server add Test ~/V To produce a release-style binary: ```bash -dotnet publish sdlna/sdlna.csproj -c Release -r osx-arm64 --self-contained -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=false -p:PublishTrimmed=false +dotnet publish sdlna/sdlna.csproj -c Release -r osx-arm64 --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=false ``` -Both of the last two properties matter; see [Traps](#traps). +The result is one executable with nothing beside it, because every +dependency is managed code; see [Traps](#traps). `PublishTrimmed=false` +matters too. Layout --- | Project | Assembly | Depends on | Role | |------------|------------------------------|------------------------------|------| -| `util` | `SimpleDlna.Utilities` | - | Logging base class, SQLite helpers, ffmpeg discovery and invocation, `StreamPump`, MAC lookup, natural sorting, `Repository` | +| `util` | `SimpleDlna.Utilities` | - | Logging base class, ffmpeg discovery and invocation, `StreamPump`, MAC lookup, natural sorting, `Repository` | | `server` | `SimpleDlna.Server` | util | HTTP server, SSDP, UPnP/DLNA handlers, MIME and profile maps, views, comparers | | `thumbs` | `SimpleDlna.Thumbnails` | util, server | Thumbnails: images through ImageSharp, video through ffmpeg | -| `fsserver` | `SimpleDlna.FileMediaServer` | util, server, thumbs | `FileServer`: scans folders into media items, reads tags with TagLibSharp, caches metadata in SQLite | +| `fsserver` | `SimpleDlna.FileMediaServer` | util, server, thumbs | `FileServer`: scans folders into media items, reads tags with TagLibSharp, caches metadata in LiteDB | | `sdlna` | `sdlna` | util, server, fsserver | Console entry point, command-line options, configuration file, `--server` commands | | `tests` | `SimpleDlna.Tests` | all of the above | xUnit v3 test suite | @@ -101,7 +103,7 @@ Management; `PackageReference` items in projects carry no `Version`). - **Views** (`server/Views`) rebuild or filter the folder tree. `Identifiers` (`server/Types`) applies them in order when the tree is loaded. - **Metadata cache.** `fsserver/FileStore.cs` keeps each file's metadata and - cover in SQLite, encoded by `fsserver/Files/MediaSerializer.cs`. + cover in a LiteDB database, encoded by `fsserver/Files/MediaSerializer.cs`. - **Configuration file.** `sdlna/Configuration.cs` holds the model, validation and loading/saving; `sdlna/ServerCommand.cs` the `--server` commands. @@ -200,11 +202,13 @@ Each of these has broken something before. exist**, such as the home folder of a service account. Pass `Environment.SpecialFolderOption.DoNotVerify` when you need the path, and skip empty results when searching (`FFmpeg.GetSpecialLocations`). -- **Single-file bundles and native libraries.** With - `IncludeNativeLibrariesForSelfExtract=true`, the host extracts SQLite - into `$HOME/.net` before `Main` runs, and refuses to start at all - when `HOME` is missing or read-only. Publish them beside the executable - instead. +- **No native libraries.** The release is a single executable because every + dependency is managed code; SkiaSharp and SQLite were replaced for that. + A package with native parts either adds files beside the executable or, + bundled with `IncludeNativeLibrariesForSelfExtract`, is extracted to + `$HOME/.net` before `Main` runs, and then the program refuses to start at + all when `HOME` is missing or read-only. Check the `dotnet publish` output + before adding a package. - **Windows-only features.** Looking up a client's MAC address (`util/AddressToMacResolver.cs`) only works on Windows, so MAC restrictions never match elsewhere. The `.sdlna` folder's hidden attribute and the @@ -254,8 +258,27 @@ Each of these has broken something before. number changes, which makes existing caches be discarded and rebuilt. - **`DlnaMime` values are persisted.** Append new members at the end of the enum; never reorder or insert. -- **Microsoft.Data.Sqlite** requires named parameters (`@key`) and rejects a - parameter whose value is `null`; bind `DBNull.Value`. +- **The cache is a LiteDB database, and LiteDB needs care** (see + `fsserver/FileStore.cs`): + - Its direct mode must not have two engines on one file, yet it lets a + second process open and write the same file. Servers in one process + share one database per file, and `FileStore.LockCache` keeps other + processes out; they run without a cache. + - The collation is stored in the file when it is created. The default is + the current culture, which can't be loaded under invariant + globalization (common in containers), so it is set to `/Ordinal`. + - Index keys are limited to 1023 bytes, so documents are keyed by a + SHA-256 of the path, and the path is stored and compared on read. + - The schema number is the database's `UserVersion`. Anything that isn't + this version's database (including SQLite caches from 2.1.x and + earlier) is deleted and recreated, but never a file that is merely + locked or read-only. + - While it is open, LiteDB keeps a `-log` file beside the database, and + the lock file sits there too. `FileStore.IsStoreFile` keeps changes to + all three from triggering rescans. +- **A stored cover belongs to one version of a file.** Metadata is often + stored again without the cover, which loads lazily, so the stored cover is + kept, but only while the file's size and modification time are unchanged. ### Configuration file diff --git a/Directory.Packages.props b/Directory.Packages.props index 5dc55e7a..b21f43d6 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,8 +14,8 @@ + - diff --git a/Readme.md b/Readme.md index 7c144c1d..74e8f26a 100644 --- a/Readme.md +++ b/Readme.md @@ -148,7 +148,7 @@ It is created by the first `sdlna --server add`. A complete example: | Key | Meaning | Default | |---|---|---| | `port` | HTTP port; `0` picks any free port each run. Clients find the server either way, but a fixed port keeps its web page at a stable address. | `0` | -| `cache` | File that stores media metadata and thumbnails, so restarts don't rescan every file. `"none"` turns it off. A leading `~` means your home folder. If missing or empty, the default is used. | `~/.sdlna/cache.db` | +| `cache` | File that stores media metadata and thumbnails, so restarts don't rescan every file. `"none"` turns it off. A leading `~` means your home folder. If missing or empty, the default is used. Only one `sdlna` process can use a cache file at a time; another one runs without it. | `~/.sdlna/cache.db` | | `editor` | Command that `--edit` opens the file with. | `notepad` on Windows, `nano` elsewhere | **Per server** @@ -405,10 +405,10 @@ Project layout | Project | Output | Role | |------------|-------------------------------|-------------------------------------------------------------| -| `util` | `SimpleDlna.Utilities` | SQLite access, ffmpeg invocation, stream pumps, sorting | +| `util` | `SimpleDlna.Utilities` | ffmpeg invocation, stream pumps, sorting | | `server` | `SimpleDlna.Server` | HTTP and SSDP servers, UPnP/DLNA handlers, views, comparers | -| `thumbs` | `SimpleDlna.Thumbnails` | Thumbnail generation | -| `fsserver` | `SimpleDlna.FileMediaServer` | Filesystem media source and its metadata cache | +| `thumbs` | `SimpleDlna.Thumbnails` | Thumbnail generation (ImageSharp) | +| `fsserver` | `SimpleDlna.FileMediaServer` | Filesystem media source and its metadata cache (LiteDB) | | `sdlna` | `sdlna` | Console entry point and configuration file | | `tests` | `SimpleDlna.Tests` | Test suite | diff --git a/fsserver/FileServer.cs b/fsserver/FileServer.cs index 4c7d49d4..d1d78634 100644 --- a/fsserver/FileServer.cs +++ b/fsserver/FileServer.cs @@ -210,8 +210,7 @@ private bool HandleFileDeleted(string fullPath) private void OnChanged(object source, FileSystemEventArgs e) { try { - if (store != null && - icomparer.Equals(e.FullPath, store.StoreFile.FullName)) { + if (store != null && store.IsStoreFile(e.FullPath, icomparer)) { return; } var ext = string.Empty; @@ -521,7 +520,7 @@ public void SetCacheFile(FileInfo info) store = new FileStore(info); } catch (Exception ex) { - Warn("FileStore is not available; failed to load SQLite Adapter", ex); + Warn($"The cache {info.FullName} is not available; running without it", ex); store = null; } } diff --git a/fsserver/FileStore.cs b/fsserver/FileStore.cs index 5c903051..c653ee5d 100644 --- a/fsserver/FileStore.cs +++ b/fsserver/FileStore.cs @@ -1,235 +1,166 @@ using System; -using System.Data; -using System.Data.Common; +using System.Collections.Generic; +using System.Globalization; using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; using System.Threading; +using LiteDB; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Utilities; namespace NMaier.SimpleDlna.FileMediaServer { + /// + /// The metadata cache: each file's serialized metadata and cover, kept in + /// a LiteDB database and valid while the file's size and modification + /// time are unchanged. + /// + /// + /// + /// LiteDB is written in C#, so the cache needs no native library beside + /// the single-file executable. Each document is + /// {_id, path, size, time, data, cover}. The id is a SHA-256 hash + /// of the path rather than the path itself: LiteDB index keys are + /// limited to 1023 bytes, which a deep path can exceed. + /// + /// + /// LiteDB's direct mode must not have two engines on one file. Several + /// servers in this process share one database per file, and a lock file + /// beside it keeps other processes out; a second sdlna using the same + /// cache runs without one. + /// + /// internal sealed class FileStore : Logging, IDisposable { - private const uint SCHEMA = 0x20260912; + private const string COLLECTION = "store"; - private static readonly FileStoreVacuumer vacuumer = - new FileStoreVacuumer(); - - private static readonly object globalLock = new object(); - - private readonly IDbConnection connection; - - private readonly IDbCommand insert; - - private readonly IDbDataParameter insertCover; - - private readonly IDbDataParameter insertData; - - private readonly IDbDataParameter insertKey; - - private readonly IDbDataParameter insertSize; + /// + /// Stored as the database's UserVersion. Bump it when a cached payload + /// changes (see ): a database from another + /// version is discarded and rebuilt. + /// + internal const int SCHEMA = 0x20260916; - private readonly IDbDataParameter insertTime; + private static readonly Dictionary databases = + new Dictionary(StringComparer.Ordinal); - private readonly IDbCommand select; - - private readonly IDbCommand selectCover; - - private readonly IDbDataParameter selectCoverKey; - - private readonly IDbDataParameter selectCoverSize; - - private readonly IDbDataParameter selectCoverTime; - - private readonly IDbDataParameter selectKey; + private static readonly FileStoreVacuumer vacuumer = + new FileStoreVacuumer(); - private readonly IDbDataParameter selectSize; + private readonly SharedDatabase shared; - private readonly IDbDataParameter selectTime; + private bool disposed; public readonly FileInfo StoreFile; internal FileStore(FileInfo storeFile) { StoreFile = storeFile; - - OpenConnection(storeFile, out connection); - SetupDatabase(); - - select = connection.CreateCommand(); - select.CommandText = - "SELECT data FROM store WHERE key = @key AND size = @size AND time = @time"; - select.Parameters.Add(selectKey = select.CreateParameter()); - selectKey.ParameterName = "@key"; - selectKey.DbType = DbType.String; - select.Parameters.Add(selectSize = select.CreateParameter()); - selectSize.ParameterName = "@size"; - selectSize.DbType = DbType.Int64; - select.Parameters.Add(selectTime = select.CreateParameter()); - selectTime.ParameterName = "@time"; - selectTime.DbType = DbType.Int64; - - selectCover = connection.CreateCommand(); - selectCover.CommandText = - "SELECT cover FROM store WHERE key = @key AND size = @size AND time = @time"; - selectCover.Parameters.Add(selectCoverKey = selectCover.CreateParameter()); - selectCoverKey.ParameterName = "@key"; - selectCoverKey.DbType = DbType.String; - selectCover.Parameters.Add(selectCoverSize = selectCover.CreateParameter()); - selectCoverSize.ParameterName = "@size"; - selectCoverSize.DbType = DbType.Int64; - selectCover.Parameters.Add(selectCoverTime = selectCover.CreateParameter()); - selectCoverTime.ParameterName = "@time"; - selectCoverTime.DbType = DbType.Int64; - - insert = connection.CreateCommand(); - insert.CommandText = - "INSERT OR REPLACE INTO store " + - "VALUES(@key, @size, @time, @data, COALESCE(@cover, (SELECT cover FROM store WHERE key = @key)))"; - insert.Parameters.Add(insertKey = insert.CreateParameter()); - insertKey.DbType = DbType.String; - insertKey.ParameterName = "@key"; - insert.Parameters.Add(insertSize = insert.CreateParameter()); - insertSize.DbType = DbType.Int64; - insertSize.ParameterName = "@size"; - insert.Parameters.Add(insertTime = insert.CreateParameter()); - insertTime.DbType = DbType.Int64; - insertTime.ParameterName = "@time"; - insert.Parameters.Add(insertData = insert.CreateParameter()); - insertData.DbType = DbType.Binary; - insertData.ParameterName = "@data"; - insert.Parameters.Add(insertCover = insert.CreateParameter()); - insertCover.DbType = DbType.Binary; - insertCover.ParameterName = "@cover"; - + shared = SharedDatabase.Acquire(storeFile, this); InfoFormat("FileStore at {0} is ready", storeFile.FullName); - - vacuumer.Add(connection); + vacuumer.Add(this); } public void Dispose() { - insert?.Dispose(); - @select?.Dispose(); - if (connection != null) { - vacuumer.Remove(connection); - Sqlite.ClearPool(connection); - connection.Dispose(); + if (disposed) { + return; } + disposed = true; + vacuumer.Remove(this); + shared.Release(); } - private void OpenConnection(FileInfo storeFile, - out IDbConnection newConnection) + /// + /// LiteDB's write-ahead log, kept beside the database while it is open. + /// + internal static string LogFileOf(FileInfo storeFile) { - lock (globalLock) { - newConnection = Sqlite.GetDatabaseConnection(storeFile); - try { - using (var ver = newConnection.CreateCommand()) { - ver.CommandText = "PRAGMA user_version"; - var currentVersion = (uint)(long)ver.ExecuteScalar(); - if (!currentVersion.Equals(SCHEMA)) { - throw new IndexOutOfRangeException("SCHEMA"); - } - } - } - catch (Exception ex) { - NoticeFormat( - "Recreating database, schema update. ({0})", - ex.Message - ); - Sqlite.ClearPool(newConnection); - newConnection.Close(); - newConnection.Dispose(); - newConnection = null; - for (var i = 0; i < 10; ++i) { - try { - GC.Collect(); - storeFile.Delete(); - break; - } - catch (IOException) { - Thread.Sleep(100); - } - } - newConnection = Sqlite.GetDatabaseConnection(storeFile); - } - using (var pragma = connection.CreateCommand()) { - pragma.CommandText = "PRAGMA journal_size_limt = 33554432"; - pragma.ExecuteNonQuery(); - } - } + return Path.Combine( + storeFile.DirectoryName ?? string.Empty, + Path.GetFileNameWithoutExtension(storeFile.Name) + "-log" + storeFile.Extension); } - private void SetupDatabase() + internal static string LockFileOf(FileInfo storeFile) { - using (var transaction = connection.BeginTransaction()) { - using (var pragma = connection.CreateCommand()) { - pragma.CommandText = $"PRAGMA user_version = {SCHEMA}"; - pragma.ExecuteNonQuery(); - pragma.CommandText = "PRAGMA page_size = 8192"; - pragma.ExecuteNonQuery(); - } - using (var create = connection.CreateCommand()) { - create.CommandText = - "CREATE TABLE IF NOT EXISTS store (key TEXT PRIMARY KEY ON CONFLICT REPLACE, size INT, time INT, data BINARY, cover BINARY)"; - create.ExecuteNonQuery(); - } - transaction.Commit(); - } + return storeFile.FullName + ".lock"; } - internal bool HasCover(BaseFile file) + /// + /// Takes the lock that keeps other processes out of the database, held + /// for as long as it is open. + /// + /// Another process holds it. + internal static FileStream LockCache(FileInfo storeFile) { - if (connection == null) { - return false; - } + return new FileStream( + LockFileOf(storeFile), FileMode.OpenOrCreate, FileAccess.ReadWrite, + FileShare.None, 1, FileOptions.DeleteOnClose); + } - var info = file.Item; - lock (connection) { - selectCoverKey.Value = info.FullName; - selectCoverSize.Value = info.Length; - selectCoverTime.Value = info.LastWriteTimeUtc.Ticks; - try { - var data = selectCover.ExecuteScalar(); - return data is byte[]; - } - catch (DbException ex) { - Error("Failed to lookup file cover existence from store", ex); - return false; - } - } + /// + /// Whether is one of the files the cache keeps, + /// so that a cache inside a served folder does not trigger rescans. + /// + internal bool IsStoreFile(string path, StringComparer comparer) + { + return comparer.Equals(path, StoreFile.FullName) || + comparer.Equals(path, LogFileOf(StoreFile)) || + comparer.Equals(path, LockFileOf(StoreFile)); } - internal Cover MaybeGetCover(BaseFile file) + private static string KeyOf(string path) + { + return Convert.ToHexStringLower( + SHA256.HashData(Encoding.UTF8.GetBytes(path))); + } + + /// + /// The entry for , if it was stored for this + /// version of the file. + /// + private BsonDocument Find(FileInfo info, string operation) { - if (connection == null) { + if (disposed) { return null; } + BsonDocument doc; + try { + doc = shared.Collection.FindById(KeyOf(info.FullName)); + } + catch (Exception ex) when (ex is LiteException || ex is IOException) { + Error($"Failed to look up {operation} in the store", ex); + return null; + } + return IsCurrent(doc, info) ? doc : null; + } + + private static bool IsCurrent(BsonDocument doc, FileInfo info) + { + return doc != null && + doc["path"].IsString && doc["path"].AsString == info.FullName && + doc["size"].IsInt64 && doc["size"].AsInt64 == info.Length && + doc["time"].IsInt64 && + doc["time"].AsInt64 == info.LastWriteTimeUtc.Ticks; + } + internal bool HasCover(BaseFile file) + { + var doc = Find(file.Item, "a file cover's existence"); + return doc != null && doc["cover"].IsBinary; + } + + internal Cover MaybeGetCover(BaseFile file) + { var info = file.Item; - byte[] data; - lock (connection) { - try { - selectCoverKey.Value = info.FullName; - selectCoverSize.Value = info.Length; - selectCoverTime.Value = info.LastWriteTimeUtc.Ticks; - try { - data = selectCover.ExecuteScalar() as byte[]; - } - catch (DbException ex) { - Error("Failed to lookup file cover from store", ex); - return null; - } - } - finally { - selectCover.Cancel(); - } - } - if (data == null) { + var doc = Find(info, "a file cover"); + if (doc == null || !doc["cover"].IsBinary) { return null; } try { - using (var s = new MemoryStream(data)) { + using (var s = new MemoryStream(doc["cover"].AsBinary)) { return MediaSerializer.DeserializeCover( s, new DeserializeInfo(null, info, DlnaMime.ImageJPEG)); } @@ -248,32 +179,12 @@ internal Cover MaybeGetCover(BaseFile file) internal BaseFile MaybeGetFile(FileServer server, FileInfo info, DlnaMime type) { - if (connection == null) { - return null; - } - byte[] data; - lock (connection) { - try { - selectKey.Value = info.FullName; - selectSize.Value = info.Length; - selectTime.Value = info.LastWriteTimeUtc.Ticks; - try { - data = select.ExecuteScalar() as byte[]; - } - catch (DbException ex) { - Error("Failed to lookup file from store", ex); - return null; - } - } - finally { - select.Cancel(); - } - } - if (data == null) { + var doc = Find(info, "a file"); + if (doc == null || !doc["data"].IsBinary) { return null; } try { - using (var s = new MemoryStream(data)) { + using (var s = new MemoryStream(doc["data"].AsBinary)) { var rv = MediaSerializer.DeserializeFile( s, new DeserializeInfo(server, info, type)); rv.Item = info; @@ -289,7 +200,7 @@ internal BaseFile MaybeGetFile(FileServer server, FileInfo info, internal void MaybeStoreFile(BaseFile file) { - if (connection == null) { + if (disposed) { return; } if (!MediaSerializer.CanSerialize(file)) { @@ -307,34 +218,43 @@ internal void MaybeStoreFile(BaseFile file) } } catch (NotSupportedException) { - // Ignore and store null. Clearing the local is what makes the - // "store null" actually happen: the insert below keys off it, - // and a throw part way through SerializeCover would otherwise - // persist a truncated cover blob. + // Ignore and store no cover. Clearing the local is what makes + // that happen: a throw part way through SerializeCover would + // otherwise persist a truncated cover blob. cover = null; } - lock (connection) { - using (var trans = connection.BeginTransaction()) { - insertKey.Value = file.Item.FullName; - insertSize.Value = file.Item.Length; - insertTime.Value = file.Item.LastWriteTimeUtc.Ticks; - insertData.Value = s.ToArray(); - - // Microsoft.Data.Sqlite rejects an unset parameter value, so - // an absent cover has to be bound as DBNull rather than null. - insertCover.Value = DBNull.Value; - if (cover != null) { - insertCover.Value = c.ToArray(); - } - try { - insert.Transaction = trans; - insert.ExecuteNonQuery(); - trans.Commit(); - } - catch (DbException ex) { - Error("Failed to put file cover into store", ex); + var info = file.Item; + var key = KeyOf(info.FullName); + // Read, merge and write as one step, for servers sharing this + // database. + lock (shared) { + try { + var coverValue = cover != null + ? new BsonValue(c.ToArray()) + : BsonValue.Null; + if (cover == null) { + // Metadata is often stored again without the cover, which + // loads lazily and may since have been collected. Keep the + // stored one, but only for this version of the file: a + // changed file needs a new cover. + var existing = shared.Collection.FindById(key); + if (IsCurrent(existing, info) && existing["cover"].IsBinary) { + coverValue = existing["cover"]; + } } + shared.Collection.Upsert(new BsonDocument + { + ["_id"] = key, + ["path"] = info.FullName, + ["size"] = info.Length, + ["time"] = info.LastWriteTimeUtc.Ticks, + ["data"] = s.ToArray(), + ["cover"] = coverValue + }); + } + catch (Exception ex) when (ex is LiteException || ex is IOException) { + Error("Failed to put a file into the store", ex); } } } @@ -345,5 +265,162 @@ internal void MaybeStoreFile(BaseFile file) throw; } } + + /// + /// Removes the entries of files that no longer exist. + /// + internal void PurgeMissingFiles() + { + if (disposed) { + return; + } + List entries; + lock (shared) { + entries = shared.Collection.Query() + .Select("{_id, path}") + .ToList(); + } + var gone = entries + .Where(e => !e["path"].IsString || !File.Exists(e["path"].AsString)) + .ToList(); + foreach (var entry in gone) { + lock (shared) { + shared.Collection.Delete(entry["_id"]); + } + DebugFormat("Purged {0}", entry["path"]); + } + DebugFormat("Purged {0} of {1} entries", gone.Count, entries.Count); + } + + /// + /// One open database, shared by every FileStore on the same file. + /// + private sealed class SharedDatabase + { + private LiteDatabase database; + + private FileStream lockFile; + + private string path; + + private int references; + + public ILiteCollection Collection { get; private set; } + + public static SharedDatabase Acquire(FileInfo storeFile, Logging log) + { + var path = storeFile.FullName; + lock (databases) { + SharedDatabase rv; + if (databases.TryGetValue(path, out rv)) { + rv.references++; + return rv; + } + // A second process gets an IOException here and runs without the + // cache. + var lockFile = LockCache(storeFile); + try { + var database = Open(storeFile, log); + rv = new SharedDatabase + { + database = database, + lockFile = lockFile, + path = path, + references = 1, + Collection = database.GetCollection(COLLECTION) + }; + databases.Add(path, rv); + return rv; + } + catch (Exception) { + lockFile.Dispose(); + throw; + } + } + } + + public void Release() + { + lock (databases) { + if (--references != 0) { + return; + } + databases.Remove(path); + database.Dispose(); + lockFile.Dispose(); + } + } + + private static LiteDatabase Connect(FileInfo storeFile) + { + return new LiteDatabase(new ConnectionString + { + Filename = storeFile.FullName, + Connection = ConnectionType.Direct, + // Stored in the file when it is created. The default, the current + // culture, cannot be loaded under invariant globalization (common in + // containers), which would make the file unreadable there. + Collation = new Collation("/Ordinal"), + Upgrade = false + }); + } + + private static LiteDatabase Open(FileInfo storeFile, Logging log) + { + try { + var database = Connect(storeFile); + try { + if (database.UserVersion == SCHEMA) { + return database; + } + if (database.UserVersion == 0 && + !database.GetCollectionNames().Any()) { + database.UserVersion = SCHEMA; + return database; + } + throw new InvalidDataException(string.Format( + CultureInfo.InvariantCulture, + "schema {0:X} instead of {1:X}", database.UserVersion, SCHEMA)); + } + catch (Exception) { + database.Dispose(); + throw; + } + } + catch (Exception ex) when ( + ex is LiteException || ex is InvalidDataException || + ex is CultureNotFoundException) { + // Another version's cache (including the SQLite caches of earlier + // releases) or a damaged one: it is only a cache, so start over. + log.NoticeFormat("Recreating the cache database. ({0})", ex.Message); + Delete(storeFile); + var database = Connect(storeFile); + database.UserVersion = SCHEMA; + return database; + } + } + + /// + /// Deletes the database with its LiteDB log, and the journals SQLite + /// kept beside the caches of earlier releases. + /// + private static void Delete(FileInfo storeFile) + { + var path = storeFile.FullName; + foreach (var file in new[] { + path, LogFileOf(storeFile), path + "-journal", path + "-wal", path + "-shm" + }) { + for (var i = 0; i < 10; ++i) { + try { + File.Delete(file); + break; + } + catch (IOException) { + Thread.Sleep(100); + } + } + } + } + } } } diff --git a/fsserver/Files/FileStoreVacuumer.cs b/fsserver/Files/FileStoreVacuumer.cs index cd5bb755..9893a346 100644 --- a/fsserver/Files/FileStoreVacuumer.cs +++ b/fsserver/Files/FileStoreVacuumer.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Data; -using System.IO; using System.Linq; using System.Threading.Tasks; using System.Timers; @@ -9,14 +7,18 @@ namespace NMaier.SimpleDlna.FileMediaServer { + /// + /// Every half hour to four hours, removes the cache entries of files that + /// no longer exist. (With SQLite it also ran VACUUM; LiteDB reuses freed + /// pages instead.) + /// internal sealed class FileStoreVacuumer : Logging, IDisposable { private const int MAX_TIME = 240 * 60 * 1000; private const int MIN_TIME = 30 * 60 * 1000; - private readonly Dictionary connections = - new Dictionary(); + private readonly List stores = new List(); private readonly Random rnd = new Random(); @@ -35,29 +37,29 @@ public void Dispose() private void Run(object sender, ElapsedEventArgs e) { - IDbConnection[] conns; - lock (connections) { - conns = (from c in connections.Values - let conn = c.Target as IDbConnection - where conn != null - select conn).ToArray(); + // Stores sharing a database file are purged once. + FileStore[] current; + lock (stores) { + current = (from s in stores + let store = s.Target as FileStore + where store != null + group store by store.StoreFile.FullName + into sameFile + select sameFile.First()).ToArray(); } - if (conns.Length == 0) { - return; - } - - Task.Factory.StartNew(() => - { - foreach (var conn in conns) { - try { - Vacuum(conn); - } - catch (Exception ex) { - Error("Failed to vacuum a store", ex); + if (current.Length != 0) { + Task.Factory.StartNew(() => + { + foreach (var store in current) { + try { + store.PurgeMissingFiles(); + } + catch (Exception ex) { + Error("Failed to purge a store", ex); + } } - } - }, TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent); - + }, TaskCreationOptions.LongRunning); + } Schedule(); } @@ -65,73 +67,20 @@ private void Schedule() { timer.Interval = rnd.Next(MIN_TIME, MAX_TIME); timer.Enabled = true; - DebugFormat("Scheduling next vaccuum in {0}", timer.Interval); - } - - private void Vacuum(IDbConnection connection) - { - DebugFormat("VACUUM {0}", connection.Database); - var files = new List(); - - lock (connection) { - using (var q = connection.CreateCommand()) { - q.CommandText = "SELECT key FROM store"; - using (var r = q.ExecuteReader()) { - while (r.Read()) { - files.Add(r.GetString(0)); - } - } - } - } - var gone = from f in files - let m = new FileInfo(f) - where !m.Exists - select f; - lock (connection) { - using (var trans = connection.BeginTransaction()) { - using (var q = connection.CreateCommand()) { - q.Transaction = trans; - q.CommandText = "DELETE FROM store WHERE key = @key"; - var p = q.CreateParameter(); - p.ParameterName = "@key"; - p.DbType = DbType.String; - q.Parameters.Add(p); - foreach (var f in gone) { - p.Value = f; - lock (connection) { - q.ExecuteNonQuery(); - } - DebugFormat("Purging {0}", f); - } - } - } - } - lock (connection) { - using (var q = connection.CreateCommand()) { - q.CommandText = "VACUUM"; - try { - q.ExecuteNonQuery(); - } - catch (Exception ex) { - Error("Failed to vacuum", ex); - } - } - } - Debug("Vacuum done!"); + DebugFormat("Scheduling next purge in {0}", timer.Interval); } - public void Add(IDbConnection connection) + public void Add(FileStore store) { - lock (connections) { - connections[connection.ConnectionString] = - new WeakReference(connection); + lock (stores) { + stores.Add(new WeakReference(store)); } } - public void Remove(IDbConnection connection) + public void Remove(FileStore store) { - lock (connections) { - connections.Remove(connection.ConnectionString); + lock (stores) { + stores.RemoveAll(s => s.Target == null || s.Target == store); } } } diff --git a/fsserver/GlobalSuppressions.cs b/fsserver/GlobalSuppressions.cs index 55b9529d..e72c26d2 100644 --- a/fsserver/GlobalSuppressions.cs +++ b/fsserver/GlobalSuppressions.cs @@ -1,10 +1,6 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Scope = "member", Target = "NMaier.SimpleDlna.FileMediaServer.TagLibFileAbstraction.#CloseStream(System.IO.Stream)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "NMaier.SimpleDlna.FileMediaServer.ImageFile.#.ctor(System.Runtime.Serialization.SerializationInfo,NMaier.SimpleDlna.FileMediaServer.DeserializeInfo)")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities", Scope = "member", Target = "NMaier.SimpleDlna.FileMediaServer.FileStore.#SetupDatabase()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Scope = "member", Target = "NMaier.SimpleDlna.FileMediaServer.FileStore.#OpenConnection(System.IO.FileInfo,System.Data.IDbConnection&)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dlna")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect", Scope = "member", Target = "NMaier.SimpleDlna.FileMediaServer.FileStore.#OpenConnection(System.IO.FileInfo,System.Data.IDbConnection&)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "NMaier.SimpleDlna.FileMediaServer")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dlna", Scope = "namespace", Target = "NMaier.SimpleDlna.FileMediaServer")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "NMaier.SimpleDlna.FileMediaServer.FileStore.#OpenConnection(System.IO.FileInfo,System.Data.IDbConnection&)")] diff --git a/fsserver/fsserver.csproj b/fsserver/fsserver.csproj index 9f2509e2..9cec3a95 100644 --- a/fsserver/fsserver.csproj +++ b/fsserver/fsserver.csproj @@ -6,6 +6,7 @@ + diff --git a/sdlna/Program.cs b/sdlna/Program.cs index 1fbca5cd..9d51ccd9 100644 --- a/sdlna/Program.cs +++ b/sdlna/Program.cs @@ -201,6 +201,7 @@ private static void Main(string[] args) using (new ProgramIcon()) { var server = new HttpServer(options.Port); + var fileServers = new List(); try { using (var authorizer = new HttpAuthorizer(server)) { if (options.Ips.Length != 0) { @@ -229,6 +230,7 @@ private static void Main(string[] args) server.InfoFormat("Mounting FileServer for {0}", d.FullName); var fs = SetupFileServer( options, types, new[] {d}); + fileServers.Add(fs); friendlyName = fs.FriendlyName; server.RegisterMediaServer(fs); server.NoticeFormat("{0} mounted", d.FullName); @@ -239,6 +241,7 @@ private static void Main(string[] args) "Mounting FileServer for {0} ({1})", options.Directories[0], options.Directories.Length); var fs = SetupFileServer(options, types, options.Directories); + fileServers.Add(fs); friendlyName = fs.FriendlyName; server.RegisterMediaServer(fs); server.NoticeFormat( @@ -253,6 +256,7 @@ private static void Main(string[] args) } finally { server.Dispose(); + DisposeAll(fileServers); } } } @@ -316,6 +320,23 @@ private static void WarnServingCurrentDirectory(bool fileExists, warnings.WriteLine(); } + /// + /// HttpServer only unregisters its media servers. Disposing them closes + /// their caches, which checkpoints the database and releases its lock. + /// + private static void DisposeAll(IEnumerable fileServers) + { + foreach (var fs in fileServers) { + try { + fs.Dispose(); + } + catch (Exception ex) { + LogManager.GetLogger(typeof (Program)).Warn( + $"Failed to shut down {fs.FriendlyName}", ex); + } + } + } + private static void Run(HttpServer server) { server.Info("CTRL-C to terminate"); @@ -388,6 +409,7 @@ private static void RunConfiguredServers(Options options, using (new ProgramIcon()) { var httpServer = new HttpServer(port); + var fileServers = new List(); try { Console.Title = "SimpleDLNA - starting ..."; var mounted = 0; @@ -395,6 +417,7 @@ private static void RunConfiguredServers(Options options, try { httpServer.InfoFormat("Mounting server {0}", server.Name); var fs = SetupConfiguredServer(server, cacheFile, options.Rescanning, httpServer); + fileServers.Add(fs); httpServer.RegisterMediaServer(fs); ++mounted; httpServer.NoticeFormat("{0} mounted", server.Name); @@ -415,6 +438,7 @@ private static void RunConfiguredServers(Options options, } finally { httpServer.Dispose(); + DisposeAll(fileServers); } } } diff --git a/tests/FileStoreTests.cs b/tests/FileStoreTests.cs index 49f0e872..5d0b0c1c 100644 --- a/tests/FileStoreTests.cs +++ b/tests/FileStoreTests.cs @@ -1,5 +1,8 @@ using System; using System.IO; +using System.Linq; +using System.Text; +using LiteDB; using NMaier.SimpleDlna.FileMediaServer; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Tests.Support; @@ -8,11 +11,13 @@ namespace NMaier.SimpleDlna.Tests { /// - /// The SQLite-backed metadata cache: Microsoft.Data.Sqlite with named - /// parameters, DBNull for a missing cover, and the schema check. + /// The metadata cache, a LiteDB database: entries valid for one version of + /// a file, schema checks, and how the database file is shared. /// public sealed class FileStoreTests : IDisposable { + private readonly FileInfo database; + private readonly TempDirectory temp = new TempDirectory(); private readonly FileServer server; @@ -20,6 +25,7 @@ public sealed class FileStoreTests : IDisposable public FileStoreTests() { server = TestFileServer.Create(temp.Info); + database = new FileInfo(temp.Combine("cache.db")); } public void Dispose() @@ -28,21 +34,39 @@ public void Dispose() temp.Dispose(); } + private VideoFile Video(FileInfo media) + { + return new VideoFile(server, media, DlnaMime.VideoMKV) + .Set("subTitle", new Subtitle()) + .Set("initialized", true); + } + + /// + /// A video whose cover has been generated. The caller keeps the cover + /// alive: files only hold it through a weak reference. + /// + private VideoFile VideoWithCover(FileInfo media, out object cover) + { + var image = TestMedia.WriteJpeg(temp.Combine(Guid.NewGuid() + ".jpg"), 64, 48); + using (var stream = image.OpenRead()) { + cover = Activator.CreateInstance( + typeof (VideoFile).Assembly.GetType("NMaier.SimpleDlna.FileMediaServer.Cover"), + System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, + null, new object[] {media, stream}, null); + } + return Video(media).Set("weakCover", new WeakReference(cover)); + } + [Fact] public void StoredFileIsReadBackAfterReopeningTheDatabase() { - var database = new FileInfo(temp.Combine("cache.db")); var media = temp.WriteFile("movie.mkv", 1024); - var video = new VideoFile(server, media, DlnaMime.VideoMKV) + var video = Video(media) .Set("title", "Cached") .Set("width", (int?)1280) - .Set("height", (int?)720) - .Set("subTitle", new Subtitle()) - .Set("initialized", true); + .Set("height", (int?)720); using (var store = new FileStore(database)) { - // No cover has been generated, so this also exercises binding a - // missing cover as DBNull, which Microsoft.Data.Sqlite requires. store.MaybeStoreFile(video); Assert.False(store.HasCover(video)); } @@ -58,14 +82,10 @@ public void StoredFileIsReadBackAfterReopeningTheDatabase() [Fact] public void ChangedFileIsNotServedFromTheCache() { - var database = new FileInfo(temp.Combine("cache.db")); var media = temp.WriteFile("clip.mkv", 1024); - var video = new VideoFile(server, media, DlnaMime.VideoMKV) - .Set("subTitle", new Subtitle()) - .Set("initialized", true); using (var store = new FileStore(database)) { - store.MaybeStoreFile(video); + store.MaybeStoreFile(Video(media)); } // The cache is keyed by path, size and modification time. @@ -78,19 +98,221 @@ public void ChangedFileIsNotServedFromTheCache() } [Fact] - public void DatabaseFromAnOlderSchemaIsReplaced() + public void CoverIsStoredAndReadBack() + { + var media = temp.WriteFile("film.mkv", 1024); + object cover; + var video = VideoWithCover(media, out cover); + + using (var store = new FileStore(database)) { + store.MaybeStoreFile(video); + } + + using (var store = new FileStore(database)) { + var file = Video(media); + Assert.True(store.HasCover(file)); + var cached = store.MaybeGetCover(file); + Assert.NotNull(cached); + using (var data = cached.CreateContentStream()) { + var bytes = new byte[3]; + data.ReadExactly(bytes); + Assert.True(TestMedia.IsJpeg(bytes.Concat(new byte[1]).ToArray())); + } + } + GC.KeepAlive(cover); + } + + /// + /// Metadata is stored again later without the cover, which loads lazily; + /// the stored cover is kept for that. + /// + [Fact] + public void StoringAgainWithoutTheCoverKeepsIt() { - var database = new FileInfo(temp.Combine("old.db")); - File.WriteAllText(database.FullName, "not a SQLite database from this version"); + var media = temp.WriteFile("film.mkv", 1024); + object cover; using (var store = new FileStore(database)) { - var media = temp.WriteFile("a.mkv"); - store.MaybeStoreFile( - new VideoFile(server, media, DlnaMime.VideoMKV) - .Set("subTitle", new Subtitle()) - .Set("initialized", true)); + store.MaybeStoreFile(VideoWithCover(media, out cover)); + store.MaybeStoreFile(Video(media)); + + Assert.True(store.HasCover(Video(media))); + } + GC.KeepAlive(cover); + } + + /// + /// Regression: the SQLite store kept the previous cover whenever a file + /// was stored without one, even after the file had changed. The stale + /// cover then matched the new size and time, so it was never replaced. + /// + [Fact] + public void ChangedFileDoesNotKeepItsOldCover() + { + var media = temp.WriteFile("film.mkv", 1024); + object cover; + + using (var store = new FileStore(database)) { + store.MaybeStoreFile(VideoWithCover(media, out cover)); + + File.WriteAllBytes(media.FullName, new byte[2048]); + media.Refresh(); + store.MaybeStoreFile(Video(media)); + + Assert.NotNull(store.MaybeGetFile(server, media, DlnaMime.VideoMKV)); + Assert.False(store.HasCover(Video(media))); + } + GC.KeepAlive(cover); + } + + [Fact] + public void SqliteCacheFromEarlierReleasesIsReplaced() + { + var header = Encoding.ASCII.GetBytes("SQLite format 3\0"); + File.WriteAllBytes(database.FullName, header.Concat(new byte[8176]).ToArray()); + var media = temp.WriteFile("a.mkv"); + + using (var store = new FileStore(database)) { + store.MaybeStoreFile(Video(media)); Assert.NotNull(store.MaybeGetFile(server, media, DlnaMime.VideoMKV)); } + Assert.False(File.ReadAllBytes(database.FullName).AsSpan().StartsWith(header)); + } + + [Fact] + public void DatabaseFromAnotherSchemaIsReplaced() + { + using (var other = new LiteDatabase($"Filename={database.FullName};Collation=/Ordinal")) { + other.GetCollection("store").Insert(new BsonDocument {["_id"] = "stale"}); + other.UserVersion = FileStore.SCHEMA - 1; + } + + using (var store = new FileStore(database)) { + } + + using (var reopened = new LiteDatabase($"Filename={database.FullName}")) { + Assert.Equal(FileStore.SCHEMA, reopened.UserVersion); + Assert.Null(reopened.GetCollection("store").FindById("stale")); + } + } + + [Fact] + public void StoresOnTheSameFileShareOneDatabase() + { + var media = temp.WriteFile("shared.mkv"); + var first = new FileStore(database); + using (var second = new FileStore(database)) { + first.MaybeStoreFile(Video(media)); + first.Dispose(); + + // Still open for the second store, and still locked. + Assert.NotNull(second.MaybeGetFile(server, media, DlnaMime.VideoMKV)); + Assert.True(File.Exists(FileStore.LockFileOf(database))); + } + Assert.False(File.Exists(FileStore.LockFileOf(database))); + } + + /// + /// LiteDB lets a second process open the same file and write to it, + /// which corrupts it. The lock file prevents that; the second sdlna runs + /// without a cache (FileServer catches the exception) and must leave the + /// database alone. + /// + [Fact] + public void CacheHeldByAnotherProcessIsLeftAlone() + { + var media = temp.WriteFile("held.mkv"); + using (var store = new FileStore(database)) { + store.MaybeStoreFile(Video(media)); + } + var before = File.ReadAllBytes(database.FullName); + + // Taken the way another sdlna process would take it. + using (FileStore.LockCache(database)) { + Assert.Throws(() => new FileStore(database)); + } + + Assert.Equal(before, File.ReadAllBytes(database.FullName)); + } + + /// + /// Entries are keyed by a hash of the path: LiteDB index keys are limited + /// to 1023 bytes, and its default collation ignores case. + /// + [Fact] + public void LongPathsAreStored() + { + var directory = temp.Path; + try { + while (Encoding.UTF8.GetByteCount(directory) < 1100) { + directory = Directory.CreateDirectory( + Path.Combine(directory, new string('d', 100))).FullName; + } + } + catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { + Assert.Skip($"this file system cannot hold a path that long: {ex.Message}"); + } + var media = new FileInfo(Path.Combine(directory, "deep.mkv")); + File.WriteAllBytes(media.FullName, new byte[16]); + + using (var store = new FileStore(database)) { + store.MaybeStoreFile(Video(media)); + Assert.NotNull(store.MaybeGetFile(server, media, DlnaMime.VideoMKV)); + } + } + + [Fact] + public void PathsDifferingOnlyInCaseAreSeparateEntries() + { + var lower = temp.WriteFile("case.mkv", 16); + var upper = new FileInfo(temp.Combine("CASE.mkv")); + Assert.SkipWhen(upper.Exists, "this file system ignores case"); + File.WriteAllBytes(upper.FullName, new byte[16]); + upper.Refresh(); + File.SetLastWriteTimeUtc(upper.FullName, lower.LastWriteTimeUtc); + upper.Refresh(); + + using (var store = new FileStore(database)) { + store.MaybeStoreFile(Video(lower).Set("title", "lower")); + store.MaybeStoreFile(Video(upper).Set("title", "upper")); + + Assert.EndsWith("lower", + store.MaybeGetFile(server, lower, DlnaMime.VideoMKV).Title); + Assert.EndsWith("upper", + store.MaybeGetFile(server, upper, DlnaMime.VideoMKV).Title); + } + } + + [Fact] + public void PurgeRemovesEntriesOfDeletedFiles() + { + var kept = temp.WriteFile("kept.mkv"); + var deleted = temp.WriteFile("deleted.mkv"); + + using (var store = new FileStore(database)) { + store.MaybeStoreFile(Video(kept)); + store.MaybeStoreFile(Video(deleted)); + File.Delete(deleted.FullName); + + store.PurgeMissingFiles(); + } + + using (var db = new LiteDatabase($"Filename={database.FullName}")) { + Assert.Equal(new[] {kept.FullName}, + db.GetCollection("store").FindAll().Select(d => d["path"].AsString).ToArray()); + } + } + + [Fact] + public void CacheFilesDoNotCountAsMediaChanges() + { + using (var store = new FileStore(database)) { + var ignoreCase = StringComparer.OrdinalIgnoreCase; + Assert.True(store.IsStoreFile(database.FullName, ignoreCase)); + Assert.True(store.IsStoreFile(temp.Combine("cache-log.db"), ignoreCase)); + Assert.True(store.IsStoreFile(temp.Combine("cache.db.lock"), ignoreCase)); + Assert.False(store.IsStoreFile(temp.Combine("cache.mkv"), ignoreCase)); + } } } } diff --git a/util/GlobalSuppressions.cs b/util/GlobalSuppressions.cs index 35499ac3..c48c4845 100644 --- a/util/GlobalSuppressions.cs +++ b/util/GlobalSuppressions.cs @@ -21,8 +21,6 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "MAC", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.IP.#IsAcceptedMAC(System.String)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.Repository`1.#ListItems()")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.Repository`1.#Lookup(System.String)")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sqlite", Scope = "type", Target = "NMaier.SimpleDlna.Utilities.Sqlite")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.Sqlite.#GetDatabaseConnectionSDS(System.String)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.FFmpeg.#IdentifyInternalFromProcess(System.IO.FileInfo)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ffmpeg", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.FFmpeg.#IdentifyInternalFromProcess(System.IO.FileInfo)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Booley", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.Formatting.#Booley(System.String)")] diff --git a/util/Sqlite.cs b/util/Sqlite.cs deleted file mode 100644 index 7c0b058d..00000000 --- a/util/Sqlite.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Data; -using System.IO; -using log4net; -using Microsoft.Data.Sqlite; - -namespace NMaier.SimpleDlna.Utilities -{ - public static class Sqlite - { - public static void ClearPool(IDbConnection conn) - { - var sqlite = conn as SqliteConnection; - if (sqlite != null) { - SqliteConnection.ClearPool(sqlite); - } - } - - public static IDbConnection GetDatabaseConnection(FileInfo database) - { - if (database == null) { - throw new ArgumentNullException(nameof(database)); - } - if (database.Exists && database.IsReadOnly) { - throw new ArgumentException( - "Database file is read only", - nameof(database) - ); - } - - var cs = new SqliteConnectionStringBuilder - { - DataSource = database.FullName, - Mode = SqliteOpenMode.ReadWriteCreate, - Pooling = true, - DefaultTimeout = 5 - }.ConnectionString; - - var rv = new SqliteConnection(cs); - rv.Open(); - try { - using (var pragma = rv.CreateCommand()) { - // System.Data.SQLite accepted "Synchronous" and "journal mode" as - // connection string keywords. Microsoft.Data.Sqlite does not, so - // they are applied as pragmas once the connection is open. - pragma.CommandText = - "PRAGMA synchronous=OFF; PRAGMA journal_mode=TRUNCATE;"; - pragma.ExecuteNonQuery(); - } - } - catch (Exception ex) { - LogManager.GetLogger(typeof (Sqlite)).Error( - "Failed to configure sqlite connection", ex); - } - return rv; - } - } -} diff --git a/util/util.csproj b/util/util.csproj index f2546ea4..e956e7a4 100644 --- a/util/util.csproj +++ b/util/util.csproj @@ -7,7 +7,6 @@ - From f572fa27a26b5089ccddc2b44a5918e8291468c0 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Wed, 16 Sep 2026 19:40:22 -0500 Subject: [PATCH 31/37] Shut down gracefully on SIGTERM, as on Ctrl+C sdlna only handled Ctrl+C (SIGINT). Services and containers are stopped with SIGTERM (systemctl stop, docker stop, most init systems and NAS packages), and .NET's default for SIGTERM ends the process without returning to Main. Main is where the HTTP server and, since the previous commit, the file servers are disposed, so a stopped service never closed its cache: LiteDB's log was not checkpointed and the cache's lock file was left behind on Linux and macOS. Found while writing a smoke test for the release binaries: a server started in the background from a script ignores SIGINT (non-interactive shells start background jobs that way), and SIGTERM is how such a server gets stopped. Program now registers a PosixSignalRegistration for SIGTERM that cancels the default termination and releases Main the same way Ctrl+C does. Both go through RequestShutdown, which logs "Termination requested" or "Shutdown requested". The registration is kept in a static field, since collecting it would unregister the handler. Where the platform doesn't support the signal, Ctrl+C still works. The emergency exit after the fourth Ctrl+C is unchanged. Verified with a single-file osx-arm64 publish, started as a background job with a cache: kill -TERM stopped it within a second, it logged "Termination requested" and "Closed!", and only cache.db remained (no cache-log.db, no cache.db.lock). There is no unit test: that would mean starting the real server, which announces itself on the network. The release workflow's smoke test on Linux and macOS will stop the binaries this way. AGENTS.md: a trap about keeping shutdown graceful. dotnet build: zero warnings. dotnet test: 110 tests, 107 passed, 3 skipped. Co-Authored-By: Claude Opus 5 --- AGENTS.md | 5 +++++ sdlna/Program.cs | 31 ++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 5611f47c..f8614bf6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -209,6 +209,11 @@ Each of these has broken something before. `$HOME/.net` before `Main` runs, and then the program refuses to start at all when `HOME` is missing or read-only. Check the `dotnet publish` output before adding a package. +- **Shutdown has to be graceful.** Ctrl+C and SIGTERM (how services and + containers are stopped) both release `Main`, which then disposes the HTTP + server and every file server; that closes the caches and removes their + lock files. `HttpServer.Dispose` alone only unregisters the file servers. + Anything else that must be released at exit belongs on that path. - **Windows-only features.** Looking up a client's MAC address (`util/AddressToMacResolver.cs`) only works on Windows, so MAC restrictions never match elsewhere. The `.sdlna` folder's hidden attribute and the diff --git a/sdlna/Program.cs b/sdlna/Program.cs index 9d51ccd9..ccb7e965 100644 --- a/sdlna/Program.cs +++ b/sdlna/Program.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading; using log4net; @@ -22,6 +23,11 @@ public static class Program private static uint cancelHitCount; + /// + /// Kept referenced: the handler is unregistered when this is collected. + /// + private static PosixSignalRegistration terminateRegistration; + private static void CancelKeyPressed(object sender, ConsoleCancelEventArgs e) { @@ -31,8 +37,24 @@ private static void CancelKeyPressed(object sender, return; } e.Cancel = true; + RequestShutdown("Shutdown requested"); + } + + /// + /// Services and containers are stopped with SIGTERM (systemctl stop, + /// docker stop), which otherwise ends the process without the shutdown + /// Ctrl+C gets, leaving the caches unclosed. + /// + private static void TerminateRequested(PosixSignalContext context) + { + context.Cancel = true; + RequestShutdown("Termination requested"); + } + + private static void RequestShutdown(string reason) + { blockEvent.Set(); - LogManager.GetLogger(typeof (Program)).Info("Shutdown requested"); + LogManager.GetLogger(typeof (Program)).Info(reason); Console.Title = "SimpleDLNA - shutting down ..."; } @@ -167,6 +189,13 @@ private static void Main(string[] args) try { Console.TreatControlCAsInput = false; Console.CancelKeyPress += CancelKeyPressed; + try { + terminateRegistration = PosixSignalRegistration.Create( + PosixSignal.SIGTERM, TerminateRequested); + } + catch (PlatformNotSupportedException) { + // Ctrl+C still works. + } options.Parse(args); if (options.ShowHelp) { From cfca0a764e9d6c17addcfd79e446d1bf10618f08 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Wed, 16 Sep 2026 19:50:25 -0500 Subject: [PATCH 32/37] List no cover for audio without art, and answer 404 for a missing cover An audio file without embedded album art was listed in Browse results with an albumArtURI and an upnp:icon, and fetching that link returned a 500. Reproduced with a tag-less MP3 from "ffmpeg -f lavfi -i sine=duration=2 -c:a libmp3lame song.mp3", in the 2.1.3 release and on this branch. Why the cover was listed: AudioFile.Cover reads the tags before it answers and returns null when they hold no picture, both before and after the tags are loaded, so null reliably means "no cover" for audio. MediaMount.AddCover did not check for it. It appended the albumArtURI and icon elements, then threw a NullReferenceException on c.PN while building the cover res, and its catch-all swallowed the exception. The item kept the two links and had no cover res. Why fetching it was a 500: the "cover/" handler passed the null cover to ItemResponse, whose constructor threw a NullReferenceException on item.Type. HttpClient answers any exception other than HttpStatusException with a 500. Covers of images and videos fail differently. BaseFile.Cover always returns a lazy Cover, before and after loading, and the thumbnail is only made when the cover is first fetched. When that fails (a damaged image, a video ffmpeg can't read), ThumbnailMaker throws ArgumentException, Cover.ForceLoad logs it and leaves the bytes null, and the size is null. ItemResponse then sent an empty Content-Length and the body threw NotSupportedException, which was also a 500. The next fetch tries again. The fix covers both cases: - AddCover lists nothing when the item's Cover is null. Clients take an albumArtURI as a promise of an image and fetch it, so not listing a cover the item doesn't have is the real fix. The three elements are now appended only once all of them are built, so a failure part way can't leave a dangling albumArtURI again. - The cover handler answers 404 when the item has no cover, or when its cover has no InfoSize, meaning no thumbnail could be made. Lazy covers can't be ruled out at browse time without making every thumbnail in a folder (running ffmpeg once per video), and clients keep old links, as does the server's own browse cache. A 404 says the image doesn't exist; a 500 reports a server fault. Reading InfoSize here costs nothing extra: ItemResponse read it anyway, and a loaded cover keeps its bytes. Checked against a running server with an ffmpeg MP3 without art, an ffmpeg MP4 and an unreadable .mp4. The MP3 has no cover links and its cover URL returns 404. The MP4's cover is still a JPEG. The unreadable file's cover is still listed and now returns 404 instead of 500. Tests (HttpServerTests, on the shared DlnaTestServer): - AudioWithoutArtHasNoCover: an MP3 of plain bytes has no cover link in the DIDL, and its cover URL returns 404. Before the fix it had one, and the URL returned 500. - CoverThatCannotBeMadeIsNotFound: a .jpg that isn't an image returns 404 for its cover, twice. Before the fix it returned 500. - AudioArtIsServed: an MP3 with an embedded front cover still gets a cover link that returns a JPEG. This guards against the fix hiding real art; no test covered audio art before. Test support: BrowsedItem carries the DIDL item id, so tests can build a cover URL for an item that lists none. TestMedia.WriteMp3WithArt writes silent MPEG frames by hand and tags them with TagLib, so the art test needs no encoder. AGENTS.md: a protocol trap saying a listed cover must exist, or be a 404. dotnet build: zero warnings. dotnet test: 113 tests, 110 passed, 3 skipped. Co-Authored-By: Claude Opus 5 --- AGENTS.md | 6 +++ server/Handlers/MediaMount.cs | 11 +++++- server/Handlers/MediaMount_SOAP.cs | 20 +++++++--- tests/HttpServerTests.cs | 62 ++++++++++++++++++++++++++++++ tests/Support/DlnaClient.cs | 3 ++ tests/Support/TestMedia.cs | 31 +++++++++++++++ 6 files changed, 125 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f8614bf6..75255397 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -253,6 +253,12 @@ Each of these has broken something before. header exactly, including case. - **Audio-only servers get the `music` view.** `FileServer.Load` adds it when the server serves only audio and has no views. +- **A listed cover must exist, or be a 404.** Clients fetch every + `albumArtURI` they are given. An item whose `Cover` is null (audio without + embedded art) gets no cover links. Other covers are thumbnails made when + first fetched, so a Browse can list one that can't be made; the cover + handler answers 404 when a cover has no `InfoSize`. Both cases used to end + in a 500. ### Persistence diff --git a/server/Handlers/MediaMount.cs b/server/Handlers/MediaMount.cs index 7a574342..d8d867e9 100644 --- a/server/Handlers/MediaMount.cs +++ b/server/Handlers/MediaMount.cs @@ -102,10 +102,17 @@ public IResponse HandleRequest(IRequest request) var id = path.Split('/')[1]; InfoFormat("Serving cover {0}", id); var item = GetItem(id) as IMediaCover; - if (item == null) { + var cover = item?.Cover; + // Thumbnails are made when first fetched, not when browsed, so a + // cover can be listed that turns out not to exist: a video ffmpeg + // can't read, a damaged image. Such a cover has no size, and serving + // it anyway failed with a 500. So did a link to an item without a + // cover, kept by a client or from a cached browse result. + var meta = cover as IMetaInfo; + if (cover == null || (meta != null && meta.InfoSize == null)) { throw new HttpStatusException(HttpCode.NotFound); } - return new ItemResponse(Prefix, request, item.Cover, "Interactive"); + return new ItemResponse(Prefix, request, cover, "Interactive"); } if (path.StartsWith("subtitle/", StringComparison.Ordinal)) { var id = path.Split('/')[1]; diff --git a/server/Handlers/MediaMount_SOAP.cs b/server/Handlers/MediaMount_SOAP.cs index 843e0c91..f6ecf504 100644 --- a/server/Handlers/MediaMount_SOAP.cs +++ b/server/Handlers/MediaMount_SOAP.cs @@ -61,21 +61,24 @@ private void AddCover(IRequest request, IMediaItem resource, return; } try { + // Clients take an albumArtURI as a promise of an image and fetch it, + // so an item without a cover (audio without embedded art) gets none. var c = cover.Cover; + if (c == null) { + return; + } var curl = $"http://{request.LocalEndPoint.Address}:{request.LocalEndPoint.Port}{Prefix}cover/{resource.Id}/i.jpg"; - var icon = result.CreateElement("upnp", "albumArtURI", NS_UPNP); + var albumArt = result.CreateElement("upnp", "albumArtURI", NS_UPNP); var profile = result.CreateAttribute("dlna", "profileID", NS_DLNA); profile.InnerText = "JPEG_TN"; - icon.SetAttributeNode(profile); - icon.InnerText = curl; - item.AppendChild(icon); - icon = result.CreateElement("upnp", "icon", NS_UPNP); + albumArt.SetAttributeNode(profile); + albumArt.InnerText = curl; + var icon = result.CreateElement("upnp", "icon", NS_UPNP); profile = result.CreateAttribute("dlna", "profileID", NS_DLNA); profile.InnerText = "JPEG_TN"; icon.SetAttributeNode(profile); icon.InnerText = curl; - item.AppendChild(icon); var res = result.CreateElement(string.Empty, "res", NS_DIDL); res.InnerText = curl; @@ -94,6 +97,11 @@ private void AddCover(IRequest request, IMediaItem resource, } res.SetAttribute("protocolInfo", $"http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS={DlnaMaps.DefaultInteractive}"); + + // Appended only once all three are built: a failure part way used to + // leave the albumArtURI and icon behind without the res. + item.AppendChild(albumArt); + item.AppendChild(icon); item.AppendChild(res); } catch (Exception) { diff --git a/tests/HttpServerTests.cs b/tests/HttpServerTests.cs index ddc54c54..c855a540 100644 --- a/tests/HttpServerTests.cs +++ b/tests/HttpServerTests.cs @@ -233,6 +233,68 @@ public void ImageThumbnailIsServed() Assert.True(TestMedia.IsJpeg(DlnaClient.GetBytes(Assert.Single(items).CoverUrl))); } + private HttpStatusCode CoverStatus(string prefix, BrowsedItem item) + { + using (var response = DlnaClient.Get($"http://127.0.0.1:{server.Port}{prefix}cover/{item.Id}/i.jpg")) { + return response.StatusCode; + } + } + + /// + /// Regression: an audio file without embedded art was listed with an + /// albumArtURI and an icon all the same, and fetching them failed with + /// a 500. The item has no cover, so there is nothing to link to, and a + /// link a client kept from elsewhere is not found. + /// + [Fact] + public void AudioWithoutArtHasNoCover() + { + media.WriteFile("song.mp3"); + var prefix = Mount(); + + var (_, items, didl) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + + var item = Assert.Single(items); + Assert.Null(item.CoverUrl); + Assert.DoesNotContain("/cover/", didl); + Assert.Equal(HttpStatusCode.NotFound, CoverStatus(prefix, item)); + } + + [Fact] + public void AudioArtIsServed() + { + var art = media.Combine("art.jpg"); + TestMedia.WriteJpeg(art, 500, 500); + TestMedia.WriteMp3WithArt(media.Combine("song.mp3"), File.ReadAllBytes(art)); + File.Delete(art); + var prefix = Mount(); + + var (_, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + + var item = Assert.Single(items); + Assert.Equal("object.item.audioItem.musicTrack", item.Class); + Assert.True(TestMedia.IsJpeg(DlnaClient.GetBytes(item.CoverUrl))); + } + + /// + /// Regression: a thumbnail is only made when its link is fetched, and + /// when that failed (here, a file that isn't an image) the response was + /// a 500. + /// + [Fact] + public void CoverThatCannotBeMadeIsNotFound() + { + media.WriteFile("photo.jpg"); + var prefix = Mount(); + + var (_, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + + var item = Assert.Single(items); + Assert.Equal(HttpStatusCode.NotFound, CoverStatus(prefix, item)); + // Failures aren't remembered, so asking again tries again. + Assert.Equal(HttpStatusCode.NotFound, CoverStatus(prefix, item)); + } + [Fact] public void VideoDurationAndThumbnailComeFromFFmpeg() { diff --git a/tests/Support/DlnaClient.cs b/tests/Support/DlnaClient.cs index 74146910..d3685e4c 100644 --- a/tests/Support/DlnaClient.cs +++ b/tests/Support/DlnaClient.cs @@ -19,6 +19,8 @@ internal sealed class BrowsedItem public string Duration; + public string Id; + public string MimeType; public string Title; @@ -107,6 +109,7 @@ public static (HttpStatusCode Status, List Items, string Didl) Brow var res = item.Elements().First(e => e.Name.LocalName == "res" && !e.Value.Contains("/cover/")); return new BrowsedItem { + Id = item.Attribute("id")?.Value, Title = item.Elements().First(e => e.Name.LocalName == "title").Value, Class = item.Elements().First(e => e.Name.LocalName == "class").Value, Url = res.Value, diff --git a/tests/Support/TestMedia.cs b/tests/Support/TestMedia.cs index 34f2f76c..5c2d36d8 100644 --- a/tests/Support/TestMedia.cs +++ b/tests/Support/TestMedia.cs @@ -70,6 +70,37 @@ public static bool IsJpeg(byte[] data) data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF; } + /// + /// Half a second of silent MP3 frames, written by hand so that no + /// encoder is needed, with an ID3v2 tag holding + /// as the front cover. + /// + public static FileInfo WriteMp3WithArt(string path, byte[] art) + { + // MPEG-1 Layer III, 128 kbit/s, 44.1 kHz: 417 bytes a frame. + var frame = new byte[417]; + frame[0] = 0xFF; + frame[1] = 0xFB; + frame[2] = 0x90; + using (var stream = File.Create(path)) { + for (var i = 0; i < 20; i++) { + stream.Write(frame); + } + } + using (var file = TagLib.File.Create(path)) { + file.GetTag(TagLib.TagTypes.Id3v2, true).Pictures = new TagLib.IPicture[] + { + new TagLib.Picture(new TagLib.ByteVector(art)) + { + Type = TagLib.PictureType.FrontCover, + MimeType = "image/jpeg" + } + }; + file.Save(); + } + return new FileInfo(path); + } + public static bool HasFFmpeg => FFmpeg.FFmpegExecutable != null; /// From 4e794567ec7990b99dcd311a39036c59316b4779 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Wed, 16 Sep 2026 19:50:48 -0500 Subject: [PATCH 33/37] Send media durations in the UPnP form, whatever the machine's culture VideoFile and AudioFile put each file's duration into its Duration property with TimeSpan.ToString("g"). MediaMount_SOAP copies that property into the DIDL res@duration attribute, and "g" is culture-sensitive: on a machine set to es-CO (or any culture that writes decimals with a comma) a 2.366 s MP3 was announced as duration="0:00:02,366" instead of "0:00:02.366". UPnP ContentDirectory requires H+:MM:SS[.F+], with a dot. "g" also puts the days in front once a duration reaches 24 hours, so an audiobook of 25 h 1 min 2.5 s came out as "1:1:01:02,5", which is not that form in any culture. Formatting.FormatDuration (util) now formats durations with the invariant culture as total hours, then two-digit minutes and seconds, then milliseconds after a dot: "0:00:02.366", "25:01:02.500". Milliseconds are always written with three digits, as MiniDLNA does, and anything below a millisecond is truncated, so a duration never rounds up into the next second. Both files use it. A negative duration throws; none can occur, since durations come from TagLib or ffmpeg (under 0.1 s is dropped) or from the cache (only positive values are read back). The HTML index (MediaMount_HTML) shows the same Duration property, and keeps doing so. The page is formatted on the server, so the old text followed the server's culture, not the viewer's, and a day part such as "1:1:01:02,5" was hard to read anyway. "25:01:02.500" reads the same everywhere, and one property keeps the page and the DIDL in agreement. The cached payload is unchanged (durations are stored as ticks), so FileStore.SCHEMA stays. The response doesn't depend on anything new about the request, so the browse cache key stays too. Tests: - DurationTests: FormatDuration for durations under a second, whole minutes, 23:59:59.999, exactly a day, over four days and one tick under an hour; negative durations are rejected; AudioFile and VideoFile give "0:00:02.366" and "25:01:02.500" (duration set through Fields.Set); a file without a duration has no Duration property. - HttpServerTests.DurationIsSentWithADecimalPointInAnyCulture browses a mounted MP3 and checks res@duration and the HTML index. Responses are built on the server's threads, so this test also changes CultureInfo.DefaultThreadCurrentCulture; the HTTP server collection runs alone. Checked that the change reaches those threads: with en-US instead of es-CO, the test passed on this es-CO machine before the fix. - VideoDurationAndThumbnailComeFromFFmpeg now checks the duration's form and parses it with the invariant culture; before, TimeSpan.Parse accepted the comma form on an es-CO machine, which is why nothing caught this. - tests/Support/CultureScope switches to es-CO for a test and back, so the tests fail on every machine and not only on those set to a comma culture. When es-CO's data is missing (invariant globalization, common in containers) the tests are skipped with a reason rather than passing without proving anything. Before the fix, the four AudioFile/VideoFile cases, the new HTTP test and the tightened ffmpeg test failed ("0:00:02,366", "1:1:01:02,5", "0:00:03"); after it they pass. With DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1, DurationTests skips its 11 culture cases and passes the other 2. AGENTS.md: a trap about keeping protocol values independent of the machine's culture, and the new test helper. dotnet build: zero warnings. dotnet test: 127 tests, 124 passed, 3 skipped (the existing long-path, case-sensitivity and Windows-only skips). Co-Authored-By: Claude Opus 5 --- AGENTS.md | 10 ++++ fsserver/Files/AudioFile.cs | 3 +- fsserver/Files/VideoFile.cs | 3 +- tests/DurationTests.cs | 106 ++++++++++++++++++++++++++++++++++ tests/HttpServerTests.cs | 32 +++++++++- tests/Support/CultureScope.cs | 65 +++++++++++++++++++++ util/Formatting.cs | 23 ++++++++ 7 files changed, 239 insertions(+), 3 deletions(-) create mode 100644 tests/DurationTests.cs create mode 100644 tests/Support/CultureScope.cs diff --git a/AGENTS.md b/AGENTS.md index 75255397..cc535799 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -168,6 +168,10 @@ runs it. - `DlnaTestServer` and `DlnaClient` host file servers on a real `HttpServer` and talk to it with SOAP, choosing the User-Agent and the local address each request connects through. + - `CultureScope.CommaDecimals` switches to es-CO, which writes decimals + with a comma, so culture-dependent output fails on every machine. With + `processWide: true` it reaches the HTTP server's threads too; use that + only in a collection that runs alone. - **Regression tests name their bug.** Each one's summary says what used to go wrong. When adding one, check that it fails with the fix reverted before relying on it. @@ -245,6 +249,12 @@ Each of these has broken something before. response's `Content-Type`, and the GetProtocolInfo list. Go through `DlnaMaps.MimeFor` and `DlnaMaps.ProtocolInfoFor` instead of reading `DlnaMaps.Mime` directly. +- **Protocol values must not depend on the machine's culture.** Durations + were once formatted with `TimeSpan`'s culture-sensitive `"g"`, so an es-CO + machine sent `duration="0:00:02,366"`. Format what goes into SOAP and DIDL + with `CultureInfo.InvariantCulture`, and durations with + `Formatting.FormatDuration` (`H+:MM:SS.FFF` in total hours, as UPnP + requires; the HTML index shows the same text). - **Loopback clients are always admitted**, by `HttpServer.AuthorizeClient` and by `MediaMount.HandleRequest`, whatever the restrictions. Restrictions can only be observed from another address. diff --git a/fsserver/Files/AudioFile.cs b/fsserver/Files/AudioFile.cs index f66ef896..8d429fc1 100644 --- a/fsserver/Files/AudioFile.cs +++ b/fsserver/Files/AudioFile.cs @@ -1,6 +1,7 @@ using System; using System.IO; using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Utilities; using TagLib; using File = TagLib.File; @@ -130,7 +131,7 @@ public override IHeaders Properties rv.Add("Description", description); } if (duration != null) { - rv.Add("Duration", duration.Value.ToString("g")); + rv.Add("Duration", duration.Value.FormatDuration()); } if (genre != null) { rv.Add("Genre", genre); diff --git a/fsserver/Files/VideoFile.cs b/fsserver/Files/VideoFile.cs index 02fd7f25..feec73c7 100644 --- a/fsserver/Files/VideoFile.cs +++ b/fsserver/Files/VideoFile.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Utilities; using TagLib; using File = TagLib.File; @@ -145,7 +146,7 @@ public override IHeaders Properties rv.Add("Director", director); } if (duration != null) { - rv.Add("Duration", duration.Value.ToString("g")); + rv.Add("Duration", duration.Value.FormatDuration()); } if (genre != null) { rv.Add("Genre", genre); diff --git a/tests/DurationTests.cs b/tests/DurationTests.cs new file mode 100644 index 00000000..550eff7d --- /dev/null +++ b/tests/DurationTests.cs @@ -0,0 +1,106 @@ +using System; +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Tests.Support; +using NMaier.SimpleDlna.Utilities; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// Media durations as clients receive them: H+:MM:SS.FFF, as UPnP + /// ContentDirectory requires for res@duration, whatever the culture. + /// + public sealed class DurationTests : IDisposable + { + private readonly TempDirectory temp = new TempDirectory(); + + private readonly FileServer server; + + public DurationTests() + { + server = TestFileServer.Create(temp.Info); + } + + public void Dispose() + { + server.Dispose(); + temp.Dispose(); + } + + public static TheoryData Durations => new TheoryData + { + {TimeSpan.FromMilliseconds(100), "0:00:00.100"}, + {TimeSpan.FromMilliseconds(2366), "0:00:02.366"}, + {TimeSpan.FromMinutes(97), "1:37:00.000"}, + {new TimeSpan(0, 23, 59, 59, 999), "23:59:59.999"}, + {TimeSpan.FromDays(1), "24:00:00.000"}, + {new TimeSpan(4, 5, 6, 7, 89), "101:06:07.089"}, + // Less than a millisecond is dropped, never rounded up into the seconds. + {TimeSpan.FromTicks(TimeSpan.TicksPerHour - 1), "0:59:59.999"} + }; + + [Theory] + [MemberData(nameof(Durations))] + public void DurationsAreFormattedInHoursWithADecimalPoint(TimeSpan duration, string expected) + { + using (CultureScope.CommaDecimals()) { + Assert.Equal(expected, duration.FormatDuration()); + } + } + + [Fact] + public void NegativeDurationsAreRejected() + { + Assert.Throws( + () => TimeSpan.FromSeconds(-1).FormatDuration()); + } + + /// + /// Regression: the Duration property used TimeSpan's "g" format, so on an + /// es-CO machine a 2.366 s MP3 was announced as "0:00:02,366", and past + /// 24 hours (an audiobook) the days came first, as in "1:1:01:02,5". + /// + [Theory] + [InlineData(2366, "0:00:02.366")] + [InlineData(90_062_500, "25:01:02.500")] + public void AudioDurationIsFormattedIndependentlyOfCulture(long milliseconds, string expected) + { + var song = new AudioFile(server, temp.WriteFile("song.mp3"), DlnaMime.AudioMP3) + .Set("duration", (TimeSpan?)TimeSpan.FromMilliseconds(milliseconds)) + .Set("initialized", true); + + using (CultureScope.CommaDecimals()) { + Assert.Equal(expected, song.Properties["Duration"]); + } + } + + /// + /// Regression: as for audio, "g" gave "0:00:02,366" on an es-CO machine + /// and "1:1:01:02,5" for a video longer than a day. + /// + [Theory] + [InlineData(2366, "0:00:02.366")] + [InlineData(90_062_500, "25:01:02.500")] + public void VideoDurationIsFormattedIndependentlyOfCulture(long milliseconds, string expected) + { + var video = new VideoFile(server, temp.WriteFile("movie.mkv"), DlnaMime.VideoMKV) + .Set("duration", (TimeSpan?)TimeSpan.FromMilliseconds(milliseconds)) + .Set("subTitle", new Subtitle()) + .Set("initialized", true); + + using (CultureScope.CommaDecimals()) { + Assert.Equal(expected, video.Properties["Duration"]); + } + } + + [Fact] + public void FilesWithoutADurationHaveNoDurationProperty() + { + var song = new AudioFile(server, temp.WriteFile("song.mp3"), DlnaMime.AudioMP3) + .Set("initialized", true); + + Assert.False(song.Properties.ContainsKey("Duration")); + } + } +} diff --git a/tests/HttpServerTests.cs b/tests/HttpServerTests.cs index c855a540..6ebb771c 100644 --- a/tests/HttpServerTests.cs +++ b/tests/HttpServerTests.cs @@ -1,8 +1,10 @@ using System; +using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; +using System.Text; using NMaier.SimpleDlna.FileMediaServer; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Tests.Support; @@ -305,9 +307,37 @@ public void VideoDurationAndThumbnailComeFromFFmpeg() var (_, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); var item = Assert.Single(items); - var duration = TimeSpan.Parse(item.Duration); + Assert.Matches(@"^\d+:\d\d:\d\d\.\d{3}$", item.Duration); + var duration = TimeSpan.Parse(item.Duration, CultureInfo.InvariantCulture); Assert.InRange(duration.TotalSeconds, 2.5, 3.5); Assert.True(TestMedia.IsJpeg(DlnaClient.GetBytes(item.CoverUrl))); } + + /// + /// Regression: res@duration was formatted with the machine's culture, so + /// on an es-CO machine a 2.366 s song was announced as + /// duration="0:00:02,366". The HTML index shows the same text. + /// + [Fact] + public void DurationIsSentWithADecimalPointInAnyCulture() + { + media.WriteFile("song.mp3"); + var fileServer = TestFileServer.Create(media.Info); + var prefix = server.Mount(fileServer); + var root = Assert.IsAssignableFrom(fileServer.GetItem(Identifiers.GENERAL_ROOT)); + Assert.IsType(Assert.Single(root.ChildItems)) + .Set("duration", (TimeSpan?)TimeSpan.FromMilliseconds(2366)) + .Set("initialized", true); + + // Responses are built on the server's threads, not this one. + using (CultureScope.CommaDecimals(processWide: true)) { + var (_, items, _) = DlnaClient.Browse("127.0.0.1", server.Port, prefix); + var html = Encoding.UTF8.GetString( + DlnaClient.GetBytes($"http://127.0.0.1:{server.Port}{prefix}index/{Identifiers.GENERAL_ROOT}")); + + Assert.Equal("0:00:02.366", Assert.Single(items).Duration); + Assert.Contains("0:00:02.366", html); + } + } } } diff --git a/tests/Support/CultureScope.cs b/tests/Support/CultureScope.cs new file mode 100644 index 00000000..5b1fa10b --- /dev/null +++ b/tests/Support/CultureScope.cs @@ -0,0 +1,65 @@ +using System; +using System.Globalization; +using Xunit; + +namespace NMaier.SimpleDlna.Tests.Support +{ + /// + /// Switches to a culture that writes decimals with a comma and switches + /// back when disposed, so culture-sensitive formatting fails on every + /// machine rather than only on those set up that way. + /// + internal sealed class CultureScope : IDisposable + { + private readonly CultureInfo previous; + + private readonly CultureInfo previousDefault; + + private readonly bool processWide; + + private CultureScope(CultureInfo culture, bool processWide) + { + this.processWide = processWide; + previous = CultureInfo.CurrentCulture; + previousDefault = CultureInfo.DefaultThreadCurrentCulture; + CultureInfo.CurrentCulture = culture; + if (processWide) { + CultureInfo.DefaultThreadCurrentCulture = culture; + } + } + + public void Dispose() + { + CultureInfo.CurrentCulture = previous; + if (processWide) { + CultureInfo.DefaultThreadCurrentCulture = previousDefault; + } + } + + /// + /// Switches the current culture to es-CO, whose decimal separator is a + /// comma. Skips the test when that culture's data is unavailable. + /// + /// + /// Also make es-CO the culture of every thread that hasn't chosen its + /// own, such as the HTTP server's. Only for tests in a collection that + /// runs alone. + /// + public static CultureScope CommaDecimals(bool processWide = false) + { + CultureInfo culture = null; + try { + culture = CultureInfo.GetCultureInfo("es-CO"); + } + catch (CultureNotFoundException) { + } + // Under invariant globalization (common in containers) the culture + // either doesn't exist or formats like the invariant culture, and the + // test would pass without proving anything. + Assert.SkipWhen( + culture?.NumberFormat.NumberDecimalSeparator != ",", + "es-CO culture data is unavailable (invariant globalization?)"); + return new CultureScope(culture, processWide); + } + } +} diff --git a/util/Formatting.cs b/util/Formatting.cs index d4273747..c6cbcfde 100644 --- a/util/Formatting.cs +++ b/util/Formatting.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Runtime.InteropServices; using System.Text.RegularExpressions; @@ -32,6 +33,28 @@ public static bool Booley(string maybeBoolean) return sc.Equals("yes", maybeBoolean) || sc.Equals("1", maybeBoolean) || sc.Equals("true", maybeBoolean); } + /// + /// Formats a media duration as UPnP ContentDirectory requires for + /// res@duration: H+:MM:SS.FFF, total hours first. TimeSpan's own formats + /// don't fit: "g" writes the current culture's decimal separator (a + /// comma on an es-CO machine, "0:00:02,366"), and it and "c" both put + /// the days in front once a duration reaches 24 hours. + /// + public static string FormatDuration(this TimeSpan duration) + { + if (duration < TimeSpan.Zero) { + throw new ArgumentOutOfRangeException( + nameof(duration), duration, "Durations cannot be negative"); + } + return string.Format( + CultureInfo.InvariantCulture, + "{0}:{1:D2}:{2:D2}.{3:D3}", + duration.Ticks / TimeSpan.TicksPerHour, + duration.Minutes, + duration.Seconds, + duration.Milliseconds); + } + public static string FormatFileSize(this long size) { if (size < 900) { From f0683499c39dcb54f18cc256790437c4026db733 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Wed, 16 Sep 2026 19:54:13 -0500 Subject: [PATCH 34/37] Start on Windows without a console for input, and report startup errors The smoke test of the release binaries failed on Windows: sdlna.exe, started in the background by Git Bash, printed its first blank line and exited with status 0, with nothing else in its output. Main sets Console.TreatControlCAsInput = false before anything else. On Windows that changes the console's input mode, and throws IOException when standard input is not a console: a background job, a scheduled task, a service wrapper, or input redirected from a file. Release builds catch every exception at the end of Main and only log it through log4net, which at that point is not yet configured, so the error went nowhere and the exit status stayed 0. The same silent exit would happen for any other exception raised before logging is set up. - TreatControlCAsInput is only set when standard input is a console (Console.IsInputRedirected is false). Ctrl+C can't arrive through redirected input anyway, and the value is already false by default. - The catch-all also writes "Error: " to standard error and sets exit status 1, so a failure is visible without a log. - Console titles go through SetTitle, which ignores the IOException, PlatformNotSupportedException or Win32Exception thrown when there is no console window to title. They were set at startup, when running and on shutdown, where such an exception would stop the server or its shutdown. Checked on macOS: the smoke test passes with a single-file publish of this code, and running it with standard input from /dev/null still works. The Windows smoke test in the release workflow checks the Windows case. The new catch-all output also exposed an older bug, left for a separate change: in single-file builds, "sdlna --help" and the usage printed after an unknown option fail with "The value cannot be an empty string", because GetOptNet names the program from Assembly.Location, which is empty there. 2.1.3 aborts the same way. dotnet build: zero warnings. dotnet test: 127 tests, 124 passed, 3 skipped. Co-Authored-By: Claude Opus 5 --- sdlna/Program.cs | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/sdlna/Program.cs b/sdlna/Program.cs index ccb7e965..5b1009e4 100644 --- a/sdlna/Program.cs +++ b/sdlna/Program.cs @@ -55,7 +55,23 @@ private static void RequestShutdown(string reason) { blockEvent.Set(); LogManager.GetLogger(typeof (Program)).Info(reason); - Console.Title = "SimpleDLNA - shutting down ..."; + SetTitle("SimpleDLNA - shutting down ..."); + } + + /// + /// Sets the console window's title, if there is a console window: a + /// service or scheduled task may run without one. + /// + private static void SetTitle(string title) + { + try { + Console.Title = title; + } + catch (Exception ex) when ( + ex is IOException || ex is PlatformNotSupportedException || + ex is System.ComponentModel.Win32Exception) { + // No console to title. + } } private static void ListOrders() @@ -187,7 +203,12 @@ private static void Main(string[] args) var options = new Options(); try { - Console.TreatControlCAsInput = false; + // On Windows this changes the console's input mode, and throws when + // standard input is not a console: a background job, a scheduled task, + // a service wrapper. Ctrl+C can't arrive through such an input anyway. + if (!Console.IsInputRedirected) { + Console.TreatControlCAsInput = false; + } Console.CancelKeyPress += CancelKeyPressed; try { terminateRegistration = PosixSignalRegistration.Create( @@ -244,7 +265,7 @@ private static void Main(string[] args) new UserAgentAuthorizer(options.UserAgents)); } - Console.Title = "SimpleDLNA - starting ..."; + SetTitle("SimpleDLNA - starting ..."); var types = options.Types[0]; foreach (var t in options.Types) { @@ -278,7 +299,7 @@ private static void Main(string[] args) options.Directories[0], options.Directories.Length); } - Console.Title = $"{friendlyName} - running ..."; + SetTitle($"{friendlyName} - running ..."); Run(server); } @@ -300,6 +321,10 @@ private static void Main(string[] args) #if !DEBUG catch (Exception ex) { LogManager.GetLogger(typeof (Program)).Fatal("Failed to run", ex); + // Logging may not be set up yet, and then the line above goes + // nowhere: without this, sdlna would exit silently with status 0. + Console.Error.WriteLine("Error: {0}", ex.Message); + Environment.ExitCode = 1; } #endif } @@ -440,7 +465,7 @@ private static void RunConfiguredServers(Options options, var httpServer = new HttpServer(port); var fileServers = new List(); try { - Console.Title = "SimpleDLNA - starting ..."; + SetTitle("SimpleDLNA - starting ..."); var mounted = 0; foreach (var server in config.Servers) { try { @@ -459,9 +484,9 @@ private static void RunConfiguredServers(Options options, throw new ConfigurationException("None of the configured servers could be started."); } - Console.Title = mounted == 1 + SetTitle(mounted == 1 ? $"{config.Servers[0].Name} - running ..." - : $"SimpleDLNA - {mounted} servers running ..."; + : $"SimpleDLNA - {mounted} servers running ..."); Run(httpServer); } From 3b4fabd680d6f381da45a2ea4e3423b1f0f8074d Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Thu, 17 Sep 2026 00:06:03 -0500 Subject: [PATCH 35/37] Print usage in single-file builds, naming the program sdlna MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In every 2.x release, "sdlna --help" failed, and so did the usage printed after an unknown option. With the startup error reporting added in the previous commit, both print "Error: The value cannot be an empty string. (Parameter 'path')". Before it, --help printed only a blank line and exited with status 0 (the error went to log4net, which was not yet configured), and an unknown option ended in an unhandled ArgumentException (exit status 134). "dotnet sdlna.dll --help" worked, because there the assembly is a file. Options derives from GetOptNet's GetOpt (4.0.8, still the same on its master branch). GetOpt.PrintUsage calls the virtual AssembleUsage, whose first step is new FileInfo((GetEntryAssembly() ?? GetCallingAssembly()).Location).Name, which names the program in the "Usage:" line. Assembly.Location is "" in a single-file executable, so FileInfo throws before anything is written. This happens even with introAndEpilogue: false, so calling the base method can't avoid it, and no attribute setting helps: UsagePrefix is a prefix style, not a name, and UsageIntro is read after the FileInfo is created. Options now overrides AssembleUsage (sdlna/OptionsUsage.cs, a new part of the now partial class) and builds the same text without the file: - The intro still comes from GetOptNet, through its protected GetUsageIntro, called with the name "sdlna", as the epilog and "sdlna --server help" already call the program. The published binary and "dotnet sdlna.dll" now both show "Usage: sdlna ...", not "sdlna.dll". - GetOptNet keeps its option list (CollectOptInfos, OptInfo) private, so the list and its layout are rebuilt from the same attributes: category filter, short and long names, help variables and their defaults (the enum list for -t), the positional parameters line, the ordinal sort and the wrapping, including GetOptNet's lines that run past the width when an option's name is long. That code is adapted from GetOptNet's GetOpt_Usage.cs and OptInfo.cs, so the file carries GetOptNet's MIT notice. It covers the attribute settings Options uses: GetOptNet's default CaseType, UsagePrefix and UsageShowAliases, arrays but no lists or counted arguments, and no commands. - Help variables are upper-cased in the invariant culture. GetOptNet uses the current UI culture, which turns "file" into "FİLE" in Turkish. - The option help texts and the epilog are unchanged. At the same width, the published binary's --help and unknown-option output are byte-for-byte what the framework-dependent build printed before, apart from the program's name. Replacing GetOptNet was the alternative. Parsing works, and a new parser would risk changing things no test covers today: case-insensitive long options, --opt=value, the -t enum values and the "what" alias, repeated array options, and the error messages. A new parser would also bring its own help layout. Tests (tests/UsageTests.cs, in the process-state collection): - UsageIsPrintedWhenTheProgramHasNoFile loads sdlna.dll from bytes, which gives an assembly whose Location is "" as in a single-file build, makes it the entry assembly with Assembly.SetEntryAssembly, and calls PrintUsage with the console captured. Without the override, it fails with the release builds' ArgumentException. - UsageLooksAsGetOptNetShowsIt compares the override with GetOptNet's own rendering (Options.AssembleGetOptNetUsage calls the base method; the test host's entry assembly has a file). It covers widths 20 to 200, variable-width fonts, no intro or epilog, and the Basic and Advanced categories. Only the program's name may differ, so an option or attribute change that the rebuilt list doesn't handle fails here. Without the override, 6 of its 7 cases fail on the name. AGENTS.md's trap about Assembly.Location now mentions GetOptNet. Checked with a single-file osx-arm64 publish (self-contained, untrimmed): --help, -h and --bogus print the usage; --version, --license, --list-views, --list-sort-orders and "--server help" work as well. Two older problems remain, both also in framework-dependent builds, left for separate changes. "-?", listed as the short form of --help, is never recognised, because GetOptNet's short-option pattern only accepts word characters after the dash; sdlna then tries to serve a folder named "-?". And an unknown option still exits with status 0. dotnet build: zero warnings. dotnet test: 135 tests, 132 passed, 3 skipped (long paths, case-sensitive file system and the Windows hidden attribute, all platform-dependent on macOS). Co-Authored-By: Claude Opus 5 --- AGENTS.md | 5 +- sdlna/Options.cs | 2 +- sdlna/OptionsUsage.cs | 235 ++++++++++++++++++++++++++++++++++++++++++ tests/UsageTests.cs | 90 ++++++++++++++++ 4 files changed, 330 insertions(+), 2 deletions(-) create mode 100644 sdlna/OptionsUsage.cs create mode 100644 tests/UsageTests.cs diff --git a/AGENTS.md b/AGENTS.md index cc535799..0530ce71 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -201,7 +201,10 @@ Each of these has broken something before. .NET.** It compiles without a warning. Use `ThreadPool.QueueUserWorkItem` or tasks. - **`Assembly.Location` is `""` in a single-file executable.** Use - `AppContext.BaseDirectory` for the program's folder. + `AppContext.BaseDirectory` for the program's folder. Libraries read it + too: GetOptNet's `AssembleUsage` names the program after the entry + assembly's file and throws there, so `sdlna/OptionsUsage.cs` replaces it, + and `UsageTests` runs the usage with a file-less entry assembly. - **`Environment.GetFolderPath` returns `""` for a folder that doesn't exist**, such as the home folder of a service account. Pass `Environment.SpecialFolderOption.DoNotVerify` when you need the path, and diff --git a/sdlna/Options.cs b/sdlna/Options.cs index aa2807bf..da6ea437 100644 --- a/sdlna/Options.cs +++ b/sdlna/Options.cs @@ -14,7 +14,7 @@ namespace NMaier.SimpleDlna { [GetOptOptions(AcceptPrefixType = ArgumentPrefixTypes.Dashes, UsageEpilog = EPILOG)] - internal class Options : GetOpt + internal partial class Options : GetOpt { private const string EPILOG = "Given folders, sdlna serves just those, using only the options above, and\n" + diff --git a/sdlna/OptionsUsage.cs b/sdlna/OptionsUsage.cs new file mode 100644 index 00000000..f0549f77 --- /dev/null +++ b/sdlna/OptionsUsage.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using NMaier.GetOptNet; + +// The option list and its layout are adapted from GetOptNet 4.0.8 +// (GetOpt_Usage.cs and OptInfo.cs, https://github.com/nmaier/GetOptNet), +// which is distributed under this notice: +// +// Copyright (c) 2009-2019 Nils Maier +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +namespace NMaier.SimpleDlna +{ + internal partial class Options + { + /// + /// The name usage shows, as the epilog and "sdlna --server help" do. + /// + private const string PROGRAM_NAME = "sdlna"; + + /// + /// GetOptNet's AssembleUsage starts with + /// new FileInfo(GetEntryAssembly().Location) to name the program. + /// Location is "" in a single-file executable, so that threw before + /// anything was written: in every release, "sdlna --help" printed + /// nothing and the usage after an unknown option ended in an unhandled + /// ArgumentException. This builds the same text without the file. + /// GetOptNet keeps its option list private, so the list and its + /// layout are rebuilt here from the same attributes, for the attribute + /// settings Options uses; UsageTests holds the result to GetOptNet's + /// own output. + /// + public override string AssembleUsage(int width, + HelpCategory category = HelpCategory.Basic, bool fixedWidthFont = true, + bool introAndEpilogue = true, bool includeCommands = true) + { + // includeCommands is moot: Options registers no commands. + var nl = Environment.NewLine; + var rv = new StringBuilder(); + + if (introAndEpilogue) { + var intro = GetUsageIntro(PROGRAM_NAME, string.Empty); + if (!string.IsNullOrEmpty(intro)) { + rv.Append(intro); + rv.Append(nl); + } + } + + var entries = UsageEntries(category); + if (entries.Count > 0) { + rv.Append(nl); + rv.Append("Options:"); + rv.Append(nl); + + // GetOptNet's layout, overlong lines included: help text starts + // after the option when that fits in half the width, and is then + // wrapped as if it had started in the help column. + var maxLine = width / 2; + var maxArg = width / 4; + foreach (var (argText, helpText) in entries) { + rv.Append(argText); + var len = argText.Length; + if (!fixedWidthFont || len > maxLine) { + rv.Append(nl); + len = 0; + } + rv.Append(' ', Math.Max(1, maxArg - len)); + + len = width - maxArg; + foreach (var word in helpText.Split(' ', '\t')) { + var w = word + " "; + if (len < w.Length) { + rv.Append(nl); + rv.Append(' ', maxArg); + len = width - maxArg; + } + rv.Append(w); + len -= w.Length; + } + rv.Append(nl); + } + } + + if (introAndEpilogue) { + rv.Append(nl); + rv.Append(EPILOG); + } + + rv.Append(nl); + return rv.ToString(); + } + + /// + /// GetOptNet's own rendering, for tests to compare against. It throws + /// when the entry assembly has no file, as in a single-file executable. + /// + internal string AssembleGetOptNetUsage(int width, HelpCategory category, + bool fixedWidthFont, bool introAndEpilogue) + { + return base.AssembleUsage(width, category, fixedWidthFont, introAndEpilogue); + } + + /// + /// One line per option, sorted by the name shown first, then the + /// positional parameters. Options keeps GetOptNet's default CaseType, + /// UsagePrefix and UsageShowAliases: long names in lower case, dashes, + /// and no aliases. + /// + private List<(string ArgText, string HelpText)> UsageEntries( + HelpCategory category) + { + const BindingFlags FLAGS = + BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance; + var type = GetType(); + var members = type.GetFields(FLAGS).Cast() + .Concat(type.GetProperties(FLAGS)); + + var options = new List<(string SortName, string ArgText, string HelpText)>(); + (string ArgText, string HelpText)? parameters = null; + foreach (var member in members) { + var memberType = member is FieldInfo field + ? field.FieldType + : ((PropertyInfo)member).PropertyType; + var elementType = memberType.IsArray + ? memberType.GetElementType() + : memberType; + + var parametersAttribute = member.GetCustomAttribute(); + if (parametersAttribute != null) { + var helpVar = string.IsNullOrEmpty(parametersAttribute.HelpVar) + ? DefaultHelpVar(elementType) + : parametersAttribute.HelpVar.ToUpperInvariant(); + parameters = parametersAttribute.Min == 1 && parametersAttribute.Max == 1 + ? (" " + helpVar, "Positional parameter") + : (" " + helpVar + ", ...", "Positional parameters"); + } + + var argument = member.GetCustomAttribute(); + if (argument == null || argument.Category > category) { + continue; + } + var longName = (string.IsNullOrEmpty(argument.Arg) + ? member.Name + : argument.Arg).ToLowerInvariant(); + var flag = memberType == typeof (bool); + var value = string.IsNullOrEmpty(argument.HelpVar) + ? DefaultHelpVar(elementType) + : argument.HelpVar.ToUpperInvariant(); + + var names = new List(); + var shortArgument = member.GetCustomAttribute(); + if (shortArgument != null) { + names.Add(flag ? $"-{shortArgument.Arg}" : $"-{shortArgument.Arg} {value}"); + } + names.Add(flag ? $"--{longName}" : $"--{longName}={value}"); + options.Add(( + shortArgument != null ? shortArgument.Arg.ToString() : longName, + " " + string.Join(", ", names), + argument.HelpText)); + } + + var entries = options + .OrderBy(o => o.SortName, StringComparer.Ordinal) + .Select(o => (o.ArgText, o.HelpText)) + .ToList(); + if (parameters != null) { + entries.Add(parameters.Value); + } + return entries; + } + + /// + /// What GetOptNet shows for the value of an option without a HelpVar. + /// + private static string DefaultHelpVar(Type type) + { + if (type.IsEnum) { + var names = Enum.GetNames(type).Select(n => n.ToLowerInvariant()); + return $"<{string.Join(", ", names)}>"; + } + if (type == typeof (bool)) { + return "BOOL"; + } + if (type == typeof (ushort)) { + return "USHORT"; + } + if (type == typeof (int)) { + return "INT"; + } + if (type == typeof (uint)) { + return "UINT"; + } + if (type == typeof (long)) { + return "LONG"; + } + if (type == typeof (ulong)) { + return "ULONG"; + } + if (type == typeof (DirectoryInfo)) { + return "DIRECTORY"; + } + if (type == typeof (FileInfo)) { + return "FILE"; + } + if (type == typeof (string)) { + return "..."; + } + return type.Name.ToUpperInvariant(); + } + } +} diff --git a/tests/UsageTests.cs b/tests/UsageTests.cs new file mode 100644 index 00000000..2ba2f6e6 --- /dev/null +++ b/tests/UsageTests.cs @@ -0,0 +1,90 @@ +using System; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; +using NMaier.GetOptNet; +using NMaier.SimpleDlna.Tests.Support; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// The usage text that "sdlna --help" prints, as does an invalid option. + /// + [Collection(ProcessStateCollection.NAME)] + public sealed class UsageTests + { + private static readonly string nl = Environment.NewLine; + + /// + /// GetOptNet named the program after the entry assembly's file, and + /// Assembly.Location is "" in a single-file executable, so every + /// release threw instead of printing usage: "sdlna --help" printed + /// nothing, and an unknown option ended in an unhandled + /// ArgumentException. An assembly loaded from bytes has no Location + /// either, so as the entry assembly it stands in for a release build. + /// + [Fact] + public void UsageIsPrintedWhenTheProgramHasNoFile() + { + var fileless = Assembly.Load(File.ReadAllBytes(typeof (Options).Assembly.Location)); + Assert.Equal("", fileless.Location); + + var entry = Assembly.GetEntryAssembly(); + var originalOut = Console.Out; + var output = new StringWriter(); + Assembly.SetEntryAssembly(fileless); + Console.SetOut(output); + try { + new Options().PrintUsage(); + } + finally { + Console.SetOut(originalOut); + Assembly.SetEntryAssembly(entry); + } + + var usage = output.ToString(); + Assert.StartsWith($"Usage: sdlna [OPTION] [...] Directory Directory ...{nl}{nl}Options:{nl}", usage); + Assert.Contains($"{nl} -?, --help ", usage); + Assert.EndsWith($"see 'sdlna --server help'.{nl}", usage); + } + + /// + /// Options rebuilds the option list that GetOptNet keeps private. Apart + /// from the program's name, the text must stay what GetOptNet shows, so + /// the two can't drift apart when options change. + /// + [Theory] + [InlineData(80, true, true)] + [InlineData(20, true, true)] + [InlineData(40, true, true)] + [InlineData(120, true, true)] + [InlineData(200, true, true)] + [InlineData(80, false, true)] + [InlineData(80, true, false)] + public void UsageLooksAsGetOptNetShowsIt(int width, bool fixedWidthFont, bool introAndEpilogue) + { + // GetOptNet upper-cases help variables in the current UI culture, + // which turns "file" into "FİLE" in Turkish. Options doesn't. + var culture = CultureInfo.CurrentCulture; + var uiCulture = CultureInfo.CurrentUICulture; + CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; + CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture; + try { + var options = new Options(); + foreach (var category in new[] {HelpCategory.Basic, HelpCategory.Advanced}) { + // GetOptNet names the program after the test host. + var expected = Regex.Replace( + options.AssembleGetOptNetUsage(width, category, fixedWidthFont, introAndEpilogue), + @"^Usage: \S+ ", "Usage: sdlna "); + Assert.Equal(expected, options.AssembleUsage(width, category, fixedWidthFont, introAndEpilogue)); + } + } + finally { + CultureInfo.CurrentCulture = culture; + CultureInfo.CurrentUICulture = uiCulture; + } + } + } +} From 20d410a81d48c8c4bb9cfa488554c7d4168b6e26 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Thu, 17 Sep 2026 00:24:02 -0500 Subject: [PATCH 36/37] Read -? as help, and exit with status 2 for usage errors Two problems noted in the previous commit, both in framework-dependent builds too: "sdlna -?" never printed help, although usage lists "-?, --help", and an unknown or invalid option exited with status 0. GetOptNet 4.0.8 reads an argument as short options only when it matches ^\s*-([\w\d].*?)\s*$, so a letter or digit must follow the dash. "-?" was therefore a positional parameter, a folder to serve: "sdlna -?" started the HTTP server and SSDP, logged "Mounting FileServer for -? (1)", then failed with "The directory name '.../-?' does not exist" (an unhandled exception in Debug builds, status 134). "-h" worked. GetOptNet registers '?' all the same, so only a group such as "-d?" reached it. Main now parses with Options.ParseCommandLine (sdlna/OptionsParsing.cs), which replaces "-?" with "--help" wherever GetOptNet would have taken it for a folder, before calling GetOptNet's Parse: - Not after "--", after which GetOptNet reads every argument as a folder, so "sdlna -- -?" still serves a folder named "-?". - Not as the value of a short option, so "-n -?" still names the server "-?". GetOptNet gives the next argument to an option that ends its group and takes a value ("-n", "-dn"). The translation does the same, reading the short names of the non-flag options from the attributes GetOptNet reads. The walk over Options' fields and properties is now shared with OptionsUsage. - "/?" is replaced too, on Windows only: Windows programs read it as help, and no Windows folder can be named "?". Elsewhere "/?" is a path like any other, and Options accepts only dash prefixes. The alternative was to advertise 'h' as the short option instead. That changes the usage text and the Readme, and "-?", the spelling many Windows and other users try first, would still be served as a folder and fail confusingly. The help output is unchanged; "-?" now prints exactly what "--help" prints. Main's GetOptException handler printed the error and the usage but never set Environment.ExitCode, so scripts and service managers took a mistyped option for success. It now sets 2, the status "--server" misuse already exits with. Status 1 stays for failures: an invalid configuration file or, in Release builds, any unexpected exception. Nothing depended on status 0: the release smoke test (.github/smoke/run.sh on master) runs only a valid command line, and the workflow runs sdlna only through it. Trying invalid values found one that still wasn't a usage error. For int values GetOptNet calls int.Parse and wraps its FormatException ("-p abc") or OverflowException ("-p 99999999999") in a ProgrammingErrorException. That exception is meant for mistakes in the options class and isn't a GetOptException, so Debug builds ended with an unhandled exception (status 134), and Release builds printed "Error: The input string 'abc' was not in a correct format." without usage and exited with 1. ParseCommandLine turns those two into a GetOptException, "Invalid value: ", so they print usage and exit with 2 as well. Other ProgrammingErrorExceptions still mean a bug and are not caught. Main is internal now, so tests can run it in-process for command lines that end before serving. The Ctrl+C and SIGTERM handlers, and the Windows console input mode, are now set up after the options that only print something (--help, --version, --license, --list-views, --list-sort-orders), just before serving, so those runs leave no handlers behind in the test host. With the published binary, SIGTERM still stops a server gracefully ("Termination requested", status 0). Tests (tests/CommandLineTests.cs, in the process-state collection): - HelpIsPrintedForEachOfItsNames runs Main with --help, -h and -?. SlashQuestionMarkPrintsHelpOnWindows does the same with /? on Windows and is skipped elsewhere. - SlashQuestionMarkIsHelpOnlyOnWindows and QuestionMarkIsHelpOnlyWhereAnOptionCanBe cover the translation: -? after a folder, after a flag, after an option's value, with spaces around it, after "--", as the value of "-n" and "-dn", after "-nd" (whose value is "d") and after "-n --" (whose value is "--"). - QuestionMarkAfterAShortOptionIsReadAsGetOptNetReadsDashH checks which short options the translation thinks take a value against GetOptNet itself: for every letter and digit that names an option, "-?" after it must become "--help" exactly when GetOptNet reads "-h" after it as an option. Options added later are checked too. - UsageErrorsExitWithStatus2 runs Main with an unknown long and short option, missing values, a value given to a flag, and rejected values (-t bogus, -p 70000, -i x). AnUnreadableNumberIsAUsageError uses -p abc and --port=99999999999. Each must print "Error: ..." and the usage, and exit with 2. - tests/Support/ProgramRunner.cs runs Main with the console captured and returns the exit code it set, then restores the test host's. The console capture moved from ServerCommandRunner to CommandResult.Capture, which both use. Each part of the fix was reverted in turn, and each revert fails tests. Without the status: the 10 usage error cases. Without the translation: the -? cases (Main then starts a server and throws, as the bug did). Treating every short option as a flag, or every one as taking a value, or reading options after "--": the translation tests. Without the conversion: the unreadable numbers. Readme.md names -h, -? and, on Windows, /? beside --help, and documents status 2. AGENTS.md mentions ParseCommandLine and status 2 in the request flow, lists ProgramRunner among the helpers, and adds a trap about the command-line arguments GetOptNet misreads. Checked with a single-file osx-arm64 publish (self-contained, untrimmed): -?, -h and --help print the same usage and exit with 0, "-d -?" prints usage, and "-n -? --list-sort-orders" lists the sort orders. --bogus, -t bogus, -p abc and -p 99999999999 print the error and usage and exit with 2. --version still works. dotnet build: zero warnings. dotnet test, Debug and Release: 152 tests, 148 passed, 4 skipped (long paths, case-sensitive file system, the Windows hidden attribute and the new Windows-only /? test, all platform-dependent on macOS). Co-Authored-By: Claude Opus 5 --- AGENTS.md | 18 ++- Readme.md | 4 +- sdlna/OptionsParsing.cs | 121 +++++++++++++++++ sdlna/OptionsUsage.cs | 11 +- sdlna/Program.cs | 48 ++++--- tests/CommandLineTests.cs | 191 +++++++++++++++++++++++++++ tests/Support/ProgramRunner.cs | 29 ++++ tests/Support/ServerCommandRunner.cs | 37 ++++-- 8 files changed, 414 insertions(+), 45 deletions(-) create mode 100644 sdlna/OptionsParsing.cs create mode 100644 tests/CommandLineTests.cs create mode 100644 tests/Support/ProgramRunner.cs diff --git a/AGENTS.md b/AGENTS.md index 0530ce71..804cf8ea 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -79,9 +79,11 @@ Management; `PackageReference` items in projects carry no `Version`). 1. `sdlna/Program.cs` `Main` hands `--server ...` to `ServerCommand.Run`, which edits the configuration file and exits. Otherwise it parses - `Options`. With folders it builds one ad-hoc `FileServer`; without, - `ChooseConfiguredServers` either returns the configuration file's servers - (one `FileServer` each) or falls back to serving the current directory. + `Options` (`ParseCommandLine`); an invalid command line prints the error + and usage and exits with 2. With folders it builds one ad-hoc + `FileServer`; without, `ChooseConfiguredServers` either returns the + configuration file's servers (one `FileServer` each) or falls back to + serving the current directory. 2. Every `FileServer` is registered with a single `HttpServer` (`server/Http`), which mounts it at `/mm-N/` as a `MediaMount` (`server/Handlers`). `SsdpHandler` announces each mount over UDP multicast @@ -165,6 +167,8 @@ runs it. and reads back what was written. - `ServerCommandRunner` runs `--server` commands and captures their output and exit code. + - `ProgramRunner` does the same for `Program.Main`, for command lines that + end before serving (`--help`, an invalid option); others start a server. - `DlnaTestServer` and `DlnaClient` host file servers on a real `HttpServer` and talk to it with SOAP, choosing the User-Agent and the local address each request connects through. @@ -205,6 +209,14 @@ Each of these has broken something before. too: GetOptNet's `AssembleUsage` names the program after the entry assembly's file and throws there, so `sdlna/OptionsUsage.cs` replaces it, and `UsageTests` runs the usage with a file-less entry assembly. +- **GetOptNet misreads parts of the command line.** It reads short options + only when a letter or digit follows the dash, so `-?` was taken for a + folder, and it reports a number it can't read (`-p abc`) as a + `ProgrammingErrorException` rather than a `GetOptException`. + `Options.ParseCommandLine` (`sdlna/OptionsParsing.cs`) handles both; parse + through it rather than `Parse`. To leave `-?` alone where it is a value + (`-n -?`), it decides itself which short options take the next argument, + and `CommandLineTests` holds that to GetOptNet's own reading. - **`Environment.GetFolderPath` returns `""` for a folder that doesn't exist**, such as the home folder of a service account. Pass `Environment.SpecialFolderOption.DoNotVerify` when you need the path, and diff --git a/Readme.md b/Readme.md index 74e8f26a..4a83ebf6 100644 --- a/Readme.md +++ b/Readme.md @@ -79,7 +79,9 @@ instead, exactly as `sdlna .` would, and prints a warning explaining how to save servers. A configuration file that exists but is invalid is reported as an error rather than skipped. -The options split accordingly. `sdlna --help` lists them all. +The options split accordingly. `sdlna --help` lists them all, as do `-h`, +`-?` and, on Windows, `/?`. An unknown option or an invalid value prints the +error and that list, and exits with status 2. | Option | With folders, or no servers configured | Configured servers | |---|---|---| diff --git a/sdlna/OptionsParsing.cs b/sdlna/OptionsParsing.cs new file mode 100644 index 00000000..f4a6d7ac --- /dev/null +++ b/sdlna/OptionsParsing.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using NMaier.GetOptNet; + +namespace NMaier.SimpleDlna +{ + internal partial class Options + { + /// + /// GetOptNet's pattern for short options (regDashesShort in its + /// GetOpt.cs): a dash, a letter or digit, then more options of the + /// group or a value. An argument that matches neither this nor a long + /// option is a parameter. + /// + private static readonly Regex shortArguments = + new Regex(@"^\s*-([\w\d].*?)\s*$"); + + /// + /// Parses the command line, working around two of GetOptNet's + /// failures. + /// + /// + /// "-?" is read as --help; see . + /// And GetOptNet reports a number it can't read ("-p abc", or one too + /// large for an int) as a ProgrammingErrorException, which is meant for + /// mistakes in the options class, instead of a GetOptException. So + /// Main didn't take it for a usage error: Debug builds ended with an + /// unhandled exception, and Release builds exited with status 1 + /// without printing usage. + /// + /// The command line is invalid. + internal void ParseCommandLine(IReadOnlyList args, bool windows) + { + try { + Parse(TranslateHelpArguments(args, windows)); + } + catch (ProgrammingErrorException ex) when ( + ex.InnerException is FormatException || + ex.InnerException is OverflowException) { + throw new GetOptException( + $"Invalid value: {ex.InnerException.Message}", ex); + } + } + + /// + /// Replaces "-?" with "--help" where GetOptNet would take it for a + /// folder. + /// + /// + /// Usage lists "-?" as the short form of --help, but GetOptNet reads + /// short options only when a letter or digit follows the dash, so it + /// took "-?" for a folder: "sdlna -?" started the HTTP server, then + /// failed with "The directory name '.../-?' does not exist". After + /// "--" and as the value of a short option ("-n -?"), "-?" stays as it + /// was. With , "/?" is replaced too, as + /// Windows programs read it as help; no Windows folder can be named + /// "?". + /// + internal string[] TranslateHelpArguments(IReadOnlyList args, + bool windows) + { + var valueArguments = ShortArgumentsWithValues(); + var translated = args.ToArray(); + for (var i = 0; i < translated.Length; ++i) { + var arg = translated[i].Trim(); + if (arg == "--") { + break; + } + if (arg == "-?" || windows && arg == "/?") { + translated[i] = "--help"; + continue; + } + // GetOptNet gives the next argument to an option that ends its + // group and takes a value, as in "-n name" or "-dn name". Earlier in + // the group, the option takes the rest of the group instead. + var match = shortArguments.Match(arg); + if (match.Success) { + var group = match.Groups[1].Value; + if (group.IndexOfAny(valueArguments) == group.Length - 1) { + ++i; + } + } + } + return translated; + } + + /// + /// The short names of the options that take a value: all but the + /// flags, since Options has no counted options. + /// + private char[] ShortArgumentsWithValues() + { + return OptionMembers() + .Where(m => m.Type != typeof (bool) && + m.Member.IsDefined(typeof (ArgumentAttribute))) + .SelectMany(m => m.Member.GetCustomAttributes() + .Select(a => a.Arg) + .Concat(m.Member.GetCustomAttributes() + .Select(a => a.Alias))) + .ToArray(); + } + + /// + /// The fields and properties GetOptNet reads options and parameters + /// from, with their types. + /// + private IEnumerable<(MemberInfo Member, Type Type)> OptionMembers() + { + const BindingFlags FLAGS = + BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance; + var type = GetType(); + return type.GetFields(FLAGS) + .Select(f => ((MemberInfo)f, f.FieldType)) + .Concat(type.GetProperties(FLAGS) + .Select(p => ((MemberInfo)p, p.PropertyType))); + } + } +} diff --git a/sdlna/OptionsUsage.cs b/sdlna/OptionsUsage.cs index f0549f77..85bebc4e 100644 --- a/sdlna/OptionsUsage.cs +++ b/sdlna/OptionsUsage.cs @@ -133,18 +133,9 @@ internal string AssembleGetOptNetUsage(int width, HelpCategory category, private List<(string ArgText, string HelpText)> UsageEntries( HelpCategory category) { - const BindingFlags FLAGS = - BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance; - var type = GetType(); - var members = type.GetFields(FLAGS).Cast() - .Concat(type.GetProperties(FLAGS)); - var options = new List<(string SortName, string ArgText, string HelpText)>(); (string ArgText, string HelpText)? parameters = null; - foreach (var member in members) { - var memberType = member is FieldInfo field - ? field.FieldType - : ((PropertyInfo)member).PropertyType; + foreach (var (member, memberType) in OptionMembers()) { var elementType = memberType.IsArray ? memberType.GetElementType() : memberType; diff --git a/sdlna/Program.cs b/sdlna/Program.cs index 5b1009e4..64267ed8 100644 --- a/sdlna/Program.cs +++ b/sdlna/Program.cs @@ -188,7 +188,12 @@ void PrintGroup(string heading, bool filter) Console.WriteLine("than 50 of them; no-cascade keeps them all at the top."); } - private static void Main(string[] args) + /// + /// Exits with status 0, 1 for a failure, or 2 for a usage error. + /// Internal for tests, which run the command lines that end before + /// serving. + /// + internal static void Main(string[] args) { Console.WriteLine(); if (args.Length > 0 && args[0] == "--server") { @@ -203,22 +208,7 @@ private static void Main(string[] args) var options = new Options(); try { - // On Windows this changes the console's input mode, and throws when - // standard input is not a console: a background job, a scheduled task, - // a service wrapper. Ctrl+C can't arrive through such an input anyway. - if (!Console.IsInputRedirected) { - Console.TreatControlCAsInput = false; - } - Console.CancelKeyPress += CancelKeyPressed; - try { - terminateRegistration = PosixSignalRegistration.Create( - PosixSignal.SIGTERM, TerminateRequested); - } - catch (PlatformNotSupportedException) { - // Ctrl+C still works. - } - - options.Parse(args); + options.ParseCommandLine(args, OperatingSystem.IsWindows()); if (options.ShowHelp) { options.PrintUsage(); return; @@ -239,6 +229,26 @@ private static void Main(string[] args) ListOrders(); return; } + + // The shutdown handlers are set up only now that sdlna is going to + // serve, so the command lines above leave nothing behind when tests + // run them in-process. + // + // On Windows this changes the console's input mode, and throws when + // standard input is not a console: a background job, a scheduled task, + // a service wrapper. Ctrl+C can't arrive through such an input anyway. + if (!Console.IsInputRedirected) { + Console.TreatControlCAsInput = false; + } + Console.CancelKeyPress += CancelKeyPressed; + try { + terminateRegistration = PosixSignalRegistration.Create( + PosixSignal.SIGTERM, TerminateRequested); + } + catch (PlatformNotSupportedException) { + // Ctrl+C still works. + } + if (options.Directories.Length == 0) { var config = ChooseConfiguredServers(options, Console.Error); if (config != null) { @@ -313,6 +323,10 @@ private static void Main(string[] args) catch (GetOptException ex) { Console.Error.WriteLine("Error: {0}\n\n", ex.Message); options.PrintUsage(); + // Status 2 is a usage error, as for --server. This used to exit with + // 0, so scripts and service managers took a mistyped option for + // success. + Environment.ExitCode = 2; } catch (ConfigurationException ex) { Console.Error.WriteLine("Error: {0}", ex.Message); diff --git a/tests/CommandLineTests.cs b/tests/CommandLineTests.cs new file mode 100644 index 00000000..3ec8c7e5 --- /dev/null +++ b/tests/CommandLineTests.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NMaier.GetOptNet; +using NMaier.SimpleDlna.Tests.Support; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// How "sdlna" without --server reads its command line: the names of + /// --help, and what an invalid command line does. + /// + [Collection(ProcessStateCollection.NAME)] + public sealed class CommandLineTests + { + private static readonly string nl = Environment.NewLine; + + private static Options Parse(bool windows, params string[] args) + { + var options = new Options(); + options.ParseCommandLine(args, windows); + return options; + } + + /// + /// Usage lists "-?" as the short form of --help, but GetOptNet reads + /// short options only when a letter or digit follows the dash. So + /// "sdlna -?" took "-?" for a folder, started the HTTP server and + /// failed with "The directory name '.../-?' does not exist", in Debug + /// builds as an unhandled exception. + /// + [Theory] + [InlineData("--help")] + [InlineData("-h")] + [InlineData("-?")] + public void HelpIsPrintedForEachOfItsNames(string help) + { + var result = ProgramRunner.Run(help); + + Assert.True(result.ExitCode == 0, result.ToString()); + Assert.Equal("", result.Error); + Assert.StartsWith($"{nl}Usage: sdlna ", result.Output); + Assert.Contains($"{nl} -?, --help ", result.Output); + } + + [Fact] + public void SlashQuestionMarkPrintsHelpOnWindows() + { + Assert.SkipUnless(OperatingSystem.IsWindows(), "Elsewhere, /? is a folder"); + + var result = ProgramRunner.Run("/?"); + + Assert.True(result.ExitCode == 0, result.ToString()); + Assert.StartsWith($"{nl}Usage: sdlna ", result.Output); + } + + /// + /// No Windows folder can be named "?", and Windows programs read "/?" + /// as help. Elsewhere it is a folder like any other. + /// + [Fact] + public void SlashQuestionMarkIsHelpOnlyOnWindows() + { + Assert.True(Parse(true, "/?").ShowHelp); + + var options = Parse(false, "/?"); + Assert.False(options.ShowHelp); + Assert.Equal("/?", Assert.Single(options.Directories).ToString()); + } + + /// + /// "-?" is help wherever GetOptNet would read an option, and only + /// there: after "--" it is a folder, and after a short option that + /// takes a value, it is that value. + /// + [Fact] + public void QuestionMarkIsHelpOnlyWhereAnOptionCanBe() + { + Assert.True(Parse(false, "Videos", "-?").ShowHelp); + Assert.True(Parse(false, "-d", "-?").ShowHelp); + Assert.True(Parse(false, "-l", "DEBUG", "-?").ShowHelp); + Assert.True(Parse(false, " -? ").ShowHelp); + + var afterDashes = Parse(false, "--", "-?"); + Assert.False(afterDashes.ShowHelp); + Assert.Equal("-?", Assert.Single(afterDashes.Directories).ToString()); + + var name = Parse(false, "-n", "-?"); + Assert.False(name.ShowHelp); + Assert.Equal("-?", name.FriendlyName); + + var grouped = Parse(false, "-dn", "-?"); + Assert.False(grouped.ShowHelp); + Assert.True(grouped.DescendingOrder); + Assert.Equal("-?", grouped.FriendlyName); + + // -n takes the rest of its group, "d", so "-?" is an option again. + var nameInGroup = Parse(false, "-nd", "-?"); + Assert.True(nameInGroup.ShowHelp); + Assert.Equal("d", nameInGroup.FriendlyName); + + // "--" is the name here, not the end of the options. + var dashesAsName = Parse(false, "-n", "--", "-?"); + Assert.True(dashesAsName.ShowHelp); + Assert.Equal("--", dashesAsName.FriendlyName); + } + + /// + /// Which short options take the next argument is decided apart from + /// GetOptNet, so every short name is held to GetOptNet's own reading + /// of "-h" after it, including options added later. + /// + [Fact] + public void QuestionMarkAfterAShortOptionIsReadAsGetOptNetReadsDashH() + { + var flags = new List(); + var withValues = new List(); + var names = Enumerable.Range('a', 26) + .Concat(Enumerable.Range('A', 26)) + .Concat(Enumerable.Range('0', 10)) + .Select(c => "-" + (char)c); + foreach (var name in names) { + bool helpIsAnOption; + try { + var options = new Options(); + options.Parse(new[] {name, "-h"}); + helpIsAnOption = options.ShowHelp; + } + catch (UnknownAttributeException) { + continue; + } + catch (Exception ex) when ( + ex is GetOptException || ex is ProgrammingErrorException) { + // The option took "-h" as its value, and rejected it. + helpIsAnOption = false; + } + + (helpIsAnOption ? flags : withValues).Add(name); + Assert.Equal( + new[] {name, helpIsAnOption ? "--help" : "-?"}, + new Options().TranslateHelpArguments(new[] {name, "-?"}, false)); + } + + Assert.Contains("-d", flags); + Assert.Contains("-h", flags); + Assert.Contains("-n", withValues); + Assert.Contains("-p", withValues); + } + + /// + /// An unknown option, or an invalid value, printed the error and usage + /// and then exited with status 0, as if sdlna had run. + /// + [Theory] + [InlineData("There is no argument with the name \"--bogus\"", "--bogus")] + [InlineData("There is no argument with the name \"-z\"", "-z")] + [InlineData("Omitted value for short argument \"n\"", "-n")] + [InlineData("Omitted value for argument \"port\"", "--port")] + [InlineData("Argument \"help\" does not except a value", "--help=yes")] + [InlineData("Wrong value type for argument \"t\"", "-t", "bogus")] + [InlineData("Port must be between", "-p", "70000")] + [InlineData("Not a valid IP address: x", "-i", "x")] + public void UsageErrorsExitWithStatus2(string error, params string[] args) + { + var result = ProgramRunner.Run(args); + + Assert.True(result.ExitCode == 2, result.ToString()); + Assert.StartsWith($"Error: {error}", result.Error); + Assert.StartsWith($"{nl}Usage: sdlna ", result.Output); + } + + /// + /// GetOptNet reports a number it can't read as a mistake in the + /// options class, not as a GetOptException, so "sdlna -p abc" ended + /// with an unhandled exception in Debug builds, and exited with + /// status 1 without usage in Release builds. + /// + [Theory] + [InlineData("-p", "abc")] + [InlineData("--port=99999999999")] + public void AnUnreadableNumberIsAUsageError(params string[] args) + { + var result = ProgramRunner.Run(args); + + Assert.True(result.ExitCode == 2, result.ToString()); + Assert.StartsWith("Error: Invalid value: ", result.Error); + Assert.StartsWith($"{nl}Usage: sdlna ", result.Output); + } + } +} diff --git a/tests/Support/ProgramRunner.cs b/tests/Support/ProgramRunner.cs new file mode 100644 index 00000000..104c9eb7 --- /dev/null +++ b/tests/Support/ProgramRunner.cs @@ -0,0 +1,29 @@ +using System; + +namespace NMaier.SimpleDlna.Tests.Support +{ + /// + /// Runs sdlna's Main in-process with the console captured, and returns + /// the exit code it set. Only for command lines that end before serving, + /// such as --help or an invalid option; anything else starts a server. + /// Use only from tests in . + /// + internal static class ProgramRunner + { + public static CommandResult Run(params string[] args) + { + return CommandResult.Capture(() => + { + var originalExitCode = Environment.ExitCode; + Environment.ExitCode = 0; + try { + Program.Main(args); + return Environment.ExitCode; + } + finally { + Environment.ExitCode = originalExitCode; + } + }); + } + } +} diff --git a/tests/Support/ServerCommandRunner.cs b/tests/Support/ServerCommandRunner.cs index e7225b63..cd356cb9 100644 --- a/tests/Support/ServerCommandRunner.cs +++ b/tests/Support/ServerCommandRunner.cs @@ -11,19 +11,11 @@ internal sealed class CommandResult public string Output; - public override string ToString() - { - return $"exit {ExitCode}\n--- stdout:\n{Output}\n--- stderr:\n{Error}"; - } - } - - /// - /// Runs "sdlna --server ..." in-process with the console captured. Use - /// only from tests in . - /// - internal static class ServerCommandRunner - { - public static CommandResult Run(params string[] args) + /// + /// Runs , which returns the exit code, with + /// the console captured. + /// + public static CommandResult Capture(Func command) { var originalOut = Console.Out; var originalError = Console.Error; @@ -32,7 +24,7 @@ public static CommandResult Run(params string[] args) Console.SetOut(output); Console.SetError(error); try { - var exitCode = ServerCommand.Run(args); + var exitCode = command(); return new CommandResult { ExitCode = exitCode, @@ -45,5 +37,22 @@ public static CommandResult Run(params string[] args) Console.SetError(originalError); } } + + public override string ToString() + { + return $"exit {ExitCode}\n--- stdout:\n{Output}\n--- stderr:\n{Error}"; + } + } + + /// + /// Runs "sdlna --server ..." in-process with the console captured. Use + /// only from tests in . + /// + internal static class ServerCommandRunner + { + public static CommandResult Run(params string[] args) + { + return CommandResult.Capture(() => ServerCommand.Run(args)); + } } } From 70c1b89fcbe98cc5cad1dce7d597487ab8718e21 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Thu, 17 Sep 2026 00:37:36 -0500 Subject: [PATCH 37/37] List a file once when the watcher reports it again The release run for 74d522b (run 35186240720) failed on the macOS runner only: five HttpServerTests found each file listed twice, with the same id ("Assert.Single() Failure: The collection contained 2 items"). The release was withheld. Linux and Windows passed, as did macOS in earlier runs and locally. FileServer.Load enables its FileSystemWatchers whether or not rescanning is on, and a Created event goes to HandleFileAdded. That method looked the file up, logged "Did find an existing ..." when it was already listed, and then added it anyway. On macOS a new watcher also reports files created just before it started, and the tests write their files right before mounting, so sometimes the watcher added files the scan had already listed. Outside the tests the same happens whenever the watcher reports a listed file again: a file replaced in place, or an event racing the scan. This predates the migration. HandleFileAdded now removes the listed entry before adding the new one, as the Changed case already does through HandleFileDeleted, so the file is listed once and with its current metadata. The folder check now comes first, so nothing is removed when there is no folder to add to. OnChanged, the watcher's handler, is now internal so tests can deliver events. Tests (tests/FileServerTests.cs): - WatcherReportingAListedFileDoesNotListItTwice delivers two Created events for a file the server already listed: it is listed once. - FileCreatedAfterLoadingIsListed creates a file after loading and delivers its Created event: both files are listed, once each. Without the fix both fail. The second fails even though it delivers only one event, because macOS's watcher reported the new file as well ("clip" listed twice), which is the race the release run hit. dotnet build: zero warnings. dotnet test: 154 tests, 150 passed, 4 skipped on macOS. Co-Authored-By: Claude Opus 5 --- fsserver/FileServer.cs | 13 +++++--- tests/FileServerTests.cs | 72 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 tests/FileServerTests.cs diff --git a/fsserver/FileServer.cs b/fsserver/FileServer.cs index d1d78634..192b6bfc 100644 --- a/fsserver/FileServer.cs +++ b/fsserver/FileServer.cs @@ -173,13 +173,18 @@ private bool HandleFileAdded(string fullPath) var info = new FileInfo(fullPath); var item = ids.GetItemByPath(info.FullName) as IMediaResource; var folder = ids.GetItemByPath(info.Directory?.FullName) as PlainFolder; - if (item != null) { - DebugFormat("Did find an existing {0}", info.FullName); - } if (folder == null) { DebugFormat("Did not find folder for {0}", info.Directory?.FullName); return false; } + if (item != null) { + // The file is listed already: replaced in place, or reported by the + // watcher although the scan found it (on macOS a new watcher reports + // files created just before it started). Replace the entry; adding + // another listed the file twice. + DebugFormat("Replacing the existing {0}", info.FullName); + folder.RemoveResource(item); + } item = GetFile(folder, info); if (item == null) { DebugFormat("Failed to create new item for {0} - {1}", folder.Path, info.FullName); @@ -207,7 +212,7 @@ private bool HandleFileDeleted(string fullPath) } } - private void OnChanged(object source, FileSystemEventArgs e) + internal void OnChanged(object source, FileSystemEventArgs e) { try { if (store != null && store.IsStoreFile(e.FullPath, icomparer)) { diff --git a/tests/FileServerTests.cs b/tests/FileServerTests.cs new file mode 100644 index 00000000..763c3448 --- /dev/null +++ b/tests/FileServerTests.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; +using System.Linq; +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Tests.Support; +using Xunit; + +namespace NMaier.SimpleDlna.Tests +{ + /// + /// How a file server's listing follows the file system watcher. + /// + public sealed class FileServerTests : IDisposable + { + private readonly TempDirectory media = new TempDirectory(); + + public void Dispose() + { + media.Dispose(); + } + + private FileServer Load() + { + var server = TestFileServer.Create(media.Info); + server.Rescanning = false; + server.Load(); + return server; + } + + private static string[] Listed(FileServer server) + { + var root = (IMediaFolder)server.GetItem(Identifiers.GENERAL_ROOT); + return root.ChildItems.Select(i => i.Title).OrderBy(t => t, StringComparer.Ordinal).ToArray(); + } + + private void Created(FileServer server, string name) + { + server.OnChanged(null, new FileSystemEventArgs(WatcherChangeTypes.Created, media.Path, name)); + } + + /// + /// Regression: a Created event for a file the server already listed + /// added it a second time. On macOS a watcher reports files created just + /// before it started, so files written right before a server loaded were + /// sometimes listed twice (seen in CI). + /// + [Fact] + public void WatcherReportingAListedFileDoesNotListItTwice() + { + media.WriteFile("film.mkv"); + using (var server = Load()) { + Created(server, "film.mkv"); + Created(server, "film.mkv"); + + Assert.Equal(new[] {"film"}, Listed(server)); + } + } + + [Fact] + public void FileCreatedAfterLoadingIsListed() + { + media.WriteFile("film.mkv"); + using (var server = Load()) { + media.WriteFile("clip.mkv"); + Created(server, "clip.mkv"); + + Assert.Equal(new[] {"clip", "film"}, Listed(server)); + } + } + } +}