From d6242fb49beaa8a233322dbc916ea194439edd7a Mon Sep 17 00:00:00 2001
From: next-autumn <next-autumn@google.com>
Date: Wed, 17 Mar 2021 11:58:56 +0800
Subject: [PATCH] update subscrible and share link

---
 .../Developers/ConfigBuilder.cs               |  10 +-
 .../Developers/IParameters.cs                 |   2 +-
 .../Developers/Project.cs                     |   3 +-
 .../Developers/XrayProject.cs                 |   2 +-
 ProxySU_Core/Models/ShareLink.cs              | 170 ++++++++++++++++++
 ProxySU_Core/Models/XraySettings.cs           |   9 +-
 ProxySU_Core/ProxySU_Core.csproj              |  19 +-
 .../server/05_inbounds/Trojan_WS_TLS.json     |  28 +++
 ProxySU_Core/ViewModels/HostViewModel.cs      |   1 +
 ProxySU_Core/ViewModels/RecordViewModel.cs    |  12 ++
 .../ViewModels/XraySettingsViewModel.cs       | 148 +--------------
 ProxySU_Core/Views/MainWindow.xaml            |  24 ++-
 ProxySU_Core/Views/MainWindow.xaml.cs         |  32 +++-
 ProxySU_Core/Views/TerminalWindow.xaml.cs     |   2 +-
 ProxySU_Core/Views/TextBoxWindow.xaml         |  17 ++
 ProxySU_Core/Views/TextBoxWindow.xaml.cs      |  33 ++++
 16 files changed, 347 insertions(+), 165 deletions(-)
 rename ProxySU_Core/{ViewModels => Models}/Developers/ConfigBuilder.cs (96%)
 rename ProxySU_Core/{ViewModels => Models}/Developers/IParameters.cs (80%)
 rename ProxySU_Core/{ViewModels => Models}/Developers/Project.cs (99%)
 rename ProxySU_Core/{ViewModels => Models}/Developers/XrayProject.cs (99%)
 create mode 100644 ProxySU_Core/Models/ShareLink.cs
 create mode 100644 ProxySU_Core/Templates/xray/server/05_inbounds/Trojan_WS_TLS.json
 create mode 100644 ProxySU_Core/Views/TextBoxWindow.xaml
 create mode 100644 ProxySU_Core/Views/TextBoxWindow.xaml.cs

diff --git a/ProxySU_Core/ViewModels/Developers/ConfigBuilder.cs b/ProxySU_Core/Models/Developers/ConfigBuilder.cs
similarity index 96%
rename from ProxySU_Core/ViewModels/Developers/ConfigBuilder.cs
rename to ProxySU_Core/Models/Developers/ConfigBuilder.cs
index 5748161..c7e8723 100644
--- a/ProxySU_Core/ViewModels/Developers/ConfigBuilder.cs
+++ b/ProxySU_Core/Models/Developers/ConfigBuilder.cs
@@ -6,7 +6,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Text;
 
-namespace ProxySU_Core.ViewModels.Developers
+namespace ProxySU_Core.Models.Developers
 {
     public class ConfigBuilder
     {
@@ -96,16 +96,10 @@ namespace ProxySU_Core.ViewModels.Developers
                 xver = 1,
             }));
             xrayConfig.inbounds.Add(baseBound);
-
-            if (parameters.Types.Contains(XrayType.VLESS_TCP_XTLS))
-            {
-                baseBound.settings.clients[0].id = parameters.UUID;
-            }
+            baseBound.settings.clients[0].id = parameters.UUID;
 
             if (parameters.Types.Contains(XrayType.VLESS_WS_TLS))
             {
-                baseBound.settings.clients[0].id = parameters.UUID;
-
                 var wsInbound = LoadJsonObj(Path.Combine(ServerInboundsDir, "VLESS_WS_TLS.json"));
                 wsInbound.port = VLESS_WS_Port;
                 wsInbound.settings.clients[0].id = parameters.UUID;
diff --git a/ProxySU_Core/ViewModels/Developers/IParameters.cs b/ProxySU_Core/Models/Developers/IParameters.cs
similarity index 80%
rename from ProxySU_Core/ViewModels/Developers/IParameters.cs
rename to ProxySU_Core/Models/Developers/IParameters.cs
index c54bcbf..11554c0 100644
--- a/ProxySU_Core/ViewModels/Developers/IParameters.cs
+++ b/ProxySU_Core/Models/Developers/IParameters.cs
@@ -2,7 +2,7 @@
 using System.Collections.Generic;
 using System.Text;
 
-namespace ProxySU_Core.ViewModels.Developers
+namespace ProxySU_Core.Models.Developers
 {
     public interface IParameters
     {
diff --git a/ProxySU_Core/ViewModels/Developers/Project.cs b/ProxySU_Core/Models/Developers/Project.cs
similarity index 99%
rename from ProxySU_Core/ViewModels/Developers/Project.cs
rename to ProxySU_Core/Models/Developers/Project.cs
index 61aba94..c0bc53a 100644
--- a/ProxySU_Core/ViewModels/Developers/Project.cs
+++ b/ProxySU_Core/Models/Developers/Project.cs
@@ -1,4 +1,5 @@
 using ProxySU_Core.Tools;
+using ProxySU_Core.ViewModels;
 using Renci.SshNet;
 using System;
 using System.Collections.Generic;
@@ -9,7 +10,7 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 
-namespace ProxySU_Core.ViewModels.Developers
+namespace ProxySU_Core.Models.Developers
 {
     public enum CmdType
     {
diff --git a/ProxySU_Core/ViewModels/Developers/XrayProject.cs b/ProxySU_Core/Models/Developers/XrayProject.cs
similarity index 99%
rename from ProxySU_Core/ViewModels/Developers/XrayProject.cs
rename to ProxySU_Core/Models/Developers/XrayProject.cs
index 1d028e1..4c65360 100644
--- a/ProxySU_Core/ViewModels/Developers/XrayProject.cs
+++ b/ProxySU_Core/Models/Developers/XrayProject.cs
@@ -8,7 +8,7 @@ using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
 using ProxySU_Core.Models;
 
-namespace ProxySU_Core.ViewModels.Developers
+namespace ProxySU_Core.Models.Developers
 {
     public class XrayProject : Project<XraySettings>
     {
diff --git a/ProxySU_Core/Models/ShareLink.cs b/ProxySU_Core/Models/ShareLink.cs
new file mode 100644
index 0000000..dec2823
--- /dev/null
+++ b/ProxySU_Core/Models/ShareLink.cs
@@ -0,0 +1,170 @@
+using Newtonsoft.Json;
+using ProxySU_Core.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+
+namespace ProxySU_Core.Models
+{
+    public class ShareLink
+    {
+        public static string Build(XrayType xrayType, XraySettings settings)
+        {
+            switch (xrayType)
+            {
+                case XrayType.VLESS_TCP_TLS:
+                case XrayType.VLESS_TCP_XTLS:
+                case XrayType.VLESS_WS_TLS:
+                case XrayType.Trojan_TCP_TLS:
+                    return BuildVlessShareLink(xrayType, settings);
+                case XrayType.VMESS_TCP_TLS:
+                case XrayType.VMESS_WS_TLS:
+                    return BuildVmessShareLink(xrayType, settings);
+                default:
+                    return string.Empty;
+            }
+        }
+
+
+        private static string BuildVmessShareLink(XrayType xrayType, XraySettings settings)
+        {
+            var vmess = new Vmess
+            {
+                v = "2",
+                add = settings.Domain,
+                port = settings.Port.ToString(),
+                id = settings.UUID,
+                aid = "0",
+                net = "",
+                type = "none",
+                host = settings.Domain,
+                path = "",
+                tls = "tls",
+                ps = "",
+            };
+
+
+            switch (xrayType)
+            {
+                case XrayType.VMESS_TCP_TLS:
+                    vmess.ps = "vmess-tcp-tls";
+                    vmess.net = "tcp";
+                    vmess.type = "http";
+                    vmess.path = settings.VMESS_TCP_Path;
+                    break;
+                case XrayType.VMESS_WS_TLS:
+                    vmess.ps = "vmess-ws-tls";
+                    vmess.net = "ws";
+                    vmess.type = "none";
+                    vmess.path = settings.VMESS_WS_Path;
+                    break;
+                default:
+                    return string.Empty;
+            }
+
+            var base64Url = Base64.Encode(JsonConvert.SerializeObject(vmess));
+            return $"vmess://" + base64Url;
+        }
+
+        private static string BuildVlessShareLink(XrayType xrayType, XraySettings settings)
+        {
+            var _protocol = string.Empty;
+            var _uuid = settings.UUID;
+            var _domain = settings.Domain;
+            var _port = settings.Port;
+            var _type = string.Empty;
+            var _encryption = string.Empty;
+            var _security = "tls";
+            var _path = "/";
+            var _host = settings.Domain;
+            var _descriptiveText = string.Empty;
+
+            switch (xrayType)
+            {
+                case XrayType.VLESS_TCP_TLS:
+                    _protocol = "vless";
+                    _type = "tcp";
+                    _path = settings.VLESS_TCP_Path;
+                    _encryption = "none";
+                    _descriptiveText = "vless-tcp-tls";
+                    break;
+                case XrayType.VLESS_TCP_XTLS:
+                    _protocol = "vless";
+                    _type = "tcp";
+                    _security = "xtls";
+                    _encryption = "none";
+                    _descriptiveText = "vless-tcp-xtls";
+                    break;
+                case XrayType.VLESS_WS_TLS:
+                    _protocol = "vless";
+                    _type = "ws";
+                    _path = settings.VLESS_WS_Path;
+                    _encryption = "none";
+                    _descriptiveText = "vless-ws-tls";
+                    break;
+                case XrayType.VMESS_TCP_TLS:
+                    _protocol = "vmess";
+                    _type = "tcp";
+                    _path = settings.VMESS_TCP_Path;
+                    _encryption = "auto";
+                    _descriptiveText = "vmess-tcp-tls";
+                    break;
+                case XrayType.VMESS_WS_TLS:
+                    _protocol = "vmess";
+                    _type = "ws";
+                    _path = settings.VMESS_WS_Path;
+                    _encryption = "auto";
+                    _descriptiveText = "vmess-ws-tls";
+                    break;
+                case XrayType.Trojan_TCP_TLS:
+                    _protocol = "trojan";
+                    _descriptiveText = "trojan-tcp";
+                    break;
+                default:
+                    throw new Exception("暂未实现的协议");
+            }
+
+
+            string parametersURL = string.Empty;
+            if (xrayType != XrayType.Trojan_TCP_TLS)
+            {
+                // 4.3 传输层相关段
+                parametersURL = $"?type={_type}&encryption={_encryption}&security={_security}&host={_host}&path={HttpUtility.UrlEncode(_path)}";
+
+
+                // if mKCP
+                // if QUIC
+
+                // 4.4 TLS 相关段
+                if (xrayType == XrayType.VLESS_TCP_XTLS)
+                {
+                    parametersURL += "&flow=xtls-rprx-direct";
+                }
+            }
+
+
+            return $"{_protocol}://{HttpUtility.UrlEncode(_uuid)}@{_domain}:{_port}{parametersURL}#{HttpUtility.UrlEncode(_descriptiveText)}";
+        }
+
+    }
+
+
+
+    class Vmess
+    {
+        public string v { get; set; }
+        public string ps { get; set; }
+        public string add { get; set; }
+        public string port { get; set; }
+        public string id { get; set; }
+        public string aid { get; set; }
+        public string net { get; set; }
+        public string type { get; set; }
+        public string host { get; set; }
+        public string path { get; set; }
+        public string tls { get; set; }
+    }
+}
diff --git a/ProxySU_Core/Models/XraySettings.cs b/ProxySU_Core/Models/XraySettings.cs
index 2b1206f..36b914f 100644
--- a/ProxySU_Core/Models/XraySettings.cs
+++ b/ProxySU_Core/Models/XraySettings.cs
@@ -1,9 +1,12 @@
-using ProxySU_Core.ViewModels.Developers;
+using Newtonsoft.Json;
+using ProxySU_Core.Common;
+using ProxySU_Core.Models.Developers;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using System.Web;
 
 namespace ProxySU_Core.Models
 {
@@ -15,7 +18,7 @@ namespace ProxySU_Core.Models
             var guid = Guid.NewGuid().ToString();
             Port = 443;
             UUID = guid;
-            Types = new List<XrayType> { XrayType.VLESS_TCP_XTLS };
+            Types = new List<XrayType>();
             VLESS_WS_Path = "/vlessws";
             VLESS_TCP_Path = "/vlesstcp";
             VMESS_WS_Path = "/vmessws";
@@ -94,8 +97,10 @@ namespace ProxySU_Core.Models
                     return string.Empty;
             }
         }
+
     }
 
+
     public enum XrayType
     {
         VLESS_TCP_TLS,
diff --git a/ProxySU_Core/ProxySU_Core.csproj b/ProxySU_Core/ProxySU_Core.csproj
index abc4170..c7f9b9e 100644
--- a/ProxySU_Core/ProxySU_Core.csproj
+++ b/ProxySU_Core/ProxySU_Core.csproj
@@ -120,15 +120,16 @@
     <Compile Include="Common\Base64.cs" />
     <Compile Include="Converters\LoginSecretTypeConverter.cs" />
     <Compile Include="Models\Host.cs" />
+    <Compile Include="Models\ShareLink.cs" />
     <Compile Include="Models\XraySettings.cs" />
     <Compile Include="Tools\DateTimeUtils.cs" />
     <Compile Include="Tools\Extensions.cs" />
     <Compile Include="ViewModels\BaseCommand.cs" />
     <Compile Include="ViewModels\BaseViewModel.cs" />
-    <Compile Include="ViewModels\Developers\ConfigBuilder.cs" />
-    <Compile Include="ViewModels\Developers\IParameters.cs" />
-    <Compile Include="ViewModels\Developers\Project.cs" />
-    <Compile Include="ViewModels\Developers\XrayProject.cs" />
+    <Compile Include="Models\Developers\ConfigBuilder.cs" />
+    <Compile Include="Models\Developers\IParameters.cs" />
+    <Compile Include="Models\Developers\Project.cs" />
+    <Compile Include="Models\Developers\XrayProject.cs" />
     <Compile Include="ViewModels\HostViewModel.cs" />
     <Compile Include="Models\LocalProxy.cs" />
     <Compile Include="Models\LocalProxyType.cs" />
@@ -149,6 +150,9 @@
     <Compile Include="Views\TerminalWindow.xaml.cs">
       <DependentUpon>TerminalWindow.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Views\TextBoxWindow.xaml.cs">
+      <DependentUpon>TextBoxWindow.xaml</DependentUpon>
+    </Compile>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Converters\ProxyTypeConverter.cs" />
@@ -237,6 +241,9 @@
     <None Include="Templates\xray\server\05_inbounds\Trojan_TCP_TLS.json">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
+    <None Include="Templates\xray\server\05_inbounds\Trojan_WS_TLS.json">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
     <None Include="Templates\xray\server\05_inbounds\VLESS_TCP_XTLS.json">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
@@ -294,6 +301,10 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="Views\TextBoxWindow.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Data\" />
diff --git a/ProxySU_Core/Templates/xray/server/05_inbounds/Trojan_WS_TLS.json b/ProxySU_Core/Templates/xray/server/05_inbounds/Trojan_WS_TLS.json
new file mode 100644
index 0000000..229a245
--- /dev/null
+++ b/ProxySU_Core/Templates/xray/server/05_inbounds/Trojan_WS_TLS.json
@@ -0,0 +1,28 @@
+{
+  "port": 1320,
+  "listen": "127.0.0.1",
+  "protocol": "trojan",
+  "settings": {
+    "clients": [
+      {
+        "password": "",
+        "level": 0,
+        "email": "love@example.com"
+      }
+    ],
+    "fallbacks": [
+      {
+        "dest": 80
+      }
+    ]
+  },
+
+  "streamSettings": {
+    "network": "ws",
+    "security": "none",
+    "wsSettings": {
+      "acceptProxyProtocol": true,
+      "path": "/trojanws"
+    }
+  }
+}
diff --git a/ProxySU_Core/ViewModels/HostViewModel.cs b/ProxySU_Core/ViewModels/HostViewModel.cs
index 1d06af0..04ceb62 100644
--- a/ProxySU_Core/ViewModels/HostViewModel.cs
+++ b/ProxySU_Core/ViewModels/HostViewModel.cs
@@ -15,6 +15,7 @@ namespace ProxySU_Core.ViewModels
 
         private readonly ICommand _selectKeyCommand;
 
+
         public HostViewModel(Host host)
         {
             _selectKeyCommand = new BaseCommand(obj => OpenFileDialog(obj));
diff --git a/ProxySU_Core/ViewModels/RecordViewModel.cs b/ProxySU_Core/ViewModels/RecordViewModel.cs
index 70f0b81..e2270be 100644
--- a/ProxySU_Core/ViewModels/RecordViewModel.cs
+++ b/ProxySU_Core/ViewModels/RecordViewModel.cs
@@ -11,10 +11,22 @@ namespace ProxySU_Core.ViewModels
     public class RecordViewModel : BaseViewModel
     {
         public Record record;
+        private bool _isChecked;
 
         public RecordViewModel(Record record)
         {
             this.record = record;
+            this._isChecked = false;
+        }
+
+        public bool IsChecked
+        {
+            get => _isChecked;
+            set
+            {
+                _isChecked = value;
+                Notify("IsChecked");
+            }
         }
 
         public Host Host
diff --git a/ProxySU_Core/ViewModels/XraySettingsViewModel.cs b/ProxySU_Core/ViewModels/XraySettingsViewModel.cs
index 9f00785..54d1435 100644
--- a/ProxySU_Core/ViewModels/XraySettingsViewModel.cs
+++ b/ProxySU_Core/ViewModels/XraySettingsViewModel.cs
@@ -1,7 +1,6 @@
 using Newtonsoft.Json;
 using ProxySU_Core.Common;
 using ProxySU_Core.Models;
-using ProxySU_Core.ViewModels.Developers;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -239,164 +238,29 @@ namespace ProxySU_Core.ViewModels
 
         public string VLESS_TCP_XTLS_ShareLink
         {
-            get => BuildVlessShareLink(XrayType.VLESS_TCP_XTLS);
+            get => ShareLink.Build(XrayType.VLESS_TCP_XTLS, settings);
         }
         public string VLESS_TCP_TLS_ShareLink
         {
-            get => BuildVlessShareLink(XrayType.VLESS_TCP_TLS);
+            get => ShareLink.Build(XrayType.VLESS_TCP_TLS, settings);
         }
         public string VLESS_WS_TLS_ShareLink
         {
-            get => BuildVlessShareLink(XrayType.VLESS_WS_TLS);
+            get => ShareLink.Build(XrayType.VLESS_WS_TLS, settings);
         }
         public string VMESS_TCP_TLS_ShareLink
         {
-            get => BuildVmessShareLink(XrayType.VMESS_TCP_TLS);
+            get => ShareLink.Build(XrayType.VMESS_TCP_TLS, settings);
         }
         public string VMESS_WS_TLS_ShareLink
         {
-            get => BuildVmessShareLink(XrayType.VMESS_WS_TLS);
+            get => ShareLink.Build(XrayType.VMESS_WS_TLS, settings);
         }
         public string Trojan_TCP_TLS_ShareLink
         {
-            get => BuildVlessShareLink(XrayType.Trojan_TCP_TLS);
+            get => ShareLink.Build(XrayType.Trojan_TCP_TLS, settings);
         }
 
-        public string BuildVmessShareLink(XrayType xrayType)
-        {
-            var vmess = new Vmess
-            {
-                v = "2",
-                add = settings.Domain,
-                port = settings.Port.ToString(),
-                id = settings.UUID,
-                aid = "0",
-                net = "",
-                type = "none",
-                host = settings.Domain,
-                path = "",
-                tls = "tls",
-                ps = "",
-            };
-
-
-            switch (xrayType)
-            {
-                case XrayType.VMESS_TCP_TLS:
-                    vmess.ps = "vmess-tcp-tls";
-                    vmess.net = "tcp";
-                    vmess.type = "http";
-                    vmess.path = VMESS_TCP_Path;
-                    break;
-                case XrayType.VMESS_WS_TLS:
-                    vmess.ps = "vmess-ws-tls";
-                    vmess.net = "ws";
-                    vmess.type = "none";
-                    vmess.path = VMESS_WS_Path;
-                    break;
-                default:
-                    return string.Empty;
-            }
-
-            var base64Url = Base64.Encode(JsonConvert.SerializeObject(vmess));
-            return $"vmess://" + base64Url;
-        }
-
-        public string BuildVlessShareLink(XrayType xrayType)
-        {
-            var _protocol = string.Empty;
-            var _uuid = settings.UUID;
-            var _domain = settings.Domain;
-            var _port = settings.Port;
-            var _type = string.Empty;
-            var _encryption = string.Empty;
-            var _security = "tls";
-            var _path = "/";
-            var _host = settings.Domain;
-            var _descriptiveText = string.Empty;
-
-            switch (xrayType)
-            {
-                case XrayType.VLESS_TCP_TLS:
-                    _protocol = "vless";
-                    _type = "tcp";
-                    _path = VLESS_TCP_Path;
-                    _encryption = "none";
-                    _descriptiveText = "vless-tcp-tls";
-                    break;
-                case XrayType.VLESS_TCP_XTLS:
-                    _protocol = "vless";
-                    _type = "tcp";
-                    _security = "xtls";
-                    _encryption = "none";
-                    _descriptiveText = "vless-tcp-xtls";
-                    break;
-                case XrayType.VLESS_WS_TLS:
-                    _protocol = "vless";
-                    _type = "ws";
-                    _path = VLESS_WS_Path;
-                    _encryption = "none";
-                    _descriptiveText = "vless-ws-tls";
-                    break;
-                case XrayType.VMESS_TCP_TLS:
-                    _protocol = "vmess";
-                    _type = "tcp";
-                    _path = VMESS_TCP_Path;
-                    _encryption = "auto";
-                    _descriptiveText = "vmess-tcp-tls";
-                    break;
-                case XrayType.VMESS_WS_TLS:
-                    _protocol = "vmess";
-                    _type = "ws";
-                    _path = VMESS_WS_Path;
-                    _encryption = "auto";
-                    _descriptiveText = "vmess-ws-tls";
-                    break;
-                case XrayType.Trojan_TCP_TLS:
-                    _protocol = "trojan";
-                    _descriptiveText = "trojan-tcp";
-                    break;
-                default:
-                    throw new Exception("暂未实现的协议");
-            }
-
-
-            string parametersURL = string.Empty;
-            if (xrayType != XrayType.Trojan_TCP_TLS)
-            {
-                // 4.3 传输层相关段
-                parametersURL = $"?type={_type}&encryption={_encryption}&security={_security}&host={_host}&path={HttpUtility.UrlEncode(_path)}";
-
-
-                // if mKCP
-                // if QUIC
-
-                // 4.4 TLS 相关段
-                if (xrayType == XrayType.VLESS_TCP_XTLS)
-                {
-                    parametersURL += "&flow=xtls-rprx-direct";
-                }
-            }
-
-
-            return $"{_protocol}://{HttpUtility.UrlEncode(_uuid)}@{_domain}:{_port}{parametersURL}#{HttpUtility.UrlEncode(_descriptiveText)}";
-        }
-
-
     }
 
-    public class Vmess
-    {
-        public string v { get; set; }
-        public string ps { get; set; }
-        public string add { get; set; }
-        public string port { get; set; }
-        public string id { get; set; }
-        public string aid { get; set; }
-        public string net { get; set; }
-        public string type { get; set; }
-        public string host { get; set; }
-        public string path { get; set; }
-        public string tls { get; set; }
-    }
 }
diff --git a/ProxySU_Core/Views/MainWindow.xaml b/ProxySU_Core/Views/MainWindow.xaml
index 9fe598d..2649b91 100644
--- a/ProxySU_Core/Views/MainWindow.xaml
+++ b/ProxySU_Core/Views/MainWindow.xaml
@@ -54,9 +54,21 @@
 
                     <StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
                         <Button
-                        Content="{DynamicResource AddHost}"
-                        Click="AddHost"
-                        Width="100"/>
+                            Content="{DynamicResource AddHost}"
+                            Click="AddHost"
+                            Width="100"/>
+
+                        <Button
+                            Margin="10,0,0,0"
+                            Content="导出配置"
+                            Click="ExportXraySettings"
+                            Width="100" />
+
+                        <Button
+                            Margin="10,0,0,0"
+                            Content="导出订阅"
+                            Click="ExportXraySub"
+                            Width="100" />
                     </StackPanel>
 
                     <DataGrid ItemsSource="{Binding Records}"
@@ -71,6 +83,10 @@
                               BorderThickness="1"
                               AutoGenerateColumns="False">
                         <DataGrid.Columns>
+                            <DataGridCheckBoxColumn Header="选择"
+                                                    Binding="{Binding Path=IsChecked, UpdateSourceTrigger=PropertyChanged}"
+                                                    IsReadOnly="False"
+                                                    Width="80"/>
                             <DataGridTextColumn Header="{DynamicResource HostTag}"  
                                                 Binding="{Binding Path=Host.Tag}" 
                                                 Width="150"/>
@@ -93,7 +109,7 @@
                                             <Button Content="{DynamicResource Connect}" FontSize="12" Height="24" Click="Connect" />
                                             <Button Content="{DynamicResource Edit}" FontSize="12" Height="24" Margin="10,0,0,0" Click="EditHost" />
                                             <Button Content="查看配置" FontSize="12" Height="24" Margin="10,0,0,0" Click="ShowClientInfo" />
-                                            <Button Content="{DynamicResource Delete}" FontSize="12"  Height="24" Margin="10,0,0,0" Click="DeleteHost" />
+                                            <Button Content="{DynamicResource Delete}" FontSize="12"  Height="24" Margin="10,0,0,0" Click="DeleteHost" BorderBrush="IndianRed" Background="IndianRed" />
                                         </StackPanel>
                                     </DataTemplate>
                                 </DataGridTemplateColumn.CellTemplate>
diff --git a/ProxySU_Core/Views/MainWindow.xaml.cs b/ProxySU_Core/Views/MainWindow.xaml.cs
index a661070..5e6fcc4 100644
--- a/ProxySU_Core/Views/MainWindow.xaml.cs
+++ b/ProxySU_Core/Views/MainWindow.xaml.cs
@@ -1,9 +1,9 @@
 using MahApps.Metro.Controls.Dialogs;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Serialization;
+using ProxySU_Core.Common;
 using ProxySU_Core.Models;
 using ProxySU_Core.ViewModels;
-using ProxySU_Core.ViewModels.Developers;
 using ProxySU_Core.Views;
 using Renci.SshNet;
 using System;
@@ -117,6 +117,36 @@ namespace ProxySU_Core
             Application.Current.Resources.MergedDictionaries[0] = resource;
         }
 
+        private void ExportXraySettings(object sender, RoutedEventArgs e)
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (var record in Records.Where(x => x.IsChecked))
+            {
+                record.Settings.Types.ForEach(type =>
+                {
+                    var link = ShareLink.Build(type, record.Settings);
+                    sb.AppendLine(link);
+                });
+            }
+            var tbx = new TextBoxWindow("分享链接", sb.ToString());
+            tbx.ShowDialog();
+        }
+
+        private void ExportXraySub(object sender, RoutedEventArgs e)
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (var record in Records.Where(x => x.IsChecked))
+            {
+                record.Settings.Types.ForEach(type =>
+                {
+                    var link = ShareLink.Build(type, record.Settings);
+                    sb.AppendLine(link);
+                });
+            }
+            var result = Base64.Encode(sb.ToString());
+            var tbx = new TextBoxWindow("订阅内容", result);
+            tbx.ShowDialog();
+        }
 
         private void AddHost(object sender, RoutedEventArgs e)
         {
diff --git a/ProxySU_Core/Views/TerminalWindow.xaml.cs b/ProxySU_Core/Views/TerminalWindow.xaml.cs
index 7f6a7c8..1fd8139 100644
--- a/ProxySU_Core/Views/TerminalWindow.xaml.cs
+++ b/ProxySU_Core/Views/TerminalWindow.xaml.cs
@@ -1,8 +1,8 @@
 using MahApps.Metro.Controls.Dialogs;
 using Microsoft.Win32;
 using ProxySU_Core.Models;
+using ProxySU_Core.Models.Developers;
 using ProxySU_Core.ViewModels;
-using ProxySU_Core.ViewModels.Developers;
 using ProxySU_Core.Views;
 using Renci.SshNet;
 using System;
diff --git a/ProxySU_Core/Views/TextBoxWindow.xaml b/ProxySU_Core/Views/TextBoxWindow.xaml
new file mode 100644
index 0000000..1e10a5a
--- /dev/null
+++ b/ProxySU_Core/Views/TextBoxWindow.xaml
@@ -0,0 +1,17 @@
+<metro:MetroWindow x:Class="ProxySU_Core.Views.TextBoxWindow"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:local="clr-namespace:ProxySU_Core.Views"
+        xmlns:metro="http://metro.mahapps.com/winfx/xaml/controls"
+        mc:Ignorable="d"
+        Title="TextBoxWindow" Height="450" Width="800">
+    <Grid>
+        <TextBox Margin="20"
+                 Text="{Binding Path=Message}"
+                 TextWrapping="Wrap"
+                 FontSize="14"
+                 Style="{StaticResource MahApps.Styles.TextBox}" />
+    </Grid>
+</metro:MetroWindow>
diff --git a/ProxySU_Core/Views/TextBoxWindow.xaml.cs b/ProxySU_Core/Views/TextBoxWindow.xaml.cs
new file mode 100644
index 0000000..af105e2
--- /dev/null
+++ b/ProxySU_Core/Views/TextBoxWindow.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace ProxySU_Core.Views
+{
+    /// <summary>
+    /// TextBoxWindow.xaml 的交互逻辑
+    /// </summary>
+    public partial class TextBoxWindow
+    {
+        public string Message { get; set; }
+
+        public TextBoxWindow(string title, string message)
+        {
+            InitializeComponent();
+            this.Title = title;
+            this.Message = message;
+
+            this.DataContext = this;
+        }
+    }
+}