Skip to content

Commit a575165

Browse files
Merge pull request #123 from InvisibleManVPN/develop
InvisibleMan XRay version 2.3.2
2 parents ba1639b + a9344b9 commit a575165

18 files changed

Lines changed: 400 additions & 28 deletions

File tree

InvisibleMan-XRay/App.xaml.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ protected override void OnStartup(StartupEventArgs e)
1515
InitializeAppManager();
1616
InitializeWindowFactory();
1717
InitializeMainWindow();
18+
HandlePipes();
1819

1920
void InitializeAppManager()
2021
{
21-
appManager = new AppManager();
22+
appManager = new AppManager(e.Args);
2223
appManager.Initialize();
2324
}
2425

@@ -32,6 +33,16 @@ void InitializeMainWindow()
3233
MainWindow mainWindow = windowFactory.CreateMainWindow();
3334
mainWindow.Show();
3435
}
36+
37+
void HandlePipes()
38+
{
39+
if (IsThereAnyArg())
40+
PipeManager.SignalThisApp(e.Args);
41+
42+
PipeManager.ListenForPipes();
43+
}
44+
45+
bool IsThereAnyArg() => e.Args.Length != 0;
3546
}
3647
}
3748
}

InvisibleMan-XRay/Assets/Icons.xaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@
133133
</VisualBrush.Visual>
134134
</VisualBrush>
135135

136+
<VisualBrush x:Key="Icon.Share">
137+
<VisualBrush.Visual>
138+
<Canvas>
139+
<Path Data="M339.588,314.529c-14.215,0-27.456,4.133-38.621,11.239l-112.682-78.67c1.809-6.315,2.798-12.976,2.798-19.871c0-6.896-0.989-13.557-2.798-19.871l109.64-76.547c11.764,8.356,26.133,13.286,41.662,13.286c39.79,0,72.047-32.257,72.047-72.047C411.634,32.258,379.378,0,339.588,0c-39.79,0-72.047,32.257-72.047,72.047c0,5.255,0.578,10.373,1.646,15.308l-112.424,78.491c-10.974-6.759-23.892-10.666-37.727-10.666c-39.79,0-72.047,32.257-72.047,72.047s32.256,72.047,72.047,72.047c13.834,0,26.753-3.907,37.727-10.666l113.292,79.097c-1.629,6.017-2.514,12.34-2.514,18.872c0,39.79,32.257,72.047,72.047,72.047c39.79,0,72.047-32.257,72.047-72.047C411.635,346.787,379.378,314.529,339.588,314.529z" Fill="#ffffff"/>
140+
</Canvas>
141+
</VisualBrush.Visual>
142+
</VisualBrush>
143+
136144
<!-- Update status -->
137145
<VisualBrush x:Key="Icon.Update.Check">
138146
<VisualBrush.Visual>

InvisibleMan-XRay/Factories/WindowFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ string GetXRayCoreVersion()
132132
}
133133
}
134134

135-
private ServerWindow CreateServerWindow()
135+
public ServerWindow CreateServerWindow()
136136
{
137137
ConfigHandler configHandler = handlersManager.GetHandler<ConfigHandler>();
138138
TemplateHandler templateHandler = handlersManager.GetHandler<TemplateHandler>();
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
3+
namespace InvisibleManXRay.Handlers
4+
{
5+
using DeepLinks;
6+
using Values;
7+
8+
public class DeepLinkHandler : Handler
9+
{
10+
private IDeepLink deepLink;
11+
12+
private Action<string> onConfigLinkFetched;
13+
private Action<string> onSubscriptionLinkFetched;
14+
15+
public DeepLinkHandler()
16+
{
17+
InitializeDeepLink();
18+
}
19+
20+
public void Setup(
21+
ref Action<string> onReceiveArg,
22+
Action<string> onConfigLinkFetched,
23+
Action<string> onSubscriptionLinkFetched
24+
)
25+
{
26+
onReceiveArg = TryFetchLink;
27+
this.onConfigLinkFetched = onConfigLinkFetched;
28+
this.onSubscriptionLinkFetched = onSubscriptionLinkFetched;
29+
}
30+
31+
private void InitializeDeepLink()
32+
{
33+
this.deepLink = GetDeepLink();
34+
deepLink.Register();
35+
}
36+
37+
private IDeepLink GetDeepLink()
38+
{
39+
WindowsDeepLink windowsDeepLink = new WindowsDeepLink();
40+
return windowsDeepLink;
41+
}
42+
43+
private void TryFetchLink(string arg)
44+
{
45+
if (IsValidConfigLink())
46+
onConfigLinkFetched.Invoke(GetConfigLink());
47+
else if (IsValidSubscriptionLink())
48+
onSubscriptionLinkFetched.Invoke(GetSubscriptionLink());
49+
50+
bool IsValidConfigLink()
51+
{
52+
return arg.StartsWith(DeepLink.CONFIG)
53+
&& !string.IsNullOrEmpty(GetConfigLink());
54+
}
55+
56+
bool IsValidSubscriptionLink()
57+
{
58+
return arg.StartsWith(DeepLink.SUBSCRIPTION)
59+
&& !string.IsNullOrEmpty(GetSubscriptionLink());
60+
}
61+
62+
string GetConfigLink() => arg.Replace(DeepLink.CONFIG, "").Trim();
63+
64+
string GetSubscriptionLink() => arg.Replace(DeepLink.SUBSCRIPTION, "").Trim();
65+
}
66+
}
67+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace InvisibleManXRay.Handlers.DeepLinks
2+
{
3+
public interface IDeepLink
4+
{
5+
void Register();
6+
}
7+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using System.Windows;
3+
using Microsoft.Win32;
4+
5+
namespace InvisibleManXRay.Handlers.DeepLinks
6+
{
7+
using Values;
8+
9+
public class WindowsDeepLink : IDeepLink
10+
{
11+
private const string URI_SCHEME = $@"Software\Classes\{DeepLink.SCHEME}";
12+
private const string SHELL_OPEN_COMMAND = @"shell\open\command";
13+
private const string URL_PROTOCOL = "URL Protocol";
14+
15+
private string AppName => Application.ResourceAssembly.GetName().Name;
16+
private string AppPath => Environment.ProcessPath;
17+
18+
public void Register()
19+
{
20+
try
21+
{
22+
RegistryKey registry = GetApplicationClassRegistery();
23+
24+
registry.SetValue("", $"URL:{AppName}");
25+
registry.SetValue(URL_PROTOCOL, "");
26+
registry.CreateSubKey(SHELL_OPEN_COMMAND).SetValue(
27+
name: "",
28+
value: $"\"{AppPath}\" \"%1\""
29+
);
30+
}
31+
catch
32+
{
33+
}
34+
}
35+
36+
private RegistryKey GetApplicationClassRegistery()
37+
{
38+
RegistryKey registry = Registry.CurrentUser.CreateSubKey(URI_SCHEME);
39+
return registry;
40+
}
41+
}
42+
}

InvisibleMan-XRay/InvisibleMan-XRay.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
<PackageId>Invisible Man XRay</PackageId>
1010
<Company>Invisible Man</Company>
1111
<Copyright>Copyright (C) 2024 Invisible Man</Copyright>
12-
<Version>2.1.2.0</Version>
13-
<AssemblyVersion>2.1.2.0</AssemblyVersion>
12+
<Version>2.3.2.0</Version>
13+
<AssemblyVersion>2.3.2.0</AssemblyVersion>
1414
<Nullable>enable</Nullable>
1515
<NoWarn>0108;8600;8601;8602;8603;8604;8618;8625;8629;8762</NoWarn>
1616
<UseWPF>true</UseWPF>
@@ -25,6 +25,7 @@
2525
<ItemGroup>
2626
<PackageReference Include="NetCore5.0.Microsoft.Expression.Drawing" Version="1.0.0" />
2727
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
28+
<PackageReference Include="QRCoder.Xaml" Version="1.6.0" />
2829
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
2930
<PackageReference Include="System.Management" Version="7.0.0" />
3031
<PackageReference Include="System.Windows.Forms" />

InvisibleMan-XRay/Managers/AppManager.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,15 @@ public class AppManager
1717

1818
public WindowFactory WindowFactory => factoriesInitializer.WindowFactory;
1919

20+
private string[] args;
2021
private static Mutex mutex;
2122
private const string APP_GUID = "{7I6N0VI4-S9I1-43bl-A0eM-72A47N6EDH8M}";
2223

24+
public AppManager(string[] args)
25+
{
26+
this.args = args;
27+
}
28+
2329
public void Initialize()
2430
{
2531
AvoidRunningMultipleInstances();
@@ -42,9 +48,15 @@ private void AvoidRunningMultipleInstances()
4248

4349
if(!isCreatedNew)
4450
{
45-
MessageBox.Show(Message.APP_ALREADY_RUNNING);
51+
if (IsThereAnyArg())
52+
PipeManager.SignalOpenedApp(args);
53+
else
54+
MessageBox.Show(Message.APP_ALREADY_RUNNING);
55+
4656
Environment.Exit(0);
4757
}
58+
59+
bool IsThereAnyArg() => args.Length != 0;
4860
}
4961

5062
private void SetApplicationCurrentDirectory()

InvisibleMan-XRay/Managers/Initializers/HandlersInitializer.cs

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public void Register()
2626
HandlersManager.AddHandler(new VersionHandler());
2727
HandlersManager.AddHandler(new UpdateHandler());
2828
HandlersManager.AddHandler(new BroadcastHandler());
29+
HandlersManager.AddHandler(new DeepLinkHandler());
2930
HandlersManager.AddHandler(new LinkHandler());
3031
}
3132

@@ -40,6 +41,7 @@ WindowFactory windowFactory
4041
SetupConfigHandler();
4142
SetupUpdateHandler();
4243
SetupNotifyHandler();
44+
SetupDeepLinkHandler();
4345

4446
void SetupProcessHandler()
4547
{
@@ -95,27 +97,6 @@ void SetupNotifyHandler()
9597
onTunnelModeClick: () => { OnModeClick(Mode.TUN); }
9698
);
9799

98-
bool IsAnotherWindowOpened() => Application.Current.Windows.Count > 1;
99-
100-
bool IsMainWindow(Window window) => window == Application.Current.MainWindow;
101-
102-
void ShowMainWindow() => Application.Current.MainWindow.Show();
103-
104-
void CloseOtherWindows()
105-
{
106-
foreach (Window window in Application.Current.Windows)
107-
{
108-
if (!IsMainWindow(window))
109-
window.Close();
110-
}
111-
}
112-
113-
void OpenApplication()
114-
{
115-
ShowMainWindow();
116-
Application.Current.MainWindow.WindowState = WindowState.Normal;
117-
}
118-
119100
void CloseApplication()
120101
{
121102
core.DisableMode();
@@ -154,6 +135,62 @@ void OnModeClick(Mode mode)
154135
mainWindow.TryDisableModeAndRerun();
155136
}
156137
}
138+
139+
void SetupDeepLinkHandler()
140+
{
141+
HandlersManager.GetHandler<DeepLinkHandler>().Setup(
142+
onReceiveArg: ref PipeManager.OnReceiveArg,
143+
onConfigLinkFetched: PrepareToImportConfigLink,
144+
onSubscriptionLinkFetched: PrepareToImportSubscriptionLink
145+
);
146+
147+
void PrepareToImportConfigLink(string link)
148+
{
149+
ServerWindow serverWindow = GetServerWindow();
150+
serverWindow.OpenImportConfigWithLinkSection(link);
151+
serverWindow.ShowDialog();
152+
}
153+
154+
void PrepareToImportSubscriptionLink(string link)
155+
{
156+
ServerWindow serverWindow = GetServerWindow();
157+
serverWindow.OpenImportSubscriptionWithLinkSection(link);
158+
serverWindow.ShowDialog();
159+
}
160+
161+
ServerWindow GetServerWindow()
162+
{
163+
OpenApplication();
164+
if (IsAnotherWindowOpened())
165+
CloseOtherWindows();
166+
167+
ServerWindow serverWindow = windowFactory.CreateServerWindow();
168+
serverWindow.Owner = Application.Current.MainWindow;
169+
170+
return serverWindow;
171+
}
172+
}
173+
}
174+
175+
private void OpenApplication()
176+
{
177+
ShowMainWindow();
178+
Application.Current.MainWindow.WindowState = WindowState.Normal;
157179
}
180+
181+
private void CloseOtherWindows()
182+
{
183+
foreach (Window window in Application.Current.Windows)
184+
{
185+
if (!IsMainWindow(window))
186+
window.Close();
187+
}
188+
}
189+
190+
private void ShowMainWindow() => Application.Current.MainWindow.Show();
191+
192+
private bool IsAnotherWindowOpened() => Application.Current.Windows.Count > 1;
193+
194+
private bool IsMainWindow(Window window) => window == Application.Current.MainWindow;
158195
}
159196
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.IO;
3+
using System.IO.Pipes;
4+
using System.Windows;
5+
using System.Threading.Tasks;
6+
7+
namespace InvisibleManXRay.Managers
8+
{
9+
public static class PipeManager
10+
{
11+
private const string PIPE_NAME = "InvisibleManXRayPipe";
12+
13+
public static Action<string> OnReceiveArg = delegate{};
14+
15+
public static void ListenForPipes()
16+
{
17+
Task.Run(() => {
18+
while(true)
19+
{
20+
NamedPipeServerStream pipeServer = new NamedPipeServerStream(PIPE_NAME);
21+
pipeServer.WaitForConnection();
22+
23+
StreamReader reader = new StreamReader(pipeServer);
24+
string message = reader.ReadToEnd();
25+
Application.Current.Dispatcher.BeginInvoke(new Action(delegate {
26+
OnReceiveArg.Invoke(message);
27+
}));
28+
29+
pipeServer.Close();
30+
pipeServer.Dispose();
31+
}
32+
});
33+
}
34+
35+
public static void SignalOpenedApp(string[] args)
36+
{
37+
NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", PIPE_NAME);
38+
pipeClient.Connect();
39+
40+
StreamWriter writer = new StreamWriter(pipeClient);
41+
writer.WriteLine(args[0]);
42+
writer.Flush();
43+
writer.Close();
44+
}
45+
46+
public static void SignalThisApp(string[] args)
47+
{
48+
OnReceiveArg.Invoke(args[0]);
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)