📄 swfdec_as_interpret.c
字号:
swfdec_as_interpret_eval (SwfdecAsContext *cx, SwfdecAsObject *obj, SwfdecAsValue *val){ if (SWFDEC_AS_VALUE_IS_STRING (val)) { const char *s = SWFDEC_AS_VALUE_GET_STRING (val); if (s != SWFDEC_AS_STR_EMPTY) { swfdec_as_context_eval (cx, obj, s, val); return s; } } if (obj != NULL) SWFDEC_AS_VALUE_SET_OBJECT (val, obj); else SWFDEC_AS_VALUE_SET_UNDEFINED (val); return SWFDEC_AS_STR_EMPTY;}/* FIXME: this sucks */extern struct { gboolean needs_movie; const char * name; /* GC'd */ void (* get) (SwfdecMovie *movie, SwfdecAsValue *ret); void (* set) (SwfdecMovie *movie, const SwfdecAsValue *val);} swfdec_movieclip_props[];static voidswfdec_action_get_property (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *val; SwfdecAsObject *obj; guint id; id = swfdec_as_value_to_integer (cx, swfdec_as_stack_pop (cx)); if (id > (cx->version > 4 ? 21 : 18)) { SWFDEC_WARNING ("trying to SetProperty %u, not allowed", id); goto out; } val = swfdec_as_stack_peek (cx, 1); swfdec_as_interpret_eval (cx, NULL, val); if (SWFDEC_AS_VALUE_IS_UNDEFINED (val)) { obj = cx->frame->target; } else if (SWFDEC_AS_VALUE_IS_OBJECT (val)) { obj = SWFDEC_AS_VALUE_GET_OBJECT (val); } else { SWFDEC_WARNING ("not an object, can't GetProperty"); goto out; } swfdec_as_object_get_variable (obj, swfdec_movieclip_props[id].name, swfdec_as_stack_peek (cx, 1)); return;out: SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 1));}static voidswfdec_action_set_property (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *val; SwfdecAsObject *obj; guint id; id = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 2)); if (id > (cx->version > 4 ? 21 : 18)) { SWFDEC_WARNING ("trying to SetProperty %u, not allowed", id); goto out; } val = swfdec_as_stack_peek (cx, 3); swfdec_as_interpret_eval (cx, NULL, val); if (SWFDEC_AS_VALUE_IS_UNDEFINED (val)) { obj = cx->frame->target; } else if (SWFDEC_AS_VALUE_IS_OBJECT (val)) { obj = SWFDEC_AS_VALUE_GET_OBJECT (val); } else { SWFDEC_WARNING ("not an object, can't get SetProperty"); goto out; } swfdec_as_object_set_variable (obj, swfdec_movieclip_props[id].name, swfdec_as_stack_peek (cx, 1));out: swfdec_as_stack_pop_n (cx, 3);}static voidswfdec_action_get_member (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsObject *object = swfdec_as_value_to_object (cx, swfdec_as_stack_peek (cx, 2)); if (object) { const char *name; name = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 1)); swfdec_as_object_get_variable (object, name, swfdec_as_stack_peek (cx, 2));#ifdef SWFDEC_WARN_MISSING_PROPERTIES if (SWFDEC_AS_VALUE_IS_UNDEFINED (swfdec_as_stack_peek (cx, 2))) { SWFDEC_WARNING ("no variable named %s:%s", G_OBJECT_TYPE_NAME (object), name); }#endif } else { SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 2)); } swfdec_as_stack_pop (cx);}static voidswfdec_action_set_member (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ if (SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (cx, 3))) { const char *name = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 2)); swfdec_as_object_set_variable (SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (cx, 3)), name, swfdec_as_stack_peek (cx, 1)); } swfdec_as_stack_pop_n (cx, 3);}static voidswfdec_action_trace (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *val; const char *s; val = swfdec_as_stack_peek (cx, 1); if (val->type == SWFDEC_AS_TYPE_UNDEFINED) { s = SWFDEC_AS_STR_undefined; } else if (val->type == SWFDEC_AS_TYPE_OBJECT && SWFDEC_IS_AS_STRING (swfdec_as_value_to_object (cx, val))) { s = SWFDEC_AS_STRING (swfdec_as_value_to_object (cx, val))->string; } else { s = swfdec_as_value_to_string (cx, val); } swfdec_as_stack_pop (cx); g_signal_emit_by_name (cx, "trace", s);}/* stack looks like this: [ function, this, arg1, arg2, ... ] *//* stack must be at least 2 elements big */static gbooleanswfdec_action_call (SwfdecAsContext *cx, guint n_args){ SwfdecAsFunction *fun; SwfdecAsObject *thisp; if (!SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (cx, 1))) goto error; fun = (SwfdecAsFunction *) SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (cx, 1)); if (!SWFDEC_IS_AS_FUNCTION (fun)) goto error; if (!SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (cx, 2))) { thisp = NULL; } else { thisp = SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (cx, 2)); } swfdec_as_stack_pop_n (cx, 2); /* sanitize argument count */ if (n_args >= swfdec_as_stack_get_size (cx)) n_args = swfdec_as_stack_get_size (cx); swfdec_as_function_call (fun, thisp, n_args, NULL, NULL); if (SWFDEC_IS_AS_SUPER (fun)) { SWFDEC_LOG ("replacing super object on frame"); swfdec_as_super_replace (SWFDEC_AS_SUPER (fun), NULL); } return TRUE;error: n_args += 2; if (n_args > swfdec_as_stack_get_size (cx)) n_args = swfdec_as_stack_get_size (cx); swfdec_as_stack_pop_n (cx, n_args); SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_push (cx)); return FALSE;}static voidswfdec_action_call_function (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsFrame *frame = cx->frame; SwfdecAsObject *obj; guint n_args; const char *name; SwfdecAsValue *fun, *thisp; swfdec_as_stack_ensure_size (cx, 2); n_args = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 2)); name = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 1)); thisp = swfdec_as_stack_peek (cx, 2); fun = swfdec_as_stack_peek (cx, 1); obj = swfdec_as_frame_find_variable (frame, name); if (obj) { swfdec_as_object_get_variable (obj, name, fun); SWFDEC_AS_VALUE_SET_OBJECT (thisp, obj); } else { SWFDEC_AS_VALUE_SET_NULL (thisp); SWFDEC_AS_VALUE_SET_UNDEFINED (fun); } if (!swfdec_action_call (cx, n_args)) { SWFDEC_ERROR ("no function named %s", name); }}static voidswfdec_action_call_method (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsFrame *frame = cx->frame; SwfdecAsValue *val; SwfdecAsObject *obj; guint n_args; const char *name = NULL; swfdec_as_stack_ensure_size (cx, 3); obj = swfdec_as_value_to_object (cx, swfdec_as_stack_peek (cx, 2)); n_args = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 3)); val = swfdec_as_stack_peek (cx, 1); /* FIXME: this is a hack for constructors calling super - is this correct? */ if (SWFDEC_AS_VALUE_IS_UNDEFINED (val)) { SWFDEC_AS_VALUE_SET_STRING (val, SWFDEC_AS_STR_EMPTY); } if (obj) { if (SWFDEC_AS_VALUE_IS_STRING (val) && SWFDEC_AS_VALUE_GET_STRING (val) == SWFDEC_AS_STR_EMPTY) { SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 3)); SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_peek (cx, 2), obj); } else { SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_peek (cx, 3), obj); name = swfdec_as_value_to_string (cx, val); swfdec_as_object_get_variable (obj, name, swfdec_as_stack_peek (cx, 2)); } } else { if (SWFDEC_AS_VALUE_IS_STRING (val)) name = SWFDEC_AS_VALUE_GET_STRING (val); SWFDEC_AS_VALUE_SET_NULL (swfdec_as_stack_peek (cx, 3)); SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 2)); } swfdec_as_stack_pop (cx); if (swfdec_action_call (cx, n_args)) { /* setup super to point to the right prototype */ frame = cx->frame; if (SWFDEC_IS_AS_SUPER (obj)) { swfdec_as_super_replace (SWFDEC_AS_SUPER (obj), name); } else if (frame->super) { SwfdecAsSuper *super = SWFDEC_AS_SUPER (frame->super); if (name && cx->version > 6 && swfdec_as_object_get_variable_and_flags (frame->thisp, name, NULL, NULL, &super->object) && super->object == frame->thisp) { super->object = super->object->prototype; } } } else { SWFDEC_ERROR ("no function named %s on object %s", name ? name : "unknown", obj ? G_OBJECT_TYPE_NAME(obj) : "unknown"); }}static voidswfdec_action_pop (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ swfdec_as_stack_pop (cx);}static voidswfdec_action_binary (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ double l, r; r = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 1)); l = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 2)); switch (action) { case SWFDEC_AS_ACTION_ADD: l = l + r; break; case SWFDEC_AS_ACTION_SUBTRACT: l = l - r; break; case SWFDEC_AS_ACTION_MULTIPLY: l = l * r; break; case SWFDEC_AS_ACTION_DIVIDE: if (cx->version < 5) { if (r == 0) { SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_peek (cx, 1), SWFDEC_AS_STR__ERROR_); return; } } if (r == 0) { if (l > 0) l = INFINITY; else if (l < 0) l = -INFINITY; else l = NAN; } else { l = l / r; } break; default: g_assert_not_reached (); break; } swfdec_as_stack_pop (cx); SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), l);}static voidswfdec_action_add2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *rval, *lval, rtmp, ltmp; rval = swfdec_as_stack_peek (cx, 1); lval = swfdec_as_stack_peek (cx, 2); rtmp = *rval; ltmp = *lval; swfdec_as_value_to_primitive (&rtmp); if (!SWFDEC_AS_VALUE_IS_OBJECT (&rtmp) || SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (&rtmp))) rval = &rtmp; swfdec_as_value_to_primitive (<mp); if (!SWFDEC_AS_VALUE_IS_OBJECT (<mp) || SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (<mp))) lval = <mp; if (SWFDEC_AS_VALUE_IS_STRING (lval) || SWFDEC_AS_VALUE_IS_STRING (rval)) { const char *lstr, *rstr; lstr = swfdec_as_value_to_string (cx, lval); rstr = swfdec_as_value_to_string (cx, rval); lstr = swfdec_as_str_concat (cx, lstr, rstr); swfdec_as_stack_pop (cx); SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_peek (cx, 1), lstr); } else { double d, d2; d = swfdec_as_value_to_number (cx, lval); d2 = swfdec_as_value_to_number (cx, rval); d += d2; swfdec_as_stack_pop (cx); SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), d); }}static voidswfdec_action_new_comparison (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *lval, *rval; double l, r; rval = swfdec_as_stack_peek (cx, 1); lval = swfdec_as_stack_peek (cx, 2); /* swap if we do a greater comparison */ if (action == SWFDEC_AS_ACTION_GREATER) { SwfdecAsValue *tmp = lval; lval = rval; rval = tmp; } /* comparison with object is always false */ swfdec_as_value_to_primitive (lval); if (SWFDEC_AS_VALUE_IS_OBJECT (lval) && !SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (lval))) { swfdec_as_stack_pop (cx); SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), FALSE); return; } /* same for the rval */ swfdec_as_value_to_primitive (rval); if (SWFDEC_AS_VALUE_IS_OBJECT (rval) && !SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (rval))) { swfdec_as_stack_pop (cx); SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), FALSE); return; } /* movieclips are not objects, but they evaluate to NaN, so we can handle them here */ if (SWFDEC_AS_VALUE_IS_OBJECT (rval) || SWFDEC_AS_VALUE_IS_OBJECT (lval)) { swfdec_as_stack_pop (cx); SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 1)); return; } /* if both are strings, compare strings */ if (SWFDEC_AS_VALUE_IS_STRING (rval) && SWFDEC_AS_VALUE_IS_STRING (lval)) { const char *ls = SWFDEC_AS_VALUE_GET_STRING (lval); const char *rs = SWFDEC_AS_VALUE_GET_STRING (rval); int cmp; if (ls == SWFDEC_AS_STR_EMPTY) { cmp = rs == SWFDEC_AS_STR_EMPTY ? 0 : 1; } else if (rs == SWFDEC_AS_STR_EMPTY) { cmp = -1; } else { cmp = strcmp (ls, rs); } swfdec_as_stack_pop (cx); SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), cmp < 0); return; } /* convert to numbers and compare those */ l = swfdec_as_value_to_number (cx, lval); r = swfdec_as_value_to_number (cx, rval); swfdec_as_stack_pop (cx); /* NaN results in undefined */ if (isnan (l) || isnan (r)) { SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 1)); return; } SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), l < r);}static voidswfdec_action_not_4 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ double d; d = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 1)); SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), d == 0 ? 1 : 0);}static voidswfdec_action_not_5 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), !swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 1)));}static voidswfdec_action_jump (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ if (len != 2) { SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len); return; } cx->frame->pc += 5 + GINT16_FROM_LE (*((gint16*) data)); }static voidswfdec_action_if (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ if (len != 2) { SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len); return; } if (swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 1))) cx->frame->pc += 5 + GINT16_FROM_LE (*((gint16*) data)); swfdec_as_stack_pop (cx);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -