'''
'' PyIRCIoT_EL_ (IRC-IoT Embedded Languages class)
''
'' Copyright (c) 2019-2021 Alexey Y. Woronov
''
'' By using this file, you agree to the terms and conditions set
'' forth in the LICENSE file which can be found at the top level
'' of this package
''
'' Authors:
'' Alexey Y. Woronov <alexey@woronov.ru>
'''
# ATTENTION!!! THIS CLASS WAS TESTED ONLY ON LINUX, WHILE ON THE
# OTHER OS'ES IT DOES NOT WORK YET. ALSO, USING THIS CLASS IS
# DANGEROUS, BECAUSE A POTENTIAL ATTACKER CAN GAIN REMOTE CONTROL
# ON YOUR SYSTEM. USE IT IF YOU KNOW WHAT ARE YOU DOING!
# Those Global options override default behavior and memory usage
#
CAN_debug_library = True
import re
import ast
try:
import json
except:
import simplejson as json
from io import StringIO
import tracemalloc
import contextlib
import signal
try: # insecure, but for development
from irciot_shared import *
except:
from PyIRCIoT.irciot_shared import *
def irciot_set_locale_(self, in_lang):
if not isinstance(in_lang, str):
return
self.lang = in_lang
my_desc = {}
try:
from PyIRCIoT.irciot_errors \
import irciot_get_common_error_descriptions_
my_desc.update(irciot_get_common_error_descriptions_(in_lang))
my_desc = self.validate_descriptions_(my_desc)
if my_desc != {}:
self.errors.update(my_desc)
except:
pass
my_desc = {}
try:
from PyIRCIoT.irciot_errors \
import irciot_get_EL_error_descriptions_
my_desc.update(irciot_get_EL_error_descriptions_(in_lang))
my_desc = self.validate_descriptions_(my_desc)
if my_desc != {}:
self.errors.update(my_desc)
except:
pass
def irciot_EL_error_(self, in_error_code, in_addon):
if in_error_code in self.errors.keys():
my_descr = self.errors[in_error_code]
if isinstance(in_addon, str):
my_descr += " ({})".format(in_addon)
else:
return
if not self._silence:
print(self.errors[self.CONST.err_EL_ERROR].format(in_error_code), my_descr)
#
# End of irciot_EL_error_()
def irciot_EL_check_lang_(self, in_lang):
if not isinstance(in_lang, str):
return False
if in_lang not in self.CONST_EL_.lang_ALL:
return False
return True
def irciot_EL_set_timeout_(in_timeout):
if not isinstance(in_timeout, int): return
self.__execution_timeout = in_timeout
def irciot_EL_set_code_size_(in_size):
if not isinstance(in_size, int): return
self.__maximal_code_size = in_size
# incomplete
def irciot_EL_check_environment_(self, in_lang, in_environment):
if not self.irciot_EL_check_lang_(in_lang):
return False
if not isinstance(in_environment, dict):
return False
for my_key in in_environment.keys():
if not isinstance(my_key, str):
return False
if my_key == "":
return False
if my_key[0] not in self.CONST.environment_first_chars:
return False
for my_char in my_key:
if my_char not in self.CONST.environment_second_chars:
return False
my_item = in_environment[my_key]
if not isinstance(my_item, str):
return False
return True
def irciot_EL_check_matchers_(self, in_code, in_matchers):
if not isinstance(in_matchers, list):
return True
for my_re in in_matchers:
if my_re.match(in_code):
self.irciot_EL_error_(self.CONST.err_LANGUAGE_FILTER, None)
return False
return True
# incomplete
def irciot_EL_check_BASIC_code_(self, in_code):
if not self.irciot_EL_check_matchers_(in_code, self.__BASIC_filter_matchers):
return False
return True
# incomplete
def irciot_EL_check_Java_code_(self, in_code):
if not self.irciot_EL_check_matchers_(in_code, self.__JAVA_filter_matchers):
return False
return True
# incomplete
def irciot_EL_check_JS_code_(self, in_code):
if not self.irciot_EL_check_matchers_(in_code, self.__JS_filter_matchers):
return False
return True
# incomplete
def irciot_EL_check_LUA_code_(self, in_code):
if not self.irciot_EL_check_matchers_(in_code, self.__LUA_filter_matchers):
return False
return True
# incomplete
def irciot_EL_check_PHP_code_(self, in_code):
if not self.irciot_EL_check_matchers_(in_code, self.__PHP_filter_matchers):
return False
# Warning: This code is only for testing of phply library... will be removed
my_lexer = self.__PHPLEX.lexer.clone()
my_lexer.input("<?php " + in_code + "?>")
my_error = None
while True:
try:
my_tok = my_lexer.token()
if not my_tok:
break
except:
my_error = self.errors[self.CONST.LEXICAL_ANALISIS]
break
if my_tok.type not in self.CONST.lang_filter_PHP_tokens:
my_error = "ivalid " + str(my_tok)
break
if my_error != None:
self.irciot_EL_error_(self.CONST.err_LANGUAGE_SYNTAX, my_error)
# It's not a syntax it's lexic, but we could say so ...
return False
return True
# incomplete
def irciot_EL_check_TCL_code_(self, in_code):
class TCL_checker_(ast.NodeVisitor):
def check(self, in_code):
pass
def visit(self, in_node):
pass
if not self.irciot_EL_check_matchers_(in_code, self.__TCL_filter_matchers):
return False
return True
# incomplete
def irciot_EL_check_Python_code_(self, in_code):
class Python_checker_(ast.NodeVisitor):
def check(self, in_code):
self.visit(ast.parse(in_code))
def visit_Call(self, in_node):
if in_node.func.id in self.CONST.lang_filter_PYTHON_funcs:
ast.NodeVisitor.generic_visit(self, in_node)
else:
raise SyntaxError(self.errors[self.CONST.err_ILLEGAL_FUNCT].format( \
in_node.func.id))
def visit_Name(self, in_node):
try:
eval(in_node.id)
except NameError:
ast.NodeVisitor.generic_visit(self, in_node)
else:
if in_node.id in self.CONST.lang_filter_PYTHON_names:
ast.NodeVisitor.generic_visit(self, in_node)
else:
raise SyntaxError(self.errors[self.CONST.err_RESERVED_NAME].format( \
in_node.id))
def visit_Import(self, in_node):
raise SyntaxError(self.errors[self.CONST.err_ILLEGAL_IMPORT])
def visit_ImportFrom(self, in_node):
raise SyntaxError(self.errors[self.CONST.err_ILLEGAL_IMPORTF])
def generic_visit(self, in_node):
if type(in_node).__name__ in self.CONST.lang_filter_PYTHON_types:
ast.NodeVisitor.generic_visit(self, in_node)
else:
raise SyntaxError(self.errors[self.CONST.err_ILLEGAL_TYPE].format( \
type(in_node).__name__))
if not self.irciot_EL_check_matchers_(in_code, self.__PYTHON_filter_matchers):
return False
my_check = Python_checker_();
my_check.CONST = self.CONST
my_check.errors = self.errors
try:
my_line = in_code.replace(r'[\r\n]', ';')
my_check.check(my_line)
except Exception as my_ex:
self.irciot_EL_error_(self.CONST.err_LANGUAGE_SYNTAX, str(my_ex))
return False
return True
#
# End of irciot_EL_check_Python_code_()
# incomplete
def irciot_EL_check_Ruby_code_(self, in_code):
if not self.irciot_EL_check_matchers_(in_code, self.__RUBY_filter_matchers):
return False
return True
# incomplete
def irciot_EL_check_R_code_(self, in_code):
if not self.irciot_EL_check_matchers_(in_code, self.__R_filter_matchers):
return False
return True
# incomplete
def __irciot_EL_run_Python_code_(self, in_code, in_environment):
my_dict = {}
my_MATH = self.irciot_EL_import_(self.CONST.mod_MATH)
for my_name in self.CONST.lang_filter_PYTHON_maths:
my_dict[ my_name ] = getattr(my_MATH, my_name)
for my_name in self.CONST.lang_filter_PYTHON_funcs:
if my_name not in self.CONST.lang_filter_PYTHON_maths:
my_dict[ my_name ] = eval(compile(my_name, '<str>', 'eval'))
for my_key in in_environment.keys():
my_value = in_environment[ my_key ]
if isinstance(my_value, str):
my_dict[ my_key ] = my_value
with self.python_stdout_() as my_out:
exec(in_code, { '__builtins__': None }, my_dict)
del my_MATH
return my_out.getvalue()
#
# End of __irciot_EL_run_Python_code_()
return None
#
# End of __irciot_EL_run_Ruby_code_()
# incomplete
def __irciot_EL_run_R_code_(self, in_code, in_environment = {}):
my_error = None
with self.python_stdout_() as my_out:
try:
self.__R_ROBJ.r(in_code)
except self.__R_INTF.RRuntimeError as my_ex:
my_split = str(my_ex).replace("\n", " ").split(':')
del my_split[0]
my_error = ""
for my_idx in range(len(my_split)):
my_error += " " + my_split[my_idx]
while " " in my_error:
my_error = my_error.replace(" ", " ")
except Exception as my_ex:
my_error = self.errors[self.CONST.err_UNKNOWN] \
+ ": {}".format(my_ex)
if isinstance(my_error, str):
self.irciot_EL_error_(self.CONST.err_CODE_EXECUTION, \
my_error.lstrip().rstrip())
return None
my_out = my_out.getvalue()
for my_rep in [ ( '\n\n\n[1]\n ', '\n' ),
( '[1]\n ', ''), ( '\n', '') ]:
my_out = my_out.replace(my_rep[0], my_rep[1])
return my_out
#
# End of __irciot_EL_run_R_code_()
# incomplete
def irciot_EL_run_code_(self, in_lang, in_code, in_environment = {}):
def __timeout_signal_(in_signal, in_frame):
self.__timeout_termination_()
if not self.irciot_EL_check_code_(in_lang, in_code):
return ""
if not self.irciot_EL_check_environment_(in_lang, in_environment):
self.irciot_EL_error_(self.CONST.err_BAD_ENVIRONMENT, None)
return ""
if CAN_debug_library:
self.irciot_EL_error_(self.CONST.err_DEVEL, "EL")
my_out = None
if self.__os_name == self.CONST.os_windows:
pass # Need a method to stop the script by timeout in the Windows
else:
signal.signal(signal.SIGALRM, __timeout_signal_)
signal.alarm(self.__execution_timeout)
try:
if in_lang == self.CONST.lang_ANSYML:
my_out = self.__irciot_EL_run_ANSYML_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_BASH:
my_out = self.__irciot_EL_run_BASH_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_BASIC:
my_out = self.__irciot_EL_run_BASIC_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_CSP:
pass
elif in_lang == self.CONST.lang_GO:
pass
elif in_lang == self.CONST.lang_JRE:
my_out = self.__irciot_EL_run_JAVA_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_JS:
my_out = self.__irciot_EL_run_JS_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_LUA:
my_out = self.__irciot_EL_run_LUA_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_PERL:
pass
elif in_lang == self.CONST.lang_PHP:
my_out = self.__irciot_EL_run_PHP_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_R:
my_out = self.__irciot_EL_run_R_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_PYTHON:
my_out = self.__irciot_EL_run_Python_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_RUBY:
my_out = self.__irciot_EL_run_Ruby_code_(in_code, in_environment)
elif in_lang == self.CONST.lang_SWIFT:
pass
elif in_lang == self.CONST.lang_TCL:
my_out = self.__irciot_EL_run_TCL_code_(in_code, in_environment)
except Exception as my_ex:
self.irciot_EL_error_(self.CONST.err_CODE_EXECUTION, str(my_ex))
if self.__os_name != self.CONST.os_windows:
signal.alarm(0)
if my_out == None:
my_out = ""
elif not isinstance(my_out, str):
my_out = str(my_out)
return my_out
#
# End of irciot_EL_run_code_()
def irciot_EL_import_(self, in_module_name):
import importlib
try:
return importlib.import_module(in_module_name)
except ImportError:
self.irciot_EL_error_(self.CONST.err_LOADING_MODULES, None)
return None
#
# End of irciot_EL_import_()
def irciot_EL_admit_language_(self, in_lang):
if in_lang in self.__allowed_EL:
return True
elif self.irciot_EL_check_lang_(in_lang):
self.__allowed_EL += [ in_lang ]
return True
return False
def irciot_EL_revoke_language_(self, in_lang):
if in_lang in self.__allowed_EL:
self.irciot_EL_finish_language_(in_lang)
self.__allowed_EL.remove(in_lang)
def irciot_EL_finish_language_(self, in_lang):
''' This method terminates the processes necessary for the
given Embedded Language to work and frees memory
in: in_lang -- Embedded Language ID of 'str' type
out: value with type 'bool', True when successfuly finished
'''
if not self.irciot_EL_check_lang_(in_lang):
return False
try:
if in_lang == self.CONST.lang_ANSYML:
del self.__ANSVAR
del self.__ANSINV
del self.__ANSTQM
del self.__ANSPLY
del self.__ANSLDR
del self.__ANSCBP
self.__ansible_vault_password \
= self.wipe_string_(self.__ansible_vault_password)
self.__ansible_vault_password = None
elif in_lang == self.CONST.lang_BASH:
del self.__BSHLEX
del self.__BASH_filter_matchers
elif in_lang == self.CONST.lang_BASIC:
del self.__BASTOK
del self.__BASLEX
del self.__BASPRG
del self.__BASIC_filter_matchers
elif in_lang == self.CONST.lang_CSP:
pass
elif in_lang == self.CONST.lang_GO:
pass
elif in_lang == self.CONST.lang_JRE:
del self.__JRE
del self.__JAVA_filter_matchers
elif in_lang == self.CONST.lang_JS:
del self.__JS
del self.__JS_filter_matchers
elif in_lang == self.CONST.lang_LUA:
del self.__LUA
del self.__LUA_filter_matchers
elif in_lang == self.CONST.lang_PERL:
pass
elif in_lang == self.CONST.lang_PHP:
del self.__PHPLEX
del self.__PHP_filter_matchers
elif in_lang == self.CONST.lang_R:
del self.__R_ROBJ
del self.__R_INTF
del self.__R_filter_matchers
elif in_lang == self.CONST.lang_PYTHON:
del self.__PYTHON_filter_matchers
elif in_lang == self.CONST.lang_RUBY:
del self.__RUBY_filter_matchers
elif in_lang == self.CONST.lang_SWIFT:
pass
elif in_lang == self.CONST.lang_TCL:
del self.__TCL
del self.__TCL_filter_matchers
except:
return False
return True
#
# End of irciot_EL_finish_language_()