From 76d5a8b20587329c86e53ca5f755fa7062174aef Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 7 Aug 2024 16:21:38 +0800 Subject: [PATCH] unlock with PIN (#8977) * add custom password to unlock settings * If not set, use admin password; if set, use custom settings password. * At least 4 characters. * Set with gui or command line. Signed-off-by: 21pages * Update cn.rs --------- Signed-off-by: 21pages Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com> --- flutter/lib/common/widgets/dialog.dart | 99 ++++++++++++++++++- .../desktop/pages/desktop_setting_page.dart | 46 ++++++++- flutter/lib/web/bridge.dart | 8 ++ libs/hbb_common/src/config.rs | 31 +++++- src/core_main.rs | 14 +++ src/flutter_ffi.rs | 8 ++ src/ipc.rs | 35 +++++++ src/lang/ar.rs | 4 + src/lang/be.rs | 4 + src/lang/bg.rs | 4 + src/lang/ca.rs | 4 + src/lang/cn.rs | 4 + src/lang/cs.rs | 4 + src/lang/da.rs | 4 + src/lang/de.rs | 4 + src/lang/el.rs | 4 + src/lang/eo.rs | 4 + src/lang/es.rs | 4 + src/lang/et.rs | 4 + src/lang/eu.rs | 4 + src/lang/fa.rs | 4 + src/lang/fr.rs | 4 + src/lang/he.rs | 4 + src/lang/hr.rs | 4 + src/lang/hu.rs | 4 + src/lang/id.rs | 4 + src/lang/it.rs | 6 +- src/lang/ja.rs | 4 + src/lang/ko.rs | 4 + src/lang/kz.rs | 4 + src/lang/lt.rs | 4 + src/lang/lv.rs | 4 + src/lang/nb.rs | 4 + src/lang/nl.rs | 4 + src/lang/pl.rs | 4 + src/lang/pt_PT.rs | 4 + src/lang/ptbr.rs | 4 + src/lang/ro.rs | 4 + src/lang/ru.rs | 4 + src/lang/sk.rs | 4 + src/lang/sl.rs | 4 + src/lang/sq.rs | 4 + src/lang/sr.rs | 4 + src/lang/sv.rs | 4 + src/lang/template.rs | 4 + src/lang/th.rs | 4 + src/lang/tr.rs | 4 + src/lang/tw.rs | 4 + src/lang/uk.rs | 4 + src/lang/vn.rs | 4 + src/ui_interface.rs | 19 ++++ 51 files changed, 425 insertions(+), 9 deletions(-) diff --git a/flutter/lib/common/widgets/dialog.dart b/flutter/lib/common/widgets/dialog.dart index f140a68b0..58f85feb0 100644 --- a/flutter/lib/common/widgets/dialog.dart +++ b/flutter/lib/common/widgets/dialog.dart @@ -679,6 +679,7 @@ class PasswordWidget extends StatefulWidget { this.reRequestFocus = false, this.hintText, this.errorText, + this.title, }) : super(key: key); final TextEditingController controller; @@ -686,6 +687,7 @@ class PasswordWidget extends StatefulWidget { final bool reRequestFocus; final String? hintText; final String? errorText; + final String? title; @override State createState() => _PasswordWidgetState(); @@ -729,7 +731,7 @@ class _PasswordWidgetState extends State { @override Widget build(BuildContext context) { return DialogTextField( - title: translate(DialogTextField.kPasswordTitle), + title: translate(widget.title ?? DialogTextField.kPasswordTitle), hintText: translate(widget.hintText ?? 'Enter your password'), controller: widget.controller, prefixIcon: DialogTextField.kPasswordIcon, @@ -2216,3 +2218,98 @@ void CommonConfirmDialog(OverlayDialogManager dialogManager, String content, ); }); } + +void changeUnlockPinDialog(String oldPin, Function() callback) { + final pinController = TextEditingController(text: oldPin); + final confirmController = TextEditingController(text: oldPin); + String? pinErrorText; + String? confirmationErrorText; + gFFI.dialogManager.show((setState, close, context) { + submit() async { + pinErrorText = null; + confirmationErrorText = null; + final pin = pinController.text.trim(); + final confirm = confirmController.text.trim(); + if (pin != confirm) { + setState(() { + confirmationErrorText = + translate('The confirmation is not identical.'); + }); + return; + } + final errorMsg = bind.mainSetUnlockPin(pin: pin); + if (errorMsg != '') { + setState(() { + pinErrorText = translate(errorMsg); + }); + return; + } + callback.call(); + close(); + } + + return CustomAlertDialog( + title: Text(translate("Set PIN")), + content: Column( + children: [ + DialogTextField( + title: 'PIN', + controller: pinController, + obscureText: true, + errorText: pinErrorText, + ), + DialogTextField( + title: translate('Confirmation'), + controller: confirmController, + obscureText: true, + errorText: confirmationErrorText, + ) + ], + ).marginOnly(bottom: 12), + actions: [ + dialogButton(translate("Cancel"), onPressed: close, isOutline: true), + dialogButton(translate("OK"), onPressed: submit), + ], + onSubmit: submit, + onCancel: close, + ); + }); +} + +void checkUnlockPinDialog(String correctPin, Function() passCallback) { + final controller = TextEditingController(); + String? errorText; + gFFI.dialogManager.show((setState, close, context) { + submit() async { + final pin = controller.text.trim(); + if (correctPin != pin) { + setState(() { + errorText = translate('Wrong PIN'); + }); + return; + } + passCallback.call(); + close(); + } + + return CustomAlertDialog( + content: Row( + children: [ + Expanded( + child: PasswordWidget( + title: 'PIN', + controller: controller, + errorText: errorText, + hintText: '', + )) + ], + ).marginOnly(bottom: 12), + actions: [ + dialogButton(translate("Cancel"), onPressed: close, isOutline: true), + dialogButton(translate("OK"), onPressed: submit), + ], + onSubmit: submit, + onCancel: close, + ); + }); +} diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index ba2c14d69..a016a61ae 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -1018,6 +1018,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { _OptionCheckBox(context, 'allow-only-conn-window-open-tip', 'allow-only-conn-window-open', reverse: false, enabled: enabled), + if (bind.mainIsInstalled()) unlockPin() ]); } @@ -1265,6 +1266,40 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { }(), ]; } + + Widget unlockPin() { + bool enabled = !locked; + RxString unlockPin = bind.mainGetUnlockPin().obs; + update() async { + unlockPin.value = bind.mainGetUnlockPin(); + } + + onChanged(bool? checked) async { + changeUnlockPinDialog(unlockPin.value, update); + } + + final isOptFixed = isOptionFixed(kOptionWhitelist); + return GestureDetector( + child: Obx(() => Row( + children: [ + Checkbox( + value: unlockPin.isNotEmpty, + onChanged: enabled && !isOptFixed ? onChanged : null) + .marginOnly(right: 5), + Expanded( + child: Text( + translate('Unlock with PIN'), + style: TextStyle(color: disabledTextColor(context, enabled)), + )) + ], + )), + onTap: enabled + ? () { + onChanged(!unlockPin.isNotEmpty); + } + : null, + ).marginOnly(left: _kCheckBoxLeftMargin); + } } class _Network extends StatefulWidget { @@ -2160,9 +2195,14 @@ Widget _lock( Text(translate(label)).marginOnly(left: 5), ]).marginSymmetric(vertical: 2)), onPressed: () async { - bool checked = await callMainCheckSuperUserPermission(); - if (checked) { - onUnlock(); + final unlockPin = bind.mainGetUnlockPin(); + if (unlockPin.isEmpty) { + bool checked = await callMainCheckSuperUserPermission(); + if (checked) { + onUnlock(); + } + } else { + checkUnlockPinDialog(unlockPin, onUnlock); } }, ).marginSymmetric(horizontal: 2, vertical: 4), diff --git a/flutter/lib/web/bridge.dart b/flutter/lib/web/bridge.dart index d4939c804..7795cb824 100644 --- a/flutter/lib/web/bridge.dart +++ b/flutter/lib/web/bridge.dart @@ -1622,5 +1622,13 @@ class RustdeskImpl { throw UnimplementedError(); } + String mainGetUnlockPin({dynamic hint}) { + throw UnimplementedError(); + } + + String mainSetUnlockPin({required String pin, dynamic hint}) { + throw UnimplementedError(); + } + void dispose() {} } diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 0a884e1f8..2dfa88b96 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -208,6 +208,8 @@ pub struct Config2 { nat_type: i32, #[serde(default, deserialize_with = "deserialize_i32")] serial: i32, + #[serde(default, deserialize_with = "deserialize_string")] + unlock_pin: String, #[serde(default)] socks: Option, @@ -427,14 +429,20 @@ fn patch(path: PathBuf) -> PathBuf { impl Config2 { fn load() -> Config2 { let mut config = Config::load_::("2"); + let mut store = false; if let Some(mut socks) = config.socks { - let (password, _, store) = + let (password, _, store2) = decrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION); socks.password = password; config.socks = Some(socks); - if store { - config.store(); - } + store |= store2; + } + let (unlock_pin, _, store2) = + decrypt_str_or_original(&config.unlock_pin, PASSWORD_ENC_VERSION); + config.unlock_pin = unlock_pin; + store |= store2; + if store { + config.store(); } config } @@ -450,6 +458,8 @@ impl Config2 { encrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN); config.socks = Some(socks); } + config.unlock_pin = + encrypt_str_or_original(&config.unlock_pin, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN); Config::store_(&config, "2"); } @@ -1081,6 +1091,19 @@ impl Config { NetworkType::Direct } + pub fn get_unlock_pin() -> String { + CONFIG2.read().unwrap().unlock_pin.clone() + } + + pub fn set_unlock_pin(pin: &str) { + let mut config = CONFIG2.write().unwrap(); + if pin == config.unlock_pin { + return; + } + config.unlock_pin = pin.to_string(); + config.store(); + } + pub fn get() -> Config { return CONFIG.read().unwrap().clone(); } diff --git a/src/core_main.rs b/src/core_main.rs index c7e4d1f00..3aa69f8f3 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -316,6 +316,20 @@ pub fn core_main() -> Option> { } } return None; + } else if args[0] == "--set-unlock-pin" { + #[cfg(feature = "flutter")] + if args.len() == 2 { + if crate::platform::is_installed() && is_root() { + if let Err(err) = crate::ipc::set_unlock_pin(args[1].to_owned(), false) { + println!("{err}"); + } else { + println!("Done!"); + } + } else { + println!("Installation and administrative privileges required!"); + } + } + return None; } else if args[0] == "--get-id" { println!("{}", crate::ipc::get_id()); return None; diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index cceec4cd1..46261a37e 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1617,6 +1617,14 @@ pub fn main_check_super_user_permission() -> bool { check_super_user_permission() } +pub fn main_get_unlock_pin() -> SyncReturn { + SyncReturn(get_unlock_pin()) +} + +pub fn main_set_unlock_pin(pin: String) -> SyncReturn { + SyncReturn(set_unlock_pin(pin)) +} + pub fn main_check_mouse_time() { check_mouse_time(); } diff --git a/src/ipc.rs b/src/ipc.rs index fba0000fb..be869488b 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -484,6 +484,8 @@ async fn handle(data: Data, stream: &mut Connection) { }; } else if name == "voice-call-input" { value = crate::audio_service::get_voice_call_input_device(); + } else if name == "unlock-pin" { + value = Some(Config::get_unlock_pin()); } else { value = None; } @@ -501,6 +503,8 @@ async fn handle(data: Data, stream: &mut Connection) { Config::set_salt(&value); } else if name == "voice-call-input" { crate::audio_service::set_voice_call_input_device(Some(value), true); + } else if name == "unlock-pin" { + Config::set_unlock_pin(&value); } else { return; } @@ -891,6 +895,37 @@ pub fn set_permanent_password(v: String) -> ResultType<()> { set_config("permanent-password", v) } +#[cfg(feature = "flutter")] +#[cfg(not(any(target_os = "android", target_os = "ios")))] +pub fn set_unlock_pin(v: String, translate: bool) -> ResultType<()> { + let v = v.trim().to_owned(); + let min_len = 4; + if !v.is_empty() && v.len() < min_len { + let err = if translate { + crate::lang::translate( + "Requires at least {".to_string() + &format!("{min_len}") + "} characters", + ) + } else { + // Sometimes, translated can't show normally in command line + format!("Requires at least {} characters", min_len) + }; + bail!(err); + } + Config::set_unlock_pin(&v); + set_config("unlock-pin", v) +} + +#[cfg(feature = "flutter")] +#[cfg(not(any(target_os = "android", target_os = "ios")))] +pub fn get_unlock_pin() -> String { + if let Ok(Some(v)) = get_config("unlock-pin") { + Config::set_unlock_pin(&v); + v + } else { + Config::get_unlock_pin() + } +} + pub fn get_id() -> String { if let Ok(Some(v)) = get_config("id") { // update salt also, so that next time reinstallation not causing first-time auto-login failure diff --git a/src/lang/ar.rs b/src/lang/ar.rs index 05b8ae546..d1da83ec5 100644 --- a/src/lang/ar.rs +++ b/src/lang/ar.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/be.rs b/src/lang/be.rs index 09936fb5a..a294fcae0 100644 --- a/src/lang/be.rs +++ b/src/lang/be.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/bg.rs b/src/lang/bg.rs index d4099fa24..9eb0ca63f 100644 --- a/src/lang/bg.rs +++ b/src/lang/bg.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 6b3c4c294..5bfea79ca 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 48a0875fc..6481761fd 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "关于 RustDesk"), ("Send clipboard keystrokes", "发送剪贴板按键"), ("network_error_tip", "请检查网络连接,然后点击再试"), + ("Unlock with PIN", "使用 PIN 码解锁设置"), + ("Requires at least {} characters", "不少于{}个字符"), + ("Wrong PIN", "PIN 码错误"), + ("Set PIN", "设置 PIN 码"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 4a4cc943c..2caf00e5d 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "O RustDesk"), ("Send clipboard keystrokes", "Odesílat stisky kláves schránky"), ("network_error_tip", "Zkontrolujte prosím připojení k síti a klikněte na tlačítko Opakovat."), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 5ee83337f..44d19dd46 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 3363d7e59..fc6269cb7 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "Über RustDesk"), ("Send clipboard keystrokes", "Tastenanschläge aus der Zwischenablage senden"), ("network_error_tip", "Bitte überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es dann erneut."), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index c5ed30ebd..2f929f3b1 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index f92c706c6..70d73bfc6 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index e5eaadf3b..da6c2b4ca 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/et.rs b/src/lang/et.rs index bf5742786..74c30b076 100644 --- a/src/lang/et.rs +++ b/src/lang/et.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eu.rs b/src/lang/eu.rs index 487ee23c3..55a9dcbfb 100644 --- a/src/lang/eu.rs +++ b/src/lang/eu.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index e7a5af768..e9c77bd69 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index bf40cd045..c64aa9ee2 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/he.rs b/src/lang/he.rs index 84e461c06..4e21c204d 100644 --- a/src/lang/he.rs +++ b/src/lang/he.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hr.rs b/src/lang/hr.rs index aa08949b2..f221ebcee 100644 --- a/src/lang/hr.rs +++ b/src/lang/hr.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 054c333e9..40fbf2f76 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 773a75eab..eab2e1a36 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 329db79da..5d152bfcd 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -631,6 +631,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("cancel-bot-confirm-tip", "Sei sicuro di voler annullare Telegram?"), ("About RustDesk", "Info su RustDesk"), ("Send clipboard keystrokes", "Invia sequenze tasti appunti"), - ("network_error_tip", "Controlla la connessione di rete, quindi seleziona 'Riprova'.") + ("network_error_tip", "Controlla la connessione di rete, quindi seleziona 'Riprova'."), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 7bc06d8cc..8c8c71944 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "RustDeskについて"), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 7f7e80d6b..65db10aec 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "RustDesk 대하여"), ("Send clipboard keystrokes", "클립보드 키 입력 전송"), ("network_error_tip", "네트워크 연결을 확인한 후 다시 시도하세요."), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 21ef39574..7545bff40 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lt.rs b/src/lang/lt.rs index 61ff2ee10..e659014e5 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lv.rs b/src/lang/lv.rs index 5ce48429d..3296a51ae 100644 --- a/src/lang/lv.rs +++ b/src/lang/lv.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nb.rs b/src/lang/nb.rs index 3a986ecbb..1afa22d99 100644 --- a/src/lang/nb.rs +++ b/src/lang/nb.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index eceb1b6ff..764849991 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "Over RustDesk"), ("Send clipboard keystrokes", "Klembord toetsaanslagen verzenden"), ("network_error_tip", "Controleer de netwerkverbinding en selecteer 'Opnieuw proberen'."), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 370cf59e4..5d04d76c5 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 0bf0c7304..965d934df 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 003786c46..b3804bd5c 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index bace41072..639f0a29c 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 0c8a24718..ca9e17757 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "О RustDesk"), ("Send clipboard keystrokes", "Отправлять нажатия клавиш из буфера обмена"), ("network_error_tip", "Проверьте подключение к сети, затем нажмите \"Повтор\"."), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 24b4d2e09..816106c57 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "O RustDesk"), ("Send clipboard keystrokes", "Odoslať stlačenia klávesov zo schránky"), ("network_error_tip", "Skontrolujte svoje sieťové pripojenie a potom kliknite na tlačidlo Opakovať."), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 98f33956a..1dd8280c6 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index c3ebca629..f11d48560 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index c6773955a..2bc72e6e3 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 2445bc2f1..ed7752e26 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 3d3c86e5b..7e57544a8 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index fa369336c..6789a4573 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 366265a57..e9b3d6cf2 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 8fa1c8c14..0a4b26144 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "關於 RustDesk"), ("Send clipboard keystrokes", "發送剪貼簿按鍵"), ("network_error_tip", "請檢查網路連結,然後點擊重試"), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/uk.rs b/src/lang/uk.rs index c9cee27e4..aa9458776 100644 --- a/src/lang/uk.rs +++ b/src/lang/uk.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", "Про Rustdesk"), ("Send clipboard keystrokes", "Надіслати вміст буфера обміну"), ("network_error_tip", "Будь ласка, перевірте ваше підключення до мережі та натисність \"Повторити\""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 6042a98d5..095364362 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About RustDesk", ""), ("Send clipboard keystrokes", ""), ("network_error_tip", ""), + ("Unlock with PIN", ""), + ("Requires at least {} characters", ""), + ("Wrong PIN", ""), + ("Set PIN", ""), ].iter().cloned().collect(); } diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 443f6fa42..e32fcb49d 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -1444,3 +1444,22 @@ pub fn check_hwcodec() { }) } } + +#[cfg(feature = "flutter")] +pub fn get_unlock_pin() -> String { + #[cfg(any(target_os = "android", target_os = "ios"))] + return String::default(); + #[cfg(not(any(target_os = "android", target_os = "ios")))] + return ipc::get_unlock_pin(); +} + +#[cfg(feature = "flutter")] +pub fn set_unlock_pin(pin: String) -> String { + #[cfg(any(target_os = "android", target_os = "ios"))] + return String::default(); + #[cfg(not(any(target_os = "android", target_os = "ios")))] + match ipc::set_unlock_pin(pin, true) { + Ok(_) => String::default(), + Err(err) => err.to_string(), + } +}