password max length prompt (#9248)

Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
21pages 2024-09-04 11:31:13 +08:00 committed by GitHub
parent 04c0f66ca9
commit 29e12b84a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 47 additions and 16 deletions

View File

@ -381,6 +381,7 @@ class DialogTextField extends StatelessWidget {
final FocusNode? focusNode; final FocusNode? focusNode;
final TextInputType? keyboardType; final TextInputType? keyboardType;
final List<TextInputFormatter>? inputFormatters; final List<TextInputFormatter>? inputFormatters;
final int? maxLength;
static const kUsernameTitle = 'Username'; static const kUsernameTitle = 'Username';
static const kUsernameIcon = Icon(Icons.account_circle_outlined); static const kUsernameIcon = Icon(Icons.account_circle_outlined);
@ -398,6 +399,7 @@ class DialogTextField extends StatelessWidget {
this.hintText, this.hintText,
this.keyboardType, this.keyboardType,
this.inputFormatters, this.inputFormatters,
this.maxLength,
required this.title, required this.title,
required this.controller}) required this.controller})
: super(key: key); : super(key: key);
@ -424,6 +426,7 @@ class DialogTextField extends StatelessWidget {
obscureText: obscureText, obscureText: obscureText,
keyboardType: keyboardType, keyboardType: keyboardType,
inputFormatters: inputFormatters, inputFormatters: inputFormatters,
maxLength: maxLength,
), ),
), ),
], ],
@ -681,6 +684,7 @@ class PasswordWidget extends StatefulWidget {
this.hintText, this.hintText,
this.errorText, this.errorText,
this.title, this.title,
this.maxLength,
}) : super(key: key); }) : super(key: key);
final TextEditingController controller; final TextEditingController controller;
@ -689,6 +693,7 @@ class PasswordWidget extends StatefulWidget {
final String? hintText; final String? hintText;
final String? errorText; final String? errorText;
final String? title; final String? title;
final int? maxLength;
@override @override
State<PasswordWidget> createState() => _PasswordWidgetState(); State<PasswordWidget> createState() => _PasswordWidgetState();
@ -751,6 +756,7 @@ class _PasswordWidgetState extends State<PasswordWidget> {
obscureText: !_passwordVisible, obscureText: !_passwordVisible,
errorText: widget.errorText, errorText: widget.errorText,
focusNode: _focusNode, focusNode: _focusNode,
maxLength: widget.maxLength,
); );
} }
} }
@ -2245,6 +2251,7 @@ void changeUnlockPinDialog(String oldPin, Function() callback) {
final confirmController = TextEditingController(text: oldPin); final confirmController = TextEditingController(text: oldPin);
String? pinErrorText; String? pinErrorText;
String? confirmationErrorText; String? confirmationErrorText;
final maxLength = bind.mainMaxEncryptLen();
gFFI.dialogManager.show((setState, close, context) { gFFI.dialogManager.show((setState, close, context) {
submit() async { submit() async {
pinErrorText = null; pinErrorText = null;
@ -2278,12 +2285,14 @@ void changeUnlockPinDialog(String oldPin, Function() callback) {
controller: pinController, controller: pinController,
obscureText: true, obscureText: true,
errorText: pinErrorText, errorText: pinErrorText,
maxLength: maxLength,
), ),
DialogTextField( DialogTextField(
title: translate('Confirmation'), title: translate('Confirmation'),
controller: confirmController, controller: confirmController,
obscureText: true, obscureText: true,
errorText: confirmationErrorText, errorText: confirmationErrorText,
maxLength: maxLength,
) )
], ],
).marginOnly(bottom: 12), ).marginOnly(bottom: 12),

View File

@ -1200,6 +1200,7 @@ class MyGroupPeerCard extends BasePeerCard {
} }
void _rdpDialog(String id) async { void _rdpDialog(String id) async {
final maxLength = bind.mainMaxEncryptLen();
final port = await bind.mainGetPeerOption(id: id, key: 'rdp_port'); final port = await bind.mainGetPeerOption(id: id, key: 'rdp_port');
final username = await bind.mainGetPeerOption(id: id, key: 'rdp_username'); final username = await bind.mainGetPeerOption(id: id, key: 'rdp_username');
final portController = TextEditingController(text: port); final portController = TextEditingController(text: port);
@ -1288,6 +1289,7 @@ void _rdpDialog(String id) async {
Expanded( Expanded(
child: Obx(() => TextField( child: Obx(() => TextField(
obscureText: secure.value, obscureText: secure.value,
maxLength: maxLength,
decoration: InputDecoration( decoration: InputDecoration(
labelText: isDesktop labelText: isDesktop
? null ? null

View File

@ -857,6 +857,7 @@ void setPasswordDialog({VoidCallback? notEmptyCallback}) async {
// SpecialCharacterValidationRule(), // SpecialCharacterValidationRule(),
MinCharactersValidationRule(8), MinCharactersValidationRule(8),
]; ];
final maxLength = bind.mainMaxEncryptLen();
gFFI.dialogManager.show((setState, close, context) { gFFI.dialogManager.show((setState, close, context) {
submit() { submit() {
@ -915,6 +916,7 @@ void setPasswordDialog({VoidCallback? notEmptyCallback}) async {
errMsg0 = ''; errMsg0 = '';
}); });
}, },
maxLength: maxLength,
), ),
), ),
], ],
@ -941,6 +943,7 @@ void setPasswordDialog({VoidCallback? notEmptyCallback}) async {
errMsg1 = ''; errMsg1 = '';
}); });
}, },
maxLength: maxLength,
), ),
), ),
], ],

View File

@ -2512,6 +2512,7 @@ void changeSocks5Proxy() async {
: Icons.visibility))), : Icons.visibility))),
controller: pwdController, controller: pwdController,
enabled: !isOptFixed, enabled: !isOptFixed,
maxLength: bind.mainMaxEncryptLen(),
)), )),
), ),
], ],

View File

@ -39,7 +39,7 @@ pub const REG_INTERVAL: i64 = 15_000;
pub const COMPRESS_LEVEL: i32 = 3; pub const COMPRESS_LEVEL: i32 = 3;
const SERIAL: i32 = 3; const SERIAL: i32 = 3;
const PASSWORD_ENC_VERSION: &str = "00"; const PASSWORD_ENC_VERSION: &str = "00";
const ENCRYPT_MAX_LEN: usize = 128; pub const ENCRYPT_MAX_LEN: usize = 128; // used for password, pin, etc, not for all
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
lazy_static::lazy_static! { lazy_static::lazy_static! {

View File

@ -89,11 +89,11 @@ pub fn encrypt_str_or_original(s: &str, version: &str, max_len: usize) -> String
log::error!("Duplicate encryption!"); log::error!("Duplicate encryption!");
return s.to_owned(); return s.to_owned();
} }
if s.bytes().len() > max_len { if s.chars().count() > max_len {
return String::default(); return String::default();
} }
if version == "00" { if version == "00" {
if let Ok(s) = encrypt(s.as_bytes(), max_len) { if let Ok(s) = encrypt(s.as_bytes()) {
return version.to_owned() + &s; return version.to_owned() + &s;
} }
} }
@ -130,7 +130,7 @@ pub fn encrypt_vec_or_original(v: &[u8], version: &str, max_len: usize) -> Vec<u
return vec![]; return vec![];
} }
if version == "00" { if version == "00" {
if let Ok(s) = encrypt(v, max_len) { if let Ok(s) = encrypt(v) {
let mut version = version.to_owned().into_bytes(); let mut version = version.to_owned().into_bytes();
version.append(&mut s.into_bytes()); version.append(&mut s.into_bytes());
return version; return version;
@ -155,8 +155,8 @@ pub fn decrypt_vec_or_original(v: &[u8], current_version: &str) -> (Vec<u8>, boo
(v.to_owned(), false, !v.is_empty()) (v.to_owned(), false, !v.is_empty())
} }
fn encrypt(v: &[u8], max_len: usize) -> Result<String, ()> { fn encrypt(v: &[u8]) -> Result<String, ()> {
if !v.is_empty() && v.len() <= max_len { if !v.is_empty() {
symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original)) symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original))
} else { } else {
Err(()) Err(())

View File

@ -2282,6 +2282,10 @@ pub fn main_clear_trusted_devices() {
clear_trusted_devices() clear_trusted_devices()
} }
pub fn main_max_encrypt_len() -> SyncReturn<usize> {
SyncReturn(max_encrypt_len())
}
pub fn session_request_new_display_init_msgs(session_id: SessionID, display: usize) { pub fn session_request_new_display_init_msgs(session_id: SessionID, display: usize) {
if let Some(session) = sessions::get_session_by_session_id(&session_id) { if let Some(session) = sessions::get_session_by_session_id(&session_id) {
session.request_init_msgs(display); session.request_init_msgs(display);

View File

@ -928,16 +928,23 @@ pub fn set_permanent_password(v: String) -> ResultType<()> {
pub fn set_unlock_pin(v: String, translate: bool) -> ResultType<()> { pub fn set_unlock_pin(v: String, translate: bool) -> ResultType<()> {
let v = v.trim().to_owned(); let v = v.trim().to_owned();
let min_len = 4; let min_len = 4;
if !v.is_empty() && v.len() < min_len { let max_len = crate::ui_interface::max_encrypt_len();
let err = if translate { let len = v.chars().count();
crate::lang::translate( if !v.is_empty() {
"Requires at least {".to_string() + &format!("{min_len}") + "} characters", if len < min_len {
) let err = if translate {
} else { crate::lang::translate(
// Sometimes, translated can't show normally in command line "Requires at least {".to_string() + &format!("{min_len}") + "} characters",
format!("Requires at least {} characters", min_len) )
}; } else {
bail!(err); // Sometimes, translated can't show normally in command line
format!("Requires at least {} characters", min_len)
};
bail!(err);
}
if len > max_len {
bail!("No more than {max_len} characters");
}
} }
Config::set_unlock_pin(&v); Config::set_unlock_pin(&v);
set_config("unlock-pin", v) set_config("unlock-pin", v)

View File

@ -1495,3 +1495,8 @@ pub fn clear_trusted_devices() {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
ipc::clear_trusted_devices(); ipc::clear_trusted_devices();
} }
#[cfg(feature = "flutter")]
pub fn max_encrypt_len() -> usize {
hbb_common::config::ENCRYPT_MAX_LEN
}