def test_make_seasons_list(self, mock_listitem): responses.add(responses.POST, config.TOKEN_URL, body=json.dumps({'token': 'abcdef'}), status=200) responses.add(responses.GET, config.SEASONS_URL, body=self.SEASONS_JSON, status=200) mock_listitem.side_effect = fakes.FakeListItem mock_plugin = fakes.FakePlugin() with mock.patch.dict('sys.modules', xbmcplugin=mock_plugin): import resources.lib.index as index index.make_seasons_list() expected_url = 'plugin://{addonid}/?{params}'.format( addonid='plugin.video.afl-video', params=unquote_plus( urlencode({ 'season': 'CD_S2020014', 'current_round': 'CD_R202001401', 'name': 'AFL Premiership 2020' }))) observed_url = mock_plugin.directory[0].get('url') expected = urlparse(expected_url) observed = urlparse(observed_url) for x in range(6): if x == 4: self.assertEqual(dict(parse_qsl(expected[x])), dict(parse_qsl(observed[x]))) else: self.assertEqual(expected[x], observed[x])
def __call__(self, environ, start_response): if self.filter_xpath: filter_xpath = ';filter_xpath=' query_string = environ.get('QUERY_STRING', '') if filter_xpath in query_string: environ['QUERY_STRING'], xpath = query_string.rsplit( filter_xpath, 1, ) environ['diazo.filter_xpath'] = unquote_plus(xpath) return self.filter_middleware(environ, start_response) transform_middleware = self.transform_middleware if transform_middleware is None or self.debug: transform_middleware = self.get_transform_middleware() if transform_middleware is not None and not self.debug: self.transform_middleware = transform_middleware # Set up variables, some of which are used as transform parameters request = Request(environ) environ['diazo.rules'] = self.rules environ['diazo.absolute_prefix'] = self.absolute_prefix environ['diazo.path'] = request.path environ['diazo.query_string'] = request.query_string environ['diazo.host'] = request.host environ['diazo.scheme'] = request.scheme return transform_middleware(environ, start_response)
def _title_from_url(self, url): parts = parse.urlsplit(url) name = '' if parts.scheme == 'magnet': match = re.search('(?:&dn(?:\.\d)?=)(.+?)(?:&)', parts.query) if match: name = match.group(1) else: name = posixpath.basename(parts.path) return parse.unquote_plus(name)
def parse_kodi_url(self, url): params = dict(parse_qsl(url)) for item in params.keys(): setattr(self, item, unquote_plus(params[item])) if self.date: try: self.date = datetime.datetime.strptime(self.date, "%Y-%m-%d") except TypeError: self.date = datetime.datetime( *(time.strptime(self.date, "%Y-%m-%d")[0:6]))
def parse_kodi_url(self, url): params = dict(parse_qsl(url)) for item in params.keys(): setattr(self, item, unquote_plus(params[item])) if getattr(self, 'captions', None) == 'True': self.captions = True if getattr(self, 'date', None): self.date = self.parse_datetime(self.date) if getattr(self, 'expire', None): self.expire = self.parse_datetime(self.expire)
def get_airtime(self): try: delta = self.get_tz_delta() ts_format = "%Y-%m-%dT%H:%M:%SZ" ts = datetime.datetime.fromtimestamp( time.mktime( time.strptime(unquote_plus(self.start_date), ts_format))) ts += datetime.timedelta(hours=delta) return ts.strftime("%A %d %b @ %I:%M %p").replace(' 0', ' ') except OverflowError: return ts
def get_url(s): """Build a dict from a given Kodi add-on URL""" dict = {} pairs = s.lstrip("?").split("&") for pair in pairs: if len(pair) < 3: continue kv = pair.split("=", 1) k = kv[0] v = unquote_plus(kv[1]) dict[k] = v return dict
def from_bytes(cls, bytes): """ Parse a URL from some bytes. """ try: # this belongs on the first thing likely to cause a (Type)Error scheme, _, rest = bytes.strip().partition(b":") except Exception: exception = InvalidURL("{!r} is not a valid URL".format(bytes)) raise_with_traceback(exception) if scheme and not rest.startswith(b"//"): raise InvalidURL( "{!r} is not a valid URL without initial '//'".format(bytes), ) authority, slash, rest = rest[2:].partition(b"/") userinfo, _, host_and_port = authority.rpartition(b"@") username, _, password = userinfo.partition(b":") if host_and_port.startswith(b"["): # IPv6 Host host, delimiter, port_str = host_and_port.partition(b"]:") host += b"]" if delimiter else b"" else: host, _, port_str = host_and_port.partition(b":") if not port_str: port = None else: try: port = int(unquote(port_str)) except ValueError: raise InvalidURL("{!r} is not a valid port".format(port_str)) path, _, rest = rest.partition(b"?") query, _, fragment = rest.partition(b"#") return cls.normalized( scheme=scheme, username=username, password=password, host=host, port=port, path=unquote(slash + path), query=parse_qs(query, keep_blank_values=True), fragment=unquote_plus(fragment), unnormalized=bytes, unnormalized_authority=authority, unnormalized_userinfo=userinfo, )
def test_make_list(self, mock_listitem): mock_listitem.side_effect = fakes.FakeListItem mock_plugin = fakes.FakePlugin() with mock.patch.dict('sys.modules', xbmcplugin=mock_plugin): import resources.lib.index as index index.make_list() for ind, category in enumerate(config.CATEGORIES): expected_url = 'plugin://{addonid}/?{params}'.format( addonid='plugin.video.afl-video', params=unquote_plus(urlencode({'category': category}))) observed_url = mock_plugin.directory[ind].get('url') expected = urlparse(expected_url) observed = urlparse(observed_url) for x in range(6): if x == 4: self.assertEqual(dict(parse_qsl(expected[x])), dict(parse_qsl(observed[x]))) else: self.assertEqual(expected[x], observed[x])
def from_bytes(cls, bytes): """ Parse a URL from some bytes. """ scheme, _, rest = bytes.strip().partition(b":") if scheme and not rest.startswith(b"//"): raise InvalidURL( "{!r} is not a valid URL without initial '//'".format(bytes), ) authority, slash, rest = rest[2:].partition(b"/") userinfo, _, host_and_port = authority.rpartition(b"@") username, _, password = userinfo.partition(b":") host, _, port_str = host_and_port.partition(b":") if not port_str: port = None else: try: port = int(unquote(port_str)) except ValueError: raise InvalidURL("{!r} is not a valid port".format(port_str)) path, _, rest = rest.partition(b"?") query, _, fragment = rest.partition(b"#") return cls.normalized( scheme=scheme, username=username, password=password, host=host, port=port, path=unquote(slash + path), query=parse_qs(query, keep_blank_values=True), fragment=unquote_plus(fragment), unnormalized=bytes, authority=authority, userinfo=userinfo, )
def test_list_categories(self, mock_listitem): mock_listitem.side_effect = fakes.FakeListItem mock_plugin = fakes.FakePlugin() with mock.patch.dict('sys.modules', xbmcplugin=mock_plugin): import resources.lib.categories as categories categories.list_categories() for index, category in enumerate(sorted(config.CATEGORIES.keys())): expected_url = 'plugin://{addonid}/?{params}'.format( addonid=config.ADDON_ID, params=unquote_plus( urlencode({ 'action': 'listcategories', 'category': config.CATEGORIES[category] }))) observed_url = mock_plugin.directory[index].get('url') expected = urlparse(expected_url) observed = urlparse(observed_url) for x in range(6): if x == 4: self.assertEqual(dict(parse_qsl(expected[x])), dict(parse_qsl(observed[x]))) else: self.assertEqual(expected[x], observed[x])
def _title_from_url(self, url): parts = parse.splitquery(url[url.rfind('/') + 1:]) title = parse.unquote_plus(parts[0]) return title
def parse_str(self, encode_str, decode_method, m_list): if len(m_list) > self.max_depth: return False, encode_str # encode_str = deepcopy(encode_str) encode_str = force_bytes(encode_str) if decode_method in ['zlib']: encode_str = force_bytes(encode_str) else: encode_str = force_text(encode_str) raw_encode_str = deepcopy(encode_str) if len(encode_str) <= 0: return False, raw_encode_str try: if decode_method == 'base16': # 避免无限递归 # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.upper() rex = re.compile('^[0-9A-F]+[=]*$', re.MULTILINE) if self.regex_match(rex, encode_str): decode_str = partial_base16_decode(encode_str) else: return False, raw_encode_str elif decode_method == 'base32': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') # 避免无限递归 # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.upper() rex = re.compile('^[A-Z2-7=]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = base64.b32decode(base_padding(encode_str, 8)) else: return False, raw_encode_str elif decode_method == 'base64': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') # 避免无限递归 # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9+/=]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = base64.b64decode(base_padding(encode_str, 4)) else: return False, raw_encode_str elif decode_method == 'urlsafe_b64': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9-_=]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = urlsafe_b64decode(base_padding(encode_str, 4)) else: return False, raw_encode_str elif decode_method == 'base58': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = from_base58(encode_str) else: return False, raw_encode_str elif decode_method == 'ascii_85': if len(encode_str) < 7: return False, raw_encode_str if PY2: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9!#$%&()*+\-;<=>?@^_`{|}~]+$', re.MULTILINE) if self.regex_match(rex, encode_str): decode_str = a85decode(force_bytes(encode_str)) else: return False, encode_str elif decode_method == 'base85': if len(encode_str) < 7: return False, raw_encode_str if PY2: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9!#$%&()*+\-;<=>?@^_`{|}~]+$', re.MULTILINE) if self.regex_match(rex, encode_str): decode_str = b85decode(force_bytes(encode_str)) else: return False, encode_str elif decode_method == 'rot13': # 如果这里不做限制,会无限递归下去 if 'rot13' in m_list: return False, raw_encode_str decode_str = decode_rot13(encode_str) elif decode_method == 'pawn_shop': try: encode_str = encode_str.decode('gb2312') except: pass encode_str = force_text(encode_str) encode_str = encode_str.replace(' ', '').strip() code_base = '口由中人工大王夫井羊' decode_str = [] for t in encode_str: if t in code_base: i = code_base.index(t) decode_str.append(str(i)) else: return False, raw_encode_str decode_str = ''.join(decode_str) if len(decode_str) < 0: return False, raw_encode_str elif decode_method == 'decimal': if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[0-9]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str # 解码后是 0xab1234,需要去掉前面的 0x decode_str = hex(int(encode_str))[2:].rstrip('L') elif decode_method == 'binary': rex = re.compile('^[0-1]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str # 不足8个的,在后面填充0 padding_length = (8 - len(encode_str) % 8) % 8 encode_str = '%s%s' % (encode_str, '0' * padding_length) # 解码后是 0xab1234,需要去掉前面的 0x decode_str = hex(int(encode_str, 2))[2:].rstrip('L') elif decode_method in ['octal', 'octal_ascii', 'octal_binary']: # 8进制转成16进制的数据 rex = re.compile('^[0-7]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str rex = re.compile('^[0-1]+$', re.MULTILINE) if self.regex_match(rex, encode_str): return False, raw_encode_str if len(encode_str) < 4: return False, raw_encode_str if decode_method == 'octal': # 解码后是 0xab1234,需要去掉前面的 0x decode_str = hex(int(encode_str, 8))[2:].rstrip('L') elif decode_method == 'octal_ascii': encode_str = encode_str.replace(' ', '').strip() # 8 进制的 177 转成十进制后是 128 tmp_list = list(encode_str) ascii_list = [] while len(tmp_list) > 0: tmp_str = ''.join(tmp_list[:3]) if int(tmp_str, 8) > 127: tmp_str = ''.join(tmp_list[:2]) tmp_list = tmp_list[2:] else: tmp_list = tmp_list[3:] ascii_list.append(chr(int(tmp_str, 8))) decode_str = ''.join(ascii_list) elif decode_method == 'octal_binary': # 因为这里有补0的操作,要避免无限递归 if len(m_list) > 0 and \ (m_list[-1] in ('octal_binary', 'octal', 'binary') or len(encode_str) < 8): return False, raw_encode_str # 将8进制直接转成16进制,也就是3个8进制数字转成2个16进制字符 # 先将每个8进制数字转成二进制,不足3个的前面补0 encode_str = encode_str.replace(' ', '').strip() tmp_bin_list = ['%03d' % int(bin(int(t))[2:]) for t in list(encode_str)] tmp_bin_list = [t for t in tmp_bin_list] # logger.info(tmp_bin_list) decode_str = ''.join(tmp_bin_list) else: return False, raw_encode_str elif decode_method == 'decimal_ascii': if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.replace(' ', '').strip() rex = re.compile('^[0-9]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str # ascii 字符串,10进制最大127 tmp_list = list(encode_str) ascii_list = [] while len(tmp_list) > 0: tmp_str = ''.join(tmp_list[:3]) if int(tmp_str) > 127: tmp_str = ''.join(tmp_list[:2]) tmp_list = tmp_list[2:] else: tmp_list = tmp_list[3:] ascii_list.append(chr(int(tmp_str))) decode_str = ''.join(ascii_list) elif decode_method in ['swap_case', 'reverse_alphabet', 'reverse']: # 如果这里不做限制,会无限递归下去 if len(m_list) > 0: for t in ['swap_case', 'reverse_alphabet', 'reverse']: if t in m_list: return False, raw_encode_str # 一定要包含 ascii 字符 tmp_data = [t for t in encode_str if t in string.ascii_letters] if len(tmp_data) <= 0: return False, raw_encode_str # rex = re.compile('^[A-Za-z0-9+/=]$', re.MULTILINE) # if not self.regex_match(rex, encode_str): # return False, raw_encode_str if decode_method == 'swap_case': new_data = [] for t in encode_str: if t in string.ascii_lowercase: t = t.upper() elif t in string.ascii_uppercase: t = t.lower() new_data.append(t) decode_str = ''.join(new_data) elif decode_method == 'reverse_alphabet': # 字母逆序,a->z, z->a new_data = [] for t in encode_str: if t in string.ascii_letters: if t in string.ascii_lowercase: t = ord(t) + (25 - (ord(t) - ord('a')) * 2) t = chr(t) else: t = ord(t) + (25 - (ord(t) - ord('A')) * 2) t = chr(t) new_data.append(t) decode_str = ''.join(new_data) elif decode_method == 'reverse': # 逆序 decode_str = encode_str[::-1] else: return False, raw_encode_str elif decode_method == 'urlencode': if len(encode_str) < 4: return False, raw_encode_str decode_str = unquote_plus(encode_str) elif decode_method == 'hex': if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.lower() rex = re.compile('^[a-f0-9]+$', re.MULTILINE) if self.regex_match(rex, encode_str.lower()): # 修正基数位数的16进制数据 if len(encode_str) % 2 != 0: encode_str += '0' decode_str = force_text(hex2str(encode_str)) else: return False, raw_encode_str elif decode_method == 'zlib': if len(encode_str) < 4: return False, raw_encode_str try: decode_str = zlib.decompress(force_bytes(encode_str)) if self.calc_printable_percent(decode_str) < self.printable_percent: return False, raw_encode_str except: return False, raw_encode_str else: decode_str = encode_str.decode(decode_method) if len(decode_str) <= 0: return False, raw_encode_str elif force_bytes(encode_str) == force_bytes(decode_str): return False, raw_encode_str else: # 解码的内容只有可打印字符,才认为合法 if self.only_printable: printable_percent = 1.0 else: printable_percent = self.printable_percent is_printable = True # 如果可打印字符低于一定的百分比,就认为解码失败 if self.calc_printable_percent(decode_str) < printable_percent: is_printable = False if is_printable is False: if self.last_result_printable is False: return False, raw_encode_str self.last_result_printable = is_printable return True, decode_str except Exception as e: if self.verbose: logger.exception(e) return False, raw_encode_str
def _title_from_url(self, url): parts = parse.urlsplit(url) title = parse.unquote_plus(posixpath.basename(parts.path)) return title
def parse_str(self, encode_str, decode_method, m_list): if len(m_list) > self.max_depth: return False, encode_str # encode_str = deepcopy(encode_str) encode_str = utf8(encode_str) if decode_method in ['zlib']: encode_str = utf8(encode_str) else: encode_str = to_unicode(encode_str) raw_encode_str = deepcopy(encode_str) if len(encode_str) <= 0: return False, raw_encode_str try: if decode_method == 'base16': # 避免无限递归 # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.upper() rex = re.compile('^[0-9A-F]+[=]*$', re.MULTILINE) if self.regex_match(rex, encode_str): decode_str = partial_base16_decode(encode_str) else: return False, raw_encode_str elif decode_method == 'base32': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') # 避免无限递归 # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.upper() rex = re.compile('^[A-Z2-7=]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = partial_base32_decode(encode_str) else: return False, raw_encode_str elif decode_method == 'base64': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') # 避免无限递归 # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9+/=]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = partial_base64_decode(encode_str) else: return False, raw_encode_str elif decode_method == 'urlsafe_b64': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9-_=]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = urlsafe_b64decode(base_padding(encode_str, 4)) else: return False, raw_encode_str elif decode_method == 'ascii_85': if len(encode_str) < 7: return False, raw_encode_str if PY2: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9!#$%&()*+\-;<=>?@^_`{|}~]+$', re.MULTILINE) if self.regex_match(rex, encode_str): decode_str = a85decode(utf8(encode_str)) else: return False, encode_str elif decode_method == 'base85': if len(encode_str) < 7: return False, raw_encode_str if PY2: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9!#$%&()*+\-;<=>?@^_`{|}~]+$', re.MULTILINE) if self.regex_match(rex, encode_str): decode_str = b85decode(utf8(encode_str)) else: return False, encode_str elif decode_method == 'pawn_shop': try: encode_str = encode_str.decode('gb2312') except: pass encode_str = to_unicode(encode_str) encode_str = encode_str.replace(' ', '').strip() code_base = '口由中人工大王夫井羊' decode_str = [] for t in encode_str: if t in code_base: i = code_base.index(t) decode_str.append(str(i)) else: return False, raw_encode_str decode_str = ''.join(decode_str) if len(decode_str) < 0: return False, raw_encode_str elif decode_method == 'decimal': if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[0-9]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str # 解码后是 0xab1234,需要去掉前面的 0x decode_str = hex(int(encode_str))[2:].rstrip('L') elif decode_method == 'binary': rex = re.compile('^[0-1]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str # 不足8个的,在后面填充0 padding_length = (8 - len(encode_str) % 8) % 8 encode_str = '%s%s' % (encode_str, '0' * padding_length) # 解码后是 0xab1234,需要去掉前面的 0x decode_str = hex(int(encode_str, 2))[2:].rstrip('L') elif decode_method in ['octal', 'octal_ascii', 'octal_binary']: # 8进制转成16进制的数据 rex = re.compile('^[0-7]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str rex = re.compile('^[0-1]+$', re.MULTILINE) if self.regex_match(rex, encode_str): return False, raw_encode_str if len(encode_str) < 4: return False, raw_encode_str if decode_method == 'octal': # 解码后是 0xab1234,需要去掉前面的 0x decode_str = hex(int(encode_str, 8))[2:].rstrip('L') elif decode_method == 'octal_ascii': encode_str = encode_str.replace(' ', '').strip() # 8 进制的 177 转成十进制后是 128 tmp_list = list(encode_str) ascii_list = [] while len(tmp_list) > 0: tmp_str = ''.join(tmp_list[:3]) if int(tmp_str, 8) > 127: tmp_str = ''.join(tmp_list[:2]) tmp_list = tmp_list[2:] else: tmp_list = tmp_list[3:] ascii_list.append(chr(int(tmp_str, 8))) decode_str = ''.join(ascii_list) elif decode_method == 'octal_binary': # 因为这里有补0的操作,要避免无限递归 if len(m_list) > 0 and \ (m_list[-1] in ('octal_binary', 'octal', 'binary') or len(encode_str) < 8): return False, raw_encode_str # 将8进制直接转成16进制,也就是3个8进制数字转成2个16进制字符 # 先将每个8进制数字转成二进制,不足3个的前面补0 encode_str = encode_str.replace(' ', '').strip() tmp_bin_list = ['%03d' % int(bin(int(t))[2:]) for t in list(encode_str)] tmp_bin_list = [t for t in tmp_bin_list] # logger.info(tmp_bin_list) decode_str = ''.join(tmp_bin_list) else: return False, raw_encode_str elif decode_method == 'decimal_ascii': if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.replace(' ', '').strip() rex = re.compile('^[0-9]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str # ascii 字符串,10进制最大127 tmp_list = list(encode_str) ascii_list = [] while len(tmp_list) > 0: tmp_str = ''.join(tmp_list[:3]) if int(tmp_str) > 127: tmp_str = ''.join(tmp_list[:2]) tmp_list = tmp_list[2:] else: tmp_list = tmp_list[3:] ascii_list.append(chr(int(tmp_str))) decode_str = ''.join(ascii_list) elif decode_method in ['switch_case', 'reverse_alphabet', 'reverse']: # 如果这里不做限制,会无限递归下去 if len(m_list) > 0 and m_list[-1] in ['switch_case', 'reverse_alphabet', 'reverse']: return False, raw_encode_str # 一定要包含 ascii 字符 tmp_data = [t for t in encode_str if t in string.ascii_letters] if len(tmp_data) <= 0: return False, raw_encode_str # rex = re.compile('^[A-Za-z0-9+/=]$', re.MULTILINE) # if not self.regex_match(rex, encode_str): # return False, raw_encode_str if decode_method == 'switch_case': new_data = [] for t in encode_str: if t in string.ascii_lowercase: t = t.upper() elif t in string.ascii_uppercase: t = t.lower() new_data.append(t) decode_str = ''.join(new_data) elif decode_method == 'reverse_alphabet': # 字母逆序,a->z, z->a new_data = [] for t in encode_str: if t in string.ascii_letters: if t in string.ascii_lowercase: t = ord(t) + (25 - (ord(t) - ord('a')) * 2) t = chr(t) else: t = ord(t) + (25 - (ord(t) - ord('A')) * 2) t = chr(t) new_data.append(t) decode_str = ''.join(new_data) elif decode_method == 'reverse': # 逆序 decode_str = encode_str[::-1] else: return False, raw_encode_str elif decode_method == 'urlencode': if len(encode_str) < 4: return False, raw_encode_str decode_str = unquote_plus(encode_str) elif decode_method == 'hex': if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.lower() rex = re.compile('^[a-f0-9]+$', re.MULTILINE) if self.regex_match(rex, encode_str.lower()): # 修正基数位数的16进制数据 if len(encode_str) % 2 != 0: encode_str += '0' decode_str = hex2str(encode_str) else: return False, raw_encode_str elif decode_method == 'zlib': if len(encode_str) < 4: return False, raw_encode_str try: decode_str = zlib.decompress(utf8(encode_str)) except: return False, raw_encode_str else: decode_str = encode_str.decode(decode_method) if len(decode_str) <= 0: return False, raw_encode_str elif utf8(encode_str) == utf8(decode_str): return False, raw_encode_str else: # 解码的内容只有可打印字符,才认为合法 if self.only_printable: decode_str = to_unicode(decode_str) if isinstance(decode_str, bytes): return False, raw_encode_str tmp_decode_str = list(decode_str) printable_count = 0 for t in tmp_decode_str: if str(t) in string.printable: printable_count += 1 # 如果可打印字符低于一定的百分比,就认为解码失败 if printable_count * 1.0 / len(tmp_decode_str) < self.printable_percent: return False, raw_encode_str return True, decode_str except Exception as e: if self.verbose: logger.exception(e) return False, raw_encode_str
def parse_kodi_url(self, url): params = dict(parse_qsl(url)) for item in params.keys(): setattr(self, item, unquote_plus(params[item])) if self.num_episodes: self.num_episodes = int(self.num_episodes)
def parse_params(self, params): for item in params.keys(): setattr(self, item, unquote_plus(params[item])) if self.start_date: # quote date to preserve '+' setattr(self, 'start_date', quote_plus(self.start_date))
def get_path(kwargs, required=True): path = kwargs.get('path') if path: return unquote_plus(path) elif required: raise HTTPError(http_status.HTTP_400_BAD_REQUEST)
def parse_params(self, params): for item in params.keys(): setattr(self, item, unquote_plus(params[item]))
def parse_kodi_url(self, url): params = dict(parse_qsl(url)) for item in params.keys(): setattr(self, item, unquote_plus(params[item]))
def parse_kodi_url(self, url): url = url.lstrip('?') params = dict(parse_qsl(url)) params.pop('addon_version', '') for item in params.keys(): setattr(self, item, unquote_plus(params[item]))