From f927283fa42e784413fca0e7b265837d90f768ad Mon Sep 17 00:00:00 2001 From: Belfagor2005 <72314956+Belfagor2005@users.noreply.github.com> Date: Sat, 8 Apr 2023 20:32:45 +0200 Subject: [PATCH] fix [SSL: WRONG_SIGNATURE_TYPE] --- .../python/Plugins/Extensions/Filmon/Utils.py | 66 ++- .../python/Plugins/Extensions/Filmon/cache.py | 57 +++ .../Plugins/Extensions/Filmon/client.py | 483 ++++++++++++++++++ .../Plugins/Extensions/Filmon/dom_parser.py | 203 ++++++++ .../Plugins/Extensions/Filmon/plugin.py | 120 +++-- .../Filmon/skin/images_new/50x50.png | Bin 0 -> 4241 bytes 6 files changed, 897 insertions(+), 32 deletions(-) create mode 100644 usr/lib/enigma2/python/Plugins/Extensions/Filmon/cache.py create mode 100644 usr/lib/enigma2/python/Plugins/Extensions/Filmon/client.py create mode 100644 usr/lib/enigma2/python/Plugins/Extensions/Filmon/dom_parser.py create mode 100644 usr/lib/enigma2/python/Plugins/Extensions/Filmon/skin/images_new/50x50.png diff --git a/usr/lib/enigma2/python/Plugins/Extensions/Filmon/Utils.py b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/Utils.py index 7b4eb33..f9cf864 100644 --- a/usr/lib/enigma2/python/Plugins/Extensions/Filmon/Utils.py +++ b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/Utils.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# 15.02.2023 +# 30.03.2023 # a common tips used from Lululla # import sys @@ -302,7 +302,11 @@ def downloadFile(url, target): response = urlopen(url, None, 5) with open(target, 'wb') as output: # print('response: ', response) - output.write(response.read()) + if PY3: + output.write(response.read().decode('utf-8')) + else: + output.write(response.read()) + # output.write(response.read()) response.close() return True except HTTPError: @@ -447,7 +451,7 @@ def checkRedirect(url): # print("*** check redirect ***") import requests from requests.adapters import HTTPAdapter - hdr = {"User-Agent": "Enigma2 - XCForever Plugin"} + hdr = {"User-Agent": "Enigma2 - Enigma2 Plugin"} x = "" adapter = HTTPAdapter() http = requests.Session() @@ -461,6 +465,62 @@ def checkRedirect(url): return str(url) + + + +def checkRedirect2(url): + # print("*** check redirect ***") + import requests + from requests.adapters import HTTPAdapter + # hdr = {"User-Agent": "Enigma2 - Enigma2 Plugin"} + # x = "" + # adapter = HTTPAdapter() + # http = requests.Session() + # http.mount("http://", adapter) + # http.mount("https://", adapter) + # try: + # x = http.get(url, headers=hdr, timeout=15, verify=False, stream=True) + # return str(x.url) + # except Exception as e: + # print(e) + # return str(url) + import ssl + from urllib3 import poolmanager + # class TLSAdapter(requests.adapters.HTTPAdapter): + + + # def init_poolmanager(self, connections, maxsize, block=False): + # """Create and initialize the urllib3 PoolManager.""" + # ctx = ssl.create_default_context() + # ctx.set_ciphers('DEFAULT@SECLEVEL=1') + # self.poolmanager = poolmanager.PoolManager( + # num_pools=connections, + # maxsize=maxsize, + # block=block, + # ssl_version=ssl.PROTOCOL_TLS, + # ssl_context=ctx) + + # session = requests.session() + # session.mount('https://', TLSAdapter()) + # res = session.get(url) + # return res + + class TLSAdapter(requests.adapters.HTTPAdapter): + + def init_poolmanager(self, *args, **kwargs): + ctx = ssl.create_default_context() + ctx.set_ciphers('DEFAULT@SECLEVEL=1') + kwargs['ssl_context'] = ctx + return super(TLSAdapter, self).init_poolmanager(*args, **kwargs) + + session = requests.session() + session.mount('https://', TLSAdapter()) + res = session.get(url) + print('TLSAdapter: ', res) + return res + + + def freespace(): try: diskSpace = os.statvfs('/') diff --git a/usr/lib/enigma2/python/Plugins/Extensions/Filmon/cache.py b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/cache.py new file mode 100644 index 0000000..18c0f71 --- /dev/null +++ b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/cache.py @@ -0,0 +1,57 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +''' + Tulip routine libraries, based on lambda's lamlib + Author Twilight0 + + License summary below, for more details please read license.txt file + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . +''' + + +import re +import hashlib + + +def get(function, timeout=10, *args, **table): + try: + response = None + + f = repr(function) + f = re.sub('.+\smethod\s|.+function\s|\sat\s.+|\sof\s.+', '', f) + a = hashlib.md5() + for i in args: + a.update(str(i)) + a = str(a.hexdigest()) + except: + pass + + try: + table = table['table'] + except: + table = 'rel_list' + + try: + r = function(*args) + if (r is None or r == []) and response is not None: + return response + elif (r is None or r == []): + return r + except: + return + + try: + return eval(r.encode('utf-8')) + except: + pass diff --git a/usr/lib/enigma2/python/Plugins/Extensions/Filmon/client.py b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/client.py new file mode 100644 index 0000000..705f942 --- /dev/null +++ b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/client.py @@ -0,0 +1,483 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +''' + Tulip routine libraries, based on lambda's lamlib + Author Twilight0 + + License summary below, for more details please read license.txt file + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . +''' + +import random +import re +import sys +import time + +import six +from six.moves import urllib_request, urllib_error +from six.moves import xrange +from six.moves.html_parser import HTMLParser +from six.moves.urllib.parse import urlparse, quote_plus + +# from . import cache + +try: + import requests + + requester = requests.get +except ImportError: + requester = None + +if six.PY3: + unicode = str + import http.cookiejar as cookielib + from urllib.request import ProxyHandler +elif six.PY2: + import cookielib + from urllib2 import ProxyHandler + + +def request(url, close=True, redirect=True, error=False, proxy=None, post=None, headers=None, mobile=False, limit=None, + referer=None, cookie=None, output='', timeout='30'): + handlers = [] + + if proxy is not None: + handlers += [ProxyHandler({'http': '{0}'.format(proxy)}), urllib_request.HTTPHandler] + opener = urllib_request.build_opener(*handlers) + urllib_request.install_opener(opener) + + if output == 'cookie' or output == 'extended' or close is not True: + cookies = cookielib.LWPCookieJar() + handlers += [urllib_request.HTTPHandler(), urllib_request.HTTPSHandler(), + urllib_request.HTTPCookieProcessor(cookies)] + opener = urllib_request.build_opener(*handlers) + urllib_request.install_opener(opener) + + try: + + if sys.version_info < (2, 7, 9): + raise Exception() + + import ssl + ssl_context = ssl.create_default_context() + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE + handlers += [urllib_request.HTTPSHandler(context=ssl_context)] + opener = urllib_request.build_opener(*handlers) + urllib_request.install_opener(opener) + + except: + pass + + try: + headers.update(headers) + except: + headers = {} + + if 'User-Agent' in headers: + pass + elif mobile is not True: + # headers['User-Agent'] = agent() + # headers['User-Agent'] = cache.get(randomagent, 1) + # else: + headers['User-Agent'] = 'Apple-iPhone/701.341' + + if 'Referer' in headers: + pass + elif referer is None: + headers['Referer'] = '%s://%s/' % (urlparse(url).scheme, urlparse(url).netloc) + else: + headers['Referer'] = referer + + if 'Accept-Language' not in headers: + headers['Accept-Language'] = 'en-US' + + if 'Cookie' in headers: + pass + elif cookie is not None: + headers['Cookie'] = cookie + + if redirect is False: + + class NoRedirection(urllib_error.HTTPError): + + def http_response(self, request, response): + return response + + opener = urllib_request.build_opener(NoRedirection) + urllib_request.install_opener(opener) + + try: + del headers['Referer'] + except: + pass + + req = urllib_request.Request(url, data=post, headers=headers) + + try: + response = urllib_request.urlopen(req, timeout=int(timeout)) + + except urllib_error.HTTPError as response: + + if response.code == 503: + print('error 503 ') + + # if 'cf-browser-verification' in response.read(5242880): + + # netloc = '%s://%s' % (urlparse(url).scheme, urlparse(url).netloc) + + # cf = cache.get(cfcookie, 168, netloc, headers['User-Agent'], timeout) + + # headers['Cookie'] = cf + + # request = urllib_request.Request(url, data=post, headers=headers) + + # response = urllib_request.urlopen(request, timeout=int(timeout)) + + # elif error is False: + # return + + elif error is False: + return + + if output == 'cookie': + + try: + result = '; '.join(['%s=%s' % (i.name, i.value) for i in cookies]) + except: + pass + try: + result = cf + except: + pass + + elif output == 'response': + + if limit == '0': + result = (str(response.code), response.read(224 * 1024)) + elif limit is not None: + result = (str(response.code), response.read(int(limit) * 1024)) + else: + result = (str(response.code), response.read(5242880)) + + elif output == 'chunk': + + try: + content = int(response.headers['Content-Length']) + except: + content = (2049 * 1024) + + if content < (2048 * 1024): + return + result = response.read(16 * 1024) + + elif output == 'extended': + + try: + cookie = '; '.join(['%s=%s' % (i.name, i.value) for i in cookies]) + except: + pass + try: + cookie = cf + except: + pass + content = response.headers + result = response.read(5242880) + return result, headers, content, cookie + + elif output == 'geturl': + result = response.geturl() + + elif output == 'headers': + content = response.headers + return content + + else: + if limit == '0': + result = response.read(224 * 1024) + elif limit is not None: + result = response.read(int(limit) * 1024) + else: + result = response.read(5242880) + + if close is True: + response.close() + return result + + +def retriever(source, destination, *args): + + class Opener(urllib_request.URLopener): + version = randomagent() + + Opener().retrieve(source, destination, *args) + + +def parseDOM(html, name=u"", attrs=None, ret=False): + + if attrs is None: + attrs = {} + + if isinstance(name, str): # Should be handled + try: + name = name # .decode("utf-8") + except: + pass + + if isinstance(html, str): + try: + html = [html.decode("utf-8")] # Replace with chardet thingy + except: + html = [html] + elif isinstance(html, unicode): + html = [html] + elif not isinstance(html, list): + return u"" + + if not name.strip(): + return u"" + + ret_lst = [] + for item in html: + temp_item = re.compile('(<[^>]*?\n[^>]*?>)').findall(item) + for match in temp_item: + item = item.replace(match, match.replace("\n", " ")) + + lst = _getDOMElements(item, name, attrs) + + if isinstance(ret, str): + lst2 = [] + for match in lst: + lst2 += _getDOMAttributes(match, name, ret) + lst = lst2 + else: + lst2 = [] + for match in lst: + temp = _getDOMContent(item, name, match, ret).strip() + item = item[item.find(temp, item.find(match)) + len(temp):] + lst2.append(temp) + lst = lst2 + ret_lst += lst + + return ret_lst + + +def _getDOMContent(html, name, match, ret): # Cleanup + + endstr = u"" + + start = html.find(match) + end = html.find(endstr, start) + pos = html.find("<" + name, start + 1) + + while pos < end and pos != -1: # Ignore too early return + tend = html.find(endstr, end + len(endstr)) + if tend != -1: + end = tend + pos = html.find("<" + name, pos + 1) + + if start == -1 and end == -1: + result = u"" + elif start > -1 and end > -1: + result = html[start + len(match):end] + elif end > -1: + result = html[:end] + elif start > -1: + result = html[start + len(match):] + + if ret: + endstr = html[end:html.find(">", html.find(endstr)) + 1] + result = match + result + endstr + + return result + + +def _getDOMAttributes(match, name, ret): + + lst = re.compile('<' + name + '.*?' + ret + '=([\'"].[^>]*?[\'"])>', re.M | re.S).findall(match) + if len(lst) == 0: + lst = re.compile('<' + name + '.*?' + ret + '=(.[^>]*?)>', re.M | re.S).findall(match) + ret = [] + for tmp in lst: + cont_char = tmp[0] + if cont_char in "'\"": + + # Limit down to next variable. + if tmp.find('=' + cont_char, tmp.find(cont_char, 1)) > -1: + tmp = tmp[:tmp.find('=' + cont_char, tmp.find(cont_char, 1))] + + # Limit to the last quotation mark + if tmp.rfind(cont_char, 1) > -1: + tmp = tmp[1:tmp.rfind(cont_char)] + else: + + if tmp.find(" ") > 0: + tmp = tmp[:tmp.find(" ")] + elif tmp.find("/") > 0: + tmp = tmp[:tmp.find("/")] + elif tmp.find(">") > 0: + tmp = tmp[:tmp.find(">")] + + ret.append(tmp.strip()) + + return ret + + +def _getDOMElements(item, name, attrs): + + lst = [] + for key in attrs: + lst2 = re.compile('(<' + name + '[^>]*?(?:' + key + '=[\'"]' + attrs[key] + '[\'"].*?>))', re.M | re.S).findall(item) + if len(lst2) == 0 and attrs[key].find(" ") == -1: # Try matching without quotation marks + lst2 = re.compile('(<' + name + '[^>]*?(?:' + key + '=' + attrs[key] + '.*?>))', re.M | re.S).findall(item) + + if len(lst) == 0: + lst = lst2 + lst2 = [] + else: + + test = range(len(lst)) + test.reverse() + for i in test: # Delete anything missing from the next list. + if not lst[i] in lst2: + del(lst[i]) + + if len(lst) == 0 and attrs == {}: + lst = re.compile('(<' + name + '>)', re.M | re.S).findall(item) + if len(lst) == 0: + lst = re.compile('(<' + name + ' .*?>)', re.M | re.S).findall(item) + + return lst + + +def replaceHTMLCodes(txt): + + txt = re.sub("(&#[0-9]+)([^;^0-9]+)", "\\1;\\2", txt) + txt = HTMLParser().unescape(txt) + txt = txt.replace(""", "\"") + txt = txt.replace("&", "&") + txt = txt.replace("&", "&") + txt = txt.replace(" ", "") + return txt + + +def randomagent(): + + BR_VERS = [['%s.0' % i for i in xrange(18, 43)], ['37.0.2062.103', '37.0.2062.120', '37.0.2062.124', '38.0.2125.101', + '38.0.2125.104', '38.0.2125.111', '39.0.2171.71', '39.0.2171.95', + '39.0.2171.99', '40.0.2214.93', '40.0.2214.111', '40.0.2214.115', + '42.0.2311.90', '42.0.2311.135', '42.0.2311.152', '43.0.2357.81', + '43.0.2357.124', '44.0.2403.155', '44.0.2403.157', '45.0.2454.101', + '45.0.2454.85', '46.0.2490.71', '46.0.2490.80', '46.0.2490.86', + '47.0.2526.73', '47.0.2526.80'], ['11.0']] + + WIN_VERS = ['Windows NT 10.0', 'Windows NT 7.0', 'Windows NT 6.3', 'Windows NT 6.2', 'Windows NT 6.1', 'Windows NT 6.0', + 'Windows NT 5.1', 'Windows NT 5.0'] + + FEATURES = ['; WOW64', '; Win64; IA64', '; Win64; x64', ''] + + RAND_UAS = ['Mozilla/5.0 ({win_ver}{feature}; rv:{br_ver}) Gecko/20100101 Firefox/{br_ver}', + 'Mozilla/5.0 ({win_ver}{feature}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{br_ver} Safari/537.36', + 'Mozilla/5.0 ({win_ver}{feature}; Trident/7.0; rv:{br_ver}) like Gecko'] + + index = random.randrange(len(RAND_UAS)) + + return RAND_UAS[index].format(win_ver=random.choice(WIN_VERS), feature=random.choice(FEATURES), br_ver=random.choice(BR_VERS[index])) + + +def agent(): + return 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko' + + +def mobile_agent(): + return 'Mozilla/5.0 (Android 4.4; Mobile; rv:18.0) Gecko/18.0 Firefox/18.0' + + +def ios_agent(): + return 'Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25' + + +def spoofer(_agent=True, age_str=randomagent(), referer=False, ref_str=''): + + if _agent and referer: + return '|User-Agent=' + quote_plus(age_str) + '&Referer=' + quote_plus(ref_str) + elif _agent: + return '|User-Agent=' + quote_plus(age_str) + elif referer: + return '|Referer=' + quote_plus(ref_str) + + +def cfcookie(netloc, ua, timeout): + try: + headers = {'User-Agent': ua} + + req = urllib_request.Request(netloc, headers=headers) + + try: + urllib_request.urlopen(req, timeout=int(timeout)) + except urllib_request.HTTPError as response: + result = response.read(5242880) + + jschl = re.findall('name="jschl_vc" value="(.+?)"/>', result)[0] + + init = re.findall('setTimeout\(function\(\){\s*.*?.*:(.*?)};', result)[-1] + + builder = re.findall(r"challenge-form\'\);\s*(.*)a.v", result)[0] + + decryptVal = parseJSString(init) + + lines = builder.split(';') + + for line in lines: + + if len(line) > 0 and '=' in line: + + sections = line.split('=') + line_val = parseJSString(sections[1]) + decryptVal = int(eval(str(decryptVal)+sections[0][-1]+str(line_val))) + + answer = decryptVal + len(urlparse.urlparse(netloc).netloc) + + query = '%s/cdn-cgi/l/chk_jschl?jschl_vc=%s&jschl_answer=%s' % (netloc, jschl, answer) + + if 'type="hidden" name="pass"' in result: + passval = re.findall('name="pass" value="(.*?)"', result)[0] + query = '%s/cdn-cgi/l/chk_jschl?pass=%s&jschl_vc=%s&jschl_answer=%s' % (netloc, quote_plus(passval), jschl, answer) + time.sleep(5) + + cookies = cookielib.LWPCookieJar() + handlers = [urllib_request.HTTPHandler(), urllib_request.HTTPSHandler(), urllib_request.HTTPCookieProcessor(cookies)] + opener = urllib_request.build_opener(*handlers) + urllib_request.install_opener(opener) + + try: + request = urllib_request.Request(query, headers=headers) + urllib_request.urlopen(request, timeout=int(timeout)) + except: + pass + + cookie = '; '.join(['%s=%s' % (i.name, i.value) for i in cookies]) + + return cookie + except: + pass + + +def parseJSString(s): + try: + offset = 1 if s[0] == '+' else 0 + val = int(eval(s.replace('!+[]', '1').replace('!![]', '1').replace('[]', '0').replace('(', 'str(')[offset:])) + return val + except: + pass diff --git a/usr/lib/enigma2/python/Plugins/Extensions/Filmon/dom_parser.py b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/dom_parser.py new file mode 100644 index 0000000..ba17d3e --- /dev/null +++ b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/dom_parser.py @@ -0,0 +1,203 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" + Based on Parsedom for XBMC plugins + Copyright (C) 2010-2011 Tobias Ussing And Henrik Mosgaard Jensen + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +""" +from __future__ import absolute_import +from collections import namedtuple +import re +import sys +is_py2 = sys.version_info[0] == 2 +is_py3 = sys.version_info[0] == 3 + + +if is_py2: + + _str = str + str = unicode + range = xrange + from itertools import izip + zip = izip + unicode = unicode + basestring = basestring + + def bytes(b, encoding="ascii"): + + return _str(b) + + def iteritems(d, **kw): + + return d.iteritems(**kw) + +elif is_py3: + + bytes = bytes + str = unicode = basestring = str + range = range + zip = zip + + def iteritems(d, **kw): + + return iter(d.items(**kw)) + +DomMatch = namedtuple('DOMMatch', ['attrs', 'content']) +re_type = type(re.compile('')) + + +def __get_dom_content(html, name, match): + if match.endswith('/>'): + return '' + + # override tag name with tag from match if possible + tag = re.match(r'<([^\s/>]+)', match) + if tag: + name = tag.group(1) + + start_str = '<%s' % name + end_str = " return + tend = html.find(end_str, end + len(end_str)) + if tend != -1: + end = tend + pos = html.find(start_str, pos + 1) + + if start == -1 and end == -1: + result = '' + elif start > -1 and end > -1: + result = html[start + len(match):end] + elif end > -1: + result = html[:end] + elif start > -1: + result = html[start + len(match):] + else: + result = '' + + return result + + +def __get_dom_elements(item, name, attrs): + if not attrs: + pattern = r'(<%s(?:\s[^>]*>|/?>))' % name + this_list = re.findall(pattern, item, re.M | re.S | re.I) + else: + last_list = None + for key, value in attrs.iteritems(): + value_is_regex = isinstance(value, re_type) + value_is_str = isinstance(value, basestring) + pattern = r'''(<{tag}[^>]*\s{key}=(?P['"])(.*?)(?P=delim)[^>]*>)'''.format( + tag=name, key=key) + re_list = re.findall(pattern, item, re.M | re.S | re.I) + if value_is_regex: + this_list = [r[0] for r in re_list if re.match(value, r[2])] + else: + temp_value = [value] if value_is_str else value + this_list = [r[0] for r in re_list if set( + temp_value) <= set(r[2].split(' '))] + + if not this_list: + has_space = ( + value_is_regex and ' ' in value.pattern) or ( + value_is_str and ' ' in value) + if not has_space: + pattern = r'''(<{tag}[^>]*\s{key}=((?:[^\s>]|/>)*)[^>]*>)'''.format( + tag=name, key=key) + re_list = re.findall(pattern, item, re.M | re.S | re.I) + if value_is_regex: + this_list = [r[0] + for r in re_list if re.match(value, r[1])] + else: + this_list = [r[0] for r in re_list if value == r[1]] + + if last_list is None: + last_list = this_list + else: + last_list = [item for item in this_list if item in last_list] + this_list = last_list + + return this_list + + +def __get_attribs(element): + attribs = {} + for match in re.finditer( + r'''\s+(?P[^=]+)=\s*(?:(?P["'])(?P.*?)(?P=delim)|(?P[^"'][^>\s]*))''', + element): + match = match.groupdict() + value1 = match.get('value1') + value2 = match.get('value2') + value = value1 if value1 is not None else value2 + if value is None: + continue + attribs[match['key'].lower().strip()] = value + return attribs + + +def parse_dom(html, name='', attrs=None, req=False, exclude_comments=False): + if attrs is None: + attrs = {} + name = name.strip() + + if isinstance(html, unicode) or isinstance(html, DomMatch): + html = [html] + elif isinstance(html, str): + try: + html = [html.decode("utf-8")] # Replace with chardet thingy + except BaseException: + try: + html = [html.decode("utf-8", "replace")] + except BaseException: + html = [html] + elif not isinstance(html, list): + return '' + + if not name: + return '' + + if not isinstance(attrs, dict): + return '' + + if req: + if not isinstance(req, list): + req = [req] + req = set([key.lower() for key in req]) + + all_results = [] + for item in html: + if isinstance(item, DomMatch): + item = item.content + + if exclude_comments: + item = re.sub(re.compile('', re.DOTALL), '', item) + + results = [] + for element in __get_dom_elements(item, name, attrs): + attribs = __get_attribs(element) + if req and not req <= set(attribs.keys()): + continue + temp = __get_dom_content(item, name, element).strip() + results.append(DomMatch(attribs, temp)) + item = item[item.find(temp, item.find(element)):] + all_results += results + + return all_results diff --git a/usr/lib/enigma2/python/Plugins/Extensions/Filmon/plugin.py b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/plugin.py index dcfb835..97e0ce5 100644 --- a/usr/lib/enigma2/python/Plugins/Extensions/Filmon/plugin.py +++ b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/plugin.py @@ -11,8 +11,8 @@ #--------------------# #Info http://t.me/tivustream ''' -# from __future__ import print_function -from __future__ import absolute_import +from __future__ import print_function +# from __future__ import absolute_import from Components.AVSwitch import AVSwitch from Components.ActionMap import ActionMap from Components.Label import Label @@ -23,7 +23,6 @@ from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase from Components.config import config from Plugins.Plugin import PluginDescriptor -from Screens.InfoBar import MoviePlayer from Screens.InfoBarGenerics import InfoBarMenu, InfoBarSeek from Screens.InfoBarGenerics import InfoBarAudioSelection, InfoBarNotifications from Screens.MessageBox import MessageBox @@ -46,10 +45,14 @@ import six import sys import json +import ssl +import requests +import urllib3 from . import Utils from . import html_conv global skin_path + PY3 = False PY3 = sys.version_info.major >= 3 print('Py3: ', PY3) @@ -82,6 +85,14 @@ if Utils.DreamOS(): skin_path = os.path.join(PLUGIN_PATH, 'skin/skin_cvs/defaultListScreen.xml') + +if sys.version_info >= (2, 7, 9): + try: + import ssl + sslContext = ssl._create_unverified_context() + except: + sslContext = None + try: # from OpenSSL import SSL from twisted.internet import ssl @@ -101,6 +112,17 @@ def getContext(self): ClientTLSOptions(self.hostname, ctx) return ctx + +class SslOldHttpAdapter(requests.adapters.HTTPAdapter): + def init_poolmanager(self, connections, maxsize, block=False): + ctx = ssl.create_default_context() + ctx.set_ciphers('DEFAULT@SECLEVEL=1') + + self.poolmanager = urllib3.poolmanager.PoolManager( + ssl_version=ssl.PROTOCOL_TLS, + ssl_context=ctx) + + global tmp_image tmp_image = '/tmp/filmon/poster.png' if not pathExists('/tmp/filmon/'): @@ -113,15 +135,15 @@ def getContext(self): class m2list(MenuList): + def __init__(self, list): MenuList.__init__(self, list, True, eListboxPythonMultiContent) - if Utils.isFHD(): - self.l.setItemHeight(50) + self.l.setItemHeight(60) textfont = int(30) self.l.setFont(0, gFont('Regular', textfont)) else: - self.l.setItemHeight(50) + self.l.setItemHeight(35) textfont = int(24) self.l.setFont(0, gFont('Regular', textfont)) @@ -132,9 +154,16 @@ def show_(name, link, img, session, description): img, session, description)] - page1 = os.path.join(PLUGIN_PATH, 'skin/images_new/page_select.png') - res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 5), size=(40, 40), png=loadPNG(page1))) - res.append(MultiContentEntryText(pos=(50, 0), size=(1000, 50), font=0, text=name, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER)) + page1 = os.path.join(PLUGIN_PATH, 'skin/images_new/50x50.png') + # res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 5), size=(50, 50), png=loadPNG(page1))) + # res.append(MultiContentEntryText(pos=(60, 0), size=(1000, 50), font=0, text=name, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER)) + + if Utils.isFHD(): + res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 5), size=(50, 50), png=loadPNG(page1))) + res.append(MultiContentEntryText(pos=(90, 0), size=(1000, 50), font=0, text=name, color=0xa6d1fe, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER)) + else: + res.append(MultiContentEntryPixmapAlphaTest(pos=(3, 3), size=(40, 40), png=loadPNG(page1))) + res.append(MultiContentEntryText(pos=(70, 0), size=(500, 50), font=0, text=name, color=0xa6d1fe, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER)) return res @@ -271,7 +300,7 @@ def cat(self, url): self.id = '' req = Request(url) req.add_header('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14') - req.add_header('Referer', 'https://www.filmon.com/') + req.add_header('Referer', 'http://www.filmon.com/') req.add_header('X-Requested-With', 'XMLHttpRequest') page = urlopen(req) r = page.read() @@ -304,7 +333,7 @@ def get_session(self): urlx = 'http://www.filmon.com/tv/api/init?app_android_device_model=GT-N7000&app_android_test=false&app_version=2.0.90&app_android_device_tablet=true&app_android_device_manufacturer=SAMSUNG&app_secret=wis9Ohmu7i&app_id=android-native&app_android_api_version=10%20HTTP/1.1&channelProvider=ipad&supported_streaming_protocol=rtmp' req = Request(urlx) req.add_header('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14') - req.add_header('Referer', 'https://www.filmon.com/') + req.add_header('Referer', 'http://www.filmon.com/') req.add_header('X-Requested-With', 'XMLHttpRequest') page = urlopen(req, None, 15) content = page.read() @@ -326,14 +355,14 @@ def ok(self): id = self['menulist'].getCurrent()[0][1] print('iddddd : ', id) session = self['menulist'].getCurrent()[0][3] - id = Utils.checkStr(id) - referer = 'http://www.filmon.com' + # id = Utils.checkStr(id) + referer = 'http://www.filmon.com' urlx = 'http://www.filmon.com/tv/api/init?app_android_device_model=GT-N7000&app_android_test=false&app_version=2.0.90&app_android_device_tablet=true&app_android_device_manufacturer=SAMSUNG&app_secret=wis9Ohmu7i&app_id=android-native&app_android_api_version=10%20HTTP/1.1&channelProvider=ipad&supported_streaming_protocol=rtmp' content = Utils.ReadUrl2(urlx, referer) regexvideo = 'session_key":"(.*?)"' match = re.compile(regexvideo, re.DOTALL).findall(content) print("In Filmon2 fpage match =", match) - url = 'https://www.filmon.com/api-v2/channel/' + id + "?session_key=" + session + url = 'http://www.filmon.com/api-v2/channel/' + str(id) + "?session_key=" + session self.get_rtmp(url) elif self.index == 'group': url = self['menulist'].getCurrent()[0][1] @@ -343,20 +372,34 @@ def ok(self): self.cat(url) except Exception as e: print(str(e)) - print("Error: can't find file or read data") + print("Error: can't find file") def get_rtmp(self, data): try: + # import requests + from urllib3.exceptions import InsecureRequestWarning + from urllib3 import disable_warnings + disable_warnings(InsecureRequestWarning) + referer = 'http://www.filmon.com' - content = Utils.ReadUrl2(data, referer) + from . import client + headers = {'User-Agent': client.agent(), 'Referer': referer} + content = six.ensure_str(client.request(data, headers=headers)) + + # referer = 'http://www.filmon.com' + # content = Utils.ReadUrl2(data, referer) + # # content = Utils.ReadUrl2(data) + # print('contet: ', content) + rtmp = re.findall('"quality".*?url"\:"(.*?)"', content) + # print('rtmp: ', rtmp) if rtmp: fin_url = rtmp[0].replace('\\', '') print('fin_url: ', fin_url) self.play_that_shit(str(fin_url)) except Exception as ex: print(ex) - print("Error: can't find file or read data") + print("Error: can't read data") def play_that_shit(self, data): desc = self['menulist'].l.getCurrentSelection()[0][0] @@ -601,6 +644,8 @@ def __init__(self, session, name, url): else: # self.onLayoutFinish.append(self.cicleStreamType) self.onFirstExecBegin.append(self.cicleStreamType) + + # self.onFirstExecBegin.append(self.openYtdl) self.onClose.append(self.cancel) def getAspect(self): @@ -635,7 +680,7 @@ def setAspect(self, aspect): def av(self): temp = int(self.getAspect()) - temp = temp + 1 + temp += 1 if temp > 6: temp = 0 self.new_aspect = temp @@ -646,26 +691,43 @@ def showIMDB(self): if returnIMDB(text_clear): print('show imdb/tmdb') - def slinkPlay(self, url): + def openYtdl(self): name = self.name - ref = "{0}:{1}".format(url.replace(":", "%3A"), name.replace(":", "%3A")) - print('final reference: ', ref) + url = 'streamlink%3a//' + self.url + servicetype = '4097' + ref = "{0}:0:1:0:0:0:0:0:0:0:{1}:{2}".format(servicetype, url.replace(":", "%3a"), name.replace(":", "%3a")) + print('reference youtube: ', ref) sref = eServiceReference(ref) sref.setName(name) self.session.nav.stopService() self.session.nav.playService(sref) + def slinkPlay(self, url): + ref = str(url) + ref = ref.replace(':', '%3a').replace(' ', '%20') + print('final reference 1: ', ref) + ref = "{0}:{1}".format(ref, self.name) + sref = eServiceReference(ref) + sref.setName(self.name) + self.session.nav.stopService() + self.session.nav.playService(sref) + def openTest(self, servicetype, url): - name = self.name - ref = "{0}:0:1:0:0:0:0:0:0:0:{1}:{2}".format(servicetype, url.replace(":", "%3A"), name.replace(":", "%3A")) - print('reference: ', ref) + url = url.replace(':', '%3a').replace(' ', '%20') + ref = str(servicetype) + ':0:1:0:0:0:0:0:0:0:' + str(url) # + ':' + self.name + if streaml is True: - url = 'http://127.0.0.1:8088/' + str(url) - ref = "{0}:0:1:0:0:0:0:0:0:0:{1}:{2}".format(servicetype, url.replace(":", "%3A"), name.replace(":", "%3A")) - print('streaml reference: ', ref) + ref = str(servicetype) + ':0:1:0:0:0:0:0:0:0:http%3a//127.0.0.1%3a8088/' + str(url) + ':' + self.name + # name = self.name + # ref = "{0}:0:1:0:0:0:0:0:0:0:{1}:{2}".format(servicetype, url.replace(":", "%3A"), name.replace(":", "%3A")) + # print('reference: ', ref) + # if streaml is True: + # url = 'http://127.0.0.1:8088/' + str(url) + # ref = "{0}:0:1:0:0:0:0:0:0:0:{1}:{2}".format(servicetype, url.replace(":", "%3A"), name.replace(":", "%3A")) + # print('streaml reference: ', ref) print('final reference: ', ref) sref = eServiceReference(ref) - sref.setName(name) + sref.setName(self.name) self.session.nav.stopService() self.session.nav.playService(sref) @@ -728,7 +790,7 @@ def showAfterSeek(self): self.doShow() def cancel(self): - if os.path.isfile('/tmp/hls.avi'): + if os.path.exists('/tmp/hls.avi'): os.remove('/tmp/hls.avi') self.session.nav.stopService() self.session.nav.playService(self.srefInit) diff --git a/usr/lib/enigma2/python/Plugins/Extensions/Filmon/skin/images_new/50x50.png b/usr/lib/enigma2/python/Plugins/Extensions/Filmon/skin/images_new/50x50.png new file mode 100644 index 0000000000000000000000000000000000000000..90cdf22f0e9cf870ee805b0fa4f1f9b3cbfe98df GIT binary patch literal 4241 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