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"" + name # + ">"
+
+ 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 = "%s" % name
+
+ # start/end tags without matching case cause issues
+ start = html.find(match)
+ end = html.find(end_str, start)
+ pos = html.find(start_str, start + 1)
+
+ while pos < end and pos != -1: # Ignore too early 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
zcmV;C5N_{@P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf02y>eSaefwW^{L9
za%BKPWN%_+AW3auXJt}lVPtu6$z?nM01yF5L_t(&L#
zf%=L{l%GD0P#^@W)dCTcoYfyG0|p>#)JP1v>1JdN9~OD=8sHlfIlf~j4y|906Wg}o
zN<{?_48dXnY*rha)fg2)C=`k`5y?JRd>nEoPQ)z_Jb*FN?}aBW&KTKyd@Uk@)>iC)
z=N)W)<(Ig0`V1EzfYa%O4Hg91C*Q>eu}OVkvGJ~0galgsP4G2dWuG;2-)=`U$A>s)
zTt+(XSiA^%3l<XIdf#GawYM1oxG>+|O0z`O6l>vX}%1qK=$ky=k<`{Kp0xtzwxuaBB@=df|<6FB+tF0_V2XbA=3r}BQheLF@{QC|rm(jAU&
z-5P$xVhca!a)+0CW5bL2$lDLj3H$5nj1kusMZ5QeR}C8xe%#>-FY(5Nze{-=R;)03
zyGFMbIrPB?So6?aI2eZP!64!i6EOY77jf%?M~x9*hD=s*;2^HjiWa+U|8^)r{4dzj
zisX^Q(RaiM27-=}O%P~qrgfggzBOxLiSgoUV*~Db>PMLK^3RPCUq+Wi3U}?oZ@)7W
zwm<-O4oOT(#`o6!1=-`r8za7qmWBpwnsyJW3yvbx)T9=vmnlM2<6J?yrGqY-%D`~P
zYp)`H-~cry8XvD-jSrVCgVh_0244eaytEqkEqli3?TAi^)K^tv`KU1n)YihqeBgCE
z@ziIZp-)b>F`{$qoIMAnfBg`i#6$)vhFIP+TSUUFNRv;=C%*bRWK5cb{Owzrd(0!-
zv3G2HkvL?C4DA#jJo)d~^}9bHY>;`a
z;R+mXx6vEHmmGBc^Ut%)ILr|1L0oJs=C57bfkc3=R>2H@hUG_HU7c|^0uLv5bMsZoos3HdLsz?9|7jb11LCr_S43$l#-+c8Cd%E?TZl%
z1{zJ2{firK!KI63sBiLN0rT0ohaNI|qlo-^<}4I4b9T4rXbnqa4HenJx
z)Q*c2E!?shIeB?%kl@gvL-5o5Lc&gRLPC@Ac)j>mP7V&;HXbdky=*R5#AjJYxd#ox
zw-4-Bb99EXvNF^#s7NiQNk|jRG%@mx88ZgSw7SNx{^eGjKXwca%>Hvvfg)ccCvOrmt{V(-`0~P&
zIK6M5y03^F-?kME44XD?z|{19$YyNU5Nn8;wIC6on~+FPPe($0yc%nxP_c?wM5+Oa
zOzyOFl-@lZrBm<5`6<(Ij;(0YWK_TXXZ1{cLPDD&%p~-un~_l5uT_o*2JU?JSy;ps
zoBa4}-3E0}5jnc~BRJ&D5NN@O`|?$XKpw8FtW>UJCLm293($)Y*y!7K60ot+3Hgtt
z=pMm>V+bDq9HA412%h*Hfsywi6YC(%hg!HkSUXu
z9H+~TlRLJndul}`%-Rl?=297rdGG<%A-H_`GMZWUXzhp~EleyV3oye*3)q=29Bg*w
zVuody$Q*2T`J`~C+Y2Wx(XeqNd?Y522&Ls{S^86CRaaN5ae`z9ko2L~!^${S&Es_)
zm2ItMa=Uuz62o6)acRSb8pByy*VMF4F3>^*@pLDBtwFI$8A3>`qOOf5J}rU3#!s6i
z3|pAjEPr&-C{|A(If0pkzHVS0CrZ`m&uGT*#sJldi-m=-){{t>WrBtEe?mqk;^^}N
ziOP}yg@~TaJh|DWG^8+5BxI3d9a%W%vGIs&^EboFPb>Y}*5HGM6>SQSwjR?9h(x1C
zGt1GkC2~pl*GL_btM-W`+>6}w)^Z7N^uZ9>Wtb+F{UKz`6PhQMd=d>grz@*a$wG$W
z;b6k@%*cm3|8BVNod)l;X^4H~A!Ka&5PeoWXFM5!SVcCsz${CetfiLuMkAqL1}lW1
z@}#P>XQ?D=oyt=gIJR&5pBG3wzRG^VQY81S&@#=m(1A#R}w^HC>m+5tk
zkT8;d2g}H{78VT=tLagX{Kw~l?P0Sg5G9!*GKG}DoEY6)t1h2{f#eJ`M5eZc1Rjm%
z#ztBqGS)`RSY!K0LB<7hf&RMo&7^%)6VQ-ry?>$+W@R9ERkRz1
z{NfAsGLNo<{yaNb6H?O?#*Voe0($b8PtO3uQ
z!KJfBYCra&TP3hh5gDC7oh0Z^b|*e(C9EMDkO|BJbQ3{xf|Kev8t#!J;55~2Uj->n
zuUxsJuA}9M61_aLm`{nvH@vUBr-dGo%kzmq5gEy{AwE5g8x*)yRgP2JBBill;J|^(
zKV>6o%b0~o*Z@?o0lz9odU7SAePNS#4Jn;lEug-EiNu@i#R=j?6I?~k;D?w^Xj?96Qs({
z%*-^N0*d~&3+3mE(aNwcuc>lw9jopuB7(dHkHY5hBE%?A!9w!X_I9fb7%%`aEdFF-
zEl7x&tt5L)PI7WA6;}~W>VDnioUqJ@_txR9Idc#sk;Lq5ym0ssJtz{A+bklOwelwj
z+a1dPN{=1K-&U?$VS`*J6JQ&&3xEb%w|2I@{Pc@O`ki5yb`CsohdLroHS{hFe8;-i7
zBDiQBFWu}kds#_|gnE~sE2O}m#sK6R8aM;j3(O^E65+Im7jUJec$J{$?A
zP%GH5a1s9g#+wMao$!&!8~#Sv4VTyGlt_JL6`sC+C@g*-oIHWWFbMpp;D3?CP;7>5
zT-n?bwZ!G5X%f0cLz9uFEh37Lmk-y`o%9()WAii5V8_e9MA+q2Z{nZWvI(Q6-evT*
zqf;V+<2!cX5BJZ8Ef|2ERbXOD3ckPgFBlYcvXjRpDPCfYCWK^R+B(`oLP#%OTR{4x
znw2*(LZY+7+SdPk4j;YrQ&_yQ>TUhZ)vGZ5>Gqe0W^_qJaA5sR4KfN_@
z&)&_AKAWVvgb?Wt1s`n*f6wL!Kjw`57`lXy{Bg$2aQ(%L#)$4g?S})ct>I80VBF~*
z#d{(@hAwru!izmI;klIe*OyiqyfIb&Vbo5y-ID=FP)_KfMDt
zH>Zo6FWBgVo4$R+?AaK5ZSknLncFL+R&j$XL+Ii
zghRFoH@UB-mgk7$stlL&MA80zXsl#09mtkTL&oLUkCL)l?^V$3F
zW6R6Gz(rO7L2h!FJM!+h{f}yRVoXe8IF+&`@)Dwzo7nG@0KgC}f9k;!rlo~RlSWKp
z=$%5>nmGUa@EC9RdxNh<#Ek#jyAKE6TZ^C!t$Smg{Wd>P