diff --git a/Orbot.xcodeproj/project.pbxproj b/Orbot.xcodeproj/project.pbxproj index aeed9d5..e786b34 100644 --- a/Orbot.xcodeproj/project.pbxproj +++ b/Orbot.xcodeproj/project.pbxproj @@ -86,6 +86,7 @@ A06DDCAF29264D0E001F9371 /* DebugMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A06DDCAC29264D0E001F9371 /* DebugMessage.swift */; }; A06DDCB029264D0E001F9371 /* DebugMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A06DDCAC29264D0E001F9371 /* DebugMessage.swift */; }; A08688172975A2310032B141 /* ScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08688162975A2310032B141 /* ScanViewController.swift */; }; + A086881B2975B4F80032B141 /* CaptchaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A086881A2975B4F80032B141 /* CaptchaViewController.swift */; }; A08C8FF02805D7220065B98D /* BlockerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08C8FEF2805D7220065B98D /* BlockerViewController.swift */; }; A08C8FF22805FB130065B98D /* Eureka+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08C8FF12805FB130065B98D /* Eureka+Helpers.swift */; }; A0A039B1274E9DF400D80FD1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A0A039B3274E9DF400D80FD1 /* InfoPlist.strings */; }; @@ -332,6 +333,7 @@ A06C96F5273C36AE0019ABE5 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; }; A06DDCAC29264D0E001F9371 /* DebugMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugMessage.swift; sourceTree = ""; }; A08688162975A2310032B141 /* ScanViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanViewController.swift; sourceTree = ""; }; + A086881A2975B4F80032B141 /* CaptchaViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaptchaViewController.swift; sourceTree = ""; }; A08C8FEF2805D7220065B98D /* BlockerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockerViewController.swift; sourceTree = ""; }; A08C8FF12805FB130065B98D /* Eureka+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Eureka+Helpers.swift"; sourceTree = ""; }; A08CA2C827DB697500F23100 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -555,6 +557,7 @@ A05B73B724755CE600930C40 /* MainViewController.swift */, A0EF119828043A9200A03017 /* BaseFormViewController.swift */, A04672E9296DC85400BD0F2F /* BridgesViewController.swift */, + A086881A2975B4F80032B141 /* CaptchaViewController.swift */, A05DCD05297198540017B36A /* CustomBridgesViewController.swift */, A08688162975A2310032B141 /* ScanViewController.swift */, A0C1D8A9292F840E00EB9DBB /* ChangeExitViewController.swift */, @@ -1372,6 +1375,7 @@ A06470182477F7E900311CBE /* UITextView+Helpers.swift in Sources */, A01F34DF2652D082008F9912 /* Logger.swift in Sources */, A05DCD0829719A1B0017B36A /* UIStoryboard.swift in Sources */, + A086881B2975B4F80032B141 /* CaptchaViewController.swift in Sources */, A0A735E1247566CD00073C81 /* Config.m in Sources */, A0A735EC24756CA200073C81 /* Message.swift in Sources */, A0A735F224756D6B00073C81 /* FileManager+Helpers.swift in Sources */, diff --git a/Orbot/BridgesViewController.swift b/Orbot/BridgesViewController.swift index bc96f57..564a47c 100644 --- a/Orbot/BridgesViewController.swift +++ b/Orbot/BridgesViewController.swift @@ -135,7 +135,7 @@ class BridgesViewController: BaseFormViewController, BridgesConfDelegate { .onCellSelection({ [weak self] cell, row in switch self?.section.selectedRow()?.value ?? .direct { case .request: - let vc = MoatViewController() + let vc = CaptchaViewController.make() vc.delegate = self self?.navigationController?.pushViewController(vc, animated: true) diff --git a/Orbot/CaptchaViewController.swift b/Orbot/CaptchaViewController.swift new file mode 100644 index 0000000..552fef6 --- /dev/null +++ b/Orbot/CaptchaViewController.swift @@ -0,0 +1,125 @@ +// +// CaptchaViewController.swift +// Orbot +// +// Created by Benjamin Erhart on 16.01.23. +// Copyright © 2023 Guardian Project. All rights reserved. +// + +import UIKit +import IPtProxyUI +import MBProgressHUD + +class CaptchaViewController: UIViewController { + + open weak var delegate: BridgesConfDelegate? + + @IBOutlet weak var captchaIv: UIImageView! { + didSet { + captchaIv.accessibilityLabel = MoatViewController.captchaImageText + } + } + + @IBOutlet weak var solutionTf: UITextField! { + didSet { + solutionTf.placeholder = NSLocalizedString("Enter text above", comment: "") + } + } + + @IBOutlet weak var saveBt: UIButton! { + didSet { + saveBt.setTitle(NSLocalizedString("Save", bundle: .iPtProxyUI, comment: "#bc-ignore!")) + } + } + + + private var challenge: String? + + + static func make() -> Self { + UIStoryboard.main.instantiateViewController(withIdentifier: "captcha_vc") as! Self + } + + + override func viewDidLoad() { + super.viewDidLoad() + + navigationItem.title = NSLocalizedString("Solve CAPTCHA", comment: "") + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + delegate?.startMeek() + + fetchCaptcha(nil) + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + delegate?.stopMeek() + } + + + // MARK: Actions + + @IBAction + func save() { + let hud = MBProgressHUD.showAdded(to: view, animated: true) + + MoatViewController.requestBridges(delegate, challenge, solutionTf.text) { [weak self] bridges, error in + DispatchQueue.main.async { + guard let self = self else { + return + } + + hud.hide(animated: true) + + if let error = error { + AlertHelper.present(self, message: error.localizedDescription) + return + } + + guard let bridges = bridges else { + return + } + + self.delegate?.customBridges = bridges + self.delegate?.transport = .custom + + self.delegate?.save() + + self.navigationController?.popViewController(animated: true) + } + } + } + + + // MARK: Private Methods + + @objc private func fetchCaptcha(_ sender: Any?) { + let hud = MBProgressHUD.showAdded(to: view, animated: true) + + MoatViewController.fetchCaptcha(delegate) { [weak self] challenge, captcha, error in + DispatchQueue.main.async { + guard let self = self else { + return + } + + hud.hide(animated: true) + + if let error = error { + AlertHelper.present(self, message: error.localizedDescription) + return + } + + self.challenge = challenge + + if let captcha = captcha { + self.captchaIv.image = UIImage(data: captcha) + } + } + } + } +} diff --git a/Orbot/CustomBridgesViewController.swift b/Orbot/CustomBridgesViewController.swift index f6525f4..6572751 100644 --- a/Orbot/CustomBridgesViewController.swift +++ b/Orbot/CustomBridgesViewController.swift @@ -11,8 +11,8 @@ import IPtProxyUI class CustomBridgesViewController: UIViewController, UITextViewDelegate, ScanQrDelegate { - static func make() -> CustomBridgesViewController { - UIStoryboard.main.instantiateViewController(withIdentifier: "custom_bridges_vc") as! CustomBridgesViewController + static func make() -> Self { + UIStoryboard.main.instantiateViewController(withIdentifier: "custom_bridges_vc") as! Self } diff --git a/Orbot/Main.storyboard b/Orbot/Main.storyboard index 957295b..40caf89 100644 --- a/Orbot/Main.storyboard +++ b/Orbot/Main.storyboard @@ -1,6 +1,6 @@ - + @@ -15,30 +15,30 @@ - + - + - +