2249 lines
71 KiB
Python
2249 lines
71 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# *********************************************************************************************************************
|
|
# TinyJSParser https://github.com/TmpName/TinyJSParser
|
|
#
|
|
# A basic JS interpreter in python, made for the Kodi addon Vstream https://github.com/Kodi-vStream/venom-xbmc-addons
|
|
#
|
|
# *********************************************************************************************************************
|
|
|
|
|
|
# TODO LIST
|
|
# ---------
|
|
# Regex will work only for normal name, not for exotic name
|
|
# Object
|
|
# Globla/Local variables/function/object
|
|
# utiliser un tableau special pr variable passe en parametres > clash
|
|
|
|
# help
|
|
# https://sarfraznawaz.wordpress.com/2012/01/26/javascript-self-invoking-functions/
|
|
# https://nemisj.com/python-api-javascript/
|
|
# https://fr.wikiversity.org/wiki/Python/Les_types_de_base
|
|
# https://javascriptobfuscator.com/Javascript-Obfuscator.aspx
|
|
# https://nemisj.com/python-api-javascript/
|
|
|
|
# UNICODE ERROR
|
|
# print(a.decode('utf-8').encode('ascii', 'replace'))
|
|
# true = 1 instead of true
|
|
|
|
# phrase=raw_input()
|
|
# phrase.xxx
|
|
|
|
# https://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/
|
|
|
|
|
|
import re
|
|
import types
|
|
from types import NoneType
|
|
import math
|
|
|
|
# import time
|
|
# import sys
|
|
|
|
REG_NAME = '[\w]+'
|
|
REG_OP = '[\/\*\-\+<>\|\&=~^%!]+' # not space here, and no bracket
|
|
DEBUG = False # Never enable it in kodi, too big size log
|
|
MAX_RECURSION = 50
|
|
ALPHA = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
|
|
|
|
# if(!_0x45ae41[_0x5949('28')](_0x5949('9'),document)||!(!(typeof (document.write) == 'undefined'))){
|
|
|
|
# ---------------------------------------------------------------------------------
|
|
|
|
|
|
def logwrite(stri):
|
|
fh = open('G:\\JSparser\\debug.txt', 'a')
|
|
fh.write(stri + '\n')
|
|
fh.close()
|
|
|
|
|
|
def RemoveGuil(string):
|
|
if not (isinstance(string, types.StringTypes)):
|
|
return string
|
|
string = string.strip()
|
|
if string.startswith('"') and string.endswith('"'):
|
|
return string[1:-1]
|
|
if string.startswith("'") and string.endswith("'"):
|
|
return string[1:-1]
|
|
return string
|
|
|
|
|
|
def ASCIIDecode(string):
|
|
i = 0
|
|
l = len(string)
|
|
ret = ''
|
|
while i < l:
|
|
c = string[i]
|
|
if string[i:(i + 2)] == '\\x':
|
|
c = chr(int(string[(i + 2):(i + 4)], 16))
|
|
i += 3
|
|
if string[i:(i+2)] == '\\u':
|
|
c = chr(int(string[(i + 2):(i + 6)], 16))
|
|
i += 5
|
|
ret = ret + c
|
|
i += 1
|
|
|
|
return ret
|
|
|
|
|
|
def IsUnicode(s):
|
|
if isinstance(s, unicode):
|
|
return True
|
|
return False
|
|
|
|
|
|
def out(string):
|
|
if DEBUG:
|
|
print(str(string.decode('latin-1').encode('ascii', 'replace')))
|
|
|
|
|
|
def Ustr(string):
|
|
if isinstance(string, unicode):
|
|
return str(string.encode('ascii', 'replace'))
|
|
return str(string)
|
|
|
|
|
|
def GetNextchar(string, pos):
|
|
if len(string) <= (pos + 1):
|
|
return ''
|
|
return string[pos + 1]
|
|
|
|
|
|
def GetNextUsefullchar(string):
|
|
j = 0
|
|
try:
|
|
while string[j].isspace():
|
|
j += 1
|
|
except:
|
|
return '', 0
|
|
return string[j], j
|
|
|
|
|
|
def GetPrevchar(string, pos):
|
|
if (pos - 1) < 0:
|
|
return ''
|
|
return string[pos - 1]
|
|
|
|
|
|
def CheckType(value):
|
|
if isinstance(value, types.StringTypes):
|
|
return 'String'
|
|
if isinstance(value, bool):
|
|
return 'Bool'
|
|
if isinstance(value, (int, long, float)):
|
|
return 'Numeric'
|
|
if type(value) in [list, tuple, dict]:
|
|
return 'Array'
|
|
if isinstance(value, NoneType):
|
|
return 'Undefined'
|
|
if isinstance(value, fonction):
|
|
return 'Fonction'
|
|
return 'Unknow'
|
|
|
|
|
|
# Fonction to return only one parameter from a string with correct closed [] () "" and ''
|
|
def GetItemAlone(string, separator=' '):
|
|
|
|
l = len(string) - 1
|
|
ret = ''
|
|
|
|
i = -1
|
|
p = 0 # parenthese
|
|
a = 0 # accolade
|
|
b = 0 # bracket
|
|
c1 = 0 # chain with "
|
|
c2 = 0 # chain with '
|
|
n = False
|
|
last_char = ''
|
|
|
|
s = False
|
|
|
|
while i < l:
|
|
i += 1
|
|
ch = string[i]
|
|
ret = ret + ch
|
|
n = False
|
|
|
|
# Return if the is complete and before the char wanted but not if it's the first one
|
|
if (ch in separator) and not p and not a and not b and not c1 and not c2 and not n and (i > 0):
|
|
return ret[:-1]
|
|
|
|
# Skip empty space
|
|
if ch.isspace():
|
|
continue
|
|
|
|
if ch == '"' and not GetPrevchar(string, i) == '\\' and not c2:
|
|
c1 = 1 - c1
|
|
if ch == "'" and not GetPrevchar(string, i) == '\\' and not c1:
|
|
c2 = 1 - c2
|
|
|
|
if not c1 and not c2:
|
|
if ch == '(':
|
|
p += 1
|
|
if ch == ')':
|
|
p -= 1
|
|
if ch == '{':
|
|
a += 1
|
|
if ch == '}':
|
|
a -= 1
|
|
if ch == '[':
|
|
b += 1
|
|
if ch == ']':
|
|
b -= 1
|
|
|
|
if ch == '.' and not ((last_char in '0123456789') or (string[i + 1] in '0123456789')):
|
|
n = True
|
|
|
|
# return if the chain is complete but with the char wanted
|
|
if (ch in separator) and not p and not a and not b and not c1 and not c2 and not n and (i > 0):
|
|
return ret
|
|
|
|
last_char = ch
|
|
|
|
return ret
|
|
|
|
|
|
def MySplit(string, char, NoEmpty=False):
|
|
r = []
|
|
l = len(string)
|
|
i = 0
|
|
chain = 0
|
|
p = 0
|
|
e = ''
|
|
|
|
if not l:
|
|
if NoEmpty:
|
|
return []
|
|
|
|
while l > i:
|
|
c = string[i]
|
|
if c == '"':
|
|
chain = 1-chain
|
|
if c == '(':
|
|
p += 1
|
|
if c == ')':
|
|
p -= 1
|
|
|
|
if (c == char) and not chain and not p:
|
|
r.append(e.strip())
|
|
e = ''
|
|
else:
|
|
e += c
|
|
|
|
i += 1
|
|
|
|
r.append(e.strip())
|
|
return r
|
|
|
|
|
|
def GetConstructor(value):
|
|
if isinstance(value, (int, long)):
|
|
r = fonction('Number', '', '\n [native code]\n', True)
|
|
return r
|
|
elif isinstance(value, fonction):
|
|
r = fonction('Function', '', '\n [native code]\n', True)
|
|
return r
|
|
elif isinstance(value, types.StringTypes):
|
|
r = fonction('String', '', '\n [native code]\n', True)
|
|
return r
|
|
return ''
|
|
|
|
|
|
class JSBuffer(object):
|
|
PRIORITY = {'+': 3, '-': 3, '*': 4, '/': 4, '>': 1, '<': 1, '&': 2, '|': 2}
|
|
|
|
def __init__(self):
|
|
self.type = None
|
|
self.buffer = ''
|
|
self.__op = ''
|
|
self.__value = None
|
|
|
|
# buffers
|
|
self.buf = []
|
|
self.opBuf = []
|
|
|
|
def SetOp(self, op):
|
|
if (op == '&') and (self.__op == '&'):
|
|
return
|
|
if (op == '|') and (self.__op == '|'):
|
|
return
|
|
else:
|
|
self.__op = self.__op + op
|
|
|
|
def CheckString(self):
|
|
if len(self.buf) >= len(self.opBuf):
|
|
return True
|
|
return False
|
|
|
|
# Need 3 values for priority
|
|
def AddValue(self, value):
|
|
out('ADD ' + Ustr(value) + ' ' + Ustr(type(value)) + ' a ' + Ustr(self.buf))
|
|
|
|
if not self.type:
|
|
self.type = CheckType(value)
|
|
self.Push(value, self.__op)
|
|
return
|
|
|
|
if not self.__op:
|
|
out('op ' + str(self.opBuf) + ' - buff ' + str(self.buf))
|
|
raise Exception('Missing operator')
|
|
|
|
self.Push(value, self.__op)
|
|
self.__op = ''
|
|
|
|
def GetPrevious(self):
|
|
ret = None
|
|
if len(self.buf) > 0:
|
|
ret = self.buf[-1]
|
|
del self.buf[-1]
|
|
self.__op = self.opBuf[-1]
|
|
del self.opBuf[-1]
|
|
if not len(self.buf):
|
|
self.type = None
|
|
|
|
return ret
|
|
|
|
def Compute(self):
|
|
|
|
# check type
|
|
if len(self.buf) > 1:
|
|
if not (self.type == CheckType(self.buf[len(self.buf) - 1])):
|
|
# Type different mais juste operation logique
|
|
if self.opBuf[1] == '==':
|
|
self.type = 'Logic'
|
|
# Type different mais JS convertis en string
|
|
else:
|
|
out('string convertion')
|
|
|
|
if not CheckType(self.buf[0]) == 'String':
|
|
self.buf[0] = self.SpecialStr(self.buf[0])
|
|
if len(self.buf) > 1:
|
|
if not CheckType(self.buf[1]) == 'String':
|
|
self.buf[1] = self.SpecialStr(self.buf[1])
|
|
self.type = 'String'
|
|
|
|
# Work for operateur + | !
|
|
if self.type == 'String':
|
|
if '!' in self.opBuf[0]:
|
|
self.buf[0] = not self.buf[0]
|
|
self.opBuf[0] = self.opBuf[0].replace('!', '')
|
|
if len(self.buf) > 1:
|
|
if self.opBuf[1] == '!':
|
|
self.buf[1] = not self.buf[1]
|
|
self.opBuf[1] = self.opBuf[1].replace('!', '')
|
|
if self.opBuf[1] == '+':
|
|
self.buf[0] = self.buf[0] + self.buf[1]
|
|
if self.opBuf[1] == '|':
|
|
if not self.buf[0]:
|
|
self.buf[0] = self.buf[1]
|
|
if '==' in self.opBuf[1]:
|
|
self.buf[0] = (self.buf[1] == self.buf[0])
|
|
self.type == 'Logic'
|
|
if '!=' in self.opBuf[1]:
|
|
self.buf[0] = (self.buf[1] != self.buf[0])
|
|
self.type == 'Logic'
|
|
|
|
# decale
|
|
del self.opBuf[-1]
|
|
del self.buf[-1]
|
|
|
|
# work for all operator
|
|
elif self.type == 'Numeric':
|
|
if len(self.buf) > 1:
|
|
self.buf[0] = self.opBuf[0] + str(self.buf[0]) + self.opBuf[1] + str(self.buf[1])
|
|
self.opBuf[0] = ''
|
|
# decale
|
|
del self.opBuf[-1]
|
|
del self.buf[-1]
|
|
else:
|
|
self.buf[0] = self.opBuf[0] + str(self.buf[0])
|
|
self.opBuf[0] = ''
|
|
|
|
# work for bool
|
|
elif self.type == 'Bool':
|
|
if len(self.buf) > 1:
|
|
self.buf[0] = self.opBuf[0] + str(self.buf[0]) + self.opBuf[1] + str(self.buf[1])
|
|
self.opBuf[0] = ''
|
|
# decale
|
|
del self.opBuf[-1]
|
|
del self.buf[-1]
|
|
else:
|
|
self.buf[0] = self.opBuf[0] + str(self.buf[0])
|
|
self.opBuf[0] = ''
|
|
|
|
# work for
|
|
elif self.type == 'Logic':
|
|
if not self.buf[0] == self.buf[1]:
|
|
self.buf[0] = False
|
|
else:
|
|
self.buf[0] = True
|
|
# decale
|
|
del self.opBuf[-1]
|
|
del self.buf[-1]
|
|
|
|
elif len(self.buf) > 1:
|
|
print(self.type)
|
|
print(self.buf)
|
|
print(self.opBuf)
|
|
raise Exception("Can't compute")
|
|
|
|
# on decale tout
|
|
def Push(self, value, op):
|
|
|
|
if len(self.buf) > 1:
|
|
self.Compute()
|
|
|
|
self.buf.append(value)
|
|
self.opBuf.append(op)
|
|
return
|
|
|
|
def SpecialStr(self, value):
|
|
if CheckType(value) == 'Numeric':
|
|
return str(value)
|
|
if value == None:
|
|
return 'Undefined'
|
|
if value == True:
|
|
return 'true'
|
|
if value == False:
|
|
return 'false'
|
|
if type(value) in [list]:
|
|
convert_first_to_generator = (str(w) for w in value)
|
|
return ','.join(convert_first_to_generator)
|
|
if type(value) in [dict]:
|
|
return '[object Object]'
|
|
if CheckType(value) == 'Fonction':
|
|
return value.ToStr()
|
|
|
|
return str(value)
|
|
|
|
# ok all finished, force compute
|
|
def GetBuffer(self):
|
|
|
|
# Force compute
|
|
self.Compute()
|
|
while len(self.buf) > 1:
|
|
self.Compute()
|
|
|
|
if self.type == 'Logic':
|
|
return self.buf[0]
|
|
|
|
if self.type == 'Numeric':
|
|
return self.SafeEval(self.buf[0])
|
|
|
|
if self.type == 'Bool':
|
|
if self.SafeEval(self.buf[0].replace('True', '1').replace('False', '0')):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
if self.type == None:
|
|
return ''
|
|
|
|
return self.buf[0]
|
|
|
|
# WARNING : Take care if you edit this function, eval is realy unsafe.
|
|
# better to use ast.literal_eval() but not implemented before python 3
|
|
def SafeEval(self, str):
|
|
if not str:
|
|
raise Exception('Nothing to eval')
|
|
f = re.search('[^0-9+-.\(\)<>=&%!*\^\/]', str)
|
|
if f:
|
|
raise Exception('Wrong parameter to Eval : ' + str)
|
|
return 0
|
|
str = str.replace('!', 'not ')
|
|
# str = str.replace('=', '==')
|
|
# print('>>' + str)
|
|
return eval(str)
|
|
|
|
|
|
class fonction(object):
|
|
def __init__(self, name, param, data, c=False):
|
|
self.name = name
|
|
self.code = data
|
|
self.param = param
|
|
self.const = c
|
|
|
|
def ToStr(self):
|
|
return 'function ' + self.name + '(' + str(self.param)[1:-1] + ') {' + self.code + '}'
|
|
|
|
|
|
class Hack(object):
|
|
def __init__(self, var):
|
|
self.var = var
|
|
|
|
def text(self):
|
|
return self.var
|
|
|
|
|
|
class JsParserHelper1(object):
|
|
def __init__(self, tmp_var):
|
|
self.reset()
|
|
self.used = False
|
|
self.Tmp_var = tmp_var
|
|
self.op = None
|
|
|
|
def reset(self):
|
|
type = None
|
|
self.name = None
|
|
self.t = None
|
|
self.arg = None
|
|
self.rest_code = ''
|
|
# self.op = None
|
|
self.eval = False
|
|
self.property = False
|
|
|
|
def process(self, JScode):
|
|
|
|
# IDK why ?
|
|
if self.op:
|
|
return False
|
|
self.reset()
|
|
self.at1 = None
|
|
|
|
# If already started
|
|
if JScode.startswith(self.Tmp_var):
|
|
self.name = self.Tmp_var
|
|
else:
|
|
# si on a rien encore trouve on recherche une variable/fonction
|
|
r = re.search('^(\w[\w]*)', JScode)
|
|
if r and not self.used:
|
|
self.name = r.group(1)
|
|
else:
|
|
return False
|
|
|
|
self.used = True
|
|
|
|
# By defaut
|
|
self.t = 'var'
|
|
JScode = JScode[(len(self.name)):]
|
|
|
|
c, p = GetNextUsefullchar(JScode)
|
|
while (c in '.[') and c and not self.at1:
|
|
JScode = JScode[p:]
|
|
if c == '[':
|
|
a = GetItemAlone(JScode, ']')
|
|
JScode = JScode[(len(a)):]
|
|
self.at1 = a[1:-1]
|
|
self.eval = True
|
|
if c == '.':
|
|
a = GetItemAlone(JScode[1:], '[(.\/*-+{}<>|=~^%!')
|
|
JScode = JScode[(len(a)+1):]
|
|
self.at1 = a
|
|
self.property = True
|
|
|
|
c, p = GetNextUsefullchar(JScode)
|
|
|
|
if c == '(':
|
|
a = GetItemAlone(JScode, ')')
|
|
JScode = JScode[(len(a)):]
|
|
self.arg = a[1:-1]
|
|
self.t = 'fct'
|
|
|
|
# operation ?
|
|
if not self.t == 'fct':
|
|
m = re.search('^(' + REG_OP + '|\[|$)', JScode, re.UNICODE)
|
|
if m and JScode:
|
|
self.op = m.group(1).strip()
|
|
if self.op == '[':
|
|
self.op = None
|
|
else:
|
|
# prb because the only possible case is ==
|
|
if len(self.op) > 1 and self.op[0] == '=' and not self.op[1] == '=':
|
|
self.op = self.op[0]
|
|
|
|
JScode = JScode[(len(self.op)):]
|
|
|
|
if self.t == 'fct':
|
|
out('Fonction :' + self.name + ' method: ' + str(self.at1) + ' arg: ' + self.arg)
|
|
elif self.t == 'var':
|
|
if self.property:
|
|
self.at1 = '"' + self.at1 + '"'
|
|
out('Variable :' + self.name + ' []= ' + str(self.at1) )
|
|
# Exit if nothing to process
|
|
if (self.name == self.Tmp_var) and not self.at1 and not self.op:
|
|
return False
|
|
if self.op:
|
|
out('operation :' + self.name + ' []= ' + str(self.at1) + ' op: ' + str(self.op) )
|
|
|
|
self.rest_code = JScode
|
|
|
|
return True
|
|
|
|
|
|
class JsParser(object):
|
|
def __init__(self):
|
|
self.Unicode = False
|
|
self.HackVars = []
|
|
self.debug = False
|
|
self.LastEval = ''
|
|
self.SpecialOption = ''
|
|
self.Return = False
|
|
self.ReturnValue = None
|
|
self.Break = False
|
|
self.continu = False
|
|
self.FastEval_vars = []
|
|
self.FastEval_recur = 0
|
|
self.option_ForceTest = False
|
|
|
|
def SetReturn(self, r, v):
|
|
self.Return = True
|
|
self.RecursionReturn = r
|
|
self.ReturnValue = v
|
|
|
|
def SetOption(self, option):
|
|
if option == 'ForceTest':
|
|
self.option_ForceTest = True
|
|
|
|
def AddHackVar(self, name, value):
|
|
self.HackVars.append((name, value))
|
|
|
|
def GetVarHack(self, name):
|
|
return self.GetVar(self.HackVars, name)
|
|
|
|
def PrintVar(self, vars):
|
|
for i, j in vars:
|
|
print(i + ' : ' + str(j))
|
|
|
|
# Need to take care at chain var with " and '
|
|
def ExtractFirstchain(self, string):
|
|
|
|
# print(string.encode('ascii', 'replace'))
|
|
|
|
if not len(string.strip()):
|
|
return '', 0
|
|
|
|
l = len(string)
|
|
string = string + ' ' # To prevent index out of range, hack
|
|
|
|
i = -1
|
|
p = 0 # parenthese
|
|
a = 0 # accolade
|
|
b = 0 # bracket
|
|
f = False # fonction ?
|
|
r = False # Regex
|
|
com1 = False
|
|
com2 = False
|
|
prev = '' # previous char
|
|
c1 = 0 # string with "
|
|
c2 = 0 # string with '
|
|
|
|
stringR = ''
|
|
|
|
while l > i:
|
|
|
|
i += 1
|
|
|
|
# ignore comment
|
|
if string[i:(i+2)] == '/*':
|
|
com1 = True
|
|
if com1:
|
|
if string[i:(i+2)] == '*/':
|
|
com1 = False
|
|
i += 1
|
|
continue
|
|
if string[i:(i+2)] == '//' and not r:
|
|
com2 = True
|
|
if com2:
|
|
if string[i] == '\n':
|
|
com2 = False
|
|
else:
|
|
continue
|
|
|
|
ch = string[i]
|
|
|
|
# if ch == '"' and not GetPrevchar(string,i) == '\\' and not c2:
|
|
if ch == '"' and not c2:
|
|
c1 = 1 - c1
|
|
if ch == "'" and not c1:
|
|
c2 = 1 - c2
|
|
|
|
# if we are in a chain no more thing to do than waiting for end
|
|
if c1 or c2:
|
|
stringR = stringR + ch
|
|
continue
|
|
|
|
if ch == '(':
|
|
p += 1
|
|
if ch == ')':
|
|
p -= 1
|
|
if ch == '{':
|
|
a += 1
|
|
if ch == '}':
|
|
a -= 1
|
|
if ch == '[':
|
|
b += 1
|
|
if ch == ']':
|
|
b -= 1
|
|
if r and ch == '/':
|
|
r = False
|
|
if ch == '/' and prev == '=':
|
|
r = True
|
|
|
|
# vire espace inutile
|
|
if ch.isspace() and not c1 and not c2:
|
|
if not(prev in ALPHA and GetNextchar(string, i) in ALPHA):
|
|
continue
|
|
|
|
stringR = stringR + ch
|
|
|
|
# memorise last char
|
|
if not ch.isspace():
|
|
prev = ch
|
|
|
|
# Dans tout les cas les parenthses doivent etre fermees, ainsi que les crochet
|
|
if not p and not b:
|
|
# Si on rencontre un ; par defaut
|
|
if (ch == ';') and not f:
|
|
# Ok, accolade fermees aussi, c'est tout bon
|
|
if not a:
|
|
return stringR, i
|
|
# Accoloade non fermee, c'est une fonction
|
|
else:
|
|
f = True
|
|
# si c'est une fonction et l'accolade fermee
|
|
if f and not a:
|
|
|
|
# quel est le caractere suivant ?
|
|
j = i + 1
|
|
while (string[j].isspace()) and (l > j):
|
|
j += 1
|
|
# Si parenthese on repart
|
|
if string[j] == '(':
|
|
continue
|
|
|
|
# Mal formated string ?
|
|
# Sometime, coder forget the last ; before the }
|
|
# Desactived for the moment, because can bug in 'a = {};'
|
|
if False:
|
|
j = -2
|
|
while (stringR[j].isspace()) or (stringR[j] == '}'):
|
|
j -= 1
|
|
if not (stringR[j] == ';'):
|
|
j += 1
|
|
stringR = stringR[:j] + ';' + stringR[j:]
|
|
|
|
# if there is a last ; add it
|
|
if string[i+1] == ';':
|
|
stringR = stringR + ';'
|
|
i += 1
|
|
|
|
return stringR, i
|
|
|
|
# chaine bugguée ?
|
|
if ';' not in string:
|
|
# out('ERROR Extract chain without ";" > ' + string)
|
|
return string.rstrip() + ';', i
|
|
|
|
raise Exception("Can't extract chain " + string)
|
|
|
|
# Everything Without a "Real" is False
|
|
def CheckTrueFalse(self, string):
|
|
# out('> Check True or false : ' + str(string))
|
|
|
|
if isinstance(string, bool):
|
|
if string == True:
|
|
return True
|
|
elif isinstance(string, types.StringTypes):
|
|
if not string == '':
|
|
return True
|
|
if isinstance(string, (int, long, float)):
|
|
if not (string == 0):
|
|
return True
|
|
if isinstance(string, (list, tuple)):
|
|
if not (string == []):
|
|
return True
|
|
return False
|
|
|
|
# Syntax > aaaaaa.bbbbbb(cccccc) ou bbbb(cccc) ou "aaaa".bb(ccc) ou aa[bb](cc)
|
|
def FonctionParser(self, vars, allow_recursion, name, function, arg2, JScode):
|
|
|
|
arg = arg2.strip()
|
|
|
|
out('fonction > Name: ' + Ustr(name) + ' arg: ' + Ustr(arg) + ' function: ' + Ustr(function))
|
|
|
|
# hack ?
|
|
if isinstance(name, Hack):
|
|
a = MySplit(arg, ',', True)
|
|
|
|
# In this case function = text but useless ATM
|
|
|
|
if a:
|
|
# ecriture
|
|
vv = self.evalJS(a[0], vars, allow_recursion)
|
|
self.AddHackVar(name.var, vv)
|
|
return vv, JScode
|
|
else:
|
|
# lecture
|
|
vv = self.GetVarHack(name.var)
|
|
out('Hack vars (set): ' + vv)
|
|
return vv, JScode
|
|
|
|
# Definite function ?
|
|
fe = self.IsFunc(vars, function)
|
|
if not fe:
|
|
try:
|
|
fe = self.IsFunc(vars, '%s["%s"]' % (name, function))
|
|
except:
|
|
pass
|
|
|
|
if fe:
|
|
|
|
if fe == '$':
|
|
a = MySplit(arg, ',', True)
|
|
vv = self.evalJS(a[0], vars, allow_recursion)
|
|
fff = Hack(vv)
|
|
|
|
return fff, JScode
|
|
|
|
elif isinstance(fe, types.MethodType):
|
|
# print(fe.im_func.__name__) # parseint
|
|
# print(fe.im_class.__name__) # Basic
|
|
function = fe.im_func.__name__
|
|
out("> function (native): " + function + ' arg=' + arg)
|
|
# and continu with native fonction
|
|
|
|
elif isinstance(fe, fonction):
|
|
out('> fonction definie par code : ' + function)
|
|
n, p, c, ct = fe.name, fe.param, fe.code, fe.const
|
|
a = MySplit(arg, ',', True)
|
|
a2 = []
|
|
# out('code de la fonction : ' + c)
|
|
|
|
if ct:
|
|
out('constructor mode')
|
|
# hack
|
|
# Make replacement
|
|
JScode = "%s(%s)%s" % (n, arg, JScode) + ';'
|
|
|
|
NewEval = self.Parse(JScode, vars, allow_recursion)
|
|
return NewEval, ''
|
|
|
|
for i in a:
|
|
vv = self.evalJS(i, vars, allow_recursion)
|
|
a2.append(RemoveGuil(vv))
|
|
|
|
List_tmpvar = []
|
|
if (len(p) > 0) and (len(a2) > 0):
|
|
nv = tuple(zip(p, a2))
|
|
for z, w in nv:
|
|
self.SetVar(vars, z, w)
|
|
List_tmpvar.append(z)
|
|
|
|
jjj = self.Parse(c, vars, allow_recursion)
|
|
|
|
# And delete tmp var
|
|
for i in List_tmpvar:
|
|
self.InitVar(vars, i)
|
|
|
|
if self.Return:
|
|
self.Return = None
|
|
|
|
# return jjj, JScode
|
|
return self.ReturnValue, JScode
|
|
|
|
else:
|
|
raise Exception("Strnage fonction")
|
|
|
|
# Native fonction
|
|
# http://stackoverflow.com/questions/1091259/how-to-test-if-a-class-attribute-is-an-instance-method
|
|
s = ''
|
|
if type(name) in [list, tuple, dict, types.MethodType, NoneType]:
|
|
s = name
|
|
else:
|
|
if name.startswith('"') or name.startswith("'"):
|
|
s = RemoveGuil(name)
|
|
else:
|
|
if self.IsVar(vars, name):
|
|
s = self.GetVar(vars, name)
|
|
else:
|
|
s = name
|
|
|
|
for lib in List_Lib:
|
|
if hasattr(lib, function):
|
|
if not function == 'eval':
|
|
arg = MySplit(arg, ',')
|
|
for i in range(len(arg)):
|
|
arg[i] = self.evalJS(arg[i], vars, allow_recursion)
|
|
|
|
# for fastcall
|
|
self.FastEval_vars = vars
|
|
self.FastEval_recur = allow_recursion
|
|
|
|
cls = lib(self, s)
|
|
|
|
r = getattr(cls, function)(arg)
|
|
|
|
# set new value if changed
|
|
if hasattr(lib, 'Get'):
|
|
NV = getattr(cls, 'Get')()
|
|
if not NV == s:
|
|
self.SetVar(vars, name, NV)
|
|
|
|
return r, JScode
|
|
|
|
# test, if all is ok, never reached
|
|
if False:
|
|
# function
|
|
if function == 'function':
|
|
pos9 = len(JScode)
|
|
v = self.MemFonction(vars, '', arg, False, JScode)[2]
|
|
JScode = JScode[pos9:]
|
|
return v, JScode
|
|
|
|
# constructor
|
|
if function == 'Function':
|
|
NewCode = RemoveGuil(arg) + ';'
|
|
|
|
v = self.MemFonction(vars, '', '', False, '{' + NewCode + '}')[2]
|
|
JScode = v + JScode
|
|
|
|
NewEval = self.Parse(JScode, vars, allow_recursion)
|
|
return NewEval, ''
|
|
|
|
self.PrintVar(vars)
|
|
raise Exception('Unknow fonction : ' + function)
|
|
|
|
def Fast_Eval(self, strg):
|
|
r = self.evalJS(strg, self.FastEval_vars, self.FastEval_recur)
|
|
return r
|
|
|
|
def VarParser(self, vars, allow_recursion, variable, op, JScode):
|
|
|
|
New_Var = False
|
|
|
|
out('Variable : ' + str(variable) + ' operator : ' + op)
|
|
|
|
# if it's a creation/modification
|
|
if op == '=':
|
|
|
|
out('creation/modification')
|
|
|
|
v1 = GetItemAlone(JScode, ',')
|
|
JScode = JScode[(len(v1)):]
|
|
|
|
v1 = v1.strip()
|
|
|
|
self.VarManage(allow_recursion, vars, variable, v1)
|
|
|
|
# and return it
|
|
r = self.GetVar(vars, variable)
|
|
return r, JScode
|
|
|
|
if not self.IsVar(vars, variable):
|
|
raise Exception("Cannot find var " + str(variable))
|
|
|
|
r = self.GetVar(vars, variable)
|
|
|
|
# Only modification
|
|
if len(op) == 2:
|
|
|
|
# just put var because not managed here
|
|
if op[0] in '=!':
|
|
return r, op + JScode
|
|
|
|
# ok so what is it ?
|
|
out('> var ' + variable + '=' + str(r))
|
|
|
|
# check if it's i++ ou i -- form
|
|
if op == '++':
|
|
self.SetVar(vars, variable, r + 1)
|
|
return r, JScode
|
|
|
|
elif op == '--':
|
|
self.SetVar(vars, variable, r-1)
|
|
return r, JScode
|
|
|
|
# a += 1 form
|
|
elif op[1] == '=' and op[0] in '+-*/%^':
|
|
n = GetItemAlone(JScode, ';,')
|
|
out('A rajouter ' + n)
|
|
r = self.evalJS(variable + op[0] + n, vars, allow_recursion)
|
|
# self.SetVar(vars, variable, r)
|
|
|
|
if isinstance(r, (int, long, float)):
|
|
self.VarManage(allow_recursion, vars, variable, str(r))
|
|
if isinstance(r, str):
|
|
self.VarManage(allow_recursion, vars, variable, '"' + r + '"')
|
|
else:
|
|
self.VarManage(allow_recursion, vars, variable, str(r))
|
|
|
|
JScode = JScode[(len(n)):]
|
|
return r, JScode
|
|
|
|
# just var
|
|
# re-ad op if not used
|
|
JScode = op + JScode
|
|
return r, JScode
|
|
|
|
def evalJS(self, JScode, vars, allow_recursion):
|
|
|
|
if allow_recursion < 0:
|
|
raise Exception('Recursion limit reached')
|
|
|
|
allow_recursion -= 1
|
|
|
|
# plus que la chaine a evaluer
|
|
JScode = JScode.strip()
|
|
|
|
out('-------------')
|
|
out(str(allow_recursion) + ' : A evaluer >' + JScode + '<\n')
|
|
|
|
# ********************************************************
|
|
|
|
InterpretedCode = JSBuffer()
|
|
|
|
while len(JScode) > 0:
|
|
c = JScode[0]
|
|
|
|
# print('InterpretedCode > ' + InterpretedCode)
|
|
out('JScode > ' + JScode.encode('ascii', 'replace') + '\n')
|
|
|
|
# parentheses
|
|
if c == '(':
|
|
|
|
c2 = GetItemAlone(JScode, ')')[1:-1]
|
|
pos2 = len(c2) + 2
|
|
JScode = JScode[pos2:]
|
|
|
|
v = self.evalJS(c2, vars, allow_recursion)
|
|
self.SetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion), v)
|
|
JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode
|
|
|
|
# remove "useless" code
|
|
if JScode.startswith('new '):
|
|
JScode = JScode[4:]
|
|
continue
|
|
|
|
# in operator
|
|
if JScode[0:2] == 'in':
|
|
A = InterpretedCode.GetPrevious()
|
|
B = GetItemAlone(JScode[2:], ',;&|')
|
|
B2 = self.evalJS(B, vars, allow_recursion)
|
|
|
|
if type(B2) in [types.MethodType, types.InstanceType]:
|
|
B2 = str(B2)
|
|
|
|
if A in B2:
|
|
InterpretedCode.AddValue(True)
|
|
else:
|
|
InterpretedCode.AddValue(False)
|
|
JScode = JScode[(len(B) + 2):]
|
|
continue
|
|
|
|
# Special value
|
|
m = re.search('^(true|false|null|String)', JScode, re.UNICODE)
|
|
if m:
|
|
v = m.group(1)
|
|
JScode = JScode[len(v):]
|
|
|
|
if v == 'true':
|
|
InterpretedCode.AddValue(True)
|
|
if v == 'false':
|
|
InterpretedCode.AddValue(False)
|
|
if v == 'null':
|
|
InterpretedCode.AddValue(None)
|
|
if v == 'String':
|
|
self.SetVar(vars, 'TEMPORARY_VARS ' + str(allow_recursion), '')
|
|
JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode
|
|
# if v == 'Array':
|
|
# InterpretedCode.AddValue([])
|
|
|
|
continue
|
|
|
|
# hackVars
|
|
r = re.search('^\$\("#([\w]+)"\)\.text\(\)', JScode)
|
|
if r:
|
|
InterpretedCode.AddValue(self.GetVar(self.HackVars, r.group(1)))
|
|
JScode = JScode[(r.end()):]
|
|
continue
|
|
|
|
if JScode[0] == '$':
|
|
InterpretedCode.AddValue('$')
|
|
JScode = JScode[1:]
|
|
continue
|
|
|
|
# new function delcaration ? Need to be before the fonction/variable parser.
|
|
# var x = function (a, b) {return a * b};
|
|
# function myFunction(a, b) {return a * b};
|
|
if JScode.startswith('function'):
|
|
m = re.search(r'^function(?: ([\w]+))* *\(([^\)]*)\) *{', JScode, re.DOTALL)
|
|
if m:
|
|
name = ''
|
|
openparenthesis = False
|
|
if m.group(1):
|
|
name = m.group(1)
|
|
|
|
replac, pos3, v = self.MemFonction(vars, name, m.group(2), openparenthesis, JScode)
|
|
JScode = replac
|
|
InterpretedCode.AddValue(v)
|
|
continue
|
|
|
|
# pointeur vers fonction ?
|
|
if hasattr(Basic, JScode):
|
|
fm = getattr(Basic(self, None), JScode)
|
|
InterpretedCode.AddValue(fm)
|
|
JScode = ''
|
|
continue
|
|
|
|
# 3 - numeric chain
|
|
r = re.search('(^(?:0x)*[0-9]+)', JScode)
|
|
if r:
|
|
v = JScode[0:r.end()]
|
|
if v.startswith('0x'):
|
|
v = int(v, 0)
|
|
else:
|
|
v = int(v)
|
|
InterpretedCode.AddValue(v)
|
|
JScode = JScode[(r.end()):]
|
|
continue # for this one continue directly
|
|
|
|
# 4 - Regex
|
|
r = re.search('^\/.*\/(.*$)', JScode)
|
|
if r:
|
|
reg = r.group(0)
|
|
flag = r.group(1)
|
|
# test if the regex is valid
|
|
if flag:
|
|
for i in flag:
|
|
if i not in 'gimuy':
|
|
reg = None
|
|
break
|
|
InterpretedCode.AddValue(reg)
|
|
JScode = JScode[(len(r.group(0))):]
|
|
continue # return directly
|
|
|
|
# 1 - Array / method
|
|
if c == '[':
|
|
c2 = GetItemAlone(JScode, ']')[1:-1]
|
|
pos2 = len(c2) + 2
|
|
# v = self.evalJS(c2,vars,allow_recursion)
|
|
|
|
# all this part is managed away but not for some rare case.
|
|
A = InterpretedCode.GetPrevious()
|
|
if not A:
|
|
valueT = MySplit(c2, ',', True)
|
|
JScode = JScode[pos2:]
|
|
InterpretedCode.AddValue(valueT)
|
|
continue
|
|
|
|
# other case
|
|
self.SetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion), A)
|
|
JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode
|
|
|
|
# 2 - Alpha chain
|
|
elif c == '"' or c == "'":
|
|
|
|
ee = GetItemAlone(JScode, c)
|
|
e = len(ee)
|
|
vv = ee[1:-1]
|
|
|
|
# raw string cannot end in a single backslash
|
|
# if vv[-1:] == '\\' and not vv[-2:-1] == '\\':
|
|
# vv = vv + '\\'
|
|
|
|
# warning with this function
|
|
# if not vv.endswith('\\'):
|
|
# vv = vv.decode('string-escape')
|
|
|
|
JScode = JScode[e:]
|
|
|
|
# to be faster
|
|
if len(JScode) == 0:
|
|
InterpretedCode.AddValue(vv)
|
|
continue
|
|
# normal way
|
|
else:
|
|
self.SetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion), vv)
|
|
JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode
|
|
|
|
item = ''
|
|
# 5 Variable/fonction/object
|
|
P1 = JsParserHelper1('TEMPORARY_VARS' + str(allow_recursion))
|
|
while P1.process(JScode):
|
|
JScode = P1.rest_code
|
|
r = None
|
|
|
|
if P1.t == 'var':
|
|
|
|
# special vars
|
|
if P1.name == 'window' and P1.at1:
|
|
P1.name = RemoveGuil(P1.at1)
|
|
P1.at1 = ''
|
|
|
|
Var_string = P1.name
|
|
if P1.at1:
|
|
Var_string = "%s[%s]" % (P1.name, str(P1.at1))
|
|
|
|
# operation / creation ?
|
|
if P1.op:
|
|
out('creation/modification ' + Var_string + ' ' + P1.op)
|
|
r, JScode = self.VarParser(vars, allow_recursion, Var_string, P1.op, JScode)
|
|
|
|
else:
|
|
if not self.IsVar(vars, P1.name):
|
|
self.PrintVar(vars)
|
|
raise Exception('Variable error : ' + P1.name)
|
|
|
|
r = self.GetVar(vars, Var_string)
|
|
|
|
elif P1.t == 'fct':
|
|
if P1.at1:
|
|
fonction = P1.at1
|
|
name = P1.name
|
|
else:
|
|
fonction = P1.name
|
|
name = ''
|
|
if P1.eval:
|
|
fonction = self.evalJS(fonction, vars, allow_recursion)
|
|
|
|
# hack, devrait etre acive tout le temps
|
|
if 'TEMPORARY_VARS' in name:
|
|
name = self.evalJS(name, vars, allow_recursion)
|
|
|
|
gg = fonction + '***' + P1.arg + '**' + JScode
|
|
r, JScode = self.FonctionParser(vars, allow_recursion, name, fonction, P1.arg, JScode)
|
|
|
|
# to speed up
|
|
if not JScode:
|
|
# It speed up but cause some TEMPORARY_VARS stay in code.
|
|
InterpretedCode.AddValue(r)
|
|
continue
|
|
# normal way
|
|
else:
|
|
self.SetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion), r)
|
|
JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode
|
|
|
|
# after this part, all TEMPORARY_VARS need to be removed
|
|
if JScode.startswith('TEMPORARY_VARS' + str(allow_recursion)):
|
|
r = self.GetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion))
|
|
self.InitVar(vars, 'TEMPORARY_VARS' + str(allow_recursion))
|
|
JScode = JScode[(len('TEMPORARY_VARS' + str(allow_recursion))):]
|
|
InterpretedCode.AddValue(r)
|
|
continue
|
|
if P1.used:
|
|
continue
|
|
|
|
# --var method, HACK
|
|
if JScode[0:2] == '--' or JScode[0:2] == '++':
|
|
m = re.search('^(\({0,1}\w[\w\.]*\){0,1} *(?:\[[^\]]+\])* *)(' + REG_OP + '|\[|$)', JScode[2:], re.UNICODE)
|
|
if m:
|
|
l = len(m.group(1))
|
|
JScode = m.group(1) + JScode[0:2] + JScode[(l+2):]
|
|
continue
|
|
else:
|
|
bb(mm)
|
|
|
|
# Space to remove
|
|
if c == ' ' or c == '\n':
|
|
JScode = JScode[1:]
|
|
continue
|
|
|
|
# Escape char
|
|
if c == '\\':
|
|
JScode = JScode[1:]
|
|
continue
|
|
|
|
# Special if (A)?(B):(C)
|
|
if c == '?':
|
|
out(" ****** Special if 1 ********* ")
|
|
# need to find all part
|
|
A = InterpretedCode.GetPrevious()
|
|
B = GetItemAlone(JScode, ':')
|
|
C = GetItemAlone(JScode[(len(B) + 1):])
|
|
|
|
Totlen = len(B) + len(C) + 2
|
|
B = B[1:]
|
|
if B.startswith('('):
|
|
B = B[1:-1]
|
|
if C.startswith('('):
|
|
C = C[1:-1]
|
|
if A:
|
|
r = self.evalJS(B, vars, allow_recursion)
|
|
else:
|
|
r = self.evalJS(C, vars, allow_recursion)
|
|
|
|
InterpretedCode.AddValue(r)
|
|
JScode = JScode[Totlen:]
|
|
continue
|
|
|
|
# Short-circuiting evaluations
|
|
if JScode[0:2] == '&&' or JScode[0:2] == '||':
|
|
out(" ****** Short-circuiting ********* ")
|
|
A = InterpretedCode.GetPrevious()
|
|
B = GetItemAlone(JScode[2:])
|
|
|
|
Totlen = len(B) + 2
|
|
if B.startswith('('):
|
|
B = B[1:-1]
|
|
|
|
# for && if the first operand evaluates to false, the second operand is never evaluated
|
|
if JScode[0:2] == '&&':
|
|
if A:
|
|
r = self.evalJS(B, vars, allow_recursion)
|
|
InterpretedCode.AddValue(r)
|
|
else:
|
|
InterpretedCode.AddValue(A)
|
|
# for || if the result of the first operand is true, the second operand is never operated
|
|
if JScode[0:2] == '||':
|
|
if not A:
|
|
r = self.evalJS(B, vars, allow_recursion)
|
|
InterpretedCode.AddValue(r)
|
|
else:
|
|
InterpretedCode.AddValue(A)
|
|
|
|
JScode = JScode[Totlen:]
|
|
continue
|
|
|
|
# Operation
|
|
if c in '+<>-*/=&%|!^.':
|
|
InterpretedCode.SetOp(c)
|
|
JScode = JScode[1:]
|
|
continue
|
|
|
|
# No sure how to put this
|
|
if JScode == '{}':
|
|
InterpretedCode.AddValue({})
|
|
JScode = JScode[2:]
|
|
continue
|
|
if JScode == '[]':
|
|
InterpretedCode.AddValue([])
|
|
JScode = JScode[2:]
|
|
continue
|
|
|
|
# ???
|
|
if JScode == ';':
|
|
JScode = JScode[1:]
|
|
continue
|
|
|
|
# comma
|
|
if c == ',':
|
|
InterpretedCode.GetPrevious()
|
|
JScode = JScode[1:]
|
|
continue
|
|
|
|
# Not found part
|
|
# We will make another turn
|
|
self.PrintVar(vars)
|
|
out("Can't eval string :" + JScode)
|
|
out('Last eval : ' + str(self.LastEval))
|
|
|
|
# print(debug.encode('ascii', 'replace'))
|
|
raise Exception(str(allow_recursion) + " : Cannot Eval chain : " + JScode)
|
|
|
|
InterpretedCode2 = InterpretedCode.GetBuffer()
|
|
|
|
out(str(allow_recursion) + ' : Evalue > ' + Ustr(InterpretedCode2) + ' type ' + Ustr(type(InterpretedCode2)))
|
|
out('-------------')
|
|
|
|
self.LastEval = InterpretedCode2
|
|
return InterpretedCode2
|
|
|
|
def InitVar(self, var, variable):
|
|
variable = variable.strip()
|
|
|
|
for j in var:
|
|
if j[0] == variable:
|
|
var.remove(j)
|
|
return
|
|
|
|
def GetVar(self, var, variable):
|
|
|
|
# variable = variable.strip()
|
|
|
|
index = None
|
|
if '[' in variable:
|
|
index = GetItemAlone(variable[(variable.find('[')):], ']')
|
|
index = index[1:-1]
|
|
variable = variable.split('[')[0]
|
|
index = self.evalJS(index, var, 50)
|
|
|
|
if '.' in variable:
|
|
index = variable.split('.')[1]
|
|
variable = variable.split('.')[0]
|
|
|
|
# out('Variable Get ' + variable + ' index :' + str(index))
|
|
|
|
for j in var:
|
|
if j[0] == variable:
|
|
k = j[1]
|
|
r = k
|
|
if not (index == None):
|
|
# Special method
|
|
if index == 'length':
|
|
r = len(k)
|
|
return r
|
|
if index == 'constructor':
|
|
return GetConstructor(k)
|
|
|
|
if type(k) in [list, tuple, str]:
|
|
if CheckType(index) == 'Numeric':
|
|
if int(index) < len(k):
|
|
r = k[int(index)]
|
|
else:
|
|
r = 'undefined'
|
|
elif CheckType(index) == 'String':
|
|
index = RemoveGuil(index)
|
|
try:
|
|
r = k[index]
|
|
except:
|
|
r = k[int(index)]
|
|
elif type(k) in [dict]:
|
|
index = RemoveGuil(index)
|
|
r = k.get(index)
|
|
elif type(k) in [type]:
|
|
r = getattr(k(self, None), index)
|
|
|
|
return r
|
|
|
|
# search it in hackvar ?
|
|
for j in self.HackVars:
|
|
if j[0] == variable:
|
|
return j[1]
|
|
|
|
raise Exception('Variable not defined: ' + str(variable))
|
|
|
|
def SetVar(self, var, variable, value, i=None):
|
|
variable = variable.strip()
|
|
|
|
# Existing var ?
|
|
for j in var:
|
|
if j[0] == variable:
|
|
|
|
if i == None:
|
|
# vars ?
|
|
if isinstance(value, types.StringTypes):
|
|
var[var.index(j)] = (variable, value)
|
|
# Numeric
|
|
else:
|
|
var[var.index(j)] = (variable, value)
|
|
else:
|
|
# Array
|
|
if type(var[var.index(j)][1]) in [list, tuple]:
|
|
|
|
Listvalue = var[var.index(j)][1]
|
|
|
|
# ok this place doesn't esist yet
|
|
l = int(i) - len(Listvalue) + 1
|
|
while l > 0:
|
|
Listvalue.append('undefined')
|
|
l -= 1
|
|
# Now modify it
|
|
if type(value) in [list, tuple]:
|
|
Listvalue = value
|
|
else:
|
|
Listvalue[int(i)] = value
|
|
var[var.index(j)] = (variable, Listvalue)
|
|
# dictionnary
|
|
elif type(var[var.index(j)][1]) in [dict]:
|
|
Listvalue = var[var.index(j)][1]
|
|
Listvalue[i] = value
|
|
var[var.index(j)] = (variable, Listvalue)
|
|
|
|
return
|
|
|
|
# New var
|
|
var.append((variable, value))
|
|
|
|
def GetTypeVar(self, var, variable):
|
|
try:
|
|
variable = variable.split('[')[0]
|
|
variable = variable.split('.')[0]
|
|
for j in var:
|
|
if j[0] == variable:
|
|
return type(j[1])
|
|
return 'Undefined'
|
|
except:
|
|
return 'Undefined'
|
|
|
|
def IsVar(self, var, variable, index=None):
|
|
try:
|
|
variable = variable.split('[')[0]
|
|
variable = variable.split('.')[0]
|
|
for j in var:
|
|
if j[0] == variable:
|
|
if index == None:
|
|
return True
|
|
if index in var[var.index(j)][1]:
|
|
return True
|
|
|
|
return False
|
|
except:
|
|
return False
|
|
|
|
# Need to use metaclass here
|
|
def IsFunc(self, vars, name):
|
|
bExist = False
|
|
bExist = self.IsVar(vars, name)
|
|
if not bExist:
|
|
return False
|
|
|
|
f = self.GetVar(vars, name)
|
|
if f == '$':
|
|
return '$'
|
|
if isinstance(f, fonction):
|
|
return f
|
|
elif isinstance(f, types.MethodType):
|
|
return f
|
|
else:
|
|
return self.IsFunc(vars, f)
|
|
|
|
def VarManage(self, allow_recursion, vars, name, value=None):
|
|
|
|
index = None
|
|
init = False
|
|
|
|
try:
|
|
value = value.strip()
|
|
except:
|
|
pass
|
|
name = name.strip()
|
|
|
|
# variable is an object
|
|
if '.' in name:
|
|
if self.GetTypeVar(vars, name) == 'tuple':
|
|
index = name.split('.')[1]
|
|
name = name.split('.')[0]
|
|
# Variable is an array ?
|
|
m = re.search(r'^\({0,1}([\w]+)\){0,1}\[(.+?)\]$', name, re.DOTALL | re.UNICODE)
|
|
if m:
|
|
name = m.group(1)
|
|
index = m.group(2)
|
|
index = self.evalJS(index, vars, allow_recursion)
|
|
|
|
if value:
|
|
if isinstance(value, (int, long, float)):
|
|
value = self.evalJS(value, vars, allow_recursion)
|
|
else:
|
|
# Values is an array []
|
|
if value.startswith('[') and value.endswith(']'):
|
|
value = value[1:-1]
|
|
|
|
# hack
|
|
if value == '':
|
|
value = []
|
|
# normal way
|
|
else:
|
|
valueT = MySplit(value, ',')
|
|
v = []
|
|
for k in valueT:
|
|
v2 = self.evalJS(k, vars, allow_recursion)
|
|
v.append(v2)
|
|
value = v
|
|
if index == None:
|
|
index = 0
|
|
init = True
|
|
# Values is an array {}
|
|
elif value.startswith('{') and value.endswith('}'):
|
|
value = value[1:-1]
|
|
valueT = MySplit(value, ',', True)
|
|
v = {}
|
|
for k in valueT:
|
|
l = k.split(':')
|
|
# WARNING : no eval here in JS
|
|
v2g = RemoveGuil(l[0])
|
|
v2d = self.evalJS(l[1], vars, allow_recursion)
|
|
v[v2g] = v2d
|
|
value = v
|
|
if index == None:
|
|
index = 0
|
|
init = True
|
|
# string and other
|
|
else:
|
|
value = self.evalJS(value, vars, allow_recursion)
|
|
|
|
name = name.strip()
|
|
|
|
# Output for debug
|
|
if not (index == None):
|
|
out('> Variable in parser => ' + Ustr(name) + '[' + Ustr(index) + ']' + ' = ' + Ustr(value))
|
|
else:
|
|
out('> Variable in parser => ' + Ustr(name) + ' = ' + Ustr(value))
|
|
|
|
# chain
|
|
if isinstance(value, types.StringTypes):
|
|
self.SetVar(vars, name, value, index)
|
|
# number
|
|
elif isinstance(value, (int, long, float)):
|
|
self.SetVar(vars, name, value, index)
|
|
# list
|
|
elif type(value) in [list, tuple, dict]:
|
|
if init:
|
|
self.InitVar(vars, name)
|
|
self.SetVar(vars, name, value, index)
|
|
# fonction
|
|
elif isinstance(value, fonction):
|
|
self.SetVar(vars, name, value, index)
|
|
# undefined
|
|
elif value == None:
|
|
self.SetVar(vars, name, None, index)
|
|
else:
|
|
print(type(value))
|
|
raise Exception('> ERROR : Var problem >' + str(value))
|
|
return
|
|
|
|
def MemFonction(self, vars, name, parametres, openparenthesis, data):
|
|
|
|
if not name:
|
|
n0 = 0
|
|
while self.IsFunc(vars, 'AnonymousFunc' + str(n0)):
|
|
n0 = n0 + 1
|
|
name = 'AnonymousFunc' + str(n0)
|
|
|
|
if self.SpecialOption:
|
|
if self.SpecialOption.split('=')[0] == 'Namefunc':
|
|
name = self.SpecialOption.split('=')[1]
|
|
self.SpecialOption = ''
|
|
|
|
param = MySplit(parametres, ',', True)
|
|
|
|
out('Extract function :' + name + ' ' + str(param))
|
|
|
|
pos = 0
|
|
replac = ''
|
|
|
|
while not data[0] == '{':
|
|
data = data[1:]
|
|
|
|
content = GetItemAlone(data, '}')[1:-1]
|
|
pos2 = len(content) + 1
|
|
|
|
fm = fonction(name, param, content.lstrip())
|
|
self.SetVar(vars, name, fm)
|
|
|
|
data = data[(pos2 + 1):]
|
|
|
|
if openparenthesis:
|
|
c, p = GetNextUsefullchar(data)
|
|
if c == ')':
|
|
data = data[(p + 1):]
|
|
openparenthesis = False
|
|
|
|
selfinvoked = False
|
|
if len(data) > 0:
|
|
if data[0] == '(':
|
|
selfinvoked = True
|
|
|
|
# self invoked ?
|
|
if selfinvoked:
|
|
paraminvoked = GetItemAlone(data, ')')
|
|
out('Self invoked ' + str(paraminvoked))
|
|
replac = name + paraminvoked
|
|
|
|
data = data[(len(paraminvoked)):]
|
|
|
|
if openparenthesis:
|
|
c, p = GetNextUsefullchar(data)
|
|
if c == ')':
|
|
data = data[(p + 1):]
|
|
openparenthesis = False
|
|
|
|
replac = replac + data
|
|
|
|
return replac, 0, name
|
|
|
|
def Parse(self, JScode, vars, allow_recursion=MAX_RECURSION):
|
|
|
|
if allow_recursion < 0:
|
|
raise Exception('Recursion limit reached')
|
|
|
|
allow_recursion -= 1
|
|
|
|
# ************************
|
|
# Post traitement
|
|
# ************************
|
|
# Need all functions first, because they can be called first and be at the bottom of the code
|
|
# So we extract all functions first, and replace them by a simple call in the code, if they are self invoked
|
|
|
|
# Make this part only if needed
|
|
if 'function' in JScode:
|
|
posG = 0
|
|
|
|
while True:
|
|
|
|
chain, pos = self.ExtractFirstchain(JScode[posG:])
|
|
if not chain:
|
|
break
|
|
|
|
Startoff = posG
|
|
Endoff = posG + pos + 1
|
|
posG = Endoff
|
|
|
|
# skip empty char
|
|
chain = chain.strip()
|
|
|
|
# fonction
|
|
m = re.search(r'^(\()* *function(?: ([\w]+))* *\(([^\)]*)\) *{', chain, re.DOTALL)
|
|
if m:
|
|
name = ''
|
|
openparenthesis = False
|
|
if m.group(2):
|
|
name = m.group(2)
|
|
if m.group(1):
|
|
openparenthesis = True
|
|
|
|
replac, pos3, xyz = self.MemFonction(vars, name, m.group(3), openparenthesis, chain)
|
|
|
|
JScode = JScode[:Startoff] + replac + JScode[Endoff:]
|
|
|
|
posG = Startoff + len(replac)
|
|
|
|
# ***********************
|
|
# The real Parser
|
|
# **********************
|
|
|
|
Parser_return = None
|
|
|
|
while True:
|
|
|
|
if self.continu:
|
|
break
|
|
|
|
chain, pos = self.ExtractFirstchain(JScode)
|
|
if not chain:
|
|
break
|
|
|
|
JScode = JScode[(pos + 1):]
|
|
|
|
chain = chain.lstrip().rstrip()
|
|
# empty ?
|
|
if chain == ';':
|
|
continue
|
|
|
|
out('D++++++++++++++++++')
|
|
out(chain.encode('ascii', 'replace'))
|
|
out('F++++++++++++++++++')
|
|
|
|
# hackVars ?
|
|
m = re.search(r'^\$\("#([^"]+)"\)\.text\(([^\)]+)\);', chain)
|
|
if m:
|
|
out('> hack ' + m.group(0) + ' , variable est ' + m.group(1))
|
|
self.SetVar(self.HackVars, m.group(1),self.GetVar(vars, m.group(2)))
|
|
continue
|
|
|
|
# break
|
|
if chain.startswith('break'):
|
|
self.Break = True
|
|
return
|
|
|
|
# continue
|
|
if chain.startswith('continue'):
|
|
self.continu = True
|
|
return
|
|
|
|
# Return ?
|
|
if chain.startswith('return'):
|
|
m = re.match(r'return *;', chain)
|
|
if m:
|
|
self.Return = True
|
|
self.ReturnValue = None
|
|
return None
|
|
m = re.match(r'^return *([^;]+)', chain)
|
|
if m:
|
|
chain = m.group(1)
|
|
r = self.evalJS(chain, vars, allow_recursion)
|
|
self.Return = True
|
|
self.ReturnValue = r
|
|
return self.ReturnValue
|
|
|
|
# Variable creation/modification ?
|
|
if chain.startswith('var '):
|
|
out('var')
|
|
|
|
chain = chain[4:]
|
|
|
|
# Now need to extract all vars from chain
|
|
while chain:
|
|
v1 = GetItemAlone(chain, ',').strip()
|
|
chain = chain[(len(v1) + 1):]
|
|
if v1.endswith(',') or v1.endswith(';'):
|
|
v1 = v1[:-1]
|
|
self.evalJS(v1, vars, allow_recursion)
|
|
continue
|
|
|
|
name = ''
|
|
# Extraction info
|
|
# Problem, catch fonction too :(
|
|
m = re.search(r'^([\w]+) *(\(|\{)', chain, re.DOTALL)
|
|
# Syntax > aaaaa(bbbbb) .........
|
|
if m:
|
|
name = m.group(1)
|
|
sp = m.group(2)
|
|
if sp == '(':
|
|
arg = GetItemAlone(chain[(m.end()-1):], ')')[1:-1]
|
|
pos3 = len(arg) + 1
|
|
|
|
code = chain[(m.end() + pos3):]
|
|
elif sp == '{':
|
|
arg = ''
|
|
code = chain[(m.end()-1):]
|
|
else:
|
|
raise Exception('> Er 74')
|
|
|
|
out('DEBUG > Name: ' + name + ' arg: ' + arg + ' code: ' + code + '\n')
|
|
|
|
# Jquery
|
|
if name == 'DOCUMENT_READY':
|
|
out('DOCUMENT_READY ' + arg)
|
|
self.SpecialOption = 'Namefunc=DR'
|
|
self.Parse(arg, vars, allow_recursion)
|
|
|
|
# It's not the correct place to do that, but for the moment ...
|
|
self.Parse('DR();', vars, allow_recursion)
|
|
|
|
continue
|
|
|
|
# For boucle ?
|
|
if name == 'for':
|
|
arg = arg.split(';')
|
|
v = arg[0] + ';'
|
|
t = arg[1]
|
|
i = arg[2] + ';'
|
|
f = code
|
|
if GetNextUsefullchar(f)[0] == '{':
|
|
f = GetItemAlone(f, '}')[1:-1]
|
|
|
|
# init var
|
|
self.Parse(v, vars, allow_recursion)
|
|
# loop
|
|
while self.CheckTrueFalse(self.evalJS(t, vars, allow_recursion)):
|
|
# fonction
|
|
self.Parse(f, vars, allow_recursion)
|
|
if self.Break:
|
|
self.Break = False
|
|
break
|
|
# incrementation
|
|
self.Parse(i, vars, allow_recursion)
|
|
|
|
continue
|
|
|
|
# boucle while ?
|
|
if name == 'while':
|
|
f = code
|
|
if GetNextUsefullchar(f)[0] == '{':
|
|
f = GetItemAlone(f, '}')[1:-1]
|
|
|
|
# loop
|
|
while self.CheckTrueFalse(self.evalJS(arg, vars, allow_recursion)):
|
|
# fonction
|
|
self.Parse(f, vars, allow_recursion)
|
|
if self.Break:
|
|
self.Break = False
|
|
break
|
|
|
|
if self.continu:
|
|
self.continu = False
|
|
|
|
continue
|
|
|
|
# boucle do/while
|
|
if name == 'do':
|
|
f = code
|
|
e = ''
|
|
if sp == '{':
|
|
f = GetItemAlone(f, '}')
|
|
|
|
if f.startswith('{'):
|
|
f = f[1:-1]
|
|
|
|
# Need to check the while part ?
|
|
chain2, pos2 = self.ExtractFirstchain(JScode)
|
|
if 'while' in chain2:
|
|
chain2 = chain2.lstrip()
|
|
JScode = JScode[(pos2 + 1):]
|
|
m2 = re.search(r'while\s*\((.+?)\);$', chain2, re.DOTALL)
|
|
if m2:
|
|
e = m2.group(1)
|
|
|
|
if not e:
|
|
raise Exception('> While error')
|
|
|
|
out('> Boucle do/while : test :' + e + ' code: ' + f)
|
|
|
|
# loop
|
|
# 1 forced execution because do/while
|
|
self.Parse(f, vars, allow_recursion)
|
|
if self.Break:
|
|
self.Break = False
|
|
continue # stop all
|
|
|
|
if self.continu:
|
|
self.continu = False
|
|
# and now the loop
|
|
while self.CheckTrueFalse(self.evalJS(e, vars, allow_recursion)):
|
|
# fonction
|
|
self.Parse(f, vars, allow_recursion)
|
|
if self.Break:
|
|
self.Break = False
|
|
break
|
|
|
|
if self.continu:
|
|
self.continu = False
|
|
|
|
continue
|
|
# boucle switch
|
|
if name == 'switch':
|
|
v = self.evalJS(arg, vars, allow_recursion)
|
|
f = code[1:]
|
|
|
|
if v == 'undefined':
|
|
continue
|
|
|
|
# Search the good case code
|
|
StrToSearch = "case%s:" % (str(v))
|
|
|
|
while (not f.startswith(StrToSearch)) and (len(f) > 0):
|
|
tmp_str = GetItemAlone(f, ';}')
|
|
f = f[(len(tmp_str) + 1):]
|
|
|
|
if len(f) < 1:
|
|
self.PrintVar(vars)
|
|
raise Exception("Can't find switch value " + str(v))
|
|
|
|
f = f[(len(StrToSearch)):]
|
|
|
|
self.Parse(f, vars, allow_recursion)
|
|
|
|
continue
|
|
|
|
# Boucle if
|
|
if name == 'if':
|
|
t = arg
|
|
f = code
|
|
e = ''
|
|
|
|
if GetNextUsefullchar(f)[0] == '{':
|
|
f = GetItemAlone(f, '}')[1:-1]
|
|
|
|
# Need to check if there is else statement ?
|
|
chain2, pos2 = self.ExtractFirstchain(JScode)
|
|
if 'else' in chain2:
|
|
chain2 = chain2.lstrip()
|
|
JScode = JScode[(pos2 + 1):]
|
|
m2 = re.search(r'else\s*{(.+?)}$', chain2, re.DOTALL)
|
|
if m2:
|
|
e = m2.group(1)
|
|
|
|
# hack, need to memorise working test in future
|
|
if self.option_ForceTest:
|
|
try:
|
|
ttt = self.CheckTrueFalse(self.evalJS(t, vars, allow_recursion))
|
|
except:
|
|
from random import choice
|
|
ttt = choice([True, False])
|
|
# thx to come every day, to help me to find bug on this code
|
|
|
|
if ttt:
|
|
self.Parse(f, vars, allow_recursion)
|
|
elif e:
|
|
self.Parse(e, vars, allow_recursion)
|
|
continue
|
|
# normal way
|
|
else:
|
|
if self.CheckTrueFalse(self.evalJS(t, vars, allow_recursion)):
|
|
self.Parse(f, vars, allow_recursion)
|
|
elif e:
|
|
self.Parse(e, vars, allow_recursion)
|
|
continue
|
|
|
|
if name == 'with':
|
|
f = code
|
|
if GetNextUsefullchar(f)[0] == '{':
|
|
f = GetItemAlone(f, '}')
|
|
|
|
# list all arg membre.
|
|
member_list = self.GetVar(vars, arg)
|
|
|
|
out('> With fonction : exp=' + arg + ' values=' + str(member_list))
|
|
# print('Before: ' + f)
|
|
# print(member_list)
|
|
|
|
def sub(g):
|
|
g = g.group()
|
|
return g[0] + arg + '["' + g[1:-1] + '"]' + g[-1:]
|
|
|
|
# Hack again
|
|
if type(member_list) in [type]:
|
|
for i in member_list.__dict__:
|
|
f = re.sub(r'[^\w]' + str(i) + '[^\w]', sub, f, re.DOTALL)
|
|
else:
|
|
for i in member_list:
|
|
f = re.sub(r'[^\w]' + i + '[^\w]', sub, f, re.DOTALL)
|
|
|
|
# print('after: ' + f)
|
|
|
|
self.Parse(f[1:-1], vars, allow_recursion)
|
|
# JScode = f[1:-1] + ';' + JScode
|
|
continue
|
|
|
|
# Pas trouve, une fonction ?
|
|
if chain.endswith(';'):
|
|
Parser_return = self.evalJS(chain[:-1], vars, allow_recursion)
|
|
# hack
|
|
# if 'return "ok"' in str(Parser_return):
|
|
# JScode = str(Parser_return)
|
|
# continue
|
|
|
|
# hack, need to be reenabled
|
|
# Non gere encore
|
|
if not chain.endswith(';'):
|
|
print('> ' + JScode)
|
|
raise Exception('> ERROR : Cannot parse >' + chain)
|
|
|
|
return Parser_return
|
|
|
|
def ProcessJS(self, JScode, vars=[]):
|
|
vars_return = []
|
|
|
|
# unicode ?
|
|
if False:
|
|
out('Unicode convertion')
|
|
JScode = unicode(JScode, 'utf-8')
|
|
self.Unicode = True
|
|
|
|
# Special
|
|
vars.append(('Math', Math))
|
|
|
|
vars.append(('String', ''))
|
|
vars.append(('document', {'write': 'ok'}))
|
|
|
|
# Hack
|
|
JScode = JScode.replace('$(document).ready', 'DOCUMENT_READY')
|
|
|
|
# Start the parsing
|
|
ret = self.Parse(JScode, vars)
|
|
|
|
# Memorise vars
|
|
|
|
return ret
|
|
|
|
|
|
# ---------------------------------------------------------------------------------------------------------------------
|
|
# fonctions
|
|
#
|
|
|
|
def toStr(str):
|
|
def decorator(f):
|
|
class _temp:
|
|
def __call__(self, *args, **kwargs):
|
|
return f(self.real_self, *args, **kwargs)
|
|
|
|
def __str__(self):
|
|
return str % f.__name__
|
|
return _temp()
|
|
return decorator
|
|
|
|
|
|
class Math(object):
|
|
def __init__(self, initV1, initV2):
|
|
pass
|
|
|
|
def max(self, arg):
|
|
t1 = arg[0]
|
|
t2 = arg[1]
|
|
return max(t1, t2)
|
|
|
|
def min(self, arg):
|
|
t1 = arg[0]
|
|
t2 = arg[1]
|
|
return min(t1, t2)
|
|
|
|
def abs(self, arg):
|
|
return abs(arg[0])
|
|
|
|
def pow(self, arg):
|
|
t1 = arg[0]
|
|
t2 = arg[1]
|
|
return pow(t1, t2)
|
|
|
|
@toStr('function %s() {\n [native code]\n}')
|
|
def sin(self, arg):
|
|
return math.sin(arg[0])
|
|
|
|
@toStr('function %s() {\n [native code]\n}')
|
|
def atan(self, arg):
|
|
return math.atan(arg[0])
|
|
|
|
def __contains__(self, arg):
|
|
if arg in ['max', 'min', 'abs', 'pow', 'sin', 'atan']:
|
|
return True
|
|
return False
|
|
|
|
|
|
class String(object):
|
|
def __init__(self, initV1, initV2=''):
|
|
self._JSParser = initV1
|
|
self._string = initV2
|
|
|
|
def Get(self):
|
|
return self._string
|
|
|
|
def charCodeAt(self, arg):
|
|
v = arg[0]
|
|
return ord(self._string[int(v)])
|
|
|
|
def length(self, arg):
|
|
return len(self._string)
|
|
|
|
def substring(self, arg):
|
|
p1 = arg[0]
|
|
if len(arg) > 1:
|
|
p2 = arg[1]
|
|
return self._string[int(p1): int(p2)]
|
|
else:
|
|
return self._string[int(p1):]
|
|
|
|
def replace(self, arg):
|
|
t1 = arg[0]
|
|
t2 = arg[1]
|
|
|
|
# if not t1.startswith('/'):
|
|
# t1 = self.evalJS(t1,vars,allow_recursion)
|
|
|
|
# regex mode ? HACK
|
|
if t1.startswith('/'):
|
|
jr = re.findall(t1.split('/')[1], self._string)
|
|
|
|
for k in jr:
|
|
if not self._JSParser.IsFunc(self._JSParser.FastEval_vars, t2):
|
|
self._string = self._string.replace(k, t2)
|
|
out('Replace (F) ' + str(k) + ' by ' + str(t2))
|
|
else:
|
|
v = self._JSParser.Fast_Eval(t2 + '(' + k + ')')
|
|
v = str(v)
|
|
self._string = self._string.replace(k, v)
|
|
out('Replace ' + str(k) + ' by ' + str(v))
|
|
# String mode
|
|
else:
|
|
# t1 = self.evalJS(t1, vars, func, allow_recursion)
|
|
self._string = s.replace(t1, t2)
|
|
return self._string
|
|
|
|
def fromCharCode(self, arg):
|
|
return chr(int(arg[0]))
|
|
|
|
def split(self, arg):
|
|
arg = arg[0].replace('"', '').replace("'", "")
|
|
if arg == '':
|
|
return list(self._string)
|
|
else:
|
|
return self._string.split(arg)
|
|
|
|
def indexOf(self, arg):
|
|
start = 0
|
|
if len(arg) > 1:
|
|
start = int(arg[1])
|
|
return self._string.find(arg[0], start)
|
|
|
|
|
|
class Array(object):
|
|
def __init__(self, initV1, initV2=[]):
|
|
self._array = initV2
|
|
|
|
def Get(self):
|
|
return self._array
|
|
|
|
def join(self, arg):
|
|
t = arg[0].replace('"', '').replace("'", "")
|
|
return t.join(self._array)
|
|
|
|
def push(self, arg):
|
|
t1 = arg[0]
|
|
if len(arg) > 1:
|
|
# use s.extend-[array])
|
|
raise Exception('Not implemented - push')
|
|
self._array.append(t1)
|
|
|
|
v = len(self._array)
|
|
return v
|
|
|
|
def slice(self, arg):
|
|
p1 = arg[0]
|
|
if len(arg) > 1:
|
|
p2 = arg[1]
|
|
sr = self._array[int(p1):int(p2)]
|
|
else:
|
|
sr = self._array[int(p1):]
|
|
sr = '"' + sr + '"'
|
|
return sr
|
|
|
|
def splice(self, arg):
|
|
t1 = arg[0]
|
|
t2 = arg[1]
|
|
if len(arg) > 2:
|
|
raise Exception('Not implemented - splice')
|
|
tab = self._array[:t1] + self._array[(t1 + t2):]
|
|
tabsup = self._array[t1:(t1 + t2)]
|
|
|
|
self._array = tab
|
|
return tabsup
|
|
|
|
def shift(self, arg):
|
|
if len(self._array) == 0:
|
|
return None
|
|
return self._array.pop(0)
|
|
|
|
|
|
class Basic(object):
|
|
def __init__(self, initV1, initV2):
|
|
self._JSParser = initV1
|
|
self._name = initV2
|
|
pass
|
|
|
|
def Setting(self, vars):
|
|
self._vars = vars
|
|
|
|
def parseInt(self, arg):
|
|
t1 = arg[0]
|
|
t2 = arg[1]
|
|
if t1 == '':
|
|
return None
|
|
r = int(t1, int(t2))
|
|
return r
|
|
|
|
def typeof(self, arg):
|
|
return type(arg)
|
|
|
|
def debug(self, arg):
|
|
print('------------------------------------')
|
|
self._JSParser.PrintVar(self._JSParser.FastEval_vars)
|
|
print('------------------------------------')
|
|
raise Exception('DEBUG')
|
|
return
|
|
|
|
def eval(self, arg):
|
|
out('To eval >' + arg)
|
|
r = self._JSParser.Parse(RemoveGuil(arg), self._JSParser.FastEval_vars, self._JSParser.FastEval_recur)
|
|
return r
|
|
|
|
def Array(self, arg):
|
|
if arg[0]:
|
|
if isinstance(arg[0], (int, long)):
|
|
return []
|
|
return arg
|
|
return []
|
|
|
|
def alert(self, arg):
|
|
# logwrite(str(arg))
|
|
print('------------ALERT-------------------')
|
|
print(arg)
|
|
print('------------------------------------')
|
|
return ''
|
|
|
|
def RegExp(self, arg):
|
|
t1 = RemoveGuil(arg[0])
|
|
t2 = RemoveGuil(arg[1])
|
|
return '/' + t1 + '/' + t2
|
|
|
|
# this fonction if for object normaly
|
|
def toString(self, arg):
|
|
t1 = arg[0]
|
|
try:
|
|
f = self._name.im_func.__name__
|
|
except:
|
|
f = "HACK'"
|
|
t = 'function %s() {\n [native code]\n}' % f
|
|
return t
|
|
|
|
|
|
List_Lib = [Basic, Array, String, Math]
|