diff --git a/.gitignore b/.gitignore index 3fa9123..ec27914 100644 --- a/.gitignore +++ b/.gitignore @@ -189,3 +189,4 @@ ModelManifest.xml .vs /Sunfish/ShareWeb/TestFS +ShareWeb diff --git a/Sunfish.sln b/Sunfish.sln new file mode 100644 index 0000000..aa67b2e --- /dev/null +++ b/Sunfish.sln @@ -0,0 +1,22 @@ + +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}") = "Sunfish", "Sunfish\Sunfish.csproj", "{5511BE4E-6AE1-479B-B5CD-5A20DC4C13F7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5511BE4E-6AE1-479B-B5CD-5A20DC4C13F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5511BE4E-6AE1-479B-B5CD-5A20DC4C13F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5511BE4E-6AE1-479B-B5CD-5A20DC4C13F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5511BE4E-6AE1-479B-B5CD-5A20DC4C13F7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Sunfish/Configurator/ConfigurationBool.cs b/Sunfish/Configurator/ConfigurationBool.cs new file mode 100644 index 0000000..737ef0a --- /dev/null +++ b/Sunfish/Configurator/ConfigurationBool.cs @@ -0,0 +1,29 @@ +using System.Drawing; +using System.Windows.Forms; + +namespace DolphinWebXplorer2.Configurator +{ + public class ConfigurationBool : ConfigurationElement + { + public ConfigurationBool(string id, string label) : base(id, label) + { + } + + public override bool isEmpty(Control c) + { + throw new System.NotImplementedException(); + } + + public override object getValue(Control c) + { + CheckBox cb = c as CheckBox; + if (cb == null) + return null; + return cb.Checked; + } + + public bool DefaultValue { get; set; } + + public override Color UIMandatoryColor => throw new System.NotImplementedException(); + } +} diff --git a/Sunfish/Configurator/ConfigurationElement.cs b/Sunfish/Configurator/ConfigurationElement.cs new file mode 100644 index 0000000..545c8d1 --- /dev/null +++ b/Sunfish/Configurator/ConfigurationElement.cs @@ -0,0 +1,25 @@ +using System.Drawing; +using System.Windows.Forms; + +namespace DolphinWebXplorer2.Configurator +{ + public abstract class ConfigurationElement + { + protected ConfigurationElement(string id, string label) + { + Id = id; + Label = label; + } + + public abstract bool isEmpty(Control c); + + public abstract object getValue(Control c); + + public string Id { get; } + public string Label { get; } + public string Tooltip { get; set; } + public bool Mandatory { get; set; } + + public abstract Color UIMandatoryColor { get; } + } +} diff --git a/Sunfish/Configurator/ConfigurationMessage.cs b/Sunfish/Configurator/ConfigurationMessage.cs new file mode 100644 index 0000000..4a9fea0 --- /dev/null +++ b/Sunfish/Configurator/ConfigurationMessage.cs @@ -0,0 +1,34 @@ +using System.Drawing; +using System.Windows.Forms; + +namespace DolphinWebXplorer2.Configurator +{ + class ConfigurationMessage : ConfigurationElement + { + public enum MessageType + { + INFO, WARNING, ERROR + } + + public ConfigurationMessage(MessageType t, string message) : base(null, null) + { + Type = t; + Message = message; + } + + public override bool isEmpty(Control c) + { + throw new System.NotImplementedException(); + } + + public override object getValue(Control c) + { + return null; + } + + public MessageType Type { get; } + public string Message { get; } + + public override Color UIMandatoryColor => throw new System.NotImplementedException(); + } +} diff --git a/Sunfish/Configurator/ConfigurationScreen.cs b/Sunfish/Configurator/ConfigurationScreen.cs new file mode 100644 index 0000000..9e564dd --- /dev/null +++ b/Sunfish/Configurator/ConfigurationScreen.cs @@ -0,0 +1,14 @@ +namespace DolphinWebXplorer2.Configurator +{ + public class ConfigurationScreen + { + + public delegate void AdvancedEditing(SunfishServiceConfiguration ssc); + //public delegate void AdvancedWebEditing(SunfishServiceConfiguration ssc, ); + + public ConfigurationElement[] Elements; + + public AdvancedEditing Advanced { get; set; } + //public AdvancedWebEditing AdvancedWeb{get;set;} + } +} diff --git a/Sunfish/Configurator/ConfigurationString.cs b/Sunfish/Configurator/ConfigurationString.cs new file mode 100644 index 0000000..56f25fb --- /dev/null +++ b/Sunfish/Configurator/ConfigurationString.cs @@ -0,0 +1,35 @@ +using System.Drawing; +using System.Windows.Forms; + +namespace DolphinWebXplorer2.Configurator +{ + public class ConfigurationString : ConfigurationElement + { + public ConfigurationString(string id, string label) : base(id, label) + { + } + + public override bool isEmpty(Control c) + { + TextBox tb = c as TextBox; + if (tb == null) + return false; + return string.IsNullOrWhiteSpace(tb.Text); + } + + public override object getValue(Control c) + { + TextBox tb = c as TextBox; + if (tb == null) + return null; + return tb.Text; + } + + public string DefaultValue { get; set; } + public bool IsPassword { get; set; } + public bool IsDirectoiryPath { get; set; } + public bool IsFilePath { get; set; } + + public override Color UIMandatoryColor => Color.LightGoldenrodYellow; + } +} diff --git a/Sunfish/Configurator/SunfishServiceConfigurator.cs b/Sunfish/Configurator/SunfishServiceConfigurator.cs new file mode 100644 index 0000000..2f0dbca --- /dev/null +++ b/Sunfish/Configurator/SunfishServiceConfigurator.cs @@ -0,0 +1,18 @@ +using System; +using System.Reflection; + +namespace DolphinWebXplorer2.Configurator +{ + public abstract class SunfishServiceConfigurator + { + internal static SunfishServiceConfigurator GetConfiguratorForService(Type t) + { + DefineConfigurator cfgr = t.GetCustomAttribute(); + if (cfgr == null) + return null; + return cfgr.Instantiate(); + } + + internal protected abstract ConfigurationScreen GetConfigurationScreen(); + } +} diff --git a/Sunfish/DefineConfigurator.cs b/Sunfish/DefineConfigurator.cs new file mode 100644 index 0000000..2a86774 --- /dev/null +++ b/Sunfish/DefineConfigurator.cs @@ -0,0 +1,22 @@ +using DolphinWebXplorer2.Configurator; +using System; + +namespace DolphinWebXplorer2 +{ + [AttributeUsage(AttributeTargets.Class)] + public class DefineConfigurator : Attribute + { + public DefineConfigurator(Type configuratorType) + { + ConfiguratorType = configuratorType; + } + + public SunfishServiceConfigurator Instantiate() + { + Type t = ConfiguratorType; + return (SunfishServiceConfigurator)t.GetConstructor(new Type[0]).Invoke(new object[0]); + } + + public Type ConfiguratorType { get; } + } +} diff --git a/Sunfish/DolphinWeb.ico b/Sunfish/DolphinWeb.ico new file mode 100644 index 0000000..8fbcd2b --- /dev/null +++ b/Sunfish/DolphinWeb.ico Binary files differ diff --git a/Sunfish/Extensions.cs b/Sunfish/Extensions.cs new file mode 100644 index 0000000..3a54f9a --- /dev/null +++ b/Sunfish/Extensions.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows.Forms; + +namespace DolphinWebXplorer2 +{ + public static class Extensions + { + public static void Show(this Exception ex) + { + MessageBox.Show(ex.Message, ex.GetType().Name, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + public static void TransferFrom(this Stream s, Stream from) + { + byte[] buf = new byte[524288];// 512Kb + int readed = buf.Length; + while (readed == buf.Length) + { + readed = from.Read(buf, 0, buf.Length); + s.Write(buf, 0, readed); + } + } + + public static void TransferFrom(this Stream s, Stream from, long length) + { + byte[] buf = new byte[Math.Min(524288, length)];// 512Kb + while (length > 0) + { + int toRead = (int)Math.Min(buf.Length, length); + int readed = from.Read(buf, 0, toRead); + if (readed == 0) + throw new IOException("Unexpected EOF"); + s.Write(buf, 0, readed); + length -= readed; + } + } + + public static T GetValue(this Dictionary dict, K key, T def) + { + T value; + if (dict.TryGetValue(key, out value)) + return value; + return def; + } + } +} diff --git a/Sunfish/FServiceConf.Designer.cs b/Sunfish/FServiceConf.Designer.cs new file mode 100644 index 0000000..91c6bfa --- /dev/null +++ b/Sunfish/FServiceConf.Designer.cs @@ -0,0 +1,217 @@ +namespace DolphinWebXplorer2 +{ + partial class FServiceConf + { + /// + /// 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.lbType = new System.Windows.Forms.Label(); + this.cbType = new System.Windows.Forms.ComboBox(); + this.lbName = new System.Windows.Forms.Label(); + this.tbName = new System.Windows.Forms.TextBox(); + this.cbActive = new System.Windows.Forms.CheckBox(); + this.label1 = new System.Windows.Forms.Label(); + this.tbLocation = new System.Windows.Forms.TextBox(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.btOk = new System.Windows.Forms.Button(); + this.btCancel = new System.Windows.Forms.Button(); + this.pScreen = new System.Windows.Forms.Panel(); + this.btAdv = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // lbType + // + this.lbType.AutoSize = true; + this.lbType.Location = new System.Drawing.Point(7, 6); + this.lbType.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.lbType.Name = "lbType"; + this.lbType.Size = new System.Drawing.Size(34, 13); + this.lbType.TabIndex = 0; + this.lbType.Text = "Type:"; + // + // cbType + // + this.cbType.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.cbType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cbType.FormattingEnabled = true; + this.cbType.Location = new System.Drawing.Point(17, 21); + this.cbType.Margin = new System.Windows.Forms.Padding(2); + this.cbType.Name = "cbType"; + this.cbType.Size = new System.Drawing.Size(255, 21); + this.cbType.TabIndex = 1; + this.toolTip1.SetToolTip(this.cbType, "Type of service."); + this.cbType.SelectedIndexChanged += new System.EventHandler(this.cbType_SelectedIndexChanged); + // + // lbName + // + this.lbName.AutoSize = true; + this.lbName.Location = new System.Drawing.Point(8, 50); + this.lbName.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.lbName.Name = "lbName"; + this.lbName.Size = new System.Drawing.Size(38, 13); + this.lbName.TabIndex = 2; + this.lbName.Text = "Name:"; + // + // tbName + // + this.tbName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tbName.BackColor = System.Drawing.Color.LightGoldenrodYellow; + this.tbName.Location = new System.Drawing.Point(17, 65); + this.tbName.Margin = new System.Windows.Forms.Padding(2); + this.tbName.Name = "tbName"; + this.tbName.Size = new System.Drawing.Size(199, 20); + this.tbName.TabIndex = 3; + this.toolTip1.SetToolTip(this.tbName, "Name of the service.\r\n(only for management)"); + // + // cbActive + // + this.cbActive.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.cbActive.AutoSize = true; + this.cbActive.Location = new System.Drawing.Point(223, 67); + this.cbActive.Margin = new System.Windows.Forms.Padding(2); + this.cbActive.Name = "cbActive"; + this.cbActive.Size = new System.Drawing.Size(56, 17); + this.cbActive.TabIndex = 4; + this.cbActive.Text = "Active"; + this.cbActive.UseVisualStyleBackColor = true; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(8, 93); + this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(51, 13); + this.label1.TabIndex = 5; + this.label1.Text = "Location:"; + // + // tbLocation + // + this.tbLocation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tbLocation.BackColor = System.Drawing.Color.LightGoldenrodYellow; + this.tbLocation.Location = new System.Drawing.Point(17, 108); + this.tbLocation.Margin = new System.Windows.Forms.Padding(2); + this.tbLocation.Name = "tbLocation"; + this.tbLocation.Size = new System.Drawing.Size(255, 20); + this.tbLocation.TabIndex = 6; + this.toolTip1.SetToolTip(this.tbLocation, "Document root on the server:\r\nThis works as a virtual directory in the url."); + // + // btOk + // + this.btOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btOk.Location = new System.Drawing.Point(141, 148); + this.btOk.Margin = new System.Windows.Forms.Padding(2); + this.btOk.Name = "btOk"; + this.btOk.Size = new System.Drawing.Size(75, 25); + this.btOk.TabIndex = 7; + this.btOk.Text = "Ok"; + this.btOk.UseVisualStyleBackColor = true; + this.btOk.Click += new System.EventHandler(this.button1_Click); + // + // btCancel + // + this.btCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btCancel.Location = new System.Drawing.Point(225, 148); + this.btCancel.Margin = new System.Windows.Forms.Padding(2); + this.btCancel.Name = "btCancel"; + this.btCancel.Size = new System.Drawing.Size(55, 25); + this.btCancel.TabIndex = 8; + this.btCancel.Text = "Cancel"; + this.btCancel.UseVisualStyleBackColor = true; + // + // pScreen + // + this.pScreen.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.pScreen.Location = new System.Drawing.Point(8, 136); + this.pScreen.Margin = new System.Windows.Forms.Padding(2); + this.pScreen.Name = "pScreen"; + this.pScreen.Size = new System.Drawing.Size(271, 1); + this.pScreen.TabIndex = 9; + // + // btAdv + // + this.btAdv.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btAdv.Location = new System.Drawing.Point(8, 148); + this.btAdv.Margin = new System.Windows.Forms.Padding(2); + this.btAdv.Name = "btAdv"; + this.btAdv.Size = new System.Drawing.Size(111, 25); + this.btAdv.TabIndex = 10; + this.btAdv.Text = "Advanced Settings"; + this.btAdv.UseVisualStyleBackColor = true; + // + // FServiceConf + // + this.AcceptButton = this.btOk; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btCancel; + this.ClientSize = new System.Drawing.Size(287, 180); + this.Controls.Add(this.btAdv); + this.Controls.Add(this.pScreen); + this.Controls.Add(this.btCancel); + this.Controls.Add(this.btOk); + this.Controls.Add(this.tbLocation); + this.Controls.Add(this.label1); + this.Controls.Add(this.cbActive); + this.Controls.Add(this.tbName); + this.Controls.Add(this.lbName); + this.Controls.Add(this.cbType); + this.Controls.Add(this.lbType); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Margin = new System.Windows.Forms.Padding(2); + this.Name = "FServiceConf"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Service"; + this.Load += new System.EventHandler(this.FServiceConf_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label lbType; + private System.Windows.Forms.ComboBox cbType; + private System.Windows.Forms.Label lbName; + private System.Windows.Forms.TextBox tbName; + private System.Windows.Forms.CheckBox cbActive; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox tbLocation; + private System.Windows.Forms.Button btOk; + private System.Windows.Forms.Button btCancel; + private System.Windows.Forms.Panel pScreen; + private System.Windows.Forms.Button btAdv; + } +} \ No newline at end of file diff --git a/Sunfish/FServiceConf.cs b/Sunfish/FServiceConf.cs new file mode 100644 index 0000000..678c523 --- /dev/null +++ b/Sunfish/FServiceConf.cs @@ -0,0 +1,246 @@ +using DolphinWebXplorer2.Configurator; +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace DolphinWebXplorer2 +{ + public partial class FServiceConf : Form + { + private SunfishServiceConfiguration ssc; + private int panelOffset; + + private FServiceConf() + { + InitializeComponent(); + panelOffset = ClientSize.Height - pScreen.Top; + cbType.Items.AddRange(SunfishService.GetTypes()); + } + + public static bool Execute(SunfishServiceConfiguration ssc) + { + using (FServiceConf f = new FServiceConf()) + { + f.ssc = ssc; + f.LoadData(); + return f.ShowDialog() == DialogResult.OK; + } + } + + private void LoadData() + { + if (ssc.Type != null) + for (int i = 0; i < cbType.Items.Count; i++) + { + object o = cbType.Items[i]; + if (o != null && o.ToString() == ssc.Type) + { + cbType.SelectedIndex = i; + break; + } + } + cbActive.Checked = ssc.Enabled; + tbName.Text = ssc.Name; + tbLocation.Text = ssc.Location; + if (string.IsNullOrWhiteSpace(tbName.Text)) + tbName.Text = "new service"; + if (string.IsNullOrWhiteSpace(tbLocation.Text)) + tbLocation.Text = "/nsrv"; + LoadScreen(); + } + + private bool ValidateData() + { + bool valid = true; + if (cbType.SelectedItem == null) + { + valid = false; + lbType.ForeColor = Color.LightCoral; + } + else + lbType.ForeColor = SystemColors.ControlText; + if (string.IsNullOrWhiteSpace(tbName.Text)) + { + valid = false; + tbName.BackColor = Color.LightCoral; + } + else + tbName.BackColor = Color.LightGoldenrodYellow; + if (string.IsNullOrWhiteSpace(tbLocation.Text)) + { + valid = false; + tbLocation.BackColor = Color.LightCoral; + } + else + tbLocation.BackColor = Color.LightGoldenrodYellow; + return valid & ValidateDynamicScreen(); + } + + private void SaveData() + { + ssc.Type = cbType.SelectedItem == null ? null : cbType.SelectedItem.ToString(); + ssc.Enabled = cbActive.Checked; + ssc.Name = tbName.Text; + ssc.Location = tbLocation.Text; + if (ssc.Location.Length > 0 && ssc.Location[0] != '/') + ssc.Location = '/' + ssc.Location; + SaveDynamicScreen(); + } + + #region Dynamic properties + private void AddElementLabel(ConfigurationElement ce, Panel p, ref int y) + { + if (string.IsNullOrEmpty(ce.Label)) + return; + y += 3; + Label l = new Label(); + l.Text = ce.Label; + l.Top = y; + l.AutoSize = true; + p.Controls.Add(l); + y += l.Height + 3; + } + + private void FinishElement(Control c, ConfigurationElement ce, Panel p, ref int y) + { + if (!string.IsNullOrEmpty(ce.Tooltip)) + toolTip1.SetToolTip(c, ce.Tooltip); + c.Top = y; + c.Tag = ce; + p.Controls.Add(c); + y += c.Height + 3; + } + + private void AddElementMessage(ConfigurationMessage ce, Panel p, ref int y) + { + AddElementLabel(ce, p, ref y); + Label c = new Label(); + c.Text = ce.Message; + c.BorderStyle = BorderStyle.FixedSingle; + c.MaximumSize = new Size(p.ClientSize.Width - 28, int.MaxValue); + c.MinimumSize = new Size(c.MaximumSize.Width, 0); + c.Left = 14; + c.AutoSize = true; + FinishElement(c, ce, p, ref y); + switch (ce.Type) + { + case ConfigurationMessage.MessageType.ERROR: + c.BackColor = Color.FromArgb(255, 200, 200); + break; + case ConfigurationMessage.MessageType.INFO: + c.BackColor = Color.FromArgb(255, 255, 255); + break; + case ConfigurationMessage.MessageType.WARNING: + c.BackColor = Color.PaleGoldenrod; + break; + } + } + + private void AddElementString(ConfigurationString ce, Panel p, ref int y) + { + AddElementLabel(ce, p, ref y); + TextBox c = new TextBox(); + c.Text = ssc.GetConf(ce.Id, ce.DefaultValue); + // WARNING: Values for standard DPI + c.Left = 9; + c.Width = p.ClientSize.Width - 16; + if (ce.IsPassword) + c.PasswordChar = '*'; + if (ce.Mandatory) + c.BackColor = ce.UIMandatoryColor; + //TODO: Handle isDirectory and IsFile properties + FinishElement(c, ce, p, ref y); + } + + private void AddElementBool(ConfigurationBool ce, Panel p, ref int y) + { + CheckBox c = new CheckBox(); + c.Text = ce.Label; + c.Checked = ssc.GetConf(ce.Id, ce.DefaultValue); + c.Left = 14; + c.Width = p.ClientSize.Width - 28; + FinishElement(c, ce, p, ref y); + } + + private void LoadScreen() + { + int height = Height; + // Remove all + pScreen.Controls.Clear(); + string type = cbType.SelectedItem == null ? null : cbType.SelectedItem.ToString(); + if (string.IsNullOrEmpty(type)) + { + ClientSize = new Size(ClientSize.Width, pScreen.Top + panelOffset); + btAdv.Visible = false; + return; + } + ConfigurationScreen cs = SunfishService.GetConfigurator(type).GetConfigurationScreen(); + btAdv.Visible = cs.Advanced != null; + // Create new + int y = 0; + foreach (ConfigurationElement ce in cs.Elements) + { + if (ce is ConfigurationMessage) + AddElementMessage((ConfigurationMessage)ce, pScreen, ref y); + else if (ce is ConfigurationString) + AddElementString((ConfigurationString)ce, pScreen, ref y); + else if (ce is ConfigurationBool) + AddElementBool((ConfigurationBool)ce, pScreen, ref y); + } + ClientSize = new Size(ClientSize.Width, y + pScreen.Top + panelOffset + 5); + if (Visible) + Top -= (Height - height) / 2; + } + + private bool ValidateDynamicScreen() + { + bool valid = true; + foreach (Control c in pScreen.Controls) + { + ConfigurationElement ce = c.Tag as ConfigurationElement; + if (ce == null || !ce.Mandatory) + continue; + if (ce.isEmpty(c)) + { + valid = false; + c.BackColor = Color.LightCoral; + } + else + { + c.BackColor = ce.UIMandatoryColor; + } + } + return valid; + } + + private void SaveDynamicScreen() + { + foreach (Control c in pScreen.Controls) + { + ConfigurationElement ce = c.Tag as ConfigurationElement; + if (ce == null || ce.Id == null) + continue; + ssc.Settings[ce.Id] = ce.getValue(c); + } + } + + #endregion + + private void FServiceConf_Load(object sender, EventArgs e) + { + } + + private void button1_Click(object sender, EventArgs e) + { + if (!ValidateData()) + return; + SaveData(); + DialogResult = DialogResult.OK; + } + + private void cbType_SelectedIndexChanged(object sender, EventArgs e) + { + LoadScreen(); + } + } +} diff --git a/Sunfish/FServiceConf.resx b/Sunfish/FServiceConf.resx new file mode 100644 index 0000000..df8339b --- /dev/null +++ b/Sunfish/FServiceConf.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + \ No newline at end of file diff --git a/Sunfish/Form1.Designer.cs b/Sunfish/Form1.Designer.cs new file mode 100644 index 0000000..c126fab --- /dev/null +++ b/Sunfish/Form1.Designer.cs @@ -0,0 +1,298 @@ +namespace DolphinWebXplorer2 +{ + partial class Form1 + { + /// + /// Variable del diseñador requerida. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Limpiar los recursos que se estén utilizando. + /// + /// true si los recursos administrados se deben eliminar; false en caso contrario, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Código generado por el Diseñador de Windows Forms + + /// + /// Método necesario para admitir el Diseñador. No se puede modificar + /// el contenido del método con el editor de código. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); + this.btDone = new System.Windows.Forms.Button(); + this.nudPort = new System.Windows.Forms.NumericUpDown(); + this.cbActive = new System.Windows.Forms.CheckBox(); + this.btAdd = new System.Windows.Forms.Button(); + this.il16 = new System.Windows.Forms.ImageList(this.components); + this.btSub = new System.Windows.Forms.Button(); + this.lbPaths = new System.Windows.Forms.ListBox(); + this.cmsItem = new System.Windows.Forms.ContextMenuStrip(this.components); + this.añadirToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.editarToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.borrarToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.btShowIp = new System.Windows.Forms.Button(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.cbRootList = new System.Windows.Forms.CheckBox(); + this.cbAdmin = new System.Windows.Forms.CheckBox(); + this.tbAdminPWD = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.nudPort)).BeginInit(); + this.cmsItem.SuspendLayout(); + this.SuspendLayout(); + // + // btDone + // + this.btDone.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btDone.Location = new System.Drawing.Point(155, 298); + this.btDone.Name = "btDone"; + this.btDone.Size = new System.Drawing.Size(92, 23); + this.btDone.TabIndex = 1; + this.btDone.Text = "Ok"; + this.toolTip1.SetToolTip(this.btDone, "Hide"); + this.btDone.UseVisualStyleBackColor = true; + this.btDone.Click += new System.EventHandler(this.button1_Click); + // + // nudPort + // + this.nudPort.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.nudPort.Location = new System.Drawing.Point(191, 6); + this.nudPort.Maximum = new decimal(new int[] { + 64000, + 0, + 0, + 0}); + this.nudPort.Name = "nudPort"; + this.nudPort.Size = new System.Drawing.Size(55, 20); + this.nudPort.TabIndex = 3; + this.toolTip1.SetToolTip(this.nudPort, "Listen port"); + this.nudPort.Value = new decimal(new int[] { + 90, + 0, + 0, + 0}); + this.nudPort.ValueChanged += new System.EventHandler(this.nudPort_ValueChanged); + // + // cbActive + // + this.cbActive.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.cbActive.AutoSize = true; + this.cbActive.Location = new System.Drawing.Point(96, 8); + this.cbActive.Name = "cbActive"; + this.cbActive.Size = new System.Drawing.Size(90, 17); + this.cbActive.TabIndex = 4; + this.cbActive.Text = "Listen on port"; + this.toolTip1.SetToolTip(this.cbActive, "Enable whole server"); + this.cbActive.UseVisualStyleBackColor = true; + this.cbActive.CheckedChanged += new System.EventHandler(this.cbActive_CheckedChanged); + // + // btAdd + // + this.btAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btAdd.Font = new System.Drawing.Font("Lucida Console", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.btAdd.ImageIndex = 0; + this.btAdd.ImageList = this.il16; + this.btAdd.Location = new System.Drawing.Point(6, 298); + this.btAdd.Name = "btAdd"; + this.btAdd.Size = new System.Drawing.Size(23, 23); + this.btAdd.TabIndex = 5; + this.toolTip1.SetToolTip(this.btAdd, "Add new access"); + this.btAdd.UseVisualStyleBackColor = true; + this.btAdd.Click += new System.EventHandler(this.btAdd_Click); + // + // il16 + // + this.il16.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("il16.ImageStream"))); + this.il16.TransparentColor = System.Drawing.Color.White; + this.il16.Images.SetKeyName(0, "bt_plus.bmp"); + this.il16.Images.SetKeyName(1, "bt_minus.bmp"); + // + // btSub + // + this.btSub.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btSub.Enabled = false; + this.btSub.Font = new System.Drawing.Font("Lucida Console", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.btSub.ImageKey = "bt_minus.bmp"; + this.btSub.ImageList = this.il16; + this.btSub.Location = new System.Drawing.Point(35, 298); + this.btSub.Name = "btSub"; + this.btSub.Size = new System.Drawing.Size(23, 23); + this.btSub.TabIndex = 6; + this.toolTip1.SetToolTip(this.btSub, "Remove >selected access"); + this.btSub.UseVisualStyleBackColor = true; + this.btSub.Click += new System.EventHandler(this.btSub_Click); + // + // lbPaths + // + this.lbPaths.AllowDrop = true; + this.lbPaths.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.lbPaths.ContextMenuStrip = this.cmsItem; + this.lbPaths.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; + this.lbPaths.FormattingEnabled = true; + this.lbPaths.IntegralHeight = false; + this.lbPaths.ItemHeight = 28; + this.lbPaths.Location = new System.Drawing.Point(0, 58); + this.lbPaths.Name = "lbPaths"; + this.lbPaths.Size = new System.Drawing.Size(253, 233); + this.lbPaths.TabIndex = 7; + this.lbPaths.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.lbPaths_DrawItem); + this.lbPaths.SelectedIndexChanged += new System.EventHandler(this.lbPaths_SelectedIndexChanged); + this.lbPaths.DragDrop += new System.Windows.Forms.DragEventHandler(this.lbPaths_DragDrop); + this.lbPaths.DragEnter += new System.Windows.Forms.DragEventHandler(this.lbPaths_DragEnter); + this.lbPaths.DoubleClick += new System.EventHandler(this.clbPaths_DoubleClick); + // + // cmsItem + // + this.cmsItem.ImageScalingSize = new System.Drawing.Size(24, 24); + this.cmsItem.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.añadirToolStripMenuItem, + this.editarToolStripMenuItem, + this.borrarToolStripMenuItem, + this.toolStripSeparator1}); + this.cmsItem.Name = "cmsItem"; + this.cmsItem.Size = new System.Drawing.Size(132, 76); + this.cmsItem.Opening += new System.ComponentModel.CancelEventHandler(this.cmsItem_Opening); + // + // añadirToolStripMenuItem + // + this.añadirToolStripMenuItem.Name = "añadirToolStripMenuItem"; + this.añadirToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Insert; + this.añadirToolStripMenuItem.Size = new System.Drawing.Size(131, 22); + this.añadirToolStripMenuItem.Text = "Añadir"; + this.añadirToolStripMenuItem.Click += new System.EventHandler(this.btAdd_Click); + // + // editarToolStripMenuItem + // + this.editarToolStripMenuItem.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold); + this.editarToolStripMenuItem.Name = "editarToolStripMenuItem"; + this.editarToolStripMenuItem.Size = new System.Drawing.Size(131, 22); + this.editarToolStripMenuItem.Text = "Editar"; + // + // borrarToolStripMenuItem + // + this.borrarToolStripMenuItem.Name = "borrarToolStripMenuItem"; + this.borrarToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Delete; + this.borrarToolStripMenuItem.Size = new System.Drawing.Size(131, 22); + this.borrarToolStripMenuItem.Text = "Borrar"; + this.borrarToolStripMenuItem.Click += new System.EventHandler(this.btSub_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(128, 6); + // + // btShowIp + // + this.btShowIp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btShowIp.Font = new System.Drawing.Font("Lucida Console", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.btShowIp.Image = global::DolphinWebXplorer2.Properties.Resources.messagebox_info; + this.btShowIp.Location = new System.Drawing.Point(126, 298); + this.btShowIp.Name = "btShowIp"; + this.btShowIp.Size = new System.Drawing.Size(23, 23); + this.btShowIp.TabIndex = 8; + this.toolTip1.SetToolTip(this.btShowIp, "Show network information"); + this.btShowIp.UseVisualStyleBackColor = true; + this.btShowIp.Click += new System.EventHandler(this.btShowIp_Click); + // + // cbRootList + // + this.cbRootList.AutoSize = true; + this.cbRootList.Location = new System.Drawing.Point(8, 8); + this.cbRootList.Margin = new System.Windows.Forms.Padding(2); + this.cbRootList.Name = "cbRootList"; + this.cbRootList.Size = new System.Drawing.Size(78, 17); + this.cbRootList.TabIndex = 9; + this.cbRootList.Text = "Root menu"; + this.toolTip1.SetToolTip(this.cbRootList, "If there is no service located at root sunfish will show a listing page with all " + + "availables services and paths."); + this.cbRootList.UseVisualStyleBackColor = true; + this.cbRootList.CheckedChanged += new System.EventHandler(this.cbRootList_CheckedChanged); + // + // cbAdmin + // + this.cbAdmin.AutoSize = true; + this.cbAdmin.Location = new System.Drawing.Point(8, 34); + this.cbAdmin.Margin = new System.Windows.Forms.Padding(2); + this.cbAdmin.Name = "cbAdmin"; + this.cbAdmin.Size = new System.Drawing.Size(85, 17); + this.cbAdmin.TabIndex = 10; + this.cbAdmin.Text = "Admin Panel"; + this.toolTip1.SetToolTip(this.cbAdmin, "If there is no service located at root sunfish will show a listing page with all " + + "availables services and paths."); + this.cbAdmin.UseVisualStyleBackColor = true; + this.cbAdmin.CheckedChanged += new System.EventHandler(this.cbAdmin_CheckedChanged); + // + // tbAdminPWD + // + this.tbAdminPWD.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tbAdminPWD.Location = new System.Drawing.Point(96, 32); + this.tbAdminPWD.Name = "tbAdminPWD"; + this.tbAdminPWD.PasswordChar = '•'; + this.tbAdminPWD.Size = new System.Drawing.Size(150, 20); + this.tbAdminPWD.TabIndex = 11; + this.tbAdminPWD.TextChanged += new System.EventHandler(this.tbAdminPWD_TextChanged); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(253, 326); + this.Controls.Add(this.tbAdminPWD); + this.Controls.Add(this.cbAdmin); + this.Controls.Add(this.cbRootList); + this.Controls.Add(this.btShowIp); + this.Controls.Add(this.lbPaths); + this.Controls.Add(this.btSub); + this.Controls.Add(this.btAdd); + this.Controls.Add(this.cbActive); + this.Controls.Add(this.nudPort); + this.Controls.Add(this.btDone); + this.Name = "Form1"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Sunfish"; + this.Activated += new System.EventHandler(this.Form1_Activated); + this.Deactivate += new System.EventHandler(this.Form1_Activated); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Form1_FormClosed); + this.LocationChanged += new System.EventHandler(this.Form1_Activated); + ((System.ComponentModel.ISupportInitialize)(this.nudPort)).EndInit(); + this.cmsItem.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button btDone; + private System.Windows.Forms.NumericUpDown nudPort; + private System.Windows.Forms.CheckBox cbActive; + private System.Windows.Forms.Button btAdd; + private System.Windows.Forms.Button btSub; + private System.Windows.Forms.ListBox lbPaths; + private System.Windows.Forms.Button btShowIp; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.ImageList il16; + private System.Windows.Forms.ContextMenuStrip cmsItem; + private System.Windows.Forms.ToolStripMenuItem editarToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem añadirToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem borrarToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.CheckBox cbRootList; + private System.Windows.Forms.CheckBox cbAdmin; + private System.Windows.Forms.TextBox tbAdminPWD; + } +} + diff --git a/Sunfish/Form1.cs b/Sunfish/Form1.cs new file mode 100644 index 0000000..2bfecc7 --- /dev/null +++ b/Sunfish/Form1.cs @@ -0,0 +1,280 @@ +using DolphinWebXplorer2.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Text; +using System.Windows.Forms; + +namespace DolphinWebXplorer2 +{ + public partial class Form1 : Form + { + public Font smallfont; + public Brush itembrushgray; + private Screen myscreen; + public Form1() + { + InitializeComponent(); + itembrushgray = new SolidBrush(Color.Gray); + smallfont = new Font(Font.FontFamily, 7, FontStyle.Regular); + Icon = Resources.sunfishWebServer; + PopulateData(); + Text += " " + Program.VERSION; + myscreen = Screen.FromControl(this); + } + + private void PopulateData() + { + Enabled = false; + nudPort.Value = Sunfish.Port; + cbActive.Checked = Sunfish.Active; + cbRootList.Checked = Sunfish.RootMenu; + cbAdmin.Checked = Sunfish.AdminPanel; + tbAdminPWD.Text = Sunfish.AdminPwd; + lbPaths.Items.Clear(); + foreach (SunfishService s in Sunfish.Services) + lbPaths.Items.Add(s); + Enabled = true; + tbAdminPWD.Enabled = cbAdmin.Checked; + } + + private List ListInterfacesIPs() + { + List result = new List(); + foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces()) + if (item.NetworkInterfaceType != NetworkInterfaceType.Loopback && item.OperationalStatus == OperationalStatus.Up) + foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses) + if (ip.Address.AddressFamily == AddressFamily.InterNetwork) + result.Add(new IpInfo(item, ip.Address.ToString())); + return result; + } + + private void EditConfiguration(SunfishServiceConfiguration ssc, SunfishService oldService) + { + if (FServiceConf.Execute(ssc)) + { + try + { + if (oldService == null) + lbPaths.Items.Add(Sunfish.AddService(ssc)); + else + { + SunfishService s = Sunfish.ReplaceService(oldService, ssc); + int idx = lbPaths.Items.IndexOf(oldService); + if (idx < 0) + lbPaths.Items.Add(s); + else + lbPaths.Items[idx] = s; + } + } + catch (Exception ex) + { + ex.Show(); + } + } + } + + public Screen MyScreen { get { lock (this) return myscreen; } } + + private void button1_Click(object sender, EventArgs e) + { + WindowState = FormWindowState.Minimized; + } + + private void Form1_FormClosed(object sender, FormClosedEventArgs e) + { + try + { + Sunfish.Save(); + } + catch { }; + Sunfish.Active = false; + } + + private void cbActive_CheckedChanged(object sender, EventArgs e) + { + nudPort.Enabled = !cbActive.Checked; + if (!Enabled) + return; + try + { + Sunfish.Active = cbActive.Checked; + } + catch (Exception ex) + { + ex.Show(); + } + cbActive.Checked = Sunfish.Active; + } + + private void nudPort_ValueChanged(object sender, EventArgs e) + { + if (!Enabled) + return; + Sunfish.Port = (int)nudPort.Value; + cbActive.Checked = Sunfish.Active; + } + + private void btAdd_Click(object sender, EventArgs e) + { + SunfishServiceConfiguration ssc = new SunfishServiceConfiguration(); + ssc.Type = "WebService"; + EditConfiguration(ssc, null); + } + + private void clbPaths_DoubleClick(object sender, EventArgs e) + { + SunfishService s = (SunfishService)lbPaths.SelectedItem; + if (s == null) + return; + EditConfiguration(s.Configuration, s); + } + + private void lbPaths_DrawItem(object sender, DrawItemEventArgs e) + { + e.DrawBackground(); + e.DrawFocusRectangle(); + if (e.Index < 0) + return; + SunfishService s = (SunfishService)lbPaths.Items[e.Index]; + Graphics g = e.Graphics; + int y = e.Bounds.Top + 2; + using (Brush itembrush = new SolidBrush(e.ForeColor)) + { + g.DrawImage(s.Enabled ? Resources.foldericon : Resources.foldericond, 1, y, 24, 24); + g.DrawString(s.Configuration.Name, lbPaths.Font, itembrush, 28, y); + g.DrawString(s.Configuration.Location, smallfont, itembrushgray, 33, y + 12); + //if (sh.AllowSubfolders) + // g.DrawImage(Resources.osubf, 16, y + 13); + //if (sh.AllowUpload) + // g.DrawImage(Resources.ouplo, 3, y + 13); + } + } + + private void lbPaths_SelectedIndexChanged(object sender, EventArgs e) + { + btSub.Enabled = lbPaths.SelectedItem != null; + } + + private void btSub_Click(object sender, EventArgs e) + { + SunfishService sh = (SunfishService)lbPaths.SelectedItem; + if (sh == null) + return; + if (MessageBox.Show("Delete access " + sh.Configuration.Name + "? Can not be undone!", "Delete", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + Sunfish.DeleteService(sh); + lbPaths.Items.Remove(sh); + } + } + + private void btShowIp_Click(object sender, EventArgs e) + { + StringBuilder sb = new StringBuilder(Sunfish.Active ? "A" : "Ina"); + sb.Append("ctive.\r\n"); + foreach (IpInfo ip in ListInterfacesIPs()) + { + sb.Append(ip.InterfaceName); + sb.Append(" ("); + sb.Append(ip.InterfaceType); + sb.Append("): "); + sb.Append(ip.Address); + sb.Append(":"); + sb.Append(Sunfish.Port); + sb.Append("\r\n"); + } + sb.Append("\r\nSunfish "); + sb.Append(Program.VERSION); + sb.Append(" (C) XWolfOverride@gmail.com 2007-2021\r\nEasy folder shares"); + MessageBox.Show(sb.ToString(), "Sunfish information", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + private void cmsItem_Opening(object sender, CancelEventArgs e) + { + SunfishService s = lbPaths.SelectedItem as SunfishService; + editarToolStripMenuItem.Enabled = s != null; + borrarToolStripMenuItem.Enabled = s != null; + toolStripSeparator1.Visible = s != null; + while (cmsItem.Items.Count > 4) + cmsItem.Items.RemoveAt(cmsItem.Items.Count - 1); + if (s == null) + return; + foreach (IpInfo ip in ListInterfacesIPs()) + { + ToolStripItem tsi = cmsItem.Items.Add("Copy url for " + ip.Address + " (" + ip.InterfaceName + ", " + ip.InterfaceType + ")"); + tsi.Tag = "http://" + ip.Address + ":" + Sunfish.Port + "/" + s.Configuration.Location + "/"; + tsi.Click += tsi_Click; + } + } + + void tsi_Click(object sender, EventArgs e) + { + ToolStripItem tsi = sender as ToolStripItem; + if (tsi == null) + return; + Clipboard.SetText(tsi.Tag.ToString()); + } + + private void tstbPassword_KeyPress(object sender, KeyPressEventArgs e) + { + e.KeyChar = char.ToLower(e.KeyChar); + } + + private void Form1_Activated(object sender, EventArgs e) + { + lock (this) + myscreen = Screen.FromControl(this); + } + + private void lbPaths_DragEnter(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + e.Effect = DragDropEffects.Copy; + else + e.Effect = DragDropEffects.None; + } + + private void lbPaths_DragDrop(object sender, DragEventArgs e) + { + string[] files = e.Data.GetData(DataFormats.FileDrop) as string[]; + if (files != null) + { + foreach (string file in files) + { + SunfishServiceConfiguration ssc = new SunfishServiceConfiguration(); + ssc.Type = "WebService"; + string fil = file; + if (!Directory.Exists(file)) + fil = Path.GetDirectoryName(fil); + ssc.Name = Path.GetFileName(fil); + ssc.Location = '/' + Path.GetFileName(fil); + ssc.Enabled = true; + ssc.Settings[Services.WebServiceConfigurator.CFG_PATH] = fil; + ssc.Settings[Services.WebServiceConfigurator.CFG_SHARE] = true; + EditConfiguration(ssc, null); + } + Activate(); + } + } + + private void cbRootList_CheckedChanged(object sender, EventArgs e) + { + Sunfish.RootMenu = cbRootList.Checked; + } + + private void cbAdmin_CheckedChanged(object sender, EventArgs e) + { + Sunfish.AdminPanel = cbAdmin.Checked; + tbAdminPWD.Enabled = cbAdmin.Checked; + } + + private void tbAdminPWD_TextChanged(object sender, EventArgs e) + { + Sunfish.AdminPwd = tbAdminPWD.Text; + } + } +} diff --git a/Sunfish/Form1.resx b/Sunfish/Form1.resx new file mode 100644 index 0000000..086e21f --- /dev/null +++ b/Sunfish/Form1.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 114, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAq + AQAAAk1TRnQBSQFMAgEBAgEAAZABAAGQAQABEAEAARABAAT/AQUBAAj/AUIBTQF2BwABdgMAASgDAAFA + AwABEAMAAQEBAAEEBgABAhgAAYACAAGAAwACgAEAAYADAAGAAQABgAEAAoACAAPAAQADgAMAAf8CAAH/ + AwAC/wEAAf8DAAH/AQAB/wEAAv8CAAP//wD/AAMAAUIBTQE+BwABPgMAASgDAAFAAwABEAMAAQEBAAEB + BQABgBcAA/8BAAT/BAAE/wQABP8EAAH8AT8C/wQAAfwBPwL/BAAB/AE/Av8EAAHgAQcB4AEHBAAB4AEH + AeABBwQAAeABBwHgAQcEAAHgAQcB4AEHBAAB/AE/Av8EAAH8AT8C/wQAAfwBPwL/BAAE/wQABP8EAAT/ + BAAL + + + + 17, 17 + + + 185, 17 + + \ No newline at end of file diff --git a/Sunfish/IpInfo.cs b/Sunfish/IpInfo.cs new file mode 100644 index 0000000..673863e --- /dev/null +++ b/Sunfish/IpInfo.cs @@ -0,0 +1,20 @@ +using System.Net.NetworkInformation; + +namespace DolphinWebXplorer2 +{ + class IpInfo + { + private NetworkInterface iface; + private string ip; + + public IpInfo(NetworkInterface iface, string ip) + { + this.iface = iface; + this.ip = ip; + } + + public string InterfaceName { get { return iface.Name; } } + public NetworkInterfaceType InterfaceType { get { return iface.NetworkInterfaceType; } } + public string Address { get { return ip; } } + } +} diff --git a/Sunfish/Library/Json.Net/IJsonConverter.cs b/Sunfish/Library/Json.Net/IJsonConverter.cs new file mode 100644 index 0000000..1bb2c86 --- /dev/null +++ b/Sunfish/Library/Json.Net/IJsonConverter.cs @@ -0,0 +1,14 @@ +using System; + +namespace Json.Net +{ + /// + /// Converter interface + /// + public interface IJsonConverter + { + Type GetConvertingType(); + string Serializer(object obj); + object Deserializer(string txt); + } +} diff --git a/Sunfish/Library/Json.Net/IPropertyNameTransform.cs b/Sunfish/Library/Json.Net/IPropertyNameTransform.cs new file mode 100644 index 0000000..8fb26c3 --- /dev/null +++ b/Sunfish/Library/Json.Net/IPropertyNameTransform.cs @@ -0,0 +1,7 @@ +namespace Json.Net +{ + public interface IPropertyNameTransform + { + string Transform(string propertyName); + } +} diff --git a/Sunfish/Library/Json.Net/JsonConverter.cs b/Sunfish/Library/Json.Net/JsonConverter.cs new file mode 100644 index 0000000..1c4556b --- /dev/null +++ b/Sunfish/Library/Json.Net/JsonConverter.cs @@ -0,0 +1,37 @@ +using System; + +namespace Json.Net +{ + /// + /// Custom type converter for serializer and deserializer + /// + /// + public class JsonConverter : IJsonConverter + { + public JsonConverter( + Func serializer, + Func deserializer) + { + Serializer = serializer; + Deserializer = deserializer; + } + + public Func Serializer; + public Func Deserializer; + + Type IJsonConverter.GetConvertingType() + { + return typeof(T); + } + + string IJsonConverter.Serializer(object obj) + { + return Serializer((T)obj); + } + + object IJsonConverter.Deserializer(string txt) + { + return Deserializer(txt); + } + } +} diff --git a/Sunfish/Library/Json.Net/JsonNet.cs b/Sunfish/Library/Json.Net/JsonNet.cs new file mode 100644 index 0000000..a075e26 --- /dev/null +++ b/Sunfish/Library/Json.Net/JsonNet.cs @@ -0,0 +1,262 @@ +using System.IO; +using System.Text; + +namespace Json.Net +{ + /// + /// Json.Net Helper Class + /// + public static class JsonNet + { + /// + /// Deserializes an object from a JSON text. + /// + /// Deserialized object's type + /// JSON text + /// Serialization options. + /// + public static T Deserialize(string json, SerializationOptions options = null) + { + return (T)JsonParser.Instance.Initialize(json, options) + .FromJson(typeof(T)); + } + + + /// + /// Deserializes an object from a JSON text stream. + /// + /// Deserialized object's type + /// Source JSON text stream + /// Serialization options. + /// + public static T Deserialize(Stream stream, SerializationOptions options = null) + { + return (T)JsonParser.Instance.Initialize(new StreamReader(stream), options) + .FromJson(typeof(T)); + } + + + /// + /// Deserializes an object from a JSON text reader. + /// + /// Deserialized object's type + /// Source JSON text reader + /// Serialization options. + /// + public static T Deserialize(TextReader reader, SerializationOptions options = null) + { + return (T)JsonParser.Instance.Initialize(reader, options) + .FromJson(typeof(T)); + } + + + /// + /// Serializes an object to its JSON text representation. + /// + /// Object to be serialized + /// Serialization options. + /// + public static string Serialize(object obj, SerializationOptions options = null) + { + var serializer = JsonSerializer.Instance.Initialize(); + + serializer.Serialize(obj, options); + + return serializer.Builder.ToString(); + } + + + /// + /// Serializes an object to its JSON text representation and writes to specified stream. + /// + /// Object to be serialized + /// Destination stream + /// Serialization options. + /// + public static void Serialize(object obj, Stream stream, SerializationOptions options = null) + { + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + { + Serialize(obj, sw, options); + } + } + + + /// + /// Serializes an object to its JSON text representation and writes to a textwriter. + /// + /// Object to be serialized + /// Destination text writer + /// Serialization options. + /// + public static void Serialize(object obj, TextWriter writer, SerializationOptions options = null) + { + JsonSerializer.Instance.Initialize(writer) + .Serialize(obj, options); + + writer.Flush(); + } + + + /// + /// Deserializes an object from a JSON text. + /// + /// Deserialized object's type + /// JSON text + /// Custom converters. + /// + public static T Deserialize(string json, params IJsonConverter[] converters) + { + return Deserialize(json, new SerializationOptions { Converters = converters }); + } + + + /// + /// Deserializes an object from a JSON text stream. + /// + /// Deserialized object's type + /// Source JSON text stream + /// Custom converters. + /// + public static T Deserialize(Stream stream, params IJsonConverter[] converters) + { + return Deserialize(new StreamReader(stream), new SerializationOptions { Converters = converters }); + } + + + /// + /// Deserializes an object from a JSON text reader. + /// + /// Deserialized object's type + /// Source JSON text reader + /// Custom converters. + /// + public static T Deserialize(TextReader reader, params IJsonConverter[] converters) + { + return Deserialize(reader, new SerializationOptions { Converters = converters }); + } + + + /// + /// Serializes an object to its JSON text representation. + /// + /// Object to be serialized + /// Custom type converters. + /// + public static string Serialize(object obj, params IJsonConverter[] converters) + { + return Serialize(obj, new SerializationOptions { Converters = converters }); + } + + + /// + /// Serializes an object to its JSON text representation and writes to specified stream. + /// + /// Object to be serialized + /// Destination stream + /// Custom type converters. + /// + public static void Serialize(object obj, Stream stream, params IJsonConverter[] converters) + { + Serialize(obj, stream, new SerializationOptions { Converters = converters }); + } + + + /// + /// Serializes an object to its JSON text representation and writes to a textwriter. + /// + /// Object to be serialized + /// Destination text writer + /// Custom type converters. + /// + public static void Serialize(object obj, TextWriter writer, params IJsonConverter[] converters) + { + Serialize(obj, new SerializationOptions { Converters = converters }); + } + + + /// + /// Deserializes an object from a JSON text. + /// + /// Deserialized object's type + /// JSON text + /// Property name tranform + /// Custom converters. + /// + public static T Deserialize(string json, IPropertyNameTransform propertyNameTransform, params IJsonConverter[] converters) + { + return Deserialize(json, new SerializationOptions { PropertyNameTransform = propertyNameTransform, Converters = converters }); + } + + + /// + /// Deserializes an object from a JSON text stream. + /// + /// Deserialized object's type + /// Source JSON text stream + /// Property name tranform + /// Custom converters. + /// + public static T Deserialize(Stream stream, IPropertyNameTransform propertyNameTransform, params IJsonConverter[] converters) + { + return Deserialize(new StreamReader(stream), new SerializationOptions { PropertyNameTransform = propertyNameTransform, Converters = converters }); + } + + + /// + /// Deserializes an object from a JSON text reader. + /// + /// Deserialized object's type + /// Source JSON text reader + /// Property name tranform + /// Custom converters. + /// + public static T Deserialize(TextReader reader, IPropertyNameTransform propertyNameTransform, params IJsonConverter[] converters) + { + return Deserialize(reader, new SerializationOptions { PropertyNameTransform = propertyNameTransform, Converters = converters }); + } + + + /// + /// Serializes an object to its JSON text representation. + /// + /// Object to be serialized + /// Property name tranform + /// Custom type converters. + /// + public static string Serialize(object obj, IPropertyNameTransform propertyNameTransform, params IJsonConverter[] converters) + { + return Serialize(obj, new SerializationOptions { PropertyNameTransform = propertyNameTransform, Converters = converters }); + } + + + /// + /// Serializes an object to its JSON text representation and writes to specified stream. + /// + /// Object to be serialized + /// Destination stream + /// Property name tranform + /// Custom type converters. + /// + public static void Serialize(object obj, Stream stream, IPropertyNameTransform propertyNameTransform, params IJsonConverter[] converters) + { + Serialize(obj, stream, new SerializationOptions { PropertyNameTransform = propertyNameTransform, Converters = converters }); + } + + + /// + /// Serializes an object to its JSON text representation and writes to a textwriter. + /// + /// Object to be serialized + /// Destination text writer + /// Property name tranform + /// Custom type converters. + /// + public static void Serialize(object obj, TextWriter writer, IPropertyNameTransform propertyNameTransform, params IJsonConverter[] converters) + { + Serialize(obj, new SerializationOptions { PropertyNameTransform = propertyNameTransform, Converters = converters }); + } + + } + +} \ No newline at end of file diff --git a/Sunfish/Library/Json.Net/JsonParser.cs b/Sunfish/Library/Json.Net/JsonParser.cs new file mode 100644 index 0000000..7106629 --- /dev/null +++ b/Sunfish/Library/Json.Net/JsonParser.cs @@ -0,0 +1,363 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; + + +namespace Json.Net +{ + /// + /// JSON Parser Class + /// + public class JsonParser : ParserBase + { + IJsonConverter[] Converters; + IPropertyNameTransform PropertyNameTransform; + + static Dictionary EscapeMap = + new Dictionary() + { + { 'b', (char)8 }, + { 't', (char)9 }, + { 'n', (char)10 }, + { 'f', (char)12 }, + { 'r', (char)13 } + }; + + + public JsonParser() + { + } + + + [ThreadStatic] + static JsonParser _Instance; + + public static JsonParser Instance + { + get + { + return _Instance ?? + (_Instance = new JsonParser()); + } + } + + + public JsonParser Initialize(string json, SerializationOptions options) + { + base.Initialize(json); + Converters = options?.Converters; + PropertyNameTransform = options?.PropertyNameTransform; + return this; + } + + + public JsonParser Initialize(TextReader jsonReader, SerializationOptions options) + { + base.Initialize(jsonReader); + Converters = options?.Converters; + PropertyNameTransform = options.PropertyNameTransform; + return this; + } + + + StringBuilder text = new StringBuilder(); + + public object FromJson(Type type) + { + object result; + + SkipWhite(); + + if (NextChar == '{') + { + ReadNext(); + SkipWhite(); + + if (type.IsValueType) + throw new FormatException("Unexpected type!"); + + result = Activator.CreateInstance(type); + + var nameType = result is IDictionary ? + type.GenericTypeArguments[0] : + typeof(string); + + var valueType = result is IDictionary ? + type.GenericTypeArguments[1] : + null; + + var mIndex = 0; + + while (NextChar != '}') + { + var name = (string)FromJson(nameType); + + SkipWhite(); + Match(":"); + + var map = SerializerMap.GetSerializerMap(type); + + MemberAccessor field = null; + + if (valueType == null) + { + for (var i = mIndex; i < map.Members.Length; i++) + { + string memberName = map.Members[i].Name; + if (PropertyNameTransform != null) + memberName = PropertyNameTransform.Transform(memberName); + if (memberName == name) + { + field = map.Members[i]; + break; + } + } + } + + var fieldType = field == null ? valueType : field.ValueType; + + var value = FromJson(fieldType); + + if (field != null) + { + field.SetValue(result, value); + } + else + { + ((IDictionary)result).Add(name, value); + } + + SkipWhite(); + + if (NextChar == ',') + { + ReadNext(); + SkipWhite(); + continue; + } + + break; + } + + Match("}"); + + return result; + } + + if (NextChar == '[') + { + ReadNext(); + SkipWhite(); + + var elementType = + type.IsArray ? + type.GetElementType() : + type.IsGenericType ? + type.GenericTypeArguments[0] : + typeof(object); + + var list = + type.IsArray ? + new ArrayList() : + (IList)Activator.CreateInstance(type); + + while (NextChar != ']') + { + var item = FromJson(elementType); + + list.Add(item); + + SkipWhite(); + + if (NextChar == ',') + { + ReadNext(); + SkipWhite(); + continue; + } + + break; + } + + Match("]"); + + if (list is ArrayList) + return ((ArrayList)list).ToArray(elementType); + else + return list; + } + + if (NextChar == '"') + { + ReadNext(); + + while (!EndOfStream && NextChar != '"') + { + if (NextChar == '\\') + { + ReadNext(); + + switch (NextChar) + { + case 'b': + case 't': + case 'n': + case 'f': + case 'r': + text.Append(EscapeMap[NextChar]); + break; + + case 'u': + ReadNext(); + + var unicode = ""; + + while (unicode.Length < 4 && IsHexDigit) + { + unicode += NextChar; + ReadNext(); + } + + text.Append(char.ConvertFromUtf32(int.Parse("0x" + unicode))); + continue; + + default: + text.Append(NextChar); + break; + } + } + else + text.Append(NextChar); + + ReadNext(); + } + + SkipWhite(); + Match("\""); + + result = text.ToString(); + + text.Clear(); + + var converter = Converters?.FirstOrDefault(c => c.GetConvertingType() == type); + + if (converter != null) + return converter.Deserializer((string)result); + + if (type == typeof(DateTime) + || type == typeof(DateTime?)) + return DateTime.Parse((string)result, CultureInfo.InvariantCulture); + + if (type == typeof(DateTimeOffset) + || type == typeof(DateTimeOffset?)) + return DateTimeOffset.Parse((string)result, CultureInfo.InvariantCulture); + + if (type == typeof(TimeSpan) + || type == typeof(TimeSpan?)) + return TimeSpan.Parse((string)result, CultureInfo.InvariantCulture); + + return result; + } + else if (NextChar == 't') + { + Match("true"); + return true; + } + else if (NextChar == 'f') + { + Match("false"); + return false; + } + else if (NextChar == 'n') + { + Match("null"); + + if (!(type.IsClass + || Nullable.GetUnderlyingType(type) != null)) + throw new InvalidDataException("Type " + type.Name + "'s value cannot be null!"); + + return null; + } + else if (NextChar == '-' || IsDigit) + { + if (NextChar == '-') + { + text.Append('-'); + ReadNext(); + } + + if (NextChar == '0') + { + text.Append('0'); + ReadNext(); + } + else if (IsDigit) + { + do + { + text.Append(NextChar); + ReadNext(); + } + while (IsDigit); + } + else + throw new FormatException("Digit expected!"); + + if (NextChar == '.') + { + text.Append('.'); + ReadNext(); + + while (IsDigit) + { + text.Append(NextChar); + ReadNext(); + } + } + + if (NextChar == 'e' || NextChar == 'E') + { + text.Append('e'); + ReadNext(); + + if (NextChar == '+' || NextChar == '-') + { + text.Append(NextChar); + ReadNext(); + } + + while (IsDigit) + { + text.Append(NextChar); + ReadNext(); + } + } + + var t = text.ToString(); + text.Clear(); + + var inv = CultureInfo.InvariantCulture; + + if (type.IsEnum + || type == typeof(int) + || type == typeof(int?)) + return int.Parse(t, inv); + + if (type == typeof(long) + || type == typeof(long?)) + return long.Parse(t, inv); + + return double.Parse(t, inv); + } + + throw new FormatException("Unexpected character! " + NextChar); + } + + + + } +} diff --git a/Sunfish/Library/Json.Net/JsonSerializer.cs b/Sunfish/Library/Json.Net/JsonSerializer.cs new file mode 100644 index 0000000..b2e3f11 --- /dev/null +++ b/Sunfish/Library/Json.Net/JsonSerializer.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; + +namespace Json.Net +{ + public class JsonSerializer + { + TextWriter Writer; + public StringBuilder Builder = new StringBuilder(1024); + + protected Action Write; + + public JsonSerializer() + { } + + + + public JsonSerializer Initialize() + { + Writer = null; + Builder.Clear(); + Write = s => Builder.Append(s); + return this; + } + + + public JsonSerializer Initialize(TextWriter writer) + { + Writer = writer; + Write = s => Writer.Write(s); + return this; + } + + + [ThreadStatic] + static JsonSerializer _Instance; + + public static JsonSerializer Instance + { + get + { + return _Instance ?? + (_Instance = new JsonSerializer()); + } + } + + + static Dictionary> SerializerCache = + new Dictionary>(); + + + public void Serialize(object obj, SerializationOptions options) + { + if (obj == null) + { + Write("null"); + return; + } + + var objectType = obj.GetType(); + + var converter = options?.Converters?.FirstOrDefault(c => c.GetConvertingType() == objectType); + + if (converter != null) + { + Serialize(converter.Serializer(obj), options); + return; + } + + Func cnv; + Type genericType; + + if (!SerializerCache.TryGetValue(objectType, out cnv)) + { + var strConverter = new Func( + s => + { + var t = (string)s; + var r = "\""; + + for (var i = 0; i < t.Length; i++) + { + var c = t[i]; + + r += c == '\r' ? "\\r" : + c == '\n' ? "\\n" : + c == '\t' ? "\\t" : + c == '"' ? "\\\"" : + c == '\\' ? "\\\\" : + c == '/' ? "\\/" : + c == '\b' ? "\\b" : + c == '\f' ? "\\f" : + c.ToString(); + } + + r += "\""; + + return r; + }); + + if (obj is string) + { + cnv = strConverter; + } + else if (obj is IEnumerable) + { + Write(obj is IDictionary ? "{" : "["); + + var first = true; + + foreach (var o in (IEnumerable)obj) + { + if (first) + first = false; + else + Write(","); + + Serialize(o, options); + } + + Write(obj is IDictionary ? "}" : "]"); + return; + } + else if (obj is bool || obj is bool?) + { + cnv = b => (bool)b ? "true" : "false"; + } + else if (obj is int || obj is int? + || obj is short || obj is short? + || obj is long || obj is long? + || obj is uint || obj is uint? + || obj is ushort || obj is ushort? + || obj is ulong || obj is ulong? + || obj is float || obj is float? + || obj is double || obj is double? + || obj is decimal || obj is decimal? + || obj is float || obj is uint? + || obj is ushort || obj is ushort? + || obj is ulong || obj is ulong?) + { + cnv = n => string.Format(CultureInfo.InvariantCulture, "{0}", n); + } + else if (obj is DateTime || obj is DateTime?) + { + cnv = d => strConverter(((DateTime)d).ToString(CultureInfo.InvariantCulture)); + } + else if (obj is DateTimeOffset || obj is DateTimeOffset?) + { + cnv = d => strConverter(((DateTimeOffset)d).ToString(CultureInfo.InvariantCulture)); + } + else if (obj is TimeSpan || obj is TimeSpan?) + { + cnv = d => strConverter(((TimeSpan)d).ToString("c")); + } + else if (obj is Enum) + { + cnv = e => ((int)e).ToString(CultureInfo.InvariantCulture); + } + else if (objectType.IsGenericType + && objectType.GenericTypeArguments.Length == 2 + && objectType == (genericType = typeof(KeyValuePair<,>).MakeGenericType(objectType.GenericTypeArguments))) + { + var k = genericType.GetProperty("Key").GetValue(obj).ToString(); + var v = genericType.GetProperty("Value").GetValue(obj); + + Write(strConverter(k)); + Write(":"); + Serialize(v, options); + return; + } + else if (!objectType.IsPrimitive) + { + Write("{"); + + var first = true; + + foreach (var m in SerializerMap.GetSerializerMap(objectType) + .Members) + { + if (first) + first = false; + else + Write(","); + + if (objectType == typeof(DictionaryEntry)) + { + var d = (DictionaryEntry)obj; + Write(strConverter(d.Key.ToString())); + Write(":"); + Serialize(d.Value, options); + } + else + { + string memberName = m.Name; + if (options?.PropertyNameTransform != null) + memberName = options?.PropertyNameTransform.Transform(m.Name); + Write(strConverter(memberName)); + Write(":"); + + try + { + Serialize(m.GetValue(obj), options); + } + catch (TargetInvocationException) + { + Serialize(null, options); + } + } + } + + Write("}"); + return; + } + + SerializerCache[objectType] = + cnv ?? + throw new InvalidOperationException( + "Unknown object type! " + objectType.FullName); ; + } + + Write(cnv(obj)); + } + } +} diff --git a/Sunfish/Library/Json.Net/ParserBase.cs b/Sunfish/Library/Json.Net/ParserBase.cs new file mode 100644 index 0000000..0b7650e --- /dev/null +++ b/Sunfish/Library/Json.Net/ParserBase.cs @@ -0,0 +1,142 @@ +using System; +using System.IO; + +namespace Json.Net +{ + public class ParserBase + { + TextReader Reader; + + char[] ReaderBuffer; + + string Buffer; + int BufferIndex; + + protected char NextChar; + + const char EOF = (char)27; + + protected bool EndOfStream; + + protected static string WhiteSpace = " \t\r\n"; + protected static string Digits = "0123456789"; + protected static string HexDigits = "0123456789ABCDEFabcdef"; + + protected static string Alpha = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "abcdefghijklmnopqrstuvwxyz"; + + protected static string AlphaNumeric = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "abcdefghijklmnopqrstuvwxyz" + + "0123456789"; + + + public ParserBase(int bufferSize = 1024) + { + ReaderBuffer = new char[bufferSize]; + } + + + ParserBase _Initialize() + { + EndOfStream = false; + BufferIndex = -1; + ReadNext(); + return this; + } + + + public ParserBase Initialize(string json) + { + Reader = null; + Buffer = json; + return _Initialize(); + } + + + public ParserBase Initialize(TextReader textReader) + { + Reader = textReader; + Buffer = ""; + return _Initialize(); + } + + + + protected void ReadNext() + { + if (EndOfStream) + return; + + if (++BufferIndex < Buffer.Length) + { + NextChar = Buffer[BufferIndex]; + return; + } + + if (Reader != null) + { + var read = Reader.ReadBlock(ReaderBuffer, 0, ReaderBuffer.Length); + + Buffer = new string(ReaderBuffer, 0, read); + BufferIndex = 0; + + if (read > 0) + return; + } + + Buffer = ""; + BufferIndex = 0; + EndOfStream = true; + NextChar = EOF; + } + + + protected bool IsWhite + { + get { return WhiteSpace.IndexOf(NextChar) >= 0; } + } + + + protected bool IsAlpha + { + get { return Alpha.IndexOf(NextChar) >= 0; } + } + + + protected bool IsAlphaNumeric + { + get { return AlphaNumeric.IndexOf(NextChar) >= 0; } + } + + + protected bool IsDigit + { + get { return Digits.IndexOf(NextChar) >= 0; } + } + + + protected bool IsHexDigit + { + get { return HexDigits.IndexOf(NextChar) >= 0; } + } + + + protected void SkipWhite() + { + while (IsWhite) + ReadNext(); + } + + + protected void Match(string s) + { + foreach (var c in s) + if (NextChar == c) + ReadNext(); + else + throw new FormatException(s + " expected, but " + NextChar + " found!"); + } + } +} \ No newline at end of file diff --git a/Sunfish/Library/Json.Net/PropertyNameTransforms.cs b/Sunfish/Library/Json.Net/PropertyNameTransforms.cs new file mode 100644 index 0000000..e84b28a --- /dev/null +++ b/Sunfish/Library/Json.Net/PropertyNameTransforms.cs @@ -0,0 +1,7 @@ +namespace Json.Net +{ + public static class PropertyNameTransforms + { + public static IPropertyNameTransform TitleToCamelCase { get; } = new TitleToCamelCase(); + } +} diff --git a/Sunfish/Library/Json.Net/SerializationOptions.cs b/Sunfish/Library/Json.Net/SerializationOptions.cs new file mode 100644 index 0000000..23f4045 --- /dev/null +++ b/Sunfish/Library/Json.Net/SerializationOptions.cs @@ -0,0 +1,9 @@ +namespace Json.Net +{ + public class SerializationOptions + { + public IJsonConverter[] Converters { get; set; } + + public IPropertyNameTransform PropertyNameTransform { get; set; } + } +} diff --git a/Sunfish/Library/Json.Net/SerializerMap.cs b/Sunfish/Library/Json.Net/SerializerMap.cs new file mode 100644 index 0000000..ef9c27b --- /dev/null +++ b/Sunfish/Library/Json.Net/SerializerMap.cs @@ -0,0 +1,93 @@ +using System; +using System.Linq; +using System.Reflection; + +namespace Json.Net +{ + public class MemberAccessor + { + public string Name; + public Type ValueType; + public Func GetValue; + public Action SetValue; + } + + + public class SerializerMap + { + public readonly Type ObjectType; + public readonly MemberAccessor[] Members; + + [ThreadStatic] + static SerializerMap[] _GlobalMaps; + + static SerializerMap[] GlobalMaps + { + get + { + return _GlobalMaps ?? + (_GlobalMaps = new SerializerMap[0]); + } + } + + + public SerializerMap(Type type) + { + ObjectType = type; + + Members = + type.GetMembers(BindingFlags.Instance | BindingFlags.Public) + .Where(m => m.MemberType == MemberTypes.Field + || (m.MemberType == MemberTypes.Property + && type.GetProperty(m.Name).CanRead)) + .Select(m => + m.MemberType == MemberTypes.Property ? + new MemberAccessor + { + Name = m.Name, + ValueType = ((PropertyInfo)m).PropertyType, + GetValue = ((PropertyInfo)m).GetValue, + SetValue = ((PropertyInfo)m).SetValue + } : + new MemberAccessor + { + Name = m.Name, + ValueType = ((FieldInfo)m).FieldType, + GetValue = ((FieldInfo)m).GetValue, + SetValue = ((FieldInfo)m).SetValue + }) + .ToArray(); + } + + + public static SerializerMap GetSerializerMap(Type type) + { + SerializerMap result; + + if ((result = GlobalMaps.FirstOrDefault(m => m.ObjectType == type)) == null) + lock (_GlobalMaps) + { + if ((result = _GlobalMaps.FirstOrDefault(m => m.ObjectType == type)) == null) + { + var l = _GlobalMaps.Length; + Array.Resize(ref _GlobalMaps, l + 1); + + _GlobalMaps[l] = result = new SerializerMap(type); + + foreach (var t in result.Members + .Select(v => v.ValueType) + .Where(t => t != typeof(string) + && (t.IsClass || (t.IsValueType && !t.IsPrimitive))) + .Except(GlobalMaps.Select(m => m.ObjectType)) + .Distinct()) + { + GetSerializerMap(t); + } + } + } + + return result; + } + + } +} diff --git a/Sunfish/Library/Json.Net/TitleToCamelCase.cs b/Sunfish/Library/Json.Net/TitleToCamelCase.cs new file mode 100644 index 0000000..ff080e4 --- /dev/null +++ b/Sunfish/Library/Json.Net/TitleToCamelCase.cs @@ -0,0 +1,8 @@ +namespace Json.Net +{ + public class TitleToCamelCase : IPropertyNameTransform + { + public string Transform(string propertyName) => + char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwAuthorizedApplication.cs b/Sunfish/Library/NetFwTypeLib/INetFwAuthorizedApplication.cs new file mode 100644 index 0000000..dfac91d --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwAuthorizedApplication.cs @@ -0,0 +1,77 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("B5E64FFA-C2C5-444E-A301-FB5E00018050"), TypeLibType(4160)] + [ComImport] + public interface INetFwAuthorizedApplication + { + [DispId(1)] + string Name + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(2)] + string ProcessImageFileName + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(3)] + NET_FW_IP_VERSION_ IpVersion + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(4)] + NET_FW_SCOPE_ Scope + { + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(5)] + string RemoteAddresses + { + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(6)] + bool Enabled + { + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwAuthorizedApplications.cs b/Sunfish/Library/NetFwTypeLib/INetFwAuthorizedApplications.cs new file mode 100644 index 0000000..95b3e92 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwAuthorizedApplications.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("644EFD52-CCF9-486C-97A2-39F352570B30"), TypeLibType(4160)] + [ComImport] + public interface INetFwAuthorizedApplications : IEnumerable + { + [DispId(1)] + int Count + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + void Add([MarshalAs(UnmanagedType.Interface)] [In] INetFwAuthorizedApplication app); + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + void Remove([MarshalAs(UnmanagedType.BStr)] [In] string imageFileName); + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + INetFwAuthorizedApplication Item([MarshalAs(UnmanagedType.BStr)] [In] string imageFileName); + [DispId(-4), TypeLibFunc(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler")] + IEnumerator GetEnumerator(); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwIcmpSettings.cs b/Sunfish/Library/NetFwTypeLib/INetFwIcmpSettings.cs new file mode 100644 index 0000000..cbf0236 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwIcmpSettings.cs @@ -0,0 +1,111 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("A6207B2E-7CDD-426A-951E-5E1CBC5AFEAD"), TypeLibType(4160)] + [ComImport] + public interface INetFwIcmpSettings + { + [DispId(1)] + bool AllowOutboundDestinationUnreachable + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(2)] + bool AllowRedirect + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(3)] + bool AllowInboundEchoRequest + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(4)] + bool AllowOutboundTimeExceeded + { + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(5)] + bool AllowOutboundParameterProblem + { + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(6)] + bool AllowOutboundSourceQuench + { + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(7)] + bool AllowInboundRouterRequest + { + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(8)] + bool AllowInboundTimestampRequest + { + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(9)] + bool AllowInboundMaskRequest + { + [DispId(9)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(9)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(10)] + bool AllowOutboundPacketTooBig + { + [DispId(10)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(10)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwMgr.cs b/Sunfish/Library/NetFwTypeLib/INetFwMgr.cs new file mode 100644 index 0000000..27b252a --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwMgr.cs @@ -0,0 +1,35 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("F7898AF5-CAC4-4632-A2EC-DA06E5111AF2"), TypeLibType(4160)] + [ComImport] + public interface INetFwMgr + { + [DispId(1)] + INetFwPolicy LocalPolicy + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(2)] + NET_FW_PROFILE_TYPE_ CurrentProfileType + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + void RestoreDefaults(); + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + void IsPortAllowed([MarshalAs(UnmanagedType.BStr)] [In] string imageFileName, [In] NET_FW_IP_VERSION_ IpVersion, [In] int portNumber, [MarshalAs(UnmanagedType.BStr)] [In] string localAddress, [In] NET_FW_IP_PROTOCOL_ ipProtocol, [MarshalAs(UnmanagedType.Struct)] out object allowed, [MarshalAs(UnmanagedType.Struct)] out object restricted); + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + void IsIcmpTypeAllowed([In] NET_FW_IP_VERSION_ IpVersion, [MarshalAs(UnmanagedType.BStr)] [In] string localAddress, [In] byte Type, [MarshalAs(UnmanagedType.Struct)] out object allowed, [MarshalAs(UnmanagedType.Struct)] out object restricted); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwOpenPort.cs b/Sunfish/Library/NetFwTypeLib/INetFwOpenPort.cs new file mode 100644 index 0000000..7a34295 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwOpenPort.cs @@ -0,0 +1,92 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("E0483BA0-47FF-4D9C-A6D6-7741D0B195F7"), TypeLibType(4160)] + [ComImport] + public interface INetFwOpenPort + { + [DispId(1)] + string Name + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(2)] + NET_FW_IP_VERSION_ IpVersion + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(3)] + NET_FW_IP_PROTOCOL_ Protocol + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(4)] + int Port + { + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(5)] + NET_FW_SCOPE_ Scope + { + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(6)] + string RemoteAddresses + { + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(7)] + bool Enabled + { + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(8)] + bool BuiltIn + { + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwOpenPorts.cs b/Sunfish/Library/NetFwTypeLib/INetFwOpenPorts.cs new file mode 100644 index 0000000..abeaaed --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwOpenPorts.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("C0E9D7FA-E07E-430A-B19A-090CE82D92E2"), TypeLibType(4160)] + [ComImport] + public interface INetFwOpenPorts : IEnumerable + { + [DispId(1)] + int Count + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + void Add([MarshalAs(UnmanagedType.Interface)] [In] INetFwOpenPort Port); + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + void Remove([In] int portNumber, [In] NET_FW_IP_PROTOCOL_ ipProtocol); + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + INetFwOpenPort Item([In] int portNumber, [In] NET_FW_IP_PROTOCOL_ ipProtocol); + [DispId(-4), TypeLibFunc(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler")] + IEnumerator GetEnumerator(); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwPolicy.cs b/Sunfish/Library/NetFwTypeLib/INetFwPolicy.cs new file mode 100644 index 0000000..5f108b0 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwPolicy.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("D46D2478-9AC9-4008-9DC7-5563CE5536CC"), TypeLibType(4160)] + [ComImport] + public interface INetFwPolicy + { + [DispId(1)] + INetFwProfile CurrentProfile + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + INetFwProfile GetProfileByType([In] NET_FW_PROFILE_TYPE_ profileType); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwPolicy2.cs b/Sunfish/Library/NetFwTypeLib/INetFwPolicy2.cs new file mode 100644 index 0000000..c08c9e0 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwPolicy2.cs @@ -0,0 +1,129 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("98325047-C671-4174-8D81-DEFCD3F03186"), TypeLibType(4160)] + [ComImport] + public interface INetFwPolicy2 + { + [DispId(1)] + int CurrentProfileTypes + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(2)] + bool FirewallEnabled + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(3)] + object ExcludedInterfaces + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Struct)] + get; + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.Struct)] + set; + } + [DispId(4)] + bool BlockAllInboundTraffic + { + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(5)] + bool NotificationsDisabled + { + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(6)] + bool UnicastResponsesToMulticastBroadcastDisabled + { + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(7)] + INetFwRules Rules + { + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(8)] + INetFwServiceRestriction ServiceRestriction + { + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(12)] + NET_FW_ACTION_ DefaultInboundAction + { + [DispId(12)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(12)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(13)] + NET_FW_ACTION_ DefaultOutboundAction + { + [DispId(13)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(13)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(14)] + bool IsRuleGroupCurrentlyEnabled + { + [DispId(14)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(15)] + NET_FW_MODIFY_STATE_ LocalPolicyModifyState + { + [DispId(15)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(9)] + [MethodImpl(MethodImplOptions.InternalCall)] + void EnableRuleGroup([In] int profileTypesBitmask, [MarshalAs(UnmanagedType.BStr)] [In] string group, [In] bool enable); + [DispId(10)] + [MethodImpl(MethodImplOptions.InternalCall)] + bool IsRuleGroupEnabled([In] int profileTypesBitmask, [MarshalAs(UnmanagedType.BStr)] [In] string group); + [DispId(11)] + [MethodImpl(MethodImplOptions.InternalCall)] + void RestoreLocalFirewallDefaults(); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwProduct.cs b/Sunfish/Library/NetFwTypeLib/INetFwProduct.cs new file mode 100644 index 0000000..9ed2b89 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwProduct.cs @@ -0,0 +1,43 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("71881699-18F4-458B-B892-3FFCE5E07F75"), TypeLibType(4160)] + [ComImport] + public interface INetFwProduct + { + [DispId(1)] + object RuleCategories + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Struct)] + get; + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.Struct)] + set; + } + [DispId(2)] + string DisplayName + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(3)] + string PathToSignedProductExe + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwProducts.cs b/Sunfish/Library/NetFwTypeLib/INetFwProducts.cs new file mode 100644 index 0000000..e39e815 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwProducts.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("39EB36E0-2097-40BD-8AF2-63A13B525362"), TypeLibType(4160)] + [ComImport] + public interface INetFwProducts : IEnumerable + { + [DispId(1)] + int Count + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.IUnknown)] + object Register([MarshalAs(UnmanagedType.Interface)] [In] INetFwProduct product); + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + INetFwProduct Item([In] int index); + [DispId(-4), TypeLibFunc(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler")] + IEnumerator GetEnumerator(); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwProfile.cs b/Sunfish/Library/NetFwTypeLib/INetFwProfile.cs new file mode 100644 index 0000000..4a4b51b --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwProfile.cs @@ -0,0 +1,98 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("174A0DDA-E9F9-449D-993B-21AB667CA456"), TypeLibType(4160)] + [ComImport] + public interface INetFwProfile + { + [DispId(1)] + NET_FW_PROFILE_TYPE_ Type + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(2)] + bool FirewallEnabled + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(3)] + bool ExceptionsNotAllowed + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(4)] + bool NotificationsDisabled + { + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(5)] + bool UnicastResponsesToMulticastBroadcastDisabled + { + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(6)] + INetFwRemoteAdminSettings RemoteAdminSettings + { + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(7)] + INetFwIcmpSettings IcmpSettings + { + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(8)] + INetFwOpenPorts GloballyOpenPorts + { + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(9)] + INetFwServices Services + { + [DispId(9)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(10)] + INetFwAuthorizedApplications AuthorizedApplications + { + [DispId(10)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwRemoteAdminSettings.cs b/Sunfish/Library/NetFwTypeLib/INetFwRemoteAdminSettings.cs new file mode 100644 index 0000000..351c499 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwRemoteAdminSettings.cs @@ -0,0 +1,53 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("D4BECDDF-6F73-4A83-B832-9C66874CD20E"), TypeLibType(4160)] + [ComImport] + public interface INetFwRemoteAdminSettings + { + [DispId(1)] + NET_FW_IP_VERSION_ IpVersion + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(2)] + NET_FW_SCOPE_ Scope + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(3)] + string RemoteAddresses + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(4)] + bool Enabled + { + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwRule.cs b/Sunfish/Library/NetFwTypeLib/INetFwRule.cs new file mode 100644 index 0000000..aeade53 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwRule.cs @@ -0,0 +1,215 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("AF230D27-BABA-4E42-ACED-F524F22CFCE2"), TypeLibType(4160)] + [ComImport] + public interface INetFwRule + { + [DispId(1)] + string Name + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(2)] + string Description + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(3)] + string ApplicationName + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(4)] + string serviceName + { + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(5)] + int Protocol + { + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(6)] + string LocalPorts + { + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(7)] + string RemotePorts + { + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(8)] + string LocalAddresses + { + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(9)] + string RemoteAddresses + { + [DispId(9)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(9)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(10)] + string IcmpTypesAndCodes + { + [DispId(10)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(10)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(11)] + NET_FW_RULE_DIRECTION_ Direction + { + [DispId(11)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(11)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(12)] + object Interfaces + { + [DispId(12)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Struct)] + get; + [DispId(12)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.Struct)] + set; + } + [DispId(13)] + string InterfaceTypes + { + [DispId(13)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(13)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(14)] + bool Enabled + { + [DispId(14)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(14)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(15)] + string Grouping + { + [DispId(15)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(15)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(16)] + int Profiles + { + [DispId(16)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(16)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(17)] + bool EdgeTraversal + { + [DispId(17)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(17)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(18)] + NET_FW_ACTION_ Action + { + [DispId(18)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(18)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwRule2.cs b/Sunfish/Library/NetFwTypeLib/INetFwRule2.cs new file mode 100644 index 0000000..cbd4456 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwRule2.cs @@ -0,0 +1,225 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("9C27C8DA-189B-4DDE-89F7-8B39A316782C"), TypeLibType(4160)] + [ComImport] + public interface INetFwRule2 : INetFwRule + { + [DispId(1)] + string Name + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(2)] + string Description + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(3)] + string ApplicationName + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(4)] + string serviceName + { + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(5)] + int Protocol + { + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(6)] + string LocalPorts + { + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(7)] + string RemotePorts + { + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(8)] + string LocalAddresses + { + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(9)] + string RemoteAddresses + { + [DispId(9)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(9)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(10)] + string IcmpTypesAndCodes + { + [DispId(10)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(10)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(11)] + NET_FW_RULE_DIRECTION_ Direction + { + [DispId(11)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(11)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(12)] + object Interfaces + { + [DispId(12)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Struct)] + get; + [DispId(12)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.Struct)] + set; + } + [DispId(13)] + string InterfaceTypes + { + [DispId(13)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(13)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(14)] + bool Enabled + { + [DispId(14)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(14)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(15)] + string Grouping + { + [DispId(15)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(15)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(16)] + int Profiles + { + [DispId(16)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(16)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(17)] + bool EdgeTraversal + { + [DispId(17)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(17)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(18)] + NET_FW_ACTION_ Action + { + [DispId(18)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(18)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(19)] + int EdgeTraversalOptions + { + [DispId(19)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(19)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwRules.cs b/Sunfish/Library/NetFwTypeLib/INetFwRules.cs new file mode 100644 index 0000000..63418b2 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwRules.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("9C4C6277-5027-441E-AFAE-CA1F542DA009"), TypeLibType(4160)] + [ComImport] + public interface INetFwRules : IEnumerable + { + [DispId(1)] + int Count + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + void Add([MarshalAs(UnmanagedType.Interface)] [In] INetFwRule rule); + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + void Remove([MarshalAs(UnmanagedType.BStr)] [In] string Name); + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + INetFwRule Item([MarshalAs(UnmanagedType.BStr)] [In] string Name); + [DispId(-4), TypeLibFunc(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler")] + IEnumerator GetEnumerator(); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwService.cs b/Sunfish/Library/NetFwTypeLib/INetFwService.cs new file mode 100644 index 0000000..bd4bb3d --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwService.cs @@ -0,0 +1,83 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("79FD57C8-908E-4A36-9888-D5B3F0A444CF"), TypeLibType(4160)] + [ComImport] + public interface INetFwService + { + [DispId(1)] + string Name + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(2)] + NET_FW_SERVICE_TYPE_ Type + { + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(3)] + bool Customized + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(4)] + NET_FW_IP_VERSION_ IpVersion + { + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(5)] + NET_FW_SCOPE_ Scope + { + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(6)] + string RemoteAddresses + { + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(6)] + [MethodImpl(MethodImplOptions.InternalCall)] + [param: MarshalAs(UnmanagedType.BStr)] + set; + } + [DispId(7)] + bool Enabled + { + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [DispId(7)] + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + [DispId(8)] + INetFwOpenPorts GloballyOpenPorts + { + [DispId(8)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwServiceRestriction.cs b/Sunfish/Library/NetFwTypeLib/INetFwServiceRestriction.cs new file mode 100644 index 0000000..cbb84b0 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwServiceRestriction.cs @@ -0,0 +1,25 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("8267BBE3-F890-491C-B7B6-2DB1EF0E5D2B"), TypeLibType(4160)] + [ComImport] + public interface INetFwServiceRestriction + { + [DispId(3)] + INetFwRules Rules + { + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + void RestrictService([MarshalAs(UnmanagedType.BStr)] [In] string serviceName, [MarshalAs(UnmanagedType.BStr)] [In] string appName, [In] bool RestrictService, [In] bool serviceSidRestricted); + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + bool ServiceRestricted([MarshalAs(UnmanagedType.BStr)] [In] string serviceName, [MarshalAs(UnmanagedType.BStr)] [In] string appName); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/INetFwServices.cs b/Sunfish/Library/NetFwTypeLib/INetFwServices.cs new file mode 100644 index 0000000..689e049 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/INetFwServices.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +namespace NetFwTypeLib +{ + [Guid("79649BB4-903E-421B-94C9-79848E79F6EE"), TypeLibType(4160)] + [ComImport] + public interface INetFwServices : IEnumerable + { + [DispId(1)] + int Count + { + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.Interface)] + INetFwService Item([In] NET_FW_SERVICE_TYPE_ svcType); + [DispId(-4), TypeLibFunc(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler")] + IEnumerator GetEnumerator(); + } +} diff --git a/Sunfish/Library/NetFwTypeLib/NET_FW_ACTION_.cs b/Sunfish/Library/NetFwTypeLib/NET_FW_ACTION_.cs new file mode 100644 index 0000000..107bc14 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/NET_FW_ACTION_.cs @@ -0,0 +1,10 @@ +using System; +namespace NetFwTypeLib +{ + public enum NET_FW_ACTION_ + { + NET_FW_ACTION_BLOCK, + NET_FW_ACTION_ALLOW, + NET_FW_ACTION_MAX + } +} diff --git a/Sunfish/Library/NetFwTypeLib/NET_FW_IP_PROTOCOL_.cs b/Sunfish/Library/NetFwTypeLib/NET_FW_IP_PROTOCOL_.cs new file mode 100644 index 0000000..204b1fd --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/NET_FW_IP_PROTOCOL_.cs @@ -0,0 +1,10 @@ +using System; +namespace NetFwTypeLib +{ + public enum NET_FW_IP_PROTOCOL_ + { + NET_FW_IP_PROTOCOL_TCP = 6, + NET_FW_IP_PROTOCOL_UDP = 17, + NET_FW_IP_PROTOCOL_ANY = 256 + } +} diff --git a/Sunfish/Library/NetFwTypeLib/NET_FW_IP_VERSION_.cs b/Sunfish/Library/NetFwTypeLib/NET_FW_IP_VERSION_.cs new file mode 100644 index 0000000..aa3c94d --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/NET_FW_IP_VERSION_.cs @@ -0,0 +1,11 @@ +using System; +namespace NetFwTypeLib +{ + public enum NET_FW_IP_VERSION_ + { + NET_FW_IP_VERSION_V4, + NET_FW_IP_VERSION_V6, + NET_FW_IP_VERSION_ANY, + NET_FW_IP_VERSION_MAX + } +} diff --git a/Sunfish/Library/NetFwTypeLib/NET_FW_MODIFY_STATE_.cs b/Sunfish/Library/NetFwTypeLib/NET_FW_MODIFY_STATE_.cs new file mode 100644 index 0000000..3ac6bb3 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/NET_FW_MODIFY_STATE_.cs @@ -0,0 +1,10 @@ +using System; +namespace NetFwTypeLib +{ + public enum NET_FW_MODIFY_STATE_ + { + NET_FW_MODIFY_STATE_OK, + NET_FW_MODIFY_STATE_GP_OVERRIDE, + NET_FW_MODIFY_STATE_INBOUND_BLOCKED + } +} diff --git a/Sunfish/Library/NetFwTypeLib/NET_FW_PROFILE_TYPE2_.cs b/Sunfish/Library/NetFwTypeLib/NET_FW_PROFILE_TYPE2_.cs new file mode 100644 index 0000000..5312829 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/NET_FW_PROFILE_TYPE2_.cs @@ -0,0 +1,11 @@ +using System; +namespace NetFwTypeLib +{ + public enum NET_FW_PROFILE_TYPE2_ + { + NET_FW_PROFILE2_DOMAIN = 1, + NET_FW_PROFILE2_PRIVATE, + NET_FW_PROFILE2_PUBLIC = 4, + NET_FW_PROFILE2_ALL = 2147483647 + } +} diff --git a/Sunfish/Library/NetFwTypeLib/NET_FW_PROFILE_TYPE_.cs b/Sunfish/Library/NetFwTypeLib/NET_FW_PROFILE_TYPE_.cs new file mode 100644 index 0000000..6465d12 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/NET_FW_PROFILE_TYPE_.cs @@ -0,0 +1,11 @@ +using System; +namespace NetFwTypeLib +{ + public enum NET_FW_PROFILE_TYPE_ + { + NET_FW_PROFILE_DOMAIN, + NET_FW_PROFILE_STANDARD, + NET_FW_PROFILE_CURRENT, + NET_FW_PROFILE_TYPE_MAX + } +} diff --git a/Sunfish/Library/NetFwTypeLib/NET_FW_RULE_DIRECTION_.cs b/Sunfish/Library/NetFwTypeLib/NET_FW_RULE_DIRECTION_.cs new file mode 100644 index 0000000..8c4dca1 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/NET_FW_RULE_DIRECTION_.cs @@ -0,0 +1,10 @@ +using System; +namespace NetFwTypeLib +{ + public enum NET_FW_RULE_DIRECTION_ + { + NET_FW_RULE_DIR_IN = 1, + NET_FW_RULE_DIR_OUT, + NET_FW_RULE_DIR_MAX + } +} diff --git a/Sunfish/Library/NetFwTypeLib/NET_FW_SCOPE_.cs b/Sunfish/Library/NetFwTypeLib/NET_FW_SCOPE_.cs new file mode 100644 index 0000000..89478df --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/NET_FW_SCOPE_.cs @@ -0,0 +1,11 @@ +using System; +namespace NetFwTypeLib +{ + public enum NET_FW_SCOPE_ + { + NET_FW_SCOPE_ALL, + NET_FW_SCOPE_LOCAL_SUBNET, + NET_FW_SCOPE_CUSTOM, + NET_FW_SCOPE_MAX + } +} diff --git a/Sunfish/Library/NetFwTypeLib/NET_FW_SERVICE_TYPE_.cs b/Sunfish/Library/NetFwTypeLib/NET_FW_SERVICE_TYPE_.cs new file mode 100644 index 0000000..019ab13 --- /dev/null +++ b/Sunfish/Library/NetFwTypeLib/NET_FW_SERVICE_TYPE_.cs @@ -0,0 +1,12 @@ +using System; +namespace NetFwTypeLib +{ + public enum NET_FW_SERVICE_TYPE_ + { + NET_FW_SERVICE_FILE_AND_PRINT, + NET_FW_SERVICE_UPNP, + NET_FW_SERVICE_REMOTE_DESKTOP, + NET_FW_SERVICE_NONE, + NET_FW_SERVICE_TYPE_MAX + } +} diff --git a/Sunfish/Middleware/HttpServer.cs b/Sunfish/Middleware/HttpServer.cs new file mode 100644 index 0000000..f619e33 --- /dev/null +++ b/Sunfish/Middleware/HttpServer.cs @@ -0,0 +1,498 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Net; +using System.Security.Principal; +using System.Text; +using System.Threading; +using System.Web; + +namespace DolphinWebXplorer2.Middleware +{ + class HttpServer + { + private int port; + private HttpListener lis = null; + private Thread loop = null; + private List processors = new List(); + private List errors = new List(); + private Processor prc; + //private WindowsFirewallRule fwRule; + public delegate void ErrorEventHandler(HttpServer server, Exception e); + public delegate void Processor(HttpServer server, HttpCall call); + public event ErrorEventHandler Error; + + public HttpServer(int port, Processor prc) + { + this.port = port; + this.prc = prc; + } + + public void Start() + { + if (lis != null) + return; + lis = new HttpListener(); + + // WARNING: This require the server to be launched as administrative process + // This is very problematic due the actions that the server do are width administrator + // rights, even the (future) embedded execution of C#, the file upload and deletion + // and also the execution of server applications. + + lis.Prefixes.Add("http://+:" + port + "/"); + + try + { + lis.Start(); + } + catch (HttpListenerException e) + { + lis = null; + throw e; + } + loop = new Thread(ServerLoop); + loop.Start(); + //fwRule = WindowsFirewall.Allow(port); + } + + private void ServerLoop() + { + for (; ; ) + { + HttpListenerContext ctx = lis.GetContext(); + new Thread(new ParameterizedThreadStart(MultithreadCall)).Start(ctx); + } + } + + private void MultithreadCall(object octx) + { + lock (processors) + { + processors.Add(Thread.CurrentThread); + } + try + { + CallNewProcessor((HttpListenerContext)octx); + } + catch (Exception e) + { + LogError(e); + } + finally + { + lock (processors) + { + processors.Remove(Thread.CurrentThread); + } + } + } + + private void CallNewProcessor(HttpListenerContext ctx) + { + HttpCall call = new HttpCall(ctx); + try + { + prc(this, call); + } + finally + { + call.Response.StatusCode = 500; + call.Close(); + } + } + + public bool Stop() + { + if (lis == null) + return false; + if (loop != null) + { + try { loop.Abort(); } + catch { }; + loop = null; + } + try { lis.Stop(); } + catch { }; + try { lis.Close(); } + catch { }; + try + { + lis = null; + foreach (Thread son in processors.ToArray()) + try { son.Abort(); } + catch { }; + } + finally + { + //WindowsFirewall.Remove(fwRule); + } + return true; + } + + internal void LogError(Exception e) + { + errors.Add(new LogError(e)); + Error?.Invoke(this, e); + } + + public bool Up { get { return lis != null; } } + public int Port { get { return port; } set { port = value; } } + } + + public class HttpCall + { + private static char[] CRLF = { '\r', '\n' }; + private BufferedStream bs; + private StreamWriter swout; + private Dictionary parameters = new Dictionary(); + private Dictionary files = new Dictionary(); + + internal HttpCall(HttpListenerContext ctx) + { + Request = ctx.Request; + Response = ctx.Response; + User = ctx.User; + if ("POST" == Request.HttpMethod) + ProcessPost(Request.InputStream, Request.ContentType, Request.ContentEncoding); + GetHeaders(); + } + + private void GetHeaders() + { + string qs = Request.Url.Query; + if (qs.StartsWith("?")) + ReadEncodedParameters(qs.Substring(1)); + } + + private void ReadEncodedParameters(string qs) + { + string[] args = qs.Split('&'); + foreach (string arg in args) + { + int ppos = arg.IndexOf('='); + if (ppos == -1) + parameters[arg] = "true"; + else + { + string aname = arg.Substring(0, ppos); + string aval = arg.Substring(ppos + 1); + parameters[aname] = HttpUtility.UrlDecode(aval); + } + } + } + + public void OpenOutput(string contentType = null, Encoding encoding = null) + { + if (encoding == null) + encoding = new UTF8Encoding(false); + if (string.IsNullOrEmpty(contentType) || string.IsNullOrWhiteSpace(contentType)) + contentType = Response.ContentType; + if (string.IsNullOrEmpty(contentType) || string.IsNullOrWhiteSpace(contentType)) + contentType = "text/html"; + bs = new BufferedStream(Response.OutputStream); + swout = new StreamWriter(bs, encoding); + Response.ContentType = contentType; + Response.Headers[HttpResponseHeader.ContentType] = contentType; + Response.Headers[HttpResponseHeader.ContentEncoding] = encoding.WebName; + } + + #region POST + private void ProcessPost(Stream input, string contentType, Encoding enc) + { + string[] cttp = contentType.Split(';'); + string ctype = cttp[0]; + Dictionary cttParams = null; + BufferedStream bfs = new BufferedStream(input, 1024 * 1024); + if (cttp.Length > 1) + { + cttParams = new Dictionary(); + for (int i = 1; i < cttp.Length; i++) + { + string[] s = cttp[i].Trim().Split('='); + cttParams[s[0]] = s.Length > 1 ? s[1] : "X"; + } + } + if ("multipart/form-data".Equals(ctype, StringComparison.InvariantCultureIgnoreCase)) + ReadPostMultipart(bfs, cttParams, enc); + else if ("application/x-www-form-urlencoded".Equals(ctype, StringComparison.InvariantCultureIgnoreCase)) + ReadPostForm(bfs, enc); + bfs.Close(); + input.Close(); + } + + private void ReadPostForm(Stream input, Encoding encoding) + { + MemoryStream ms = new MemoryStream(); + byte[] buf = new byte[102400]; + int readed = 0; + while ((readed = input.Read(buf, 0, buf.Length)) > 0) + { + ms.Write(buf, 0, readed); + if (ms.Length > 1024 * 1024) + return; + } + ms.Close(); + string args = encoding.GetString(ms.ToArray()); + ReadEncodedParameters(args); + } + + private void ReadPostMultipart(Stream input, Dictionary cttParams, Encoding encoding) + { + string mimeBoundary = "--" + cttParams["boundary"]; + BinaryReader br = new BinaryReader(input, encoding); + string bnd = ReadLine(br); + if (bnd == mimeBoundary + "--") + return; //empty + if (bnd != mimeBoundary) + throw new Exception("form-data boundary error."); + mimeBoundary = "\r\n" + mimeBoundary; + char[] mimeBoundaryChr = mimeBoundary.ToCharArray(); + byte[] mimeBoundaryBytes = Encoding.ASCII.GetBytes(mimeBoundary); + while (ReadFormData(br, mimeBoundaryChr, mimeBoundaryBytes)) ; + } + + private bool ReadFormData(BinaryReader br, char[] mimeBoundaryChr, byte[] mimeBoundaryBytes) + { + Dictionary hdrs = new Dictionary(); + while (true) + { + string line = ReadLine(br); + if (line.Length == 0) + break; + int dp = line.IndexOf(':'); + if (dp < 0) + throw new Exception("multipart form data error"); + hdrs[line.Substring(0, dp)] = line.Substring(dp + 2); //jump ':' and space + } + Dictionary cdisp = GetContentDisposition(hdrs); + if (hdrs.ContainsKey("Content-Type") || cdisp.ContainsKey("filename")) + { + byte[] data = ReadUntil(br, mimeBoundaryBytes); //TODO: Slow + string fname = cdisp["filename"]; + if (fname.Length > 0) + files[cdisp["name"]] = new HttpPostFile(fname, data, hdrs["Content-Type"]); + } + else + { + string data = ReadStringToBoundary(br, mimeBoundaryChr); + parameters[cdisp["name"]] = data; + } + char ch1 = br.ReadChar(); + char ch2 = br.ReadChar(); + if (ch1 == '\r' && ch2 == '\n') + return true; + if (ch1 == '-' && ch2 == '-') + return false; + throw new Exception("Error reading multipart (" + ch1 + ch2 + ")"); + } + + private static string ReadLine(BinaryReader br) + { + return ReadUntil(br, CRLF); + } + + private static string ReadStringToBoundary(BinaryReader br, char[] mimeBoundaryChr) + { + return ReadUntil(br, mimeBoundaryChr); + } + + private static string ReadUntil(BinaryReader br, char[] signal) + { + List chars = new List(); + while (true) + { + char ch = br.ReadChar(); + chars.Add(ch); + if (chars.Count >= signal.Length) + { + bool eq = true; + for (int i = 0; i < signal.Length; i++) + { + if (signal[i] != chars[(chars.Count - signal.Length) + i]) + { + eq = false; + break; + } + } + if (eq) + { + char[] chs = chars.ToArray(); + return new string(chs, 0, chs.Length - signal.Length); + } + } + } + } + + private static byte[] ReadUntil(BinaryReader br, byte[] signal) + { + MemoryStream ms = new MemoryStream(10240); + int signalIdx = 0; + long end = 0; + byte[] onebyte = new byte[1]; + byte b; + + while (true) + { + b = onebyte[0] = br.ReadByte(); + ms.Write(onebyte, 0, 1); + if (b == signal[signalIdx]) + { + signalIdx++; + if (signalIdx == signal.Length) + { + ms.SetLength(end); + return ms.ToArray(); + } + } + else + { + end += signalIdx + 1; + signalIdx = 0; + } + } + } + + private static Dictionary GetContentDisposition(Dictionary hdrs) + { + if (!hdrs.ContainsKey("Content-Disposition")) + return null; + Dictionary result = new Dictionary(); + foreach (string cd in hdrs["Content-Disposition"].Split(';')) + { + int pos = cd.IndexOf("="); + if (pos < 0) + continue; + string name = cd.Substring(1, pos - 1); + string var = cd.Substring(pos + 1); + if (var.Length > 0 && var[0] == '"') + var = var.Substring(1, var.Length - 2); + result[name] = var; + } + return result; + } + #endregion + + #region Output + + public void Redirect(string to) + { + Response.StatusCode = 307; //Temporary Redirect + Response.Headers["Location"] = to; + } + + public void HTTPBadRequest() + { + Response.StatusCode = 400; + Response.StatusDescription = "Bad Request"; + } + + public void HTTPForbidden() + { + Response.StatusCode = 402; + Response.StatusDescription = "Forbidden"; + } + + public void HTTPNotFound() + { + Response.StatusCode = 404; + Response.StatusDescription = "Not found"; + } + + public void Write(string s) + { + if (s != null) + GetOut().Write(s); + } + + public void Write(object o) + { + if (o != null) + GetOut().Write(o); + } + + public void Write(byte[] data) + { + GetOut().Flush(); + GetOut().BaseStream.Write(data, 0, data.Length); + } + + public void Write(byte[] data, int offset, int count) + { + GetOut().Flush(); + GetOut().BaseStream.Write(data, offset, count); + } + + public void Write(Stream s) + { + GetOut().Flush(); + GetOut().BaseStream.TransferFrom(s); + } + + public void Close() + { + if (swout == null) + GetOut(); + swout.Close(); + } + + #endregion + + private StreamWriter GetOut() + { + if (swout == null) + OpenOutput(); + return swout; + } + + public HttpListenerRequest Request { get; } + public HttpListenerResponse Response { get; } + public IPrincipal User { get; } + public StreamWriter Out => GetOut(); + + public Dictionary Parameters => parameters; + } + + public class LogError + { + public LogError(Exception e) + { + Exception = e; + } + + public DateTime Time { get; } = DateTime.Now; + public Exception Exception { get; } + } + + public class HttpPostFile + { + internal HttpPostFile(string filename, byte[] data, string mimeType) + { + Filename = filename; + MimeType = mimeType; + Data = data; + } + + public string Filename { get; } + public string MimeType { get; } + public byte[] Data { get; } + } + + public static class HttpTools + { + public static string nl2br(string s) + { + return s.Replace("\r\n", "
").Replace("\n", "
").Replace("\r", "
"); + } + + public static string UrlEncode(string url) + { + return HttpUtility.UrlEncode(url); + } + + public static string UrlDecode(string url) + { + return HttpUtility.UrlDecode(url); + } + } +} diff --git a/Sunfish/Middleware/MimeTypes.cs b/Sunfish/Middleware/MimeTypes.cs new file mode 100644 index 0000000..848e9af --- /dev/null +++ b/Sunfish/Middleware/MimeTypes.cs @@ -0,0 +1,589 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DolphinWebXplorer2.Middleware +{ + class MimeTypes + { + private static IDictionary _mappings = new Dictionary(StringComparer.InvariantCultureIgnoreCase) { + + #region Big freaking list of mime types + // combination of values from Windows 7 Registry and + // from C:\Windows\System32\inetsrv\config\applicationHost.config + // some added, including .7z and .dat + {".323", "text/h323"}, + {".3g2", "video/3gpp2"}, + {".3gp", "video/3gpp"}, + {".3gp2", "video/3gpp2"}, + {".3gpp", "video/3gpp"}, + {".7z", "application/x-7z-compressed"}, + {".aa", "audio/audible"}, + {".AAC", "audio/aac"}, + {".aaf", "application/octet-stream"}, + {".aax", "audio/vnd.audible.aax"}, + {".ac3", "audio/ac3"}, + {".aca", "application/octet-stream"}, + {".accda", "application/msaccess.addin"}, + {".accdb", "application/msaccess"}, + {".accdc", "application/msaccess.cab"}, + {".accde", "application/msaccess"}, + {".accdr", "application/msaccess.runtime"}, + {".accdt", "application/msaccess"}, + {".accdw", "application/msaccess.webapplication"}, + {".accft", "application/msaccess.ftemplate"}, + {".acx", "application/internet-property-stream"}, + {".AddIn", "text/xml"}, + {".ade", "application/msaccess"}, + {".adobebridge", "application/x-bridge-url"}, + {".adp", "application/msaccess"}, + {".ADT", "audio/vnd.dlna.adts"}, + {".ADTS", "audio/aac"}, + {".afm", "application/octet-stream"}, + {".ai", "application/postscript"}, + {".aif", "audio/x-aiff"}, + {".aifc", "audio/aiff"}, + {".aiff", "audio/aiff"}, + {".air", "application/vnd.adobe.air-application-installer-package+zip"}, + {".amc", "application/x-mpeg"}, + {".application", "application/x-ms-application"}, + {".art", "image/x-jg"}, + {".asa", "application/xml"}, + {".asax", "application/xml"}, + {".ascx", "application/xml"}, + {".asd", "application/octet-stream"}, + {".asf", "video/x-ms-asf"}, + {".ashx", "application/xml"}, + {".asi", "application/octet-stream"}, + {".asm", "text/plain"}, + {".asmx", "application/xml"}, + {".aspx", "application/xml"}, + {".asr", "video/x-ms-asf"}, + {".asx", "video/x-ms-asf"}, + {".atom", "application/atom+xml"}, + {".au", "audio/basic"}, + {".avi", "video/x-msvideo"}, + {".axs", "application/olescript"}, + {".bas", "text/plain"}, + {".bcpio", "application/x-bcpio"}, + {".bin", "application/octet-stream"}, + {".bmp", "image/bmp"}, + {".c", "text/plain"}, + {".cab", "application/octet-stream"}, + {".caf", "audio/x-caf"}, + {".calx", "application/vnd.ms-office.calx"}, + {".cat", "application/vnd.ms-pki.seccat"}, + {".cc", "text/plain"}, + {".cd", "text/plain"}, + {".cdda", "audio/aiff"}, + {".cdf", "application/x-cdf"}, + {".cer", "application/x-x509-ca-cert"}, + {".chm", "application/octet-stream"}, + {".class", "application/x-java-applet"}, + {".clp", "application/x-msclip"}, + {".cmx", "image/x-cmx"}, + {".cnf", "text/plain"}, + {".cod", "image/cis-cod"}, + {".config", "application/xml"}, + {".contact", "text/x-ms-contact"}, + {".coverage", "application/xml"}, + {".cpio", "application/x-cpio"}, + {".cpp", "text/plain"}, + {".crd", "application/x-mscardfile"}, + {".crl", "application/pkix-crl"}, + {".crt", "application/x-x509-ca-cert"}, + {".cs", "text/plain"}, + {".csdproj", "text/plain"}, + {".csh", "application/x-csh"}, + {".csproj", "text/plain"}, + {".css", "text/css"}, + {".csv", "text/csv"}, + {".cur", "application/octet-stream"}, + {".cxx", "text/plain"}, + {".dat", "application/octet-stream"}, + {".datasource", "application/xml"}, + {".dbproj", "text/plain"}, + {".dcr", "application/x-director"}, + {".def", "text/plain"}, + {".deploy", "application/octet-stream"}, + {".der", "application/x-x509-ca-cert"}, + {".dgml", "application/xml"}, + {".dib", "image/bmp"}, + {".dif", "video/x-dv"}, + {".dir", "application/x-director"}, + {".disco", "text/xml"}, + {".dll", "application/x-msdownload"}, + {".dll.config", "text/xml"}, + {".dlm", "text/dlm"}, + {".doc", "application/msword"}, + {".docm", "application/vnd.ms-word.document.macroEnabled.12"}, + {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, + {".dot", "application/msword"}, + {".dotm", "application/vnd.ms-word.template.macroEnabled.12"}, + {".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, + {".dsp", "application/octet-stream"}, + {".dsw", "text/plain"}, + {".dtd", "text/xml"}, + {".dtsConfig", "text/xml"}, + {".dv", "video/x-dv"}, + {".dvi", "application/x-dvi"}, + {".dwf", "drawing/x-dwf"}, + {".dwp", "application/octet-stream"}, + {".dxr", "application/x-director"}, + {".eml", "message/rfc822"}, + {".emz", "application/octet-stream"}, + {".eot", "application/octet-stream"}, + {".eps", "application/postscript"}, + {".etl", "application/etl"}, + {".etx", "text/x-setext"}, + {".evy", "application/envoy"}, + {".exe", "application/octet-stream"}, + {".exe.config", "text/xml"}, + {".fdf", "application/vnd.fdf"}, + {".fif", "application/fractals"}, + {".filters", "Application/xml"}, + {".fla", "application/octet-stream"}, + {".flr", "x-world/x-vrml"}, + {".flv", "video/x-flv"}, + {".fsscript", "application/fsharp-script"}, + {".fsx", "application/fsharp-script"}, + {".generictest", "application/xml"}, + {".gif", "image/gif"}, + {".group", "text/x-ms-group"}, + {".gsm", "audio/x-gsm"}, + {".gtar", "application/x-gtar"}, + {".gz", "application/x-gzip"}, + {".h", "text/plain"}, + {".hdf", "application/x-hdf"}, + {".hdml", "text/x-hdml"}, + {".hhc", "application/x-oleobject"}, + {".hhk", "application/octet-stream"}, + {".hhp", "application/octet-stream"}, + {".hlp", "application/winhlp"}, + {".hpp", "text/plain"}, + {".hqx", "application/mac-binhex40"}, + {".hta", "application/hta"}, + {".htc", "text/x-component"}, + {".htm", "text/html"}, + {".html", "text/html"}, + {".htt", "text/webviewhtml"}, + {".hxa", "application/xml"}, + {".hxc", "application/xml"}, + {".hxd", "application/octet-stream"}, + {".hxe", "application/xml"}, + {".hxf", "application/xml"}, + {".hxh", "application/octet-stream"}, + {".hxi", "application/octet-stream"}, + {".hxk", "application/xml"}, + {".hxq", "application/octet-stream"}, + {".hxr", "application/octet-stream"}, + {".hxs", "application/octet-stream"}, + {".hxt", "text/html"}, + {".hxv", "application/xml"}, + {".hxw", "application/octet-stream"}, + {".hxx", "text/plain"}, + {".i", "text/plain"}, + {".ico", "image/x-icon"}, + {".ics", "application/octet-stream"}, + {".idl", "text/plain"}, + {".ief", "image/ief"}, + {".iii", "application/x-iphone"}, + {".inc", "text/plain"}, + {".inf", "application/octet-stream"}, + {".inl", "text/plain"}, + {".ins", "application/x-internet-signup"}, + {".ipa", "application/x-itunes-ipa"}, + {".ipg", "application/x-itunes-ipg"}, + {".ipproj", "text/plain"}, + {".ipsw", "application/x-itunes-ipsw"}, + {".iqy", "text/x-ms-iqy"}, + {".isp", "application/x-internet-signup"}, + {".ite", "application/x-itunes-ite"}, + {".itlp", "application/x-itunes-itlp"}, + {".itms", "application/x-itunes-itms"}, + {".itpc", "application/x-itunes-itpc"}, + {".IVF", "video/x-ivf"}, + {".jar", "application/java-archive"}, + {".java", "application/octet-stream"}, + {".jck", "application/liquidmotion"}, + {".jcz", "application/liquidmotion"}, + {".jfif", "image/pjpeg"}, + {".jnlp", "application/x-java-jnlp-file"}, + {".jpb", "application/octet-stream"}, + {".jpe", "image/jpeg"}, + {".jpeg", "image/jpeg"}, + {".jpg", "image/jpeg"}, + {".js", "application/x-javascript"}, + {".json", "application/json"}, + {".jsx", "text/jscript"}, + {".jsxbin", "text/plain"}, + {".latex", "application/x-latex"}, + {".library-ms", "application/windows-library+xml"}, + {".lit", "application/x-ms-reader"}, + {".loadtest", "application/xml"}, + {".lpk", "application/octet-stream"}, + {".lsf", "video/x-la-asf"}, + {".lst", "text/plain"}, + {".lsx", "video/x-la-asf"}, + {".lzh", "application/octet-stream"}, + {".m13", "application/x-msmediaview"}, + {".m14", "application/x-msmediaview"}, + {".m1v", "video/mpeg"}, + {".m2t", "video/vnd.dlna.mpeg-tts"}, + {".m2ts", "video/vnd.dlna.mpeg-tts"}, + {".m2v", "video/mpeg"}, + {".m3u", "audio/x-mpegurl"}, + {".m3u8", "audio/x-mpegurl"}, + {".m4a", "audio/m4a"}, + {".m4b", "audio/m4b"}, + {".m4p", "audio/m4p"}, + {".m4r", "audio/x-m4r"}, + {".m4v", "video/x-m4v"}, + {".mac", "image/x-macpaint"}, + {".mak", "text/plain"}, + {".man", "application/x-troff-man"}, + {".manifest", "application/x-ms-manifest"}, + {".map", "text/plain"}, + {".master", "application/xml"}, + {".mda", "application/msaccess"}, + {".mdb", "application/x-msaccess"}, + {".mde", "application/msaccess"}, + {".mdp", "application/octet-stream"}, + {".me", "application/x-troff-me"}, + {".mfp", "application/x-shockwave-flash"}, + {".mht", "message/rfc822"}, + {".mhtml", "message/rfc822"}, + {".mid", "audio/mid"}, + {".midi", "audio/mid"}, + {".mix", "application/octet-stream"}, + {".mk", "text/plain"}, + {".mmf", "application/x-smaf"}, + {".mno", "text/xml"}, + {".mny", "application/x-msmoney"}, + {".mod", "video/mpeg"}, + {".mov", "video/quicktime"}, + {".movie", "video/x-sgi-movie"}, + {".mp2", "video/mpeg"}, + {".mp2v", "video/mpeg"}, + {".mp3", "audio/mpeg"}, + {".mp4", "video/mp4"}, + {".mp4v", "video/mp4"}, + {".mpa", "video/mpeg"}, + {".mpe", "video/mpeg"}, + {".mpeg", "video/mpeg"}, + {".mpf", "application/vnd.ms-mediapackage"}, + {".mpg", "video/mpeg"}, + {".mpp", "application/vnd.ms-project"}, + {".mpv2", "video/mpeg"}, + {".mqv", "video/quicktime"}, + {".ms", "application/x-troff-ms"}, + {".msi", "application/octet-stream"}, + {".mso", "application/octet-stream"}, + {".mts", "video/vnd.dlna.mpeg-tts"}, + {".mtx", "application/xml"}, + {".mvb", "application/x-msmediaview"}, + {".mvc", "application/x-miva-compiled"}, + {".mxp", "application/x-mmxp"}, + {".nc", "application/x-netcdf"}, + {".nsc", "video/x-ms-asf"}, + {".nws", "message/rfc822"}, + {".ocx", "application/octet-stream"}, + {".oda", "application/oda"}, + {".odc", "text/x-ms-odc"}, + {".odh", "text/plain"}, + {".odl", "text/plain"}, + {".odp", "application/vnd.oasis.opendocument.presentation"}, + {".ods", "application/oleobject"}, + {".odt", "application/vnd.oasis.opendocument.text"}, + {".one", "application/onenote"}, + {".onea", "application/onenote"}, + {".onepkg", "application/onenote"}, + {".onetmp", "application/onenote"}, + {".onetoc", "application/onenote"}, + {".onetoc2", "application/onenote"}, + {".orderedtest", "application/xml"}, + {".osdx", "application/opensearchdescription+xml"}, + {".p10", "application/pkcs10"}, + {".p12", "application/x-pkcs12"}, + {".p7b", "application/x-pkcs7-certificates"}, + {".p7c", "application/pkcs7-mime"}, + {".p7m", "application/pkcs7-mime"}, + {".p7r", "application/x-pkcs7-certreqresp"}, + {".p7s", "application/pkcs7-signature"}, + {".pbm", "image/x-portable-bitmap"}, + {".pcast", "application/x-podcast"}, + {".pct", "image/pict"}, + {".pcx", "application/octet-stream"}, + {".pcz", "application/octet-stream"}, + {".pdf", "application/pdf"}, + {".pfb", "application/octet-stream"}, + {".pfm", "application/octet-stream"}, + {".pfx", "application/x-pkcs12"}, + {".pgm", "image/x-portable-graymap"}, + {".pic", "image/pict"}, + {".pict", "image/pict"}, + {".pkgdef", "text/plain"}, + {".pkgundef", "text/plain"}, + {".pko", "application/vnd.ms-pki.pko"}, + {".pls", "audio/scpls"}, + {".pma", "application/x-perfmon"}, + {".pmc", "application/x-perfmon"}, + {".pml", "application/x-perfmon"}, + {".pmr", "application/x-perfmon"}, + {".pmw", "application/x-perfmon"}, + {".png", "image/png"}, + {".pnm", "image/x-portable-anymap"}, + {".pnt", "image/x-macpaint"}, + {".pntg", "image/x-macpaint"}, + {".pnz", "image/png"}, + {".pot", "application/vnd.ms-powerpoint"}, + {".potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"}, + {".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"}, + {".ppa", "application/vnd.ms-powerpoint"}, + {".ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"}, + {".ppm", "image/x-portable-pixmap"}, + {".pps", "application/vnd.ms-powerpoint"}, + {".ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, + {".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, + {".ppt", "application/vnd.ms-powerpoint"}, + {".pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, + {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, + {".prf", "application/pics-rules"}, + {".prm", "application/octet-stream"}, + {".prx", "application/octet-stream"}, + {".ps", "application/postscript"}, + {".psc1", "application/PowerShell"}, + {".psd", "application/octet-stream"}, + {".psess", "application/xml"}, + {".psm", "application/octet-stream"}, + {".psp", "application/octet-stream"}, + {".pub", "application/x-mspublisher"}, + {".pwz", "application/vnd.ms-powerpoint"}, + {".qht", "text/x-html-insertion"}, + {".qhtm", "text/x-html-insertion"}, + {".qt", "video/quicktime"}, + {".qti", "image/x-quicktime"}, + {".qtif", "image/x-quicktime"}, + {".qtl", "application/x-quicktimeplayer"}, + {".qxd", "application/octet-stream"}, + {".ra", "audio/x-pn-realaudio"}, + {".ram", "audio/x-pn-realaudio"}, + {".rar", "application/octet-stream"}, + {".ras", "image/x-cmu-raster"}, + {".rat", "application/rat-file"}, + {".rc", "text/plain"}, + {".rc2", "text/plain"}, + {".rct", "text/plain"}, + {".rdlc", "application/xml"}, + {".resx", "application/xml"}, + {".rf", "image/vnd.rn-realflash"}, + {".rgb", "image/x-rgb"}, + {".rgs", "text/plain"}, + {".rm", "application/vnd.rn-realmedia"}, + {".rmi", "audio/mid"}, + {".rmp", "application/vnd.rn-rn_music_package"}, + {".roff", "application/x-troff"}, + {".rpm", "audio/x-pn-realaudio-plugin"}, + {".rqy", "text/x-ms-rqy"}, + {".rtf", "application/rtf"}, + {".rtx", "text/richtext"}, + {".ruleset", "application/xml"}, + {".s", "text/plain"}, + {".safariextz", "application/x-safari-safariextz"}, + {".scd", "application/x-msschedule"}, + {".sct", "text/scriptlet"}, + {".sd2", "audio/x-sd2"}, + {".sdp", "application/sdp"}, + {".sea", "application/octet-stream"}, + {".searchConnector-ms", "application/windows-search-connector+xml"}, + {".setpay", "application/set-payment-initiation"}, + {".setreg", "application/set-registration-initiation"}, + {".settings", "application/xml"}, + {".sgimb", "application/x-sgimb"}, + {".sgml", "text/sgml"}, + {".sh", "application/x-sh"}, + {".shar", "application/x-shar"}, + {".shtml", "text/html"}, + {".sit", "application/x-stuffit"}, + {".sitemap", "application/xml"}, + {".skin", "application/xml"}, + {".sldm", "application/vnd.ms-powerpoint.slide.macroEnabled.12"}, + {".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"}, + {".slk", "application/vnd.ms-excel"}, + {".sln", "text/plain"}, + {".slupkg-ms", "application/x-ms-license"}, + {".smd", "audio/x-smd"}, + {".smi", "application/octet-stream"}, + {".smx", "audio/x-smd"}, + {".smz", "audio/x-smd"}, + {".snd", "audio/basic"}, + {".snippet", "application/xml"}, + {".snp", "application/octet-stream"}, + {".sol", "text/plain"}, + {".sor", "text/plain"}, + {".spc", "application/x-pkcs7-certificates"}, + {".spl", "application/futuresplash"}, + {".src", "application/x-wais-source"}, + {".srf", "text/plain"}, + {".SSISDeploymentManifest", "text/xml"}, + {".ssm", "application/streamingmedia"}, + {".sst", "application/vnd.ms-pki.certstore"}, + {".stl", "application/vnd.ms-pki.stl"}, + {".sv4cpio", "application/x-sv4cpio"}, + {".sv4crc", "application/x-sv4crc"}, + {".svc", "application/xml"}, + {".swf", "application/x-shockwave-flash"}, + {".t", "application/x-troff"}, + {".tar", "application/x-tar"}, + {".tcl", "application/x-tcl"}, + {".testrunconfig", "application/xml"}, + {".testsettings", "application/xml"}, + {".tex", "application/x-tex"}, + {".texi", "application/x-texinfo"}, + {".texinfo", "application/x-texinfo"}, + {".tgz", "application/x-compressed"}, + {".thmx", "application/vnd.ms-officetheme"}, + {".thn", "application/octet-stream"}, + {".tif", "image/tiff"}, + {".tiff", "image/tiff"}, + {".tlh", "text/plain"}, + {".tli", "text/plain"}, + {".toc", "application/octet-stream"}, + {".tr", "application/x-troff"}, + {".trm", "application/x-msterminal"}, + {".trx", "application/xml"}, + {".ts", "video/vnd.dlna.mpeg-tts"}, + {".tsv", "text/tab-separated-values"}, + {".ttf", "application/octet-stream"}, + {".tts", "video/vnd.dlna.mpeg-tts"}, + {".txt", "text/plain"}, + {".u32", "application/octet-stream"}, + {".uls", "text/iuls"}, + {".user", "text/plain"}, + {".ustar", "application/x-ustar"}, + {".vb", "text/plain"}, + {".vbdproj", "text/plain"}, + {".vbk", "video/mpeg"}, + {".vbproj", "text/plain"}, + {".vbs", "text/vbscript"}, + {".vcf", "text/x-vcard"}, + {".vcproj", "Application/xml"}, + {".vcs", "text/plain"}, + {".vcxproj", "Application/xml"}, + {".vddproj", "text/plain"}, + {".vdp", "text/plain"}, + {".vdproj", "text/plain"}, + {".vdx", "application/vnd.ms-visio.viewer"}, + {".vml", "text/xml"}, + {".vscontent", "application/xml"}, + {".vsct", "text/xml"}, + {".vsd", "application/vnd.visio"}, + {".vsi", "application/ms-vsi"}, + {".vsix", "application/vsix"}, + {".vsixlangpack", "text/xml"}, + {".vsixmanifest", "text/xml"}, + {".vsmdi", "application/xml"}, + {".vspscc", "text/plain"}, + {".vss", "application/vnd.visio"}, + {".vsscc", "text/plain"}, + {".vssettings", "text/xml"}, + {".vssscc", "text/plain"}, + {".vst", "application/vnd.visio"}, + {".vstemplate", "text/xml"}, + {".vsto", "application/x-ms-vsto"}, + {".vsw", "application/vnd.visio"}, + {".vsx", "application/vnd.visio"}, + {".vtx", "application/vnd.visio"}, + {".wav", "audio/wav"}, + {".wave", "audio/wav"}, + {".wax", "audio/x-ms-wax"}, + {".wbk", "application/msword"}, + {".wbmp", "image/vnd.wap.wbmp"}, + {".wcm", "application/vnd.ms-works"}, + {".wdb", "application/vnd.ms-works"}, + {".wdp", "image/vnd.ms-photo"}, + {".webarchive", "application/x-safari-webarchive"}, + {".webtest", "application/xml"}, + {".wiq", "application/xml"}, + {".wiz", "application/msword"}, + {".wks", "application/vnd.ms-works"}, + {".WLMP", "application/wlmoviemaker"}, + {".wlpginstall", "application/x-wlpg-detect"}, + {".wlpginstall3", "application/x-wlpg3-detect"}, + {".wm", "video/x-ms-wm"}, + {".wma", "audio/x-ms-wma"}, + {".wmd", "application/x-ms-wmd"}, + {".wmf", "application/x-msmetafile"}, + {".wml", "text/vnd.wap.wml"}, + {".wmlc", "application/vnd.wap.wmlc"}, + {".wmls", "text/vnd.wap.wmlscript"}, + {".wmlsc", "application/vnd.wap.wmlscriptc"}, + {".wmp", "video/x-ms-wmp"}, + {".wmv", "video/x-ms-wmv"}, + {".wmx", "video/x-ms-wmx"}, + {".wmz", "application/x-ms-wmz"}, + {".wpl", "application/vnd.ms-wpl"}, + {".wps", "application/vnd.ms-works"}, + {".wri", "application/x-mswrite"}, + {".wrl", "x-world/x-vrml"}, + {".wrz", "x-world/x-vrml"}, + {".wsc", "text/scriptlet"}, + {".wsdl", "text/xml"}, + {".wvx", "video/x-ms-wvx"}, + {".x", "application/directx"}, + {".xaf", "x-world/x-vrml"}, + {".xaml", "application/xaml+xml"}, + {".xap", "application/x-silverlight-app"}, + {".xbap", "application/x-ms-xbap"}, + {".xbm", "image/x-xbitmap"}, + {".xdr", "text/plain"}, + {".xht", "application/xhtml+xml"}, + {".xhtml", "application/xhtml+xml"}, + {".xla", "application/vnd.ms-excel"}, + {".xlam", "application/vnd.ms-excel.addin.macroEnabled.12"}, + {".xlc", "application/vnd.ms-excel"}, + {".xld", "application/vnd.ms-excel"}, + {".xlk", "application/vnd.ms-excel"}, + {".xll", "application/vnd.ms-excel"}, + {".xlm", "application/vnd.ms-excel"}, + {".xls", "application/vnd.ms-excel"}, + {".xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, + {".xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"}, + {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, + {".xlt", "application/vnd.ms-excel"}, + {".xltm", "application/vnd.ms-excel.template.macroEnabled.12"}, + {".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, + {".xlw", "application/vnd.ms-excel"}, + {".xml", "text/xml"}, + {".xmta", "application/xml"}, + {".xof", "x-world/x-vrml"}, + {".XOML", "text/plain"}, + {".xpm", "image/x-xpixmap"}, + {".xps", "application/vnd.ms-xpsdocument"}, + {".xrm-ms", "text/xml"}, + {".xsc", "application/xml"}, + {".xsd", "text/xml"}, + {".xsf", "text/xml"}, + {".xsl", "text/xml"}, + {".xslt", "text/xml"}, + {".xsn", "application/octet-stream"}, + {".xss", "application/xml"}, + {".xtp", "application/octet-stream"}, + {".xwd", "image/x-xwindowdump"}, + {".z", "application/x-compress"}, + {".zip", "application/x-zip-compressed"}, + #endregion + + }; + + public static string GetMimeType(string extension) + { + if (!extension.StartsWith(".")) + extension = "." + extension; + string mime; + return _mappings.TryGetValue(extension, out mime) ? mime : "application/octet-stream"; + } + } +} diff --git a/Sunfish/Middleware/Templater.cs b/Sunfish/Middleware/Templater.cs new file mode 100644 index 0000000..004d6cd --- /dev/null +++ b/Sunfish/Middleware/Templater.cs @@ -0,0 +1,193 @@ +using Microsoft.SqlServer.Server; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace DolphinWebXplorer2.Middleware +{ + public class Templater + { + enum TempaltePartMode + { + Literal, Value, Start, End, Call + } + + class TemplatePart + { + public TempaltePartMode Mode; + public string Key; + + public TemplatePart(TempaltePartMode mode, string key) + { + Mode = mode; + Key = key; + } + public override string ToString() + { + return "Part <" + Mode + " " + Key + ">"; + } + } + + private List parts = new List(); + + public Templater(string template) + { + Tokenize(template); + } + + private void Tokenize(string templ) //Can be optimized with indexOf?? + { + parts.Clear(); + StringBuilder sb = new StringBuilder(); + bool key = false; + for (int i = 0; i < templ.Length; i++) + { + char c = templ[i]; + if (!key && c == '{') + { + key = true; + string p = sb.ToString(); + if (!string.IsNullOrWhiteSpace(p)) + parts.Add(new TemplatePart(TempaltePartMode.Literal, p)); + sb.Clear(); + } + else if (key && c == '}') + { + key = false; + string p = sb.ToString().Trim(); + if (p.Length > 0) + if (p.StartsWith("@")) + parts.Add(new TemplatePart(TempaltePartMode.Start, p.Substring(1))); + else if (p.StartsWith("%")) + parts.Add(new TemplatePart(TempaltePartMode.Call, p.Substring(1))); + else if (p == "/") + parts.Add(new TemplatePart(TempaltePartMode.End, null)); + else if (p == "{") + parts.Add(new TemplatePart(TempaltePartMode.Literal, p)); + else parts.Add(new TemplatePart(TempaltePartMode.Value, p)); + sb.Clear(); + } + else + sb.Append(c); + } + if (sb.Length > 0) + if (key) + throw new Exception("Template placeholder not closed"); + else + parts.Add(new TemplatePart(TempaltePartMode.Literal, sb.ToString().Trim())); + } + + private object GetValue(string key, object[] data) + { + if (key == "AppName") + return "Sunfish"; + if (key == "AppVersion") + return Program.VERSION; + foreach (object o in data) + { + if (o == null) + continue; + if (o is Dictionary) + { + Dictionary d = (Dictionary)o; + object v; + if (d.TryGetValue(key, out v)) + return v; + } + else + { + Type t = o.GetType(); + try + { + PropertyInfo p = t.GetProperty(key); + if (p != null) + { + object v = p.GetValue(o); + return v; + } + } + catch { }; + } + } + return null; + } + + public string Process(params object[] data) + { + StringBuilder sb = new StringBuilder(); + int level = 0; + int ignore = int.MaxValue; + foreach (TemplatePart s in parts) + { + switch (s.Mode) + { + case TempaltePartMode.Value: + if (level < ignore) + { + string v = GetValue(s.Key, data)?.ToString(); + if (!string.IsNullOrEmpty(v)) + sb.Append(v); + } + break; + case TempaltePartMode.Literal: + if (level < ignore) + sb.Append(s.Key); + break; + case TempaltePartMode.Start: + level++; + if (level < ignore) + { + object v = GetValue(s.Key, data); + if (v == null || (v is string && ((string)v).Length == 0)) + ignore = level; + } + break; + case TempaltePartMode.End: + level--; + if (level < ignore) + ignore = int.MaxValue; + break; + case TempaltePartMode.Call: + if (level < ignore) + { + string[] cmd = s.Key.Split(':'); + if (cmd.Length != 2) + throw new Exception("Template call placeholder format is :