/* * JavaScript extension. * Copyright (c) 1998 New Generation Software (NGS) Oy * * Author: Markku Rossi <mtr@ngs.fi> */ /* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA */ /* * $Source: /tmp/cvsroot-15-2-2007/clamav-devel/libclamav/js/xjs.c,v $ * $Id: xjs.c,v 1.3 2006/10/28 11:27:44 njh Exp $ */ #if HAVE_CONFIG_H #include "clamav-config.h" #endif #ifdef CL_EXPERIMENTAL #include "js/js.h" #include "js/jsint.h" /* * Types and definitions. */ /* Class context. */ struct xjs_ctx_st { /* Methods. */ JSSymbol s_compile; JSSymbol s_eval; JSSymbol s_evalFile; JSSymbol s_evalJavaScriptFile; JSSymbol s_executeByteCodeFile; JSSymbol s_getVar; JSSymbol s_setVar; /* Properties. */ JSSymbol s_errorMessage; }; typedef struct xjs_ctx_st XJSCtx; /* Instance context. */ struct xjs_instance_ctx_st { JSInterpPtr interp; }; typedef struct xjs_instance_ctx_st XJSInstanceCtx; /* * Static functions. */ static void copy_from_type_to_node (JSVirtualMachine *vm, JSNode *to, JSType *from) { int i; switch (from->type) { case JS_TYPE_NULL: to->type = JS_NULL; break; case JS_TYPE_BOOLEAN: to->type = JS_BOOLEAN; to->u.vboolean = from->u.i; break; case JS_TYPE_INTEGER: to->type = JS_INTEGER; to->u.vinteger = from->u.i; break; case JS_TYPE_STRING: js_vm_make_string (vm, to, from->u.s->data, from->u.s->len); break; case JS_TYPE_DOUBLE: to->type = JS_FLOAT; to->u.vfloat = from->u.d; break; case JS_TYPE_ARRAY: js_vm_make_array (vm, to, from->u.array->length); for (i = 0; i < from->u.array->length; i++) copy_from_type_to_node (vm, &to->u.varray->data[i], &from->u.array->data[i]); break; default: to->type = JS_UNDEFINED; break; } } static void copy_from_node_to_type (JSInterpPtr interp, JSType *to, JSNode *from) { int i; switch (from->type) { case JS_NULL: to->type = JS_TYPE_NULL; break; case JS_BOOLEAN: to->type = JS_TYPE_BOOLEAN; to->u.i = from->u.vboolean; break; case JS_INTEGER: to->type = JS_TYPE_INTEGER; to->u.i = from->u.vinteger; break; case JS_STRING: js_type_make_string (interp, to, from->u.vstring->data, from->u.vstring->len); break; case JS_FLOAT: to->type = JS_TYPE_DOUBLE; to->u.d = from->u.vfloat; break; case JS_ARRAY: js_type_make_array (interp, to, from->u.varray->length); for (i = 0; i < from->u.varray->length; i++) copy_from_node_to_type (interp, &to->u.array->data[i], &from->u.varray->data[i]); break; default: to->type = JS_TYPE_UNDEFINED; break; } } /* Method proc. */ static int method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info, void *instance_context, JSSymbol method, JSNode *result_return, JSNode *args) { XJSCtx *ctx = builtin_info->obj_context; XJSInstanceCtx *instance = instance_context; /* The default result is false. */ result_return->type = JS_BOOLEAN; result_return->u.vboolean = 0; /* * Static methods. */ if (method == vm->syms.s_toString) { if (args->u.vinteger != 0) goto argument_error; if (instance) js_vm_make_static_string (vm, result_return, "JSInterp", 8); else js_vm_make_static_string (vm, result_return, "JS", 2); } /* ********************************************************************** */ else if (instance) { /* * Instance methods. */ if (method == ctx->s_compile) { if (args->u.vinteger != 3) goto argument_error; if (args[1].type != JS_STRING || (args[2].type != JS_NULL && args[2].type != JS_STRING) || (args[3].type != JS_NULL && args[3].type != JS_STRING)) goto argument_type_error; } /* ***************************************************************** */ else if (method == ctx->s_eval) { if (args->u.vinteger != 1) goto argument_error; if (args[1].type != JS_STRING) goto argument_type_error; result_return->type = JS_BOOLEAN; result_return->u.vboolean = (js_eval_data (instance->interp, args[1].u.vstring->data, args[1].u.vstring->len) != 0); } /* ***************************************************************** */ else if (method == ctx->s_evalFile) { char *path; if (args->u.vinteger != 1) goto argument_error; if (args[1].type != JS_STRING) goto argument_type_error; path = js_string_to_c_string (vm, &args[1]); result_return->type = JS_BOOLEAN; result_return->u.vboolean = (js_eval_file (instance->interp, path) != 0); js_free (path); } /* ***************************************************************** */ else if (method == ctx->s_evalJavaScriptFile) { char *path; if (args->u.vinteger != 1) goto argument_error; if (args[1].type != JS_STRING) goto argument_type_error; path = js_string_to_c_string (vm, &args[1]); result_return->type = JS_BOOLEAN; result_return->u.vboolean = (js_eval_javascript_file (instance->interp, path) != 0); js_free (path); } /* ***************************************************************** */ else if (method == ctx->s_executeByteCodeFile) { char *path; if (args->u.vinteger != 1) goto argument_error; if (args[1].type != JS_STRING) goto argument_type_error; path = js_string_to_c_string (vm, &args[1]); result_return->type = JS_BOOLEAN; result_return->u.vboolean = (js_execute_byte_code_file (instance->interp, path) != 0); js_free (path); } /* ***************************************************************** */ else if (method == ctx->s_getVar) { char *cp; JSType value; if (args->u.vinteger != 1) goto argument_error; if (args[1].type != JS_STRING) goto argument_type_error; cp = js_string_to_c_string (vm, &args[1]); js_get_var (instance->interp, cp, &value); js_free (cp); copy_from_type_to_node (vm, result_return, &value); } /* ***************************************************************** */ else if (method == ctx->s_setVar) { char *cp; JSType value; if (args->u.vinteger != 2) goto argument_error; if (args[1].type != JS_STRING) goto argument_type_error; copy_from_node_to_type (instance->interp, &value, &args[2]); cp = js_string_to_c_string (vm, &args[1]); js_set_var (instance->interp, cp, &value); js_free (cp); result_return->type = JS_UNDEFINED; } /* ***************************************************************** */ else return JS_PROPERTY_UNKNOWN; } /* ********************************************************************** */ else return JS_PROPERTY_UNKNOWN; return JS_PROPERTY_FOUND; /* * Error handling. */ argument_error: sprintf (vm->error, "JS.%s(): illegal amount of arguments", js_vm_symname (vm, method)); js_vm_error (vm); argument_type_error: sprintf (vm->error, "JS.%s(): illegal argument", js_vm_symname (vm, method)); js_vm_error (vm); /* NOTREACHED */ return 0; } /* Property proc. */ static int property (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info, void *instance_context, JSSymbol method, int set, JSNode *node) { XJSCtx *ctx = builtin_info->obj_context; XJSInstanceCtx *instance = instance_context; if (method == ctx->s_errorMessage) { char *cp = instance->interp->vm->error; if (set) goto immutable; js_vm_make_string (vm, node, cp, strlen (cp)); } else { if (!set) node->type = JS_UNDEFINED; return JS_PROPERTY_UNKNOWN; } return JS_PROPERTY_FOUND; /* * Error handling. */ immutable: sprintf (vm->error, "JS.%s: immutable property", js_vm_symname (vm, method)); js_vm_error (vm); /* NOTREACHED. */ return 0; } /* New proc. */ static void new_proc (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info, JSNode *args, JSNode *result_return) { XJSInstanceCtx *instance; JSInterpOptions options; if (args->u.vinteger != 0) { sprintf (vm->error, "new JS(): illegal amount of arguments"); js_vm_error (vm); } instance = js_calloc (vm, 1, sizeof (*instance)); js_init_default_options (&options); instance->interp = js_create_interp (&options); js_vm_builtin_create (vm, result_return, builtin_info, instance); } /* Delete proc. */ static void delete_proc (JSBuiltinInfo *builtin_info, void *instance_context) { XJSInstanceCtx *instance = instance_context; if (instance) { js_destroy_interp (instance->interp); js_free (instance); } } /* * Global functions. */ void js_ext_JS (JSInterpPtr interp) { JSNode *n; JSBuiltinInfo *info; JSSymbol sym; XJSCtx *ctx; JSVirtualMachine *vm = interp->vm; ctx = js_calloc (vm, 1, sizeof (*ctx)); ctx->s_compile = js_vm_intern (vm, "compile"); ctx->s_eval = js_vm_intern (vm, "eval"); ctx->s_evalFile = js_vm_intern (vm, "evalFile"); ctx->s_evalJavaScriptFile = js_vm_intern (vm, "evalJavaScriptFile"); ctx->s_executeByteCodeFile = js_vm_intern (vm, "executeByteCodeFile"); ctx->s_getVar = js_vm_intern (vm, "getVar"); ctx->s_setVar = js_vm_intern (vm, "setVar"); ctx->s_errorMessage = js_vm_intern (vm, "errorMessage"); /* Object information. */ info = js_vm_builtin_info_create (vm); info->method_proc = method; info->property_proc = property; info->new_proc = new_proc; info->delete_proc = delete_proc; info->obj_context = ctx; info->obj_context_delete = js_free; /* Define it. */ sym = js_vm_intern (vm, "JS"); n = &vm->globals[sym]; js_vm_builtin_create (vm, n, info, NULL); } #endif /*CL_EXPERIMENTAL*/