Skip to content

Commit 2933a1e

Browse files
committed
Enable CAPTCHA support when registering
1 parent d4c5a32 commit 2933a1e

11 files changed

+251
-15
lines changed

Signal-Windows/App.xaml.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,27 @@ private void OnUnhandledException(object sender, UnhandledExceptionEventArgs ex)
105105
protected override async void OnActivated(IActivatedEventArgs args)
106106
{
107107
Logger.LogInformation("OnActivated() {0}", args.GetType());
108+
if (args.Kind == ActivationKind.Protocol)
109+
{
110+
ProtocolActivatedEventArgs protocolArgs = args as ProtocolActivatedEventArgs;
111+
// We support multiple protocols so check what scheme was used to launch the app
112+
if (protocolArgs.Uri.Scheme.ToLower() == "signalpassback")
113+
{
114+
if (protocolArgs.Data.ContainsKey("token"))
115+
{
116+
string signalCaptchaToken = (string)protocolArgs.Data["token"];
117+
var registerPageInstance = CurrentSignalWindowsFrontend(MainViewId).Locator.RegisterPageInstance;
118+
registerPageInstance.CaptchaCode = signalCaptchaToken;
119+
registerPageInstance.CaptchaWebViewEnabled = false;
120+
CurrentSignalWindowsFrontend(MainViewId).Locator.CaptchaPageInstance.View.Frame.GoBack();
121+
}
122+
else
123+
{
124+
Logger.LogError("App was launched with signalpassback:// but wasn't passed a token");
125+
}
126+
return;
127+
}
128+
}
108129
DisappearingMessagesManager.DeleteExpiredMessages();
109130
if (args is ToastNotificationActivatedEventArgs toastArgs)
110131
{

Signal-Windows/Package.appxmanifest

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
<uap:DisplayName>Signal Private Messenger Message</uap:DisplayName>
3838
</uap:Protocol>
3939
</uap:Extension>
40+
<uap:Extension Category="windows.protocol">
41+
<uap:Protocol Name="signalpassback"/>
42+
</uap:Extension>
4043
</Extensions>
4144
</Application>
4245
</Applications>

Signal-Windows/Signal-Windows.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@
193193
<Compile Include="ViewModels\AdvancedSettingsPageViewModel.cs" />
194194
<Compile Include="ViewModels\AppearanceSettingsPageViewModel.cs" />
195195
<Compile Include="ViewModels\BlockedContactsPageViewModel.cs" />
196+
<Compile Include="ViewModels\CaptchaPageViewModel.cs" />
196197
<Compile Include="ViewModels\ChatsAndMediaSettingsPageViewModel.cs" />
197198
<Compile Include="ViewModels\ConversationSettingsPageViewModel.cs" />
198199
<Compile Include="ViewModels\FinishRegistrationPageViewModel.cs" />
@@ -223,6 +224,9 @@
223224
<Compile Include="Views\BlockedContactsPage.xaml.cs">
224225
<DependentUpon>BlockedContactsPage.xaml</DependentUpon>
225226
</Compile>
227+
<Compile Include="Views\CaptchaPage.xaml.cs">
228+
<DependentUpon>CaptchaPage.xaml</DependentUpon>
229+
</Compile>
226230
<Compile Include="Views\ChatsAndMediaSettingsPage.xaml.cs">
227231
<DependentUpon>ChatsAndMediaSettingsPage.xaml</DependentUpon>
228232
</Compile>
@@ -342,6 +346,10 @@
342346
<SubType>Designer</SubType>
343347
<Generator>MSBuild:Compile</Generator>
344348
</Page>
349+
<Page Include="Views\CaptchaPage.xaml">
350+
<SubType>Designer</SubType>
351+
<Generator>MSBuild:Compile</Generator>
352+
</Page>
345353
<Page Include="Views\ChatsAndMediaSettingsPage.xaml">
346354
<SubType>Designer</SubType>
347355
<Generator>MSBuild:Compile</Generator>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using GalaSoft.MvvmLight;
7+
using libsignalservice;
8+
using Microsoft.Extensions.Logging;
9+
using Signal_Windows.Views;
10+
using Windows.UI.Core;
11+
12+
namespace Signal_Windows.ViewModels
13+
{
14+
public class CaptchaPageViewModel : ViewModelBase
15+
{
16+
private readonly ILogger logger = LibsignalLogging.CreateLogger<CaptchaPageViewModel>();
17+
public CaptchaPage View { get; set; }
18+
19+
// The webview source cannot be null so set it to the blank page.
20+
private Uri webViewSource = new Uri("about:blank");
21+
public Uri WebViewSource
22+
{
23+
get { return webViewSource; }
24+
set { webViewSource = value; RaisePropertyChanged(nameof(WebViewSource)); }
25+
}
26+
27+
public void OnNavigatedTo()
28+
{
29+
Utils.EnableBackButton(BackButton_Click);
30+
WebViewSource = new Uri("https://signalcaptchas.org/registration/generate.html");
31+
}
32+
33+
public void OnNavigatingFrom()
34+
{
35+
Utils.DisableBackButton(BackButton_Click);
36+
}
37+
38+
private void BackButton_Click(object sender, BackRequestedEventArgs e)
39+
{
40+
View.Frame.GoBack();
41+
e.Handled = true;
42+
}
43+
}
44+
}

Signal-Windows/ViewModels/RegisterFinalizationPageViewModel.cs

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
using libsignal;
33
using libsignal.util;
44
using libsignalservice;
5+
using libsignalservice.push.exceptions;
56
using libsignalservice.util;
7+
using Microsoft.Extensions.Logging;
68
using Signal_Windows.Lib;
79
using Signal_Windows.Models;
810
using Signal_Windows.Storage;
@@ -22,6 +24,7 @@ namespace Signal_Windows.ViewModels
2224
{
2325
public class RegisterFinalizationPageViewModel : ViewModelBase
2426
{
27+
private readonly ILogger logger = LibsignalLogging.CreateLogger<RegisterFinalizationPageViewModel>();
2528
public RegisterFinalizationPage View { get; set; }
2629

2730
private string _VerificationCode = string.Empty;
@@ -55,35 +58,69 @@ internal void FinishButton_Click()
5558
View.Frame.Navigate(typeof(FinishRegistrationPage));
5659
}
5760

58-
internal async Task OnNavigatedTo()
61+
internal void OnNavigatedTo()
5962
{
6063
UIEnabled = false;
6164
Utils.EnableBackButton(BackButton_Click);
65+
}
66+
67+
internal async Task RegisterFinalizationPage_Loaded()
68+
{
6269
CancelSource = new CancellationTokenSource();
6370
Password = Base64.EncodeBytes(Util.GetSecretBytes(18));
6471
SignalRegistrationId = KeyHelper.generateRegistrationId(false);
6572
IdentityKeyPair = KeyHelper.generateIdentityKeyPair();
6673
try
6774
{
68-
AccountManager = await Task.Run(() => InitRegistration(false));
75+
AccountManager = await InitRegistration(false);
6976
UIEnabled = true;
7077
}
71-
catch(Exception e)
78+
catch (Exception ex)
7279
{
73-
View.Frame.Navigate(typeof(RegisterPage));
80+
logger.LogError(new EventId(), ex, ex.Message);
81+
View.Frame.GoBack();
7482
}
7583
}
7684

7785
private async Task<SignalServiceAccountManager> InitRegistration(bool voice)
7886
{
7987
App.Handle.PurgeAccountData();
80-
SignalServiceAccountManager accountManager = new SignalServiceAccountManager(LibUtils.ServiceConfiguration, App.CurrentSignalWindowsFrontend(App.MainViewId).Locator.RegisterPageInstance.FinalNumber, Password, 1 /*device id isn't actually used*/, LibUtils.USER_AGENT, LibUtils.HttpClient);
88+
SignalServiceAccountManager accountManager = new SignalServiceAccountManager(LibUtils.ServiceConfiguration,
89+
App.CurrentSignalWindowsFrontend(App.MainViewId).Locator.RegisterPageInstance.FinalNumber,
90+
Password, 1 /*device id isn't actually used*/, LibUtils.USER_AGENT, LibUtils.HttpClient);
91+
92+
string captcha = null;
93+
if (!string.IsNullOrWhiteSpace(App.CurrentSignalWindowsFrontend(App.MainViewId).Locator.RegisterPageInstance.CaptchaCode))
94+
{
95+
captcha = App.CurrentSignalWindowsFrontend(App.MainViewId).Locator.RegisterPageInstance.CaptchaCode;
96+
}
97+
98+
try
99+
{
100+
if (voice)
101+
{
102+
await accountManager.RequestVoiceVerificationCode(captcha, CancelSource.Token);
103+
}
104+
else
105+
{
106+
await accountManager.RequestSmsVerificationCode(captcha, CancelSource.Token);
107+
}
108+
}
109+
catch (CaptchaRequiredException)
81110
{
82-
await accountManager.RequestVoiceVerificationCode(CancelSource.Token);
111+
App.CurrentSignalWindowsFrontend(App.MainViewId).Locator.RegisterPageInstance.CaptchaWebViewEnabled = true;
112+
throw;
83113
}
84-
else
114+
catch (Exception ex)
85115
{
86-
await accountManager.RequestSmsVerificationCode(CancelSource.Token);
116+
await Utils.CallOnMainViewUIThreadAsync(async () =>
117+
{
118+
var title = ex.Message;
119+
var content = "Please ensure your phone number is correct and your device is connected to the internet.";
120+
MessageDialog dialog = new MessageDialog(content, title);
121+
await dialog.ShowAsync();
122+
});
123+
throw;
87124
}
88125
return accountManager;
89126
}

Signal-Windows/ViewModels/RegisterPageViewModel.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,35 @@ public string PhonePrefix
3838
}
3939
}
4040

41+
private string captchaCode = string.Empty;
42+
public string CaptchaCode
43+
{
44+
get { return captchaCode; }
45+
set { captchaCode = value; RaisePropertyChanged(nameof(CaptchaCode)); }
46+
}
47+
48+
private bool captchaCodeTextBoxVisible = false;
49+
public bool CaptchaCodeTextBoxVisible
50+
{
51+
get { return captchaCodeTextBoxVisible; }
52+
set { captchaCodeTextBoxVisible = value; RaisePropertyChanged(nameof(CaptchaCodeTextBoxVisible)); }
53+
}
54+
55+
private bool captchaWebViewEnabled = false;
56+
public bool CaptchaWebViewEnabled
57+
{
58+
get { return captchaWebViewEnabled; }
59+
set { captchaWebViewEnabled = value; RaisePropertyChanged(nameof(CaptchaWebViewEnabled)); }
60+
}
61+
4162
internal void RegisterPage_Loaded()
4263
{
64+
if (CaptchaWebViewEnabled)
65+
{
66+
CaptchaCodeTextBoxVisible = true;
67+
View.Frame.Navigate(typeof(CaptchaPage));
68+
}
69+
4370
var c = Windows.System.UserProfile.GlobalizationPreferences.HomeGeographicRegion;
4471
for (int i = 0; i < CountryArrays.Abbreviations.Length; i++)
4572
{

Signal-Windows/ViewModels/ViewModelLocator.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public ViewModelLocator()
4747
SimpleIoc.Default.Register<ChatsAndMediaSettingsPageViewModel>();
4848
SimpleIoc.Default.Register<AdvancedSettingsPageViewModel>();
4949
SimpleIoc.Default.Register<BlockedContactsPageViewModel>();
50+
SimpleIoc.Default.Register<CaptchaPageViewModel>();
5051
}
5152

5253
// <summary>
@@ -148,6 +149,11 @@ public BlockedContactsPageViewModel BlockedContactsPageInstance
148149
get { return ServiceLocator.Current.GetInstance<BlockedContactsPageViewModel>(Key.ToString()); }
149150
}
150151

152+
public CaptchaPageViewModel CaptchaPageInstance
153+
{
154+
get { return ServiceLocator.Current.GetInstance<CaptchaPageViewModel>(Key.ToString()); }
155+
}
156+
151157
// <summary>
152158
// The cleanup.
153159
// </summary>

Signal-Windows/Views/CaptchaPage.xaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Page
2+
x:Class="Signal_Windows.Views.CaptchaPage"
3+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:local="using:Signal_Windows.Views"
6+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
8+
mc:Ignorable="d"
9+
DataContext="{Binding CaptchaPageInstance, Source={StaticResource Locator}}">
10+
11+
<Grid>
12+
<WebView x:Name="webView" Source="{x:Bind Vm.WebViewSource, Mode=TwoWay}"/>
13+
</Grid>
14+
</Page>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Runtime.InteropServices.WindowsRuntime;
6+
using Signal_Windows.ViewModels;
7+
using Windows.Foundation;
8+
using Windows.Foundation.Collections;
9+
using Windows.UI.Core;
10+
using Windows.UI.Xaml;
11+
using Windows.UI.Xaml.Controls;
12+
using Windows.UI.Xaml.Controls.Primitives;
13+
using Windows.UI.Xaml.Data;
14+
using Windows.UI.Xaml.Input;
15+
using Windows.UI.Xaml.Media;
16+
using Windows.UI.Xaml.Navigation;
17+
18+
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
19+
20+
namespace Signal_Windows.Views
21+
{
22+
// Pretty much the only reason this page exists is because putting the WebView on the RegisterPage wouldn't
23+
// correctly load the CAPTCHA part of the web page for me.
24+
public sealed partial class CaptchaPage : Page
25+
{
26+
public CaptchaPageViewModel Vm
27+
{
28+
get
29+
{
30+
return (CaptchaPageViewModel)DataContext;
31+
}
32+
}
33+
34+
public CaptchaPage()
35+
{
36+
// pretty much the only reason
37+
this.InitializeComponent();
38+
Vm.View = this;
39+
KeyDown += CaptchaPage_KeyDown;
40+
}
41+
42+
private bool IsCtrlKeyPressed()
43+
{
44+
var ctrlState = CoreWindow.GetForCurrentThread().GetKeyState(Windows.System.VirtualKey.Control);
45+
return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
46+
}
47+
48+
private void CaptchaPage_KeyDown(object sender, KeyRoutedEventArgs e)
49+
{
50+
if ((IsCtrlKeyPressed() && e.Key == Windows.System.VirtualKey.R) ||
51+
e.Key == Windows.System.VirtualKey.F5)
52+
{
53+
webView.Refresh();
54+
}
55+
}
56+
57+
protected override void OnNavigatedTo(NavigationEventArgs e)
58+
{
59+
base.OnNavigatedTo(e);
60+
Vm.OnNavigatedTo();
61+
}
62+
63+
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
64+
{
65+
base.OnNavigatingFrom(e);
66+
Vm.OnNavigatingFrom();
67+
}
68+
}
69+
}

Signal-Windows/Views/RegisterFinalizationPage.xaml.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,29 +24,35 @@ namespace Signal_Windows.Views
2424
/// </summary>
2525
public sealed partial class RegisterFinalizationPage : Page
2626
{
27+
public RegisterFinalizationPageViewModel Vm
28+
{
29+
get
30+
{
31+
return (RegisterFinalizationPageViewModel)DataContext;
32+
}
33+
}
34+
2735
public RegisterFinalizationPage()
2836
{
2937
this.InitializeComponent();
3038
Vm.View = this;
39+
Loaded += RegisterFinalizationPage_Loaded;
3140
}
3241

33-
public RegisterFinalizationPageViewModel Vm
42+
private async void RegisterFinalizationPage_Loaded(object sender, RoutedEventArgs e)
3443
{
35-
get
36-
{
37-
return (RegisterFinalizationPageViewModel)DataContext;
38-
}
44+
await Vm.RegisterFinalizationPage_Loaded();
3945
}
4046

4147
private void FinishButton_Click(object sender, RoutedEventArgs e)
4248
{
4349
Vm.FinishButton_Click();
4450
}
4551

46-
protected override async void OnNavigatedTo(NavigationEventArgs e)
52+
protected override void OnNavigatedTo(NavigationEventArgs e)
4753
{
4854
base.OnNavigatedTo(e);
49-
await Vm.OnNavigatedTo();
55+
Vm.OnNavigatedTo();
5056
}
5157

5258
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)

0 commit comments

Comments
 (0)