@@ -313,15 +313,31 @@ def __init__(self, options: Optional[Dict[str, Any]] = None) -> None:
313313 if self .totp is not None :
314314 if not isinstance (self .totp , str ):
315315 raise TypeError ('The value of connection option "totp" should be a string' )
316- # Normalize: trim surrounding whitespace
317- self .totp = self .totp .strip ()
318- # Validate TOTP format: must be 6 numeric digits, with explicit non-numeric error
319- if not self .totp .isdigit ():
320- self ._logger .error ('Authentication failed: Invalid TOTP: contains non-numeric characters' )
321- raise errors .ConnectionError ('Authentication failed: Invalid TOTP: contains non-numeric characters' )
322- if len (self .totp ) != 6 :
323- self ._logger .error ('Authentication failed: Invalid TOTP: must be 6 digits' )
324- raise errors .ConnectionError ('Authentication failed: Invalid TOTP: must be 6 digits' )
316+ # Use shared TOTP validator for normalization and precedence checks
317+ try :
318+ from .totp_validation import validate_totp_code , INVALID_TOTP_MSG
319+ except Exception :
320+ validate_totp_code = None
321+ INVALID_TOTP_MSG = 'Invalid TOTP: Please enter a valid 6-digit numeric code.'
322+
323+ if validate_totp_code is not None :
324+ result = validate_totp_code (self .totp , totp_is_valid = None )
325+ if not result .ok :
326+ msg = result .message or INVALID_TOTP_MSG
327+ self ._logger .error (f'Authentication failed: { msg } ' )
328+ raise errors .ConnectionError (f'Authentication failed: { msg } ' )
329+ # normalized digits-only code
330+ self .totp = result .code
331+ else :
332+ # Fallback minimal validation
333+ s = self .totp .strip ()
334+ if not s .isdigit ():
335+ self ._logger .error (INVALID_TOTP_MSG )
336+ raise errors .ConnectionError (INVALID_TOTP_MSG )
337+ if len (s ) != 6 :
338+ self ._logger .error (INVALID_TOTP_MSG )
339+ raise errors .ConnectionError (INVALID_TOTP_MSG )
340+ self .totp = s
325341 self ._logger .info ('TOTP received in connection options' )
326342
327343 # OAuth authentication setup
@@ -983,10 +999,14 @@ def send_startup(totp_value=None):
983999 short_msg = match .group (1 ).strip () if match else error_msg .strip ()
9841000
9851001 if "Invalid TOTP" in short_msg :
986- print ("Authentication failed: Invalid TOTP" )
987- self ._logger .error ("Authentication failed: Invalid TOTP" )
1002+ try :
1003+ from .totp_validation import INVALID_TOTP_MSG
1004+ except Exception :
1005+ INVALID_TOTP_MSG = "Invalid TOTP: Please enter a valid 6-digit numeric code."
1006+ print (f"Authentication failed: { INVALID_TOTP_MSG } " )
1007+ self ._logger .error (f"Authentication failed: { INVALID_TOTP_MSG } " )
9881008 self .close_socket ()
989- raise errors .ConnectionError ("Authentication failed: Invalid TOTP " )
1009+ raise errors .ConnectionError (f "Authentication failed: { INVALID_TOTP_MSG } " )
9901010
9911011 # Generic error fallback
9921012 print (f"Authentication failed: { short_msg } " )
@@ -1009,21 +1029,28 @@ def send_startup(totp_value=None):
10091029 if ready :
10101030 totp_input = sys .stdin .readline ().strip ()
10111031
1012- # ❌ Blank TOTP entered
1013- if not totp_input :
1014- self ._logger .error ("Invalid TOTP: Cannot be empty." )
1015- raise errors .ConnectionError ("Invalid TOTP: Cannot be empty." )
1016-
1017- # ❌ Normalize: trim whitespace
1018- totp_input = totp_input .strip ()
1019- # ❌ Validate TOTP format: explicit non-numeric error, then length check
1020- if not totp_input .isdigit ():
1021- self ._logger .error ("Authentication failed: Invalid TOTP: contains non-numeric characters" )
1022- raise errors .ConnectionError ("Authentication failed: Invalid TOTP: contains non-numeric characters" )
1023- if len (totp_input ) != 6 :
1024- print ("Invalid TOTP format. Please enter a 6-digit code." )
1025- self ._logger .error ("Authentication failed: Invalid TOTP: must be 6 digits" )
1026- raise errors .ConnectionError ("Authentication failed: Invalid TOTP: must be 6 digits" )
1032+ # Validate using shared precedence
1033+ try :
1034+ from .totp_validation import validate_totp_code , INVALID_TOTP_MSG
1035+ except Exception :
1036+ validate_totp_code = None
1037+ INVALID_TOTP_MSG = "Invalid TOTP: Please enter a valid 6-digit numeric code."
1038+
1039+ if validate_totp_code is not None :
1040+ result = validate_totp_code (totp_input , totp_is_valid = None )
1041+ if not result .ok :
1042+ msg = result .message or INVALID_TOTP_MSG
1043+ print (msg )
1044+ self ._logger .error (msg )
1045+ raise errors .ConnectionError (msg )
1046+ totp_input = result .code
1047+ else :
1048+ s = totp_input .strip ()
1049+ if not s .isdigit () or len (s ) != 6 :
1050+ print (INVALID_TOTP_MSG )
1051+ self ._logger .error (INVALID_TOTP_MSG )
1052+ raise errors .ConnectionError (INVALID_TOTP_MSG )
1053+ totp_input = s
10271054 # ✅ Valid TOTP — retry connection
10281055 totp = totp_input
10291056 self .close_socket ()
0 commit comments