def _stubbornly_unquote(self, value): # Note: we can assume that the value has been unquoted (from # %-encoding) by the Pyramid stuff, but the following stubborn # unquoting is added for cases when data have been quoted by # the client "too many times"; we try to be "liberal in what we # accept" because, indeed, it is quite easy to get lost in all # this encoding stuff :-). But, on the other hand, we would # not like to allow for any ambiguities, so we accept *only* # URL-safe-Base64-encoding, not standard-Base64-encoding (as # the latter involves '+' whose meaning would not be clear: # it could be interpreted as a plus sign or as a space which, # then, could be interpreted just as an "ignorable filler"...). # Note, therefore, that it becomes *not* crucial whether we use # `urllib.unquote()` or `urllib.unquote_plus()` here -- because # URL-safe-Base64-encoding does *not* allow plus signs (and we # also *forbid* spaces, even as "ignorable fillers"). value = as_unicode(value) #3-- for _ in range(10): # ^ limited number of steps because we do not like allowing # API clients to make us go into an infinite loop... :-] value = urllib.parse.unquote_plus(value) if u'%' not in value and u'+' not in value: #3: u-- u-- break value = as_unicode(value) #3-- return value
def generate_secret_key_qr_code_url(secret_key, login, issuer_name): # type: (String, String, String) -> String login = as_unicode(login) issuer_name = as_unicode(issuer_name) if sys.version_info[0] < 3: #3-- login = as_bytes(login) #3-- issuer_name = as_bytes(issuer_name) #3-- return make_totp_handler(secret_key).provisioning_uri( name=login, issuer_name=issuer_name)
def _url_to_url_no_fqdn(self, url): if not url: return "" parsed = urllib.parse.urlparse(as_unicode(url)) #3: `as_unicode(`-- `)`-- output = [as_unicode(parsed.path)] #3: `as_unicode(`-- `)`-- if parsed.query: output.extend([u'?', as_unicode(parsed.query)]) #3: `as_unicode(`-- `)`-- if parsed.fragment: output.extend([u'#', as_unicode(parsed.fragment)]) #3: `as_unicode(`-- `)`-- return u"".join(output)
def __call__(self, value): # type: (Value) -> Iterator[String] self.verify_isinstance( value, str, error_message='{!a} is not a string'.format(value)) output_value = as_unicode(value) self._verify_length(output_value) yield output_value
def _get_port(match, scheme): scheme_key = as_unicode(scheme, 'surrogatepass') conv = _proper_conv(match) port = match.group('port') if (port is None or port == conv(':') or port == conv(':{}'.format( URL_SCHEME_TO_DEFAULT_PORT.get(scheme_key)))): port = conv('') return port
def jwt_encode( payload, # type: Dict[str, Any] secret_key, # type: StrOrBinary algorithm=JWT_ALGO_DEFAULT, # type: str required_claims=(), # type: Iterable[str] ): # type: (...) -> str _verify_required_claims(payload, required_claims, JWTEncodeError) try: secret_key = as_unicode(secret_key) token = jwt.encode(payload, secret_key, algorithm=algorithm) token = as_unicode( token) # <- TODO later: can be removed after upgrade of PyJWT... except Exception as exc: raise JWTEncodeError( exc) from None # (Because we don't want to reveal too much...) assert JWT_ROUGH_REGEX.search(token) return token
def generate_secret_key(mfa_key_base, server_secret): # type: (StrOrBinary, StrOrBinary) -> String mfa_key_base = _conv_secret_val(mfa_key_base, as_bytes, 'the given MFA key base to `bytes`') server_secret = _conv_secret_val(server_secret, as_bytes, 'the given server secret to `bytes`') hmac_result = hmac.new(server_secret, mfa_key_base, hashlib.sha384).digest() return as_unicode(base64.b32encode(hmac_result)[:LEN_OF_SECRET_KEY])
def does_look_like_http_url_without_prefix(s): """ Try to guess (using some heuristics) whether the given string (or binary data blob) may be an incomplete HTTP URL starting with the host part, i.e., an HTTP URL unprovided with the `http://` prefix. """ if isinstance(s, (bytes, bytearray)): s = as_unicode(s, 'surrogatepass') return bool( _INCOMPLETE_HTTP_URL_CANDIDATE_STARTING_WITH_HOST_REGEX.search(s))
def jwt_decode( token, # type: StrOrBinary secret_key, # type: StrOrBinary accepted_algorithms=(JWT_ALGO_DEFAULT, ), # type: Iterable[str] required_claims=(), # type: Iterable[str] ): # type: (...) -> Dict[str, Any] try: token = as_unicode(token) secret_key = as_unicode(secret_key) payload = jwt.decode(token, secret_key, algorithms=sorted(accepted_algorithms)) except Exception as exc: raise JWTDecodeError( exc) from None # (Because we don't want to reveal too much...) assert JWT_ROUGH_REGEX.search(token) assert isinstance(payload, dict) _verify_required_claims(payload, required_claims, JWTDecodeError) return payload
def _get_ipv6_addr(match): conv = _proper_conv(match) ipv6_main_part = match.group('ipv6_main_part') assert ipv6_main_part ipv6_suffix_in_ipv4_format = match.group('ipv6_suffix_in_ipv4_format') try: if ipv6_suffix_in_ipv4_format: assert ipv6_main_part.endswith(conv(':')) ipv6_suffix = _convert_ipv4_to_ipv6_suffix( ipv6_suffix_in_ipv4_format) else: assert ipv6_main_part == match.group('ipv6_addr') ipv6_suffix = '' ipv6_main_part = as_unicode(ipv6_main_part, 'surrogatepass') ipv6_suffix = as_unicode(ipv6_suffix, 'surrogatepass') #3-- ipv6_addr = ipaddress.IPv6Address(ipv6_main_part + ipv6_suffix).compressed ipv6_addr = conv(ipv6_addr) except ipaddress.AddressValueError: ipv6_addr = match.group('ipv6_addr') assert is_pure_ascii(ipv6_addr) return ipv6_addr
def _convert_ipv4_to_ipv6_suffix(ipv6_suffix_in_ipv4_format): """ >>> _convert_ipv4_to_ipv6_suffix('192.168.0.1') 'c0a8:0001' """ ipv6_suffix_in_ipv4_format = as_unicode(ipv6_suffix_in_ipv4_format, 'surrogatepass') as_ipv4 = ipaddress.IPv4Address(ipv6_suffix_in_ipv4_format) as_int = int(as_ipv4) as_ipv6 = ipaddress.IPv6Address(as_int) ipv6_suffix = as_ipv6.exploded[-9:] ipv6_suffix = str(ipv6_suffix) #3-- assert _LAST_9_CHARS_OF_EXPLODED_IPV6_REGEX.search(ipv6_suffix) return ipv6_suffix
def _adjust_server_secret(value): # type: (...) -> str if not isinstance(value, (unicode, bytes)): #3: `unicode` -> `str` raise DataConversionError('not a `str` or `bytes` - its type is `{}`' .format(ascii_str(type(value).__name__))) #3: `__name__` -> `__qualname__` try: value = as_unicode(value) except UnicodeDecodeError: # We don't want to reveal the value in the traceback etc. raise DataConversionError('contains non-UTF-8 binary data') #3: add: `from None` if not value.strip(): raise DataConversionError('an empty or whitespace-only value') value = value.encode('utf-8') #3-- assert isinstance(value, str) yield value
def _get_exception_message(exc): """ Try to get a message from a raised exception. Args: `exc`: An instance of a raised exception. Returns: Message from exception or default message, as unicode. """ if isinstance(exc, FieldValueError): return exc.public_message else: exc_message = getattr(exc, 'message', None) if exc_message and isinstance(exc_message, basestring): return as_unicode(exc_message) return u'Failed to create record.'
def get_exception_message(exc): """ Try to get a message from a raised exception. Args: `exc`: An instance of a raised exception. Returns: Message from exception, as unicode, or None. """ if isinstance(exc, FieldValueError): return exc.public_message.rstrip('.') + '.' else: exc_message = getattr(exc, 'message', None) if exc_message and isinstance(exc_message, basestring): return as_unicode(exc_message).rstrip('.') + '.' return None
def prepare_header_value( self, header_name, value): #3: remove whole method definition (keeping the above one) # type: (String, HeaderRaw) -> Header if isinstance(value, Header): return value if header_name.lower() in ADDR_HEADER_LOWERCASE_NAMES: value = self._adjust_addr_value(value) elif isinstance(value, datetime.datetime): value = self._format_dt(value) if not isinstance(value, basestring): raise TypeError('{!r} is not a string'.format(value)) if header_name.lower() == 'subject': self.validate_subject_value(value) header = Header(as_unicode(value), header_name=header_name, maxlinelen=78) return header
def _proper_conv(match): return (as_bytes if isinstance(match.group(0), bytes) else lambda part: as_unicode(part, 'surrogatepass'))
def _url_to_domain(url): parsed_url = urllib.parse.urlparse(url) return as_unicode(parsed_url.hostname) #3: `as_unicode(`-- `)`--
def generate_secret_key_qr_code_url(secret_key, login, issuer_name): # type: (String, String, String) -> String login = as_unicode(login) issuer_name = as_unicode(issuer_name) return make_totp_handler(secret_key).provisioning_uri( name=login, issuer_name=issuer_name)
def sqlalchemy_expr_to_str(sqlalchemy_expr): dialect = mysql.dialect() compiler = sqlalchemy_expr.compile(dialect=dialect) params = (compiler.params[k] for k in compiler.positiontup) escaped_params = tuple(as_unicode(escape(p, conversions)) for p in params) return compiler.string % escaped_params
def generate_new_mfa_key_base(): # type: () -> (String) return as_unicode(base64.b64encode(os.urandom(64)))