📄 swfdec_as_context.c
字号:
if (pc + 2 >= endpc) { SWFDEC_ERROR ("action %u length value out of range", action); goto error; } data = pc + 3; len = pc[1] | pc[2] << 8; if (data + len > endpc) { SWFDEC_ERROR ("action %u length %u out of range", action, len); goto error; } nextpc = pc + 3 + len; } else { data = NULL; len = 0; nextpc = pc + 1; } /* check action is valid */ exec = spec->exec[version]; if (!exec) { guint real_version; for (real_version = version + 1; !exec && real_version <= SWFDEC_AS_MAX_SCRIPT_VERSION - SWFDEC_AS_MIN_SCRIPT_VERSION; real_version++) { exec = spec->exec[real_version]; } if (!exec) { SWFDEC_WARNING ("cannot interpret action %3u 0x%02X %s for version %u, skipping it", action, action, spec->name ? spec->name : "Unknown", script->version); frame->pc = pc = nextpc; check_scope = TRUE; continue; } SWFDEC_WARNING ("cannot interpret action %3u 0x%02X %s for version %u, using version %u instead", action, action, spec->name ? spec->name : "Unknown", script->version, script->version + real_version - version); } if (spec->remove > 0) { if (spec->add > spec->remove) swfdec_as_stack_ensure_free (context, spec->add - spec->remove); swfdec_as_stack_ensure_size (context, spec->remove); } else { if (spec->add > 0) swfdec_as_stack_ensure_free (context, spec->add); } if (context->state > SWFDEC_AS_CONTEXT_RUNNING) { SWFDEC_WARNING ("context not running anymore, aborting"); goto error; }#ifndef G_DISABLE_ASSERT check = (spec->add >= 0 && spec->remove >= 0) ? context->cur + spec->add - spec->remove : NULL;#endif /* execute action */ exec (context, action, data, len); /* adapt the pc if the action did not, otherwise, leave it alone */ /* FIXME: do this via flag? */ if (frame->pc == pc) { frame->pc = pc = nextpc; check_scope = TRUE; } else { pc = frame->pc; check_scope = FALSE; } if (frame == context->frame) {#ifndef G_DISABLE_ASSERT if (check != NULL && check != context->cur) { g_error ("action %s was supposed to change the stack by %d (+%d -%d), but it changed by %td", spec->name, spec->add - spec->remove, spec->add, spec->remove, context->cur - check + spec->add - spec->remove); }#endif } else { /* someone called/returned from a function, reread variables */ goto start; } }error: while (context->frame != context->last_frame) swfdec_as_frame_return (context->frame, NULL);out: context->last_frame = last_frame; return;}/*** EVAL ***/static char *swfdec_as_slash_to_dot (const char *slash_str){ const char *cur = slash_str; GString *str = g_string_new (""); if (*cur == '/') { g_string_append (str, "_root"); } else { goto start; } while (cur && *cur == '/') { cur++;start: if (str->len > 0) g_string_append_c (str, '.'); if (cur[0] == '.' && cur[1] == '.') { g_string_append (str, "_parent"); cur += 2; } else { char *slash = strchr (cur, '/'); if (slash) { g_string_append_len (str, cur, slash - cur); cur = slash; } else { g_string_append (str, cur); cur = NULL; } } /* cur should now point to the slash */ } if (cur) { if (*cur != '\0') goto fail; } SWFDEC_DEBUG ("parsed slash-notated string \"%s\" into dot notation \"%s\"", slash_str, str->str); return g_string_free (str, FALSE);fail: SWFDEC_WARNING ("failed to parse slash-notated string \"%s\" into dot notation", slash_str); g_string_free (str, TRUE); return NULL;}static voidswfdec_as_context_eval_get_property (SwfdecAsContext *cx, SwfdecAsObject *obj, const char *name, SwfdecAsValue *ret){ if (obj) { swfdec_as_object_get_variable (obj, name, ret); } else { if (cx->frame) { obj = swfdec_as_frame_find_variable (cx->frame, name); if (obj) { swfdec_as_object_get_variable (obj, name, ret); return; } } else { SWFDEC_WARNING ("eval called without a frame"); swfdec_as_object_get_variable (cx->global, name, ret); } SWFDEC_AS_VALUE_SET_UNDEFINED (ret); }}static voidswfdec_as_context_eval_set_property (SwfdecAsContext *cx, SwfdecAsObject *obj, const char *name, const SwfdecAsValue *ret){ if (obj == NULL) { if (cx->frame == NULL) { SWFDEC_ERROR ("no frame in eval_set?"); return; } obj = swfdec_as_frame_find_variable (cx->frame, name); if (obj == NULL || obj == cx->global) obj = cx->frame->target; } swfdec_as_object_set_variable (obj, name, ret);}static voidswfdec_as_context_eval_internal (SwfdecAsContext *cx, SwfdecAsObject *obj, const char *str, SwfdecAsValue *val, gboolean set){ SwfdecAsValue cur; char **varlist; guint i; SWFDEC_LOG ("eval called with \"%s\" on %p", str, obj); if (strchr (str, '/')) { char *work = swfdec_as_slash_to_dot (str); if (!work) { SWFDEC_AS_VALUE_SET_UNDEFINED (val); return; } varlist = g_strsplit (work, ".", -1); g_free (work); } else { varlist = g_strsplit (str, ".", -1); } for (i = 0; varlist[i] != NULL; i++) { const char *dot = swfdec_as_context_get_string (cx, varlist[i]); if (varlist[i+1] != NULL) { swfdec_as_context_eval_get_property (cx, obj, dot, &cur); if (!SWFDEC_AS_VALUE_IS_OBJECT (&cur)) { SWFDEC_AS_VALUE_SET_UNDEFINED (&cur); break; } obj = SWFDEC_AS_VALUE_GET_OBJECT (&cur); } else { if (set) { swfdec_as_context_eval_set_property (cx, obj, dot, val); } else { swfdec_as_context_eval_get_property (cx, obj, dot, &cur); } goto finish; } } if (obj == NULL) { if (cx->frame) obj = cx->frame->target; else obj = cx->global; } g_assert (obj != NULL); SWFDEC_AS_VALUE_SET_OBJECT (&cur, obj);finish: g_strfreev (varlist); *val = cur;}/** * swfdec_as_context_eval: * @context: a #SwfdecAsContext * @obj: #SwfdecAsObject to use as source for evaluating or NULL for the * current frame's scope * @str: The string to evaluate * @val: location for the return value * * This function works like the Actionscript eval function used on @obj. * It handles both slash-style and dot-style notation. If an error occured * during evaluation, the return value will be the undefined value. **/voidswfdec_as_context_eval (SwfdecAsContext *context, SwfdecAsObject *obj, const char *str, SwfdecAsValue *val){ g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context)); g_return_if_fail (obj == NULL || SWFDEC_IS_AS_OBJECT (obj)); g_return_if_fail (str != NULL); g_return_if_fail (val != NULL); swfdec_as_context_eval_internal (context, obj, str, val, FALSE);}/** * swfdec_as_context_eval_set: * @context: a #SwfdecAsContext * @obj: #SwfdecAsObject to use as source for evaluating or NULL for the * default object. * @str: The string to evaluate * @val: the value to set the variable to * * Sets the variable referenced by @str to @val. If @str does not reference * a valid property, nothing happens. **/voidswfdec_as_context_eval_set (SwfdecAsContext *context, SwfdecAsObject *obj, const char *str, const SwfdecAsValue *val){ g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context)); g_return_if_fail (obj == NULL || SWFDEC_IS_AS_OBJECT (obj)); g_return_if_fail (str != NULL); g_return_if_fail (val != NULL); swfdec_as_context_eval_internal (context, obj, str, (SwfdecAsValue *) val, TRUE);}/*** AS CODE ***/static voidswfdec_as_context_ASSetPropFlags_set_one_flag (SwfdecAsObject *object, const char *s, guint *flags){ swfdec_as_object_unset_variable_flags (object, s, flags[1]); swfdec_as_object_set_variable_flags (object, s, flags[0]);}static gbooleanswfdec_as_context_ASSetPropFlags_foreach (SwfdecAsObject *object, const char *s, SwfdecAsValue *val, guint cur_flags, gpointer data){ guint *flags = data; /* shortcut if the flags already match */ if (cur_flags == ((cur_flags &~ flags[1]) | flags[0])) return TRUE; swfdec_as_context_ASSetPropFlags_set_one_flag (object, s, flags); return TRUE;}static voidswfdec_as_context_ASSetPropFlags (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval){ guint flags[2]; /* flags and mask - array so we can pass it as data pointer */ SwfdecAsObject *obj; if (cx->version < 6) { SWFDEC_FIXME ("ASSetPropFlags needs some limitations for Flash 5"); } if (!SWFDEC_AS_VALUE_IS_OBJECT (&argv[0])) return; obj = SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]); flags[0] = swfdec_as_value_to_integer (cx, &argv[2]); flags[1] = (argc > 3) ? swfdec_as_value_to_integer (cx, &argv[3]) : 0; if (flags[0] == 0 && flags[1] == 0) { // we should add autosizing length attribute here SWFDEC_FIXME ("ASSetPropFlags to set special length attribute not implemented"); return; } if (SWFDEC_AS_VALUE_IS_NULL (&argv[1])) { swfdec_as_object_foreach (obj, swfdec_as_context_ASSetPropFlags_foreach, flags); } else { char **split = g_strsplit (swfdec_as_value_to_string (cx, &argv[1]), ",", -1); guint i; for (i = 0; split[i]; i++) { swfdec_as_context_ASSetPropFlags_set_one_flag (obj, swfdec_as_context_get_string (cx, split[i]), flags); } g_strfreev (split); }}static voidswfdec_as_context_isFinite (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval){ double d = swfdec_as_value_to_number (cx, &argv[0]); SWFDEC_AS_VALUE_SET_BOOLEAN (retval, isfinite (d) ? TRUE : FALSE);}static voidswfdec_as_context_isNaN (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval){ double d = swfdec_as_value_to_number (cx, &argv[0]); SWFDEC_AS_VALUE_SET_BOOLEAN (retval, isnan (d) ? TRUE : FALSE);}static voidswfdec_as_context_parseInt (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval){ int i = swfdec_as_value_to_integer (cx, &argv[0]); SWFDEC_AS_VALUE_SET_INT (retval, i);}static voidswfdec_as_context_init_global (SwfdecAsContext *context, guint version){ SwfdecAsValue val; swfdec_as_object_add_function (context->global, SWFDEC_AS_STR_ASSetPropFlags, 0, swfdec_as_context_ASSetPropFlags, 3); SWFDEC_AS_VALUE_SET_NUMBER (&val, NAN); swfdec_as_object_set_variable (context->global, SWFDEC_AS_STR_NaN, &val); SWFDEC_AS_VALUE_SET_NUMBER (&val, HUGE_VAL); swfdec_as_object_set_variable (context->global, SWFDEC_AS_STR_Infinity, &val); swfdec_as_object_add_function (context->global, SWFDEC_AS_STR_isFinite, 0, swfdec_as_context_isFinite, 1); swfdec_as_object_add_function (context->global, SWFDEC_AS_STR_isNaN, 0, swfdec_as_context_isNaN, 1); swfdec_as_object_add_function (context->global, SWFDEC_AS_STR_parseInt, 0, swfdec_as_context_parseInt, 1);}/** * swfdec_as_context_startup: * @context: a #SwfdecAsContext * @version: Flash version to use * * Starts up the context. This function must be called before any Actionscript * is called on @context. The version is responsible for deciding which native * functions and properties are available in the context. **/voidswfdec_as_context_startup (SwfdecAsContext *context, guint version){ g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context)); g_return_if_fail (context->state == SWFDEC_AS_CONTEXT_NEW); if (!swfdec_as_stack_push_segment (context)) return; context->version = version; /* get the necessary objects up to define objects and functions sanely */ swfdec_as_function_init_context (context, version); swfdec_as_object_init_context (context, version); /* define the global object and other important ones */ swfdec_as_context_init_global (context, version); swfdec_as_array_init_context (context, version); /* define the type objects */ swfdec_as_boolean_init_context (context, version); swfdec_as_number_init_context (context, version); swfdec_as_string_init_context (context, version); /* define the rest */ swfdec_as_math_init_context (context, version); if (context->state == SWFDEC_AS_CONTEXT_NEW) context->state = SWFDEC_AS_CONTEXT_RUNNING;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -