Compare commits

...

3 commits

Author SHA1 Message Date
DHR60
7a70f630ad
Merge 0c3e42efa6 into ac43bb051d 2026-02-25 19:28:27 +08:00
DHR60
ac43bb051d
Node test with sub chain (#8778) 2026-02-25 19:28:20 +08:00
DHR60
7b31bcdd9f
Add Finalmask support (#8820)
Some checks are pending
release Linux / build (Release) (push) Waiting to run
release Linux / rpm (push) Blocked by required conditions
release macOS / build (Release) (push) Waiting to run
release Windows desktop (Avalonia UI) / build (Release) (push) Waiting to run
release Windows / build (Release) (push) Waiting to run
* Add Finalmask support

* UI
2026-02-24 21:09:17 +08:00
21 changed files with 186 additions and 29 deletions

View file

@ -254,6 +254,7 @@ public static class ConfigHandler
item.CertSha = profileItem.CertSha; item.CertSha = profileItem.CertSha;
item.EchConfigList = profileItem.EchConfigList; item.EchConfigList = profileItem.EchConfigList;
item.EchForceQuery = profileItem.EchForceQuery; item.EchForceQuery = profileItem.EchForceQuery;
item.Finalmask = profileItem.Finalmask;
item.ProtoExtra = profileItem.ProtoExtra; item.ProtoExtra = profileItem.ProtoExtra;
} }
@ -1122,6 +1123,7 @@ public static class ConfigHandler
&& AreEqual(o.Fingerprint, n.Fingerprint) && AreEqual(o.Fingerprint, n.Fingerprint)
&& AreEqual(o.PublicKey, n.PublicKey) && AreEqual(o.PublicKey, n.PublicKey)
&& AreEqual(o.ShortId, n.ShortId) && AreEqual(o.ShortId, n.ShortId)
&& AreEqual(o.Finalmask, n.Finalmask)
&& (!remarks || o.Remarks == n.Remarks); && (!remarks || o.Remarks == n.Remarks);
static bool AreEqual(string? a, string? b) static bool AreEqual(string? a, string? b)

View file

@ -99,7 +99,12 @@ public static class CoreConfigHandler
var nodes = await AppManager.Instance.GetProfileItemsByIndexIds(ids); var nodes = await AppManager.Instance.GetProfileItemsByIndexIds(ids);
foreach (var node in nodes) foreach (var node in nodes)
{ {
await FillNodeContext(context, node, false); var actNode = await FillNodeContext(context, node, true);
if (node.IndexId == actNode.IndexId)
{
continue;
}
context.ServerTestItemMap[node.IndexId] = actNode.IndexId;
} }
if (coreType == ECoreType.sing_box) if (coreType == ECoreType.sing_box)
{ {

View file

@ -73,6 +73,19 @@ public class BaseFmt
{ {
dicQuery.Add("pcs", Utils.UrlEncode(item.CertSha)); dicQuery.Add("pcs", Utils.UrlEncode(item.CertSha));
} }
if (item.Finalmask.IsNotEmpty())
{
var node = JsonUtils.ParseJson(item.Finalmask);
var finalmask = node != null
? JsonUtils.Serialize(node, new JsonSerializerOptions
{
WriteIndented = false,
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
})
: item.Finalmask;
dicQuery.Add("fm", Utils.UrlEncode(finalmask));
}
dicQuery.Add("type", item.Network.IsNotEmpty() ? item.Network : nameof(ETransport.tcp)); dicQuery.Add("type", item.Network.IsNotEmpty() ? item.Network : nameof(ETransport.tcp));
@ -214,6 +227,24 @@ public class BaseFmt
item.EchConfigList = GetQueryDecoded(query, "ech"); item.EchConfigList = GetQueryDecoded(query, "ech");
item.CertSha = GetQueryDecoded(query, "pcs"); item.CertSha = GetQueryDecoded(query, "pcs");
var finalmaskDecoded = GetQueryDecoded(query, "fm");
if (finalmaskDecoded.IsNotEmpty())
{
var node = JsonUtils.ParseJson(finalmaskDecoded);
item.Finalmask = node != null
? JsonUtils.Serialize(node, new JsonSerializerOptions
{
WriteIndented = true,
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
})
: finalmaskDecoded;
}
else
{
item.Finalmask = string.Empty;
}
if (_allowInsecureArray.Any(k => GetQueryDecoded(query, k) == "1")) if (_allowInsecureArray.Any(k => GetQueryDecoded(query, k) == "1"))
{ {
item.AllowInsecure = Global.AllowInsecure.First(); item.AllowInsecure = Global.AllowInsecure.First();

View file

@ -10,6 +10,9 @@ public record CoreConfigContext
public Config AppConfig { get; init; } = new(); public Config AppConfig { get; init; } = new();
public FullConfigTemplateItem? FullConfigTemplate { get; init; } = new(); public FullConfigTemplateItem? FullConfigTemplate { get; init; } = new();
// Test ServerTestItem Map
public Dictionary<string, string> ServerTestItemMap { get; init; } = new();
// TUN Compatibility // TUN Compatibility
public bool IsTunEnabled { get; init; } = false; public bool IsTunEnabled { get; init; } = false;
public HashSet<string> ProtectDomainList { get; init; } = new(); public HashSet<string> ProtectDomainList { get; init; } = new();

View file

@ -178,6 +178,7 @@ public class ProfileItem
public string CertSha { get; set; } public string CertSha { get; set; }
public string EchConfigList { get; set; } public string EchConfigList { get; set; }
public string EchForceQuery { get; set; } public string EchForceQuery { get; set; }
public string Finalmask { get; set; }
public string ProtoExtra { get; set; } public string ProtoExtra { get; set; }

View file

@ -341,7 +341,7 @@ public class StreamSettings4Ray
public HysteriaSettings4Ray? hysteriaSettings { get; set; } public HysteriaSettings4Ray? hysteriaSettings { get; set; }
public FinalMask4Ray? finalmask { get; set; } public Finalmask4Ray? finalmask { get; set; }
public Sockopt4Ray? sockopt { get; set; } public Sockopt4Ray? sockopt { get; set; }
} }
@ -476,7 +476,7 @@ public class HysteriaUdpHop4Ray
public string? interval { get; set; } public string? interval { get; set; }
} }
public class FinalMask4Ray public class Finalmask4Ray
{ {
public List<Mask4Ray>? tcp { get; set; } public List<Mask4Ray>? tcp { get; set; }
public List<Mask4Ray>? udp { get; set; } public List<Mask4Ray>? udp { get; set; }
@ -485,7 +485,7 @@ public class FinalMask4Ray
public class Mask4Ray public class Mask4Ray
{ {
public string type { get; set; } public string type { get; set; }
public MaskSettings4Ray? settings { get; set; } public object? settings { get; set; }
} }
public class MaskSettings4Ray public class MaskSettings4Ray

View file

@ -2916,6 +2916,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Finalmask 的本地化字符串。
/// </summary>
public static string TbFinalmask {
get {
return ResourceManager.GetString("TbFinalmask", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Fingerprint 的本地化字符串。 /// 查找类似 Fingerprint 的本地化字符串。
/// </summary> /// </summary>

View file

@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
<data name="menuServerListPreview" xml:space="preserve"> <data name="menuServerListPreview" xml:space="preserve">
<value>Configuration item preview</value> <value>Configuration item preview</value>
</data> </data>
<data name="TbFinalmask" xml:space="preserve">
<value>Finalmask</value>
</data>
</root> </root>

View file

@ -1665,4 +1665,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
<data name="menuServerListPreview" xml:space="preserve"> <data name="menuServerListPreview" xml:space="preserve">
<value>Configuration item preview</value> <value>Configuration item preview</value>
</data> </data>
<data name="TbFinalmask" xml:space="preserve">
<value>Finalmask</value>
</data>
</root> </root>

View file

@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
<data name="menuServerListPreview" xml:space="preserve"> <data name="menuServerListPreview" xml:space="preserve">
<value>Configuration item preview</value> <value>Configuration item preview</value>
</data> </data>
<data name="TbFinalmask" xml:space="preserve">
<value>Finalmask</value>
</data>
</root> </root>

View file

@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
<data name="menuServerListPreview" xml:space="preserve"> <data name="menuServerListPreview" xml:space="preserve">
<value>Configuration item preview</value> <value>Configuration item preview</value>
</data> </data>
<data name="TbFinalmask" xml:space="preserve">
<value>Finalmask</value>
</data>
</root> </root>

View file

@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
<data name="menuServerListPreview" xml:space="preserve"> <data name="menuServerListPreview" xml:space="preserve">
<value>Configuration item preview</value> <value>Configuration item preview</value>
</data> </data>
<data name="TbFinalmask" xml:space="preserve">
<value>Finalmask</value>
</data>
</root> </root>

View file

@ -1665,4 +1665,7 @@
<data name="menuServerListPreview" xml:space="preserve"> <data name="menuServerListPreview" xml:space="preserve">
<value>子配置项预览</value> <value>子配置项预览</value>
</data> </data>
<data name="TbFinalmask" xml:space="preserve">
<value>Finalmask</value>
</data>
</root> </root>

View file

@ -1665,4 +1665,7 @@
<data name="menuServerListPreview" xml:space="preserve"> <data name="menuServerListPreview" xml:space="preserve">
<value>Configuration item preview</value> <value>Configuration item preview</value>
</data> </data>
<data name="TbFinalmask" xml:space="preserve">
<value>Finalmask</value>
</data>
</root> </root>

View file

@ -167,8 +167,9 @@ public partial class CoreConfigSingboxService(CoreConfigContext context)
{ {
continue; continue;
} }
var item = context.AllProxiesMap.GetValueOrDefault(it.IndexId); var actIndexId = context.ServerTestItemMap.GetValueOrDefault(it.IndexId, it.IndexId);
if (item is null || item.IsComplex() || !item.IsValid()) var item = context.AllProxiesMap.GetValueOrDefault(actIndexId);
if (item is null || item.ConfigType is EConfigType.Custom || !item.IsValid())
{ {
continue; continue;
} }

View file

@ -124,8 +124,9 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
{ {
continue; continue;
} }
var item = context.AllProxiesMap.GetValueOrDefault(it.IndexId); var actIndexId = context.ServerTestItemMap.GetValueOrDefault(it.IndexId, it.IndexId);
if (item is null || item.IsComplex() || !item.IsValid()) var item = context.AllProxiesMap.GetValueOrDefault(actIndexId);
if (item is null || item.ConfigType is EConfigType.Custom || !item.IsValid())
{ {
continue; continue;
} }

View file

@ -354,14 +354,7 @@ public partial class CoreConfigV2rayService
var useragent = ""; var useragent = "";
if (!_config.CoreBasicItem.DefUserAgent.IsNullOrEmpty()) if (!_config.CoreBasicItem.DefUserAgent.IsNullOrEmpty())
{ {
try useragent = Global.UserAgentTexts.GetValueOrDefault(_config.CoreBasicItem.DefUserAgent, _config.CoreBasicItem.DefUserAgent);
{
useragent = Global.UserAgentTexts[_config.CoreBasicItem.DefUserAgent];
}
catch (KeyNotFoundException)
{
useragent = _config.CoreBasicItem.DefUserAgent;
}
} }
//if tls //if tls
@ -666,6 +659,11 @@ public partial class CoreConfigV2rayService
} }
break; break;
} }
if (!_node.Finalmask.IsNullOrEmpty())
{
streamSettings.finalmask = JsonUtils.Deserialize<Finalmask4Ray>(_node.Finalmask);
}
} }
catch (Exception ex) catch (Exception ex)
{ {

View file

@ -32,7 +32,7 @@
IsCancel="True" /> IsCancel="True" />
</StackPanel> </StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto"> <Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<Grid <Grid
Grid.Row="0" Grid.Row="0"
@ -407,7 +407,7 @@
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbPorts7Tips}" /> Text="{x:Static resx:ResUI.TbPorts7Tips}" />
<TextBlock <TextBlock
Grid.Row="4" Grid.Row="4"
Grid.Column="0" Grid.Column="0"
@ -420,7 +420,7 @@
Grid.Column="1" Grid.Column="1"
Width="400" Width="400"
Margin="{StaticResource Margin4}" /> Margin="{StaticResource Margin4}" />
<TextBlock <TextBlock
Grid.Row="5" Grid.Row="5"
Grid.Column="0" Grid.Column="0"
@ -722,11 +722,51 @@
Text="{x:Static resx:ResUI.TbPath}" /> Text="{x:Static resx:ResUI.TbPath}" />
</Grid> </Grid>
<Separator Grid.Row="5" Margin="{StaticResource MarginTb8}" /> <Grid
x:Name="gridFinalmask"
Grid.Row="5"
ColumnDefinitions="300,Auto">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbFinalmask}" />
<Button
Grid.Row="0"
Grid.Column="1"
Margin="{StaticResource MarginLr4}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Classes="IconButton">
<Button.Content>
<PathIcon Data="{StaticResource SemiIconMore}">
<PathIcon.RenderTransform>
<RotateTransform Angle="90" />
</PathIcon.RenderTransform>
</PathIcon>
</Button.Content>
<Button.Flyout>
<Flyout>
<StackPanel>
<TextBox
x:Name="txtFinalmask"
Width="400"
Margin="{StaticResource Margin4}"
AcceptsReturn="True"
Classes="TextArea"
TextWrapping="NoWrap" />
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
</Grid>
<Separator Grid.Row="6" Margin="{StaticResource MarginTb8}" />
<Grid <Grid
x:Name="gridTls" x:Name="gridTls"
Grid.Row="6" Grid.Row="7"
ColumnDefinitions="300,Auto" ColumnDefinitions="300,Auto"
RowDefinitions="Auto,Auto,Auto,Auto,Auto"> RowDefinitions="Auto,Auto,Auto,Auto,Auto">
@ -745,7 +785,7 @@
</Grid> </Grid>
<Grid <Grid
x:Name="gridTlsMore" x:Name="gridTlsMore"
Grid.Row="7" Grid.Row="8"
ColumnDefinitions="300,Auto" ColumnDefinitions="300,Auto"
IsVisible="False" IsVisible="False"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto"> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
@ -908,7 +948,7 @@
</Grid> </Grid>
<Grid <Grid
x:Name="gridRealityMore" x:Name="gridRealityMore"
Grid.Row="7" Grid.Row="8"
ColumnDefinitions="300,Auto" ColumnDefinitions="300,Auto"
IsVisible="False" IsVisible="False"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto"> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto">
@ -996,7 +1036,7 @@
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" /> HorizontalAlignment="Left" />
</Grid> </Grid>
<Separator Grid.Row="8" Margin="{StaticResource MarginTb8}" /> <Separator Grid.Row="9" Margin="{StaticResource MarginTb8}" />
</Grid> </Grid>
</ScrollViewer> </ScrollViewer>
</DockPanel> </DockPanel>

View file

@ -78,6 +78,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
cmbCoreType.IsEnabled = false; cmbCoreType.IsEnabled = false;
cmbFingerprint.IsEnabled = false; cmbFingerprint.IsEnabled = false;
cmbFingerprint.SelectedValue = string.Empty; cmbFingerprint.SelectedValue = string.Empty;
gridFinalmask.IsVisible = false;
cmbHeaderType8.ItemsSource = Global.TuicCongestionControls; cmbHeaderType8.ItemsSource = Global.TuicCongestionControls;
break; break;
@ -95,6 +96,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
gridAnytls.IsVisible = true; gridAnytls.IsVisible = true;
lstStreamSecurity.Add(Global.StreamSecurityReality); lstStreamSecurity.Add(Global.StreamSecurityReality);
cmbCoreType.IsEnabled = false; cmbCoreType.IsEnabled = false;
gridFinalmask.IsVisible = false;
break; break;
} }
cmbStreamSecurity.ItemsSource = lstStreamSecurity; cmbStreamSecurity.ItemsSource = lstStreamSecurity;
@ -194,6 +196,8 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
this.Bind(ViewModel, vm => vm.SelectedSource.SpiderX, v => v.txtSpiderX.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.SpiderX, v => v.txtSpiderX.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.Finalmask, v => v.txtFinalmask.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);

View file

@ -60,6 +60,8 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid Grid.Row="0"> <Grid Grid.Row="0">
@ -928,12 +930,47 @@
Text="{x:Static resx:ResUI.TbPath}" /> Text="{x:Static resx:ResUI.TbPath}" />
</Grid> </Grid>
<Grid x:Name="gridFinalmask" Grid.Row="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbFinalmask}" />
<materialDesign:PopupBox
Grid.Row="0"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
StaysOpen="True"
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
<StackPanel>
<TextBox
x:Name="txtFinalmask"
Width="400"
Margin="{StaticResource Margin4}"
AcceptsReturn="True"
HorizontalScrollBarVisibility="Auto"
MaxLines="8"
MinLines="4"
Style="{StaticResource MyOutlinedTextBox}"
TextWrapping="NoWrap"
VerticalScrollBarVisibility="Auto" />
</StackPanel>
</materialDesign:PopupBox>
</Grid>
<Separator <Separator
Grid.Row="5" Grid.Row="6"
Margin="0,2" Margin="0,2"
Style="{DynamicResource MaterialDesignSeparator}" /> Style="{DynamicResource MaterialDesignSeparator}" />
<Grid x:Name="gridTls" Grid.Row="6"> <Grid x:Name="gridTls" Grid.Row="7">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@ -963,7 +1000,7 @@
</Grid> </Grid>
<Grid <Grid
x:Name="gridTlsMore" x:Name="gridTlsMore"
Grid.Row="7" Grid.Row="8"
Visibility="Hidden"> Visibility="Hidden">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@ -1152,7 +1189,7 @@
</Grid> </Grid>
<Grid <Grid
x:Name="gridRealityMore" x:Name="gridRealityMore"
Grid.Row="7" Grid.Row="8"
Visibility="Hidden"> Visibility="Hidden">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@ -1264,7 +1301,7 @@
Style="{StaticResource DefTextBox}" /> Style="{StaticResource DefTextBox}" />
</Grid> </Grid>
<Separator <Separator
Grid.Row="8" Grid.Row="9"
Margin="0,2" Margin="0,2"
Style="{DynamicResource MaterialDesignSeparator}" /> Style="{DynamicResource MaterialDesignSeparator}" />
</Grid> </Grid>

View file

@ -73,6 +73,7 @@ public partial class AddServerWindow
cmbCoreType.IsEnabled = false; cmbCoreType.IsEnabled = false;
cmbFingerprint.IsEnabled = false; cmbFingerprint.IsEnabled = false;
cmbFingerprint.Text = string.Empty; cmbFingerprint.Text = string.Empty;
gridFinalmask.Visibility = Visibility.Collapsed;
cmbHeaderType8.ItemsSource = Global.TuicCongestionControls; cmbHeaderType8.ItemsSource = Global.TuicCongestionControls;
break; break;
@ -90,6 +91,7 @@ public partial class AddServerWindow
gridAnytls.Visibility = Visibility.Visible; gridAnytls.Visibility = Visibility.Visible;
cmbCoreType.IsEnabled = false; cmbCoreType.IsEnabled = false;
lstStreamSecurity.Add(Global.StreamSecurityReality); lstStreamSecurity.Add(Global.StreamSecurityReality);
gridFinalmask.Visibility = Visibility.Collapsed;
break; break;
} }
cmbStreamSecurity.ItemsSource = lstStreamSecurity; cmbStreamSecurity.ItemsSource = lstStreamSecurity;
@ -190,6 +192,8 @@ public partial class AddServerWindow
this.Bind(ViewModel, vm => vm.SelectedSource.SpiderX, v => v.txtSpiderX.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.SpiderX, v => v.txtSpiderX.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.Finalmask, v => v.txtFinalmask.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);