# -*- coding: utf-8 -*- """ openload.io urlresolver plugin Copyright (C) 2015 tknorris 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 . """ import urllib import re import urllib2 from HTMLParser import HTMLParser import requests #from lib.net import Net #from urlresolver import common #from urlresolver.resolver import ResolverError #net = Net() #III SIZE_LIMIT = 32 * 1024 * 1024 def caesar_shift(s, shift=13): s2 = '' for c in s: if c.isalpha(): limit = 90 if c <= 'Z' else 122 new_code = ord(c) + shift if new_code > limit: new_code -= 26 s2 += chr(new_code) else: s2 += c return s2 def unpack(html): strings = re.findall('{\s*var\s+a\s*=\s*"([^"]+)', html) shifts = re.findall('\)\);}\((\d+)\)', html) for s, shift in zip(strings, shifts): s = caesar_shift(s, int(shift)) s = urllib.unquote(s) for i, replace in enumerate(['j', '_', '__', '___']): s = s.replace(str(i), replace) html += '' % (s) return html def get_media_url(url): try: HTTP_HEADER = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', 'Accept-Encoding': 'none', 'Accept-Language': 'en-US,en;q=0.8', 'Referer': url} # 'Connection': 'keep-alive' #html = net.http_GET(url, headers=HTTP_HEADER).content html = requests.get(url, headers=HTTP_HEADER).content try: html = html.encode('utf-8') except: pass html = unpack(html) match = re.search('''>([^<]+)\s*]*>(.*?)', html, re.DOTALL): encoded = match.group(1) match = re.search("(゚ω゚ノ.*?\('_'\);)", encoded, re.DOTALL) if match: decodes.append(AADecoder(match.group(1)).decode()) match = re.search('(.=~\[\].*\(\);)', encoded, re.DOTALL) if match: decodes.append(JJDecoder(match.group(1)).decode()) if not decodes: raise ResolverError('No Encoded Section Found. Deleted?') magic_number = 0 for decode in decodes: match = re.search('charCodeAt\(\d+\)\s*\+\s*(\d+)\)', decode, re.DOTALL | re.I) if match: magic_number = match.group(1) break s = [] for idx, i in enumerate(hiddenurl): j = ord(i) if (j >= 33 & j <= 126): j = 33 + ((j + 14) % 94) if idx == len(hiddenurl) - 1: j += int(magic_number) s.append(chr(j)) res = ''.join(s) videoUrl = 'https://openload.co/stream/{0}?mime=true'.format(res) dtext = videoUrl.replace('https', 'http') headers = {'User-Agent': HTTP_HEADER['User-Agent']} req = urllib2.Request(dtext, None, headers) res = urllib2.urlopen(req) videourl = res.geturl() if int(res.headers['Content-Length']) < SIZE_LIMIT: raise ResolverError('Openload.co resolve failed. Pigeons?') res.close() return videourl except Exception as e: print 'Exception during openload resolve parse: %s' % e # -*- coding: utf-8 -*- # ------------------------------------------------------------ # pelisalacarta - XBMC Plugin # Conector for openload.io # http://blog.tvalacarta.info/plugin-xbmc/pelisalacarta/ # by DrZ3r0 # ------------------------------------------------------------ # Modified by Shani import re #from urlresolver import common #import common class AADecoder(object): def __init__(self, aa_encoded_data): self.encoded_str = aa_encoded_data.replace('/*´∇`*/', '') self.b = ["(c^_^o)", "(゚Θ゚)", "((o^_^o) - (゚Θ゚))", "(o^_^o)", "(゚ー゚)", "((゚ー゚) + (゚Θ゚))", "((o^_^o) +(o^_^o))", "((゚ー゚) + (o^_^o))", "((゚ー゚) + (゚ー゚))", "((゚ー゚) + (゚ー゚) + (゚Θ゚))", "(゚Д゚) .゚ω゚ノ", "(゚Д゚) .゚Θ゚ノ", "(゚Д゚) ['c']", "(゚Д゚) .゚ー゚ノ", "(゚Д゚) .゚Д゚ノ", "(゚Д゚) [゚Θ゚]"] def is_aaencoded(self): idx = self.encoded_str.find("゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); ") if idx == -1: return False is_encoded = self.encoded_str.find("(゚Д゚)[゚o゚]) (゚Θ゚)) ('_');", idx) != -1 return is_encoded def base_repr(self, number, base=2, padding=0): digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' if base > len(digits): base = len(digits) num = abs(number) res = [] while num: res.append(digits[num % base]) num //= base if padding: res.append('0' * padding) if number < 0: res.append('-') return ''.join(reversed(res or '0')) def decode_char(self, enc_char, radix): end_char = "+ " str_char = "" while enc_char != '': found = False # for i in range(len(self.b)): # print self.b[i], enc_char.find(self.b[i]) # if enc_char.find(self.b[i]) == 0: # str_char += self.base_repr(i, radix) # enc_char = enc_char[len(self.b[i]):] # found = True # break # print 'found', found, enc_char if not found: for i in range(len(self.b)): enc_char = enc_char.replace(self.b[i], str(i)) # enc_char = enc_char.replace('(゚Θ゚)', '1').replace('(゚ー゚)', '4').replace('(c^_^o)', '0').replace('(o^_^o)', '3') # print 'enc_char', enc_char startpos = 0 findClose = True balance = 1 result = [] if enc_char.startswith('('): l = 0 for t in enc_char[1:]: l += 1 # print 'looping', findClose, startpos, t, balance if findClose and t == ')': balance -= 1 if balance == 0: result += [enc_char[startpos:l + 1]] findClose = False continue elif not findClose and t == '(': startpos = l findClose = True balance = 1 continue elif t == '(': balance += 1 if result is None or len(result) == 0: return "" else: for r in result: value = self.decode_digit(r, radix) # print 'va', value str_char += value if value == "": return "" return str_char enc_char = enc_char[len(end_char):] return str_char def parseJSString(self, s): try: # print s # offset = 1 if s[0] == '+' else 0 tmp = (s.replace('!+[]', '1').replace('!![]', '1').replace('[]', '0')) # .replace('(','str(')[offset:]) val = int(eval(tmp)) return val except: pass def decode_digit(self, enc_int, radix): # enc_int = enc_int.replace('(゚Θ゚)', '1').replace('(゚ー゚)', '4').replace('(c^_^o)', '0').replace('(o^_^o)', '3') # print 'enc_int before', enc_int # for i in range(len(self.b)): # print self.b[i], enc_char.find(self.b[i]) # if enc_char.find(self.b[i]) > 0: # str_char += self.base_repr(i, radix) # enc_char = enc_char[len(self.b[i]):] # found = True # break # enc_int=enc_int.replace(self.b[i], str(i)) # print 'enc_int before', enc_int try: return str(eval(enc_int)) except: pass rr = '(\(.+?\)\))\+' rerr = enc_int.split('))+') # re.findall(rr, enc_int) v = "" # print rerr for c in rerr: if len(c) > 0: # print 'v', c if c.strip().endswith('+'): c = c.strip()[:-1] # print 'v', c startbrackets = len(c) - len(c.replace('(', '')) endbrackets = len(c) - len(c.replace(')', '')) if startbrackets > endbrackets: c += ')' * (startbrackets - endbrackets) if '[' in c: v += str(self.parseJSString(c)) else: # print c v += str(eval(c)) return v # unreachable code # mode 0=+, 1=- # mode = 0 # value = 0 # while enc_int != '': # found = False # for i in range(len(self.b)): # if enc_int.find(self.b[i]) == 0: # if mode == 0: # value += i # else: # value -= i # enc_int = enc_int[len(self.b[i]):] # found = True # break # if not found: # return "" # enc_int = re.sub('^\s+|\s+$', '', enc_int) # if enc_int.find("+") == 0: # mode = 0 # else: # mode = 1 # enc_int = enc_int[1:] # enc_int = re.sub('^\s+|\s+$', '', enc_int) # return self.base_repr(value, radix) def decode(self): self.encoded_str = re.sub('^\s+|\s+$', '', self.encoded_str) # get data pattern = (r"\(゚Д゚\)\[゚o゚\]\+ (.+?)\(゚Д゚\)\[゚o゚\]\)") result = re.search(pattern, self.encoded_str, re.DOTALL) if result is None: #common.log_utils.log_debug("AADecoder: data not found") print "AADecoder: data not foun" return False data = result.group(1) # hex decode string begin_char = "(゚Д゚)[゚ε゚]+" alt_char = "(o゚ー゚o)+ " out = '' # print data while data != '': # Check new char if data.find(begin_char) != 0: common.log_utils.log_debug("AADecoder: data not found") return False data = data[len(begin_char):] # Find encoded char enc_char = "" if data.find(begin_char) == -1: enc_char = data data = "" else: enc_char = data[:data.find(begin_char)] data = data[len(enc_char):] radix = 8 # Detect radix 16 for utf8 char if enc_char.find(alt_char) == 0: enc_char = enc_char[len(alt_char):] radix = 16 # print repr(enc_char), radix # print enc_char.replace('(゚Θ゚)', '1').replace('(゚ー゚)', '4').replace('(c^_^o)', '0').replace('(o^_^o)', '3') # print 'The CHAR', enc_char, radix str_char = self.decode_char(enc_char, radix) if str_char == "": #common.log_utils.log_debug("no match : "), print "no match : " #common.log_utils.log_debug(data + "\nout = " + out + "\n") print data + "\nout = " + out + "\n" return False # print 'sofar', str_char, radix,out out += chr(int(str_char, radix)) # print 'sfar', chr(int(str_char, radix)), out if out == "": #common.log_utils.log_debug("no match : " + data) print "no match : " + data return False return out # # Python version of the jjdecode function written by Syed Zainudeen # http://csc.cs.utm.my/syed/images/files/jjdecode/jjdecode.html # # +NCR/CRC! [ReVeRsEr] - crackinglandia@gmail.com # Thanks to Jose Miguel Esparza (@EternalTodo) for the final push to make it work! # class JJDecoder(object): def __init__(self, jj_encoded_data): self.encoded_str = jj_encoded_data def clean(self): return re.sub('^\s+|\s+$', '', self.encoded_str) def checkPalindrome(self, Str): startpos = -1 endpos = -1 gv, gvl = -1, -1 index = Str.find('"\'\\"+\'+",') if index == 0: startpos = Str.find('$$+"\\""+') + 8 endpos = Str.find('"\\"")())()') gv = Str[Str.find('"\'\\"+\'+",') + 9:Str.find('=~[]')] gvl = len(gv) else: gv = Str[0:Str.find('=')] gvl = len(gv) startpos = Str.find('"\\""+') + 5 endpos = Str.find('"\\"")())()') return (startpos, endpos, gv, gvl) def decode(self): self.encoded_str = self.clean() startpos, endpos, gv, gvl = self.checkPalindrome(self.encoded_str) if startpos == endpos: raise Exception('No data!') data = self.encoded_str[startpos:endpos] b = ['___+', '__$+', '_$_+', '_$$+', '$__+', '$_$+', '$$_+', '$$$+', '$___+', '$__$+', '$_$_+', '$_$$+', '$$__+', '$$_$+', '$$$_+', '$$$$+'] str_l = '(![]+"")[' + gv + '._$_]+' str_o = gv + '._$+' str_t = gv + '.__+' str_u = gv + '._+' str_hex = gv + '.' str_s = '"' gvsig = gv + '.' str_quote = '\\\\\\"' str_slash = '\\\\\\\\' str_lower = '\\\\"+' str_upper = '\\\\"+' + gv + '._+' str_end = '"+' out = '' while data != '': # l o t u if data.find(str_l) == 0: data = data[len(str_l):] out += 'l' continue elif data.find(str_o) == 0: data = data[len(str_o):] out += 'o' continue elif data.find(str_t) == 0: data = data[len(str_t):] out += 't' continue elif data.find(str_u) == 0: data = data[len(str_u):] out += 'u' continue # 0123456789abcdef if data.find(str_hex) == 0: data = data[len(str_hex):] for i in range(len(b)): if data.find(b[i]) == 0: data = data[len(b[i]):] out += '%x' % i break continue # start of s block if data.find(str_s) == 0: data = data[len(str_s):] # check if "R if data.find(str_upper) == 0: # r4 n >= 128 data = data[len(str_upper):] # skip sig ch_str = '' for i in range(2): # shouldn't be more than 2 hex chars # gv + "."+b[ c ] if data.find(gvsig) == 0: data = data[len(gvsig):] for k in range(len(b)): # for every entry in b if data.find(b[k]) == 0: data = data[len(b[k]):] ch_str = '%x' % k break else: break out += chr(int(ch_str, 16)) continue elif data.find(str_lower) == 0: # r3 check if "R // n < 128 data = data[len(str_lower):] # skip sig ch_str = '' ch_lotux = '' temp = '' b_checkR1 = 0 for j in range(3): # shouldn't be more than 3 octal chars if j > 1: # lotu check if data.find(str_l) == 0: data = data[len(str_l):] ch_lotux = 'l' break elif data.find(str_o) == 0: data = data[len(str_o):] ch_lotux = 'o' break elif data.find(str_t) == 0: data = data[len(str_t):] ch_lotux = 't' break elif data.find(str_u) == 0: data = data[len(str_u):] ch_lotux = 'u' break # gv + "."+b[ c ] if data.find(gvsig) == 0: temp = data[len(gvsig):] for k in range(8): # for every entry in b octal if temp.find(b[k]) == 0: if int(ch_str + str(k), 8) > 128: b_checkR1 = 1 break ch_str += str(k) data = data[len(gvsig):] # skip gvsig data = data[len(b[k]):] break if b_checkR1 == 1: if data.find(str_hex) == 0: # 0123456789abcdef data = data[len(str_hex):] # check every element of hex decode string for a match for i in range(len(b)): if data.find(b[i]) == 0: data = data[len(b[i]):] ch_lotux = '%x' % i break break else: break out += chr(int(ch_str, 8)) + ch_lotux continue else: # "S ----> "SR or "S+ # if there is, loop s until R 0r + # if there is no matching s block, throw error match = 0 n = None # searching for matching pure s block while True: n = ord(data[0]) if data.find(str_quote) == 0: data = data[len(str_quote):] out += '"' match += 1 continue elif data.find(str_slash) == 0: data = data[len(str_slash):] out += '\\' match += 1 continue elif data.find(str_end) == 0: # reached end off S block ? + if match == 0: raise '+ no match S block: ' + data data = data[len(str_end):] break # step out of the while loop elif data.find(str_upper) == 0: # r4 reached end off S block ? - check if "R n >= 128 if match == 0: raise 'no match S block n>128: ' + data data = data[len(str_upper):] # skip sig ch_str = '' ch_lotux = '' for j in range(10): # shouldn't be more than 10 hex chars if j > 1: # lotu check if data.find(str_l) == 0: data = data[len(str_l):] ch_lotux = 'l' break elif data.find(str_o) == 0: data = data[len(str_o):] ch_lotux = 'o' break elif data.find(str_t) == 0: data = data[len(str_t):] ch_lotux = 't' break elif data.find(str_u) == 0: data = data[len(str_u):] ch_lotux = 'u' break # gv + "."+b[ c ] if data.find(gvsig) == 0: data = data[len(gvsig):] # skip gvsig for k in range(len(b)): # for every entry in b if data.find(b[k]) == 0: data = data[len(b[k]):] ch_str += '%x' % k break else: break # done out += chr(int(ch_str, 16)) break # step out of the while loop elif data.find(str_lower) == 0: # r3 check if "R // n < 128 if match == 0: raise 'no match S block n<128: ' + data data = data[len(str_lower):] # skip sig ch_str = '' ch_lotux = '' temp = '' b_checkR1 = 0 for j in range(3): # shouldn't be more than 3 octal chars if j > 1: # lotu check if data.find(str_l) == 0: data = data[len(str_l):] ch_lotux = 'l' break elif data.find(str_o) == 0: data = data[len(str_o):] ch_lotux = 'o' break elif data.find(str_t) == 0: data = data[len(str_t):] ch_lotux = 't' break elif data.find(str_u) == 0: data = data[len(str_u):] ch_lotux = 'u' break # gv + "."+b[ c ] if data.find(gvsig) == 0: temp = data[len(gvsig):] for k in range(8): # for every entry in b octal if temp.find(b[k]) == 0: if int(ch_str + str(k), 8) > 128: b_checkR1 = 1 break ch_str += str(k) data = data[len(gvsig):] # skip gvsig data = data[len(b[k]):] break if b_checkR1 == 1: if data.find(str_hex) == 0: # 0123456789abcdef data = data[len(str_hex):] # check every element of hex decode string for a match for i in range(len(b)): if data.find(b[i]) == 0: data = data[len(b[i]):] ch_lotux = '%x' % i break else: break out += chr(int(ch_str, 8)) + ch_lotux break # step out of the while loop elif (0x21 <= n and n <= 0x2f) or (0x3A <= n and n <= 0x40) or (0x5b <= n and n <= 0x60) or (0x7b <= n and n <= 0x7f): out += data[0] data = data[1:] match += 1 continue print 'No match : ' + data break return out