def has_changed(self, initial, data): if initial is None: initial = [] if data is None: data = [] if len(initial) != len(data): return True initial_set = set(force_text(value) for value in initial) data_set = set(force_text(value) for value in data) return data_set != initial_set
def to_python(self, value): if not value: return [] elif not isinstance(value, (list, tuple)): raise ValidationError(self.error_messages['invalid_list'], code='invalid_list') return [force_text(val) for val in value]
def encode(self, password, salt): crypt = self._load_library() assert len(salt) == 2 data = crypt.crypt(force_text(password), salt) assert data is not None # A platform like OpenBSD with a dummy crypt module. # we don't need to store the salt, but Django used to do this return "%s$%s$%s" % (self.algorithm, '', data)
def __call__(self, value): """ Validates that the input matches the regular expression if inverse_match is False, otherwise raises ValidationError. """ if not (self.inverse_match is not bool( self.regex.search(force_text(value)))): raise ValidationError(self.message, code=self.code)
def __init__(self, choices, *args, **kwargs): self.grouped_choices = functional.to_choices_dict(choices) self.choices = functional.flatten_choices_dict(self.grouped_choices) self.choice_strings_to_values = { force_text(key): key for key in self.choices.keys() } super(ChoiceField, self).__init__(*args, **kwargs)
def __call__(self, value): value = force_text(value) if not value or not value.isdigit(): raise ValidationError(self.message, code=self.code) if not self.phone_regex.match(value): raise ValidationError(self.message, code=self.code)
def encode(self, password, salt): bcrypt = self._load_library() if self.digest is not None: password = binascii.hexlify( self.digest(force_bytes(password)).digest()) else: password = force_bytes(password) data = bcrypt.hash_valpw(password, salt) return "%s$%s" % (self.algorithm, force_text(data))
def to_python(self, value): try: return self.choice_strings_to_values[force_text(value)] except KeyError: choices = ', '.join(self.choice_strings_to_values.keys()) raise ValidationError( self.error_messages['invalid_choice'], code='invalid_choice', params={'choices': choices, "input": value}, )
def to_python(self, value): """ Returns a Unicode object :param value: :return: """ if value in self.empty_values: return self.empty_value value = force_text(value) if self.strip: value = value.strip() return value
def to_python(self, value): # Try to coerce the value to unicode. unicode_value = force_text(value, strings_only=True) if isinstance(unicode_value, str): value = unicode_value.strip() # If unicode, try to strptime against each input format. if isinstance(value, str): for format in self.input_formats: try: return self.strptime(value, format) except (ValueError, TypeError): continue raise ValidationError(self.error_messages['invalid'], code='invalid')
def to_python(self, value): """ Validates that int() can be called on the input. Returns the result of int(). Returns None for empty values. """ value = super(IntegerField, self).to_python(value) if value in self.empty_values: return None try: value = int(self.re_decimal.sub('', force_text(value))) except (ValueError, TypeError): raise ValidationError(self.error_messages['invalid'], code='invalid') return value
def to_python(self, value): """ Validates that the input is a decimal number. Returns a Decimal instance. Returns None for empty values. Ensures that there are no more than max_digits in the number, and no more than decimal_places digits after the decimal point. """ if value in self.empty_values: return None value = force_text(value).strip() try: value = Decimal(value) except DecimalException: raise ValidationError(self.error_messages['invalid'], code='invalid') return value
def __call__(self, value): value = force_text(value) # Check first if the scheme is valid scheme = value.split('://')[0].lower() if scheme not in self.schemes: raise ValidationError(self.message, code=self.code) # Then check full URL try: super(URLValidator, self).__call__(value) except ValidationError as e: # Trivial case failed. Try for possible IDN domain if value: try: scheme, netloc, path, query, fragment = urlsplit(value) except ValueError: # for example, "Invalid IPv6 URL" raise ValidationError(self.message, code=self.code) try: netloc = netloc.encode('idna').decode( 'ascii') # IDN -> ACE except UnicodeError: # invalid domain part raise e url = urlunsplit((scheme, netloc, path, query, fragment)) super(URLValidator, self).__call__(url) else: raise else: # Now verify IPv6 in the netloc part host_match = re.search(r'^\[(.+)\](?::\d{2,5})?$', urlsplit(value).netloc) if host_match: potential_ip = host_match.groups()[0] if not IPAddressValidator.check_ipv6(potential_ip): raise ValidationError(self.message, code=self.code) # url = value # The maximum length of a full host name is 253 characters per RFC 1034 # section 3.1. It's defined to be 255 bytes or less, but this includes # one byte for the length of the name and one byte for the trailing dot # that's used to indicate absolute names in DNS. if len(urlsplit(value).netloc) > 253: raise ValidationError(self.message, code=self.code)
def encrypt(self, text): """ 对明文进行加密 :param text: 需要加密的明文 :return: """ from Crypto.Cipher import AES # 16位随机字符串添加到明文开头 text = get_random_string(length=16) + force_text( struct.pack("I", socket.htonl(len(text)))) + text # 使用自定义的填充方式对明文进行补位填充 text = pkcs7.encode(text) # 加密 allowed_chars = string.digits + string.ascii_letters + string.punctuation iv = get_random_string(length=16, allowed_chars=allowed_chars) cryptor = AES.new(self.key, self.mode, iv) cipher_text = cryptor.encrypt(text) # 加密后的字符串转化为16进制字符串 cipher_text = force_bytes(iv) + cipher_text return str2hex(cipher_text)
def _get_error_details(data, default_code=None): """ Descend into a nested data structure, forcing any lazy translation strings or strings into `ErrorDetail`. """ if isinstance(data, list): ret = [_get_error_details(item, default_code) for item in data] return ret elif isinstance(data, dict): ret = { key: _get_error_details(value, default_code) for key, value in data.items() } return ret text = force_text(data) code = getattr(data, 'code', default_code) return ErrorDetail(text, code)
def _clean_credentials(credentials): """ 屏蔽密码或密钥等重要信息 :param credentials: :return: """ if isinstance(credentials, (type(None), list)): return credentials sensitive_credentials = re.compile( 'api|token|key|secret|password|signature|pwd', re.I) cleansed_substitute = '********************' result = {} for key, value in credentials.items(): key = force_text(key) if sensitive_credentials.search(key): result[key] = cleansed_substitute else: result[key] = value return result
def __call__(self, value): value = force_text(value) if not value or '@' not in value: raise ValidationError(self.message, code=self.code) user_part, domain_part = value.rsplit('@', 1) if not self.user_regex.match(user_part): raise ValidationError(self.message, code=self.code) if (domain_part not in self.domain_whitelist and not self.validate_domain_part(domain_part)): # Try for possible IDN domain-part try: domain_part = domain_part.encode('idna').decode('ascii') if self.validate_domain_part(domain_part): return except UnicodeError: pass raise ValidationError(self.message, code=self.code)
def decrypt(self, text): """ 对解密后的明文进行补位删除 :param text: 密文 :return: 删除填充补位后的明文 """ from Crypto.Cipher import AES cipher_text = hex2str(text) iv = cipher_text[:16] cryptor = AES.new(self.key, self.mode, iv) # 解密并去除16位随机字符串 plain_text = force_text(cryptor.decrypt(cipher_text[16:])[16:]) content = pkcs7.decode(plain_text) # pad = ord(plain_text[-1]) # # 去除16位随机字符串 # content = plain_text[16:-pad] msg_len = socket.ntohl(struct.unpack("I", force_bytes(content[:4]))[0]) msg_content = content[4:msg_len + 4] return msg_content
def json_decode(value): return json.loads(force_text(value))
def strptime(self, value, format): return datetime.datetime.strptime(force_text(value), format)
def get_format(format_type): format_type = force_text(format_type) val = getattr(settings, format_type) return val
def verify(self, password, encoded_password): crypt = self._load_library() algorithm, salt, data = encoded_password.split('$', 2) assert algorithm == self.algorithm return constant_time_compare(data, crypt.crypt(force_text(password), data))
def default(self, o): if isinstance(o, LazyString): return force_text(o) else: return super().default(o)