Actualizados
- allcalidad: Cambio de dominio - animeflv: Correción - streamcloud - Actualización interna
This commit is contained in:
@@ -0,0 +1,375 @@
|
||||
import binascii
|
||||
|
||||
from pyjsparser import PyJsParser
|
||||
import six
|
||||
if six.PY3:
|
||||
basestring = str
|
||||
long = int
|
||||
xrange = range
|
||||
unicode = str
|
||||
|
||||
REGEXP_CONVERTER = PyJsParser()
|
||||
|
||||
|
||||
def to_hex(s):
|
||||
return binascii.hexlify(s.encode('utf8')).decode(
|
||||
'utf8') # fucking python 3, I hate it so much
|
||||
|
||||
|
||||
# wtf was wrong with s.encode('hex') ???
|
||||
def indent(lines, ind=4):
|
||||
return ind * ' ' + lines.replace('\n', '\n' + ind * ' ').rstrip(' ')
|
||||
|
||||
|
||||
def inject_before_lval(source, lval, code):
|
||||
if source.count(lval) > 1:
|
||||
print()
|
||||
print(lval)
|
||||
raise RuntimeError('To many lvals (%s)' % lval)
|
||||
elif not source.count(lval):
|
||||
print()
|
||||
print(lval)
|
||||
assert lval not in source
|
||||
raise RuntimeError('No lval found "%s"' % lval)
|
||||
end = source.index(lval)
|
||||
inj = source.rfind('\n', 0, end)
|
||||
ind = inj
|
||||
while source[ind + 1] == ' ':
|
||||
ind += 1
|
||||
ind -= inj
|
||||
return source[:inj + 1] + indent(code, ind) + source[inj + 1:]
|
||||
|
||||
|
||||
def get_continue_label(label):
|
||||
return CONTINUE_LABEL % to_hex(label)
|
||||
|
||||
|
||||
def get_break_label(label):
|
||||
return BREAK_LABEL % to_hex(label)
|
||||
|
||||
|
||||
def is_valid_py_name(name):
|
||||
try:
|
||||
compile(name + ' = 11', 'a', 'exec')
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def indent(lines, ind=4):
|
||||
return ind * ' ' + lines.replace('\n', '\n' + ind * ' ').rstrip(' ')
|
||||
|
||||
|
||||
def compose_regex(val):
|
||||
reg, flags = val
|
||||
#reg = REGEXP_CONVERTER._unescape_string(reg)
|
||||
return u'/%s/%s' % (reg, flags)
|
||||
|
||||
|
||||
def float_repr(f):
|
||||
if int(f) == f:
|
||||
return repr(int(f))
|
||||
return repr(f)
|
||||
|
||||
|
||||
def argsplit(args, sep=','):
|
||||
"""used to split JS args (it is not that simple as it seems because
|
||||
sep can be inside brackets).
|
||||
|
||||
pass args *without* brackets!
|
||||
|
||||
Used also to parse array and object elements, and more"""
|
||||
parsed_len = 0
|
||||
last = 0
|
||||
splits = []
|
||||
for e in bracket_split(args, brackets=['()', '[]', '{}']):
|
||||
if e[0] not in ('(', '[', '{'):
|
||||
for i, char in enumerate(e):
|
||||
if char == sep:
|
||||
splits.append(args[last:parsed_len + i])
|
||||
last = parsed_len + i + 1
|
||||
parsed_len += len(e)
|
||||
splits.append(args[last:])
|
||||
return splits
|
||||
|
||||
|
||||
def bracket_split(source, brackets=('()', '{}', '[]'), strip=False):
|
||||
"""DOES NOT RETURN EMPTY STRINGS (can only return empty bracket content if strip=True)"""
|
||||
starts = [e[0] for e in brackets]
|
||||
in_bracket = 0
|
||||
n = 0
|
||||
last = 0
|
||||
while n < len(source):
|
||||
e = source[n]
|
||||
if not in_bracket and e in starts:
|
||||
in_bracket = 1
|
||||
start = n
|
||||
b_start, b_end = brackets[starts.index(e)]
|
||||
elif in_bracket:
|
||||
if e == b_start:
|
||||
in_bracket += 1
|
||||
elif e == b_end:
|
||||
in_bracket -= 1
|
||||
if not in_bracket:
|
||||
if source[last:start]:
|
||||
yield source[last:start]
|
||||
last = n + 1
|
||||
yield source[start + strip:n + 1 - strip]
|
||||
n += 1
|
||||
if source[last:]:
|
||||
yield source[last:]
|
||||
|
||||
|
||||
def js_comma(a, b):
|
||||
return 'PyJsComma(' + a + ',' + b + ')'
|
||||
|
||||
|
||||
def js_or(a, b):
|
||||
return '(' + a + ' or ' + b + ')'
|
||||
|
||||
|
||||
def js_bor(a, b):
|
||||
return '(' + a + '|' + b + ')'
|
||||
|
||||
|
||||
def js_bxor(a, b):
|
||||
return '(' + a + '^' + b + ')'
|
||||
|
||||
|
||||
def js_band(a, b):
|
||||
return '(' + a + '&' + b + ')'
|
||||
|
||||
|
||||
def js_and(a, b):
|
||||
return '(' + a + ' and ' + b + ')'
|
||||
|
||||
|
||||
def js_strict_eq(a, b):
|
||||
return 'PyJsStrictEq(' + a + ',' + b + ')'
|
||||
|
||||
|
||||
def js_strict_neq(a, b):
|
||||
return 'PyJsStrictNeq(' + a + ',' + b + ')'
|
||||
|
||||
|
||||
#Not handled by python in the same way like JS. For example 2==2==True returns false.
|
||||
# In JS above would return true so we need brackets.
|
||||
def js_abstract_eq(a, b):
|
||||
return '(' + a + '==' + b + ')'
|
||||
|
||||
|
||||
#just like ==
|
||||
def js_abstract_neq(a, b):
|
||||
return '(' + a + '!=' + b + ')'
|
||||
|
||||
|
||||
def js_lt(a, b):
|
||||
return '(' + a + '<' + b + ')'
|
||||
|
||||
|
||||
def js_le(a, b):
|
||||
return '(' + a + '<=' + b + ')'
|
||||
|
||||
|
||||
def js_ge(a, b):
|
||||
return '(' + a + '>=' + b + ')'
|
||||
|
||||
|
||||
def js_gt(a, b):
|
||||
return '(' + a + '>' + b + ')'
|
||||
|
||||
|
||||
def js_in(a, b):
|
||||
return b + '.contains(' + a + ')'
|
||||
|
||||
|
||||
def js_instanceof(a, b):
|
||||
return a + '.instanceof(' + b + ')'
|
||||
|
||||
|
||||
def js_lshift(a, b):
|
||||
return '(' + a + '<<' + b + ')'
|
||||
|
||||
|
||||
def js_rshift(a, b):
|
||||
return '(' + a + '>>' + b + ')'
|
||||
|
||||
|
||||
def js_shit(a, b):
|
||||
return 'PyJsBshift(' + a + ',' + b + ')'
|
||||
|
||||
|
||||
def js_add(
|
||||
a,
|
||||
b): # To simplify later process of converting unary operators + and ++
|
||||
return '(%s+%s)' % (a, b)
|
||||
|
||||
|
||||
def js_sub(a, b): # To simplify
|
||||
return '(%s-%s)' % (a, b)
|
||||
|
||||
|
||||
def js_mul(a, b):
|
||||
return '(' + a + '*' + b + ')'
|
||||
|
||||
|
||||
def js_div(a, b):
|
||||
return '(' + a + '/' + b + ')'
|
||||
|
||||
|
||||
def js_mod(a, b):
|
||||
return '(' + a + '%' + b + ')'
|
||||
|
||||
|
||||
def js_typeof(a):
|
||||
cand = list(bracket_split(a, ('()', )))
|
||||
if len(cand) == 2 and cand[0] == 'var.get':
|
||||
return cand[0] + cand[1][:-1] + ',throw=False).typeof()'
|
||||
return a + '.typeof()'
|
||||
|
||||
|
||||
def js_void(a):
|
||||
# eval and return undefined
|
||||
return 'PyJsComma(%s, Js(None))' % a
|
||||
|
||||
|
||||
def js_new(a):
|
||||
cands = list(bracket_split(a, ('()', )))
|
||||
lim = len(cands)
|
||||
if lim < 2:
|
||||
return a + '.create()'
|
||||
n = 0
|
||||
while n < lim:
|
||||
c = cands[n]
|
||||
if c[0] == '(':
|
||||
if cands[n - 1].endswith(
|
||||
'.get') and n + 1 >= lim: # last get operation.
|
||||
return a + '.create()'
|
||||
elif cands[n - 1][0] == '(':
|
||||
return ''.join(cands[:n]) + '.create' + c + ''.join(
|
||||
cands[n + 1:])
|
||||
elif cands[n - 1] == '.callprop':
|
||||
beg = ''.join(cands[:n - 1])
|
||||
args = argsplit(c[1:-1], ',')
|
||||
prop = args[0]
|
||||
new_args = ','.join(args[1:])
|
||||
create = '.get(%s).create(%s)' % (prop, new_args)
|
||||
return beg + create + ''.join(cands[n + 1:])
|
||||
n += 1
|
||||
return a + '.create()'
|
||||
|
||||
|
||||
def js_delete(a):
|
||||
#replace last get with delete.
|
||||
c = list(bracket_split(a, ['()']))
|
||||
beg, arglist = ''.join(c[:-1]).strip(), c[-1].strip(
|
||||
) #strips just to make sure... I will remove it later
|
||||
if beg[-4:] != '.get':
|
||||
print(a)
|
||||
raise SyntaxError('Invalid delete operation')
|
||||
return beg[:-3] + 'delete' + arglist
|
||||
|
||||
|
||||
def js_neg(a):
|
||||
return '(-' + a + ')'
|
||||
|
||||
|
||||
def js_pos(a):
|
||||
return '(+' + a + ')'
|
||||
|
||||
|
||||
def js_inv(a):
|
||||
return '(~' + a + ')'
|
||||
|
||||
|
||||
def js_not(a):
|
||||
return a + '.neg()'
|
||||
|
||||
|
||||
def js_postfix(a, inc, post):
|
||||
bra = list(bracket_split(a, ('()', )))
|
||||
meth = bra[-2]
|
||||
if not meth.endswith('get'):
|
||||
raise SyntaxError('Invalid ++ or -- operation.')
|
||||
bra[-2] = bra[-2][:-3] + 'put'
|
||||
bra[-1] = '(%s,Js(%s.to_number())%sJs(1))' % (bra[-1][1:-1], a,
|
||||
'+' if inc else '-')
|
||||
res = ''.join(bra)
|
||||
return res if not post else '(%s%sJs(1))' % (res, '-' if inc else '+')
|
||||
|
||||
|
||||
def js_pre_inc(a):
|
||||
return js_postfix(a, True, False)
|
||||
|
||||
|
||||
def js_post_inc(a):
|
||||
return js_postfix(a, True, True)
|
||||
|
||||
|
||||
def js_pre_dec(a):
|
||||
return js_postfix(a, False, False)
|
||||
|
||||
|
||||
def js_post_dec(a):
|
||||
return js_postfix(a, False, True)
|
||||
|
||||
|
||||
CONTINUE_LABEL = 'JS_CONTINUE_LABEL_%s'
|
||||
BREAK_LABEL = 'JS_BREAK_LABEL_%s'
|
||||
PREPARE = '''HOLDER = var.own.get(NAME)\nvar.force_own_put(NAME, PyExceptionToJs(PyJsTempException))\n'''
|
||||
RESTORE = '''if HOLDER is not None:\n var.own[NAME] = HOLDER\nelse:\n del var.own[NAME]\ndel HOLDER\n'''
|
||||
TRY_CATCH = '''%stry:\nBLOCKfinally:\n%s''' % (PREPARE, indent(RESTORE))
|
||||
|
||||
OR = {'||': js_or}
|
||||
AND = {'&&': js_and}
|
||||
BOR = {'|': js_bor}
|
||||
BXOR = {'^': js_bxor}
|
||||
BAND = {'&': js_band}
|
||||
|
||||
EQS = {
|
||||
'===': js_strict_eq,
|
||||
'!==': js_strict_neq,
|
||||
'==': js_abstract_eq, # we need == and != too. Read a note above method
|
||||
'!=': js_abstract_neq
|
||||
}
|
||||
|
||||
#Since JS does not have chained comparisons we need to implement all cmp methods.
|
||||
COMPS = {
|
||||
'<': js_lt,
|
||||
'<=': js_le,
|
||||
'>=': js_ge,
|
||||
'>': js_gt,
|
||||
'instanceof': js_instanceof, #todo change to validitate
|
||||
'in': js_in
|
||||
}
|
||||
|
||||
BSHIFTS = {'<<': js_lshift, '>>': js_rshift, '>>>': js_shit}
|
||||
|
||||
ADDS = {'+': js_add, '-': js_sub}
|
||||
|
||||
MULTS = {'*': js_mul, '/': js_div, '%': js_mod}
|
||||
BINARY = {}
|
||||
BINARY.update(ADDS)
|
||||
BINARY.update(MULTS)
|
||||
BINARY.update(BSHIFTS)
|
||||
BINARY.update(COMPS)
|
||||
BINARY.update(EQS)
|
||||
BINARY.update(BAND)
|
||||
BINARY.update(BXOR)
|
||||
BINARY.update(BOR)
|
||||
BINARY.update(AND)
|
||||
BINARY.update(OR)
|
||||
#Note they dont contain ++ and -- methods because they both have 2 different methods
|
||||
# correct method will be found automatically in translate function
|
||||
UNARY = {
|
||||
'typeof': js_typeof,
|
||||
'void': js_void,
|
||||
'new': js_new,
|
||||
'delete': js_delete,
|
||||
'!': js_not,
|
||||
'-': js_neg,
|
||||
'+': js_pos,
|
||||
'~': js_inv,
|
||||
'++': None,
|
||||
'--': None
|
||||
}
|
||||
Reference in New Issue
Block a user