📄 swfdec_as_interpret.c
字号:
if (swfdec_as_interpret_eval (cx, NULL, swfdec_as_stack_peek (cx, 1)) == SWFDEC_AS_STR_EMPTY) { SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_peek (cx, 1), cx->frame->target); } if (swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 3))) { swfdec_as_stack_ensure_size (cx, 7); n_args = 5; /* yay for order */ swfdec_as_stack_swap (cx, 4, 7); swfdec_as_stack_swap (cx, 5, 6); } if (!SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (cx, 1))) { swfdec_as_stack_pop_n (cx, n_args + 2); return; } *swfdec_as_stack_peek (cx, 3) = *swfdec_as_stack_peek (cx, 2); *swfdec_as_stack_peek (cx, 2) = *swfdec_as_stack_peek (cx, 1); swfdec_as_object_get_variable (SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (cx, 2)), SWFDEC_AS_STR_startDrag, swfdec_as_stack_peek (cx, 1)); swfdec_action_call (cx, n_args); /* FIXME: the return value will still be written to this position */ swfdec_as_stack_pop (cx);}static voidswfdec_action_end_drag (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ if (SWFDEC_IS_PLAYER (cx)) { swfdec_player_set_drag_movie (SWFDEC_PLAYER (cx), NULL, FALSE, NULL); } else { SWFDEC_WARNING ("can't end a drag on non-players"); }}static voidswfdec_action_stop_sounds (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ if (SWFDEC_IS_PLAYER (cx)) { swfdec_player_stop_all_sounds (SWFDEC_PLAYER (cx)); }}static voidswfdec_action_new_object (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *constructor; SwfdecAsFunction *fun; guint n_args; const char *name; swfdec_as_stack_ensure_size (cx, 2); constructor = swfdec_as_stack_peek (cx, 1); name = swfdec_as_interpret_eval (cx, NULL, constructor); n_args = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 2)); n_args = MIN (swfdec_as_stack_get_size (cx) - 2, n_args); if (!SWFDEC_AS_VALUE_IS_OBJECT (constructor) || !SWFDEC_IS_AS_FUNCTION (fun = (SwfdecAsFunction *) SWFDEC_AS_VALUE_GET_OBJECT (constructor))) { SWFDEC_WARNING ("%s is not a constructor", name); goto fail; } swfdec_as_stack_pop_n (cx, 2); swfdec_as_object_create (fun, n_args, NULL); return;fail: swfdec_as_stack_pop_n (cx, n_args + 1); SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 1));}static voidswfdec_action_new_method (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *constructor; SwfdecAsFunction *fun; guint n_args; const char *name; swfdec_as_stack_ensure_size (cx, 3); name = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 1)); constructor = swfdec_as_stack_peek (cx, 2); n_args = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 3)); n_args = MIN (swfdec_as_stack_get_size (cx) - 3, n_args); if (name != SWFDEC_AS_STR_EMPTY) { if (!SWFDEC_AS_VALUE_IS_OBJECT (constructor)) { SWFDEC_WARNING ("NewMethod called without an object to get variable %s from", name); goto fail; } swfdec_as_object_get_variable (SWFDEC_AS_VALUE_GET_OBJECT (constructor), name, constructor); } if (!SWFDEC_AS_VALUE_IS_OBJECT (constructor) || !SWFDEC_IS_AS_FUNCTION (fun = (SwfdecAsFunction *) SWFDEC_AS_VALUE_GET_OBJECT (constructor))) { SWFDEC_WARNING ("%s is not a constructor", name); goto fail; } swfdec_as_stack_pop_n (cx, 3); swfdec_as_object_create (fun, n_args, NULL); return;fail: swfdec_as_stack_pop_n (cx, n_args + 2); SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 1));}static voidswfdec_action_init_object (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsObject *object; guint i, n_args, size; n_args = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 1)); swfdec_as_stack_pop (cx); if (n_args * 2 > swfdec_as_stack_get_size (cx)) { size = swfdec_as_stack_get_size (cx); SWFDEC_FIXME ("InitObject action with too small stack, help!"); n_args = size / 2; size &= 1; } else { size = 0; } object = swfdec_as_object_new (cx); if (object == NULL) return; for (i = 0; i < n_args; i++) { const char *s = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 2)); swfdec_as_object_set_variable (object, s, swfdec_as_stack_peek (cx, 1)); swfdec_as_stack_pop_n (cx, 2); } swfdec_as_stack_pop_n (cx, size); SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_push (cx), object);}static voidswfdec_action_init_array (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ int i, n; SwfdecAsObject *array; swfdec_as_stack_ensure_size (cx, 1); n = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 1)); swfdec_as_stack_pop (cx); array = swfdec_as_array_new (cx); if (array == NULL) return; /* NB: we can't increase the stack here, as the number can easily be MAXINT */ for (i = 0; i < n && swfdec_as_stack_get_size (cx) > 0; i++) { swfdec_as_stack_ensure_size (cx, 1); swfdec_as_array_push (SWFDEC_AS_ARRAY (array), swfdec_as_stack_pop (cx)); } if (i != n) { SwfdecAsValue val; SWFDEC_AS_VALUE_SET_INT (&val, i); swfdec_as_object_set_variable (array, SWFDEC_AS_STR_length, &val); } SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_push (cx), array);}static voidswfdec_action_define_function (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ char *function_name; const char *name = NULL; guint i, n_args, size, n_registers; SwfdecBuffer *buffer; SwfdecBits bits; SwfdecAsFunction *fun; SwfdecAsFrame *frame; SwfdecScript *script; guint flags = 0; SwfdecScriptArgument *args; gboolean v2 = (action == 0x8e); frame = cx->frame; swfdec_bits_init_data (&bits, data, len); function_name = swfdec_bits_get_string_with_version (&bits, cx->version); if (function_name == NULL) { SWFDEC_ERROR ("could not parse function name"); return; } n_args = swfdec_bits_get_u16 (&bits); if (v2) { n_registers = swfdec_bits_get_u8 (&bits); if (n_registers == 0) n_registers = 4; flags = swfdec_bits_get_u16 (&bits); } else { n_registers = 5; } if (n_args) { args = g_new0 (SwfdecScriptArgument, n_args); for (i = 0; i < n_args && swfdec_bits_left (&bits); i++) { if (v2) { args[i].preload = swfdec_bits_get_u8 (&bits); if (args[i].preload && args[i].preload >= n_registers) { SWFDEC_ERROR ("argument %u cannot be preloaded into register %u out of %u", i, args[i].preload, n_registers); /* FIXME: figure out correct error handling here */ args[i].preload = 0; } } args[i].name = swfdec_bits_get_string_with_version (&bits, cx->version); if (args[i].name == NULL || args[i].name == '\0') { SWFDEC_ERROR ("empty argument name not allowed"); g_free (args); return; } /* FIXME: check duplicate arguments */ } } else { args = NULL; } size = swfdec_bits_get_u16 (&bits); /* check the script can be created */ if (frame->script->buffer->data + frame->script->buffer->length < frame->pc + 3 + len + size) { SWFDEC_ERROR ("size of function is too big"); g_free (args); g_free (function_name); return; } /* create the script */ buffer = swfdec_buffer_new_subbuffer (frame->script->buffer, frame->pc + 3 + len - frame->script->buffer->data, size); swfdec_bits_init (&bits, buffer); if (*function_name) { name = function_name; } else if (swfdec_as_stack_get_size (cx) > 0) { /* This is kind of a hack that uses a feature of the Adobe compiler: * foo = function () {} is compiled as these actions: * Push "foo", DefineFunction, SetVariable/SetMember * With this knowledge we can inspect the topmost stack member, since * it will contain the name this function will soon be assigned to. */ if (SWFDEC_AS_VALUE_IS_STRING (swfdec_as_stack_peek (cx, 1))) name = SWFDEC_AS_VALUE_GET_STRING (swfdec_as_stack_peek (cx, 1)); } if (name == NULL) name = "unnamed_function"; script = swfdec_script_new_from_bits (&bits, name, cx->version); swfdec_buffer_unref (buffer); if (script == NULL) { SWFDEC_ERROR ("failed to create script"); g_free (args); g_free (function_name); return; } if (frame->constant_pool_buffer) script->constant_pool = swfdec_buffer_ref (frame->constant_pool_buffer); script->flags = flags; script->n_registers = n_registers; script->n_arguments = n_args; script->arguments = args; /* see function-scope tests */ if (cx->version > 5) { /* FIXME: or original target? */ fun = swfdec_as_script_function_new (frame->scope ? frame->scope : SWFDEC_AS_SCOPE (frame), frame->target, script); } else { SwfdecAsScope *scope = frame->scope ? frame->scope : SWFDEC_AS_SCOPE (frame); while (scope->next) scope = scope->next; fun = swfdec_as_script_function_new (scope, frame->target, script); } if (fun == NULL) return; /* attach the function */ if (*function_name == '\0') { swfdec_as_stack_ensure_free (cx, 1); SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_push (cx), SWFDEC_AS_OBJECT (fun)); } else { SwfdecAsValue funval; /* FIXME: really varobj? Not eval or sth like that? */ name = swfdec_as_context_get_string (cx, function_name); SWFDEC_AS_VALUE_SET_OBJECT (&funval, SWFDEC_AS_OBJECT (fun)); swfdec_as_object_set_variable (frame->target, name, &funval); } /* update current context */ frame->pc += 3 + len + size; g_free (function_name);}static voidswfdec_action_bitwise (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ int a, b; a = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 1)); b = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 2)); switch (action) { case 0x60: a = (int) (a & b); break; case 0x61: a = (int) (a | b); break; case 0x62: a = (int) (a ^ b); break; default: g_assert_not_reached (); break; } swfdec_as_stack_pop (cx); SWFDEC_AS_VALUE_SET_INT (swfdec_as_stack_peek (cx, 1), a);}static voidswfdec_action_shift (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ int amount, value; amount = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 1)); amount &= 31; value = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 2)); switch (action) { case 0x63: value = value << amount; break; case 0x64: value = ((gint) value) >> amount; break; case 0x65: value = ((guint) value) >> amount; break; default: g_assert_not_reached (); } swfdec_as_stack_pop (cx); SWFDEC_AS_VALUE_SET_INT (swfdec_as_stack_peek (cx, 1), value);}static voidswfdec_action_to_integer (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *val = swfdec_as_stack_peek (cx, 1); SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (cx, val));}static voidswfdec_action_target_path (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *val; SwfdecMovie *movie; char *s; val = swfdec_as_stack_peek (cx, 1); if (!SWFDEC_AS_VALUE_IS_OBJECT (val) || !SWFDEC_IS_MOVIE (movie = (SwfdecMovie *) SWFDEC_AS_VALUE_GET_OBJECT (val))) { SWFDEC_FIXME ("What's the TargetPath for non-movies?"); SWFDEC_AS_VALUE_SET_UNDEFINED (val); return; } s = swfdec_movie_get_path (movie); SWFDEC_AS_VALUE_SET_STRING (val, swfdec_as_context_give_string (cx, s));}static voidswfdec_action_define_local (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsObject *target; const char *name; name = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 2)); if (cx->frame->is_local) { target = SWFDEC_AS_OBJECT (cx->frame); } else { target = cx->frame->target; } swfdec_as_object_set_variable (target, name, swfdec_as_stack_peek (cx, 1)); swfdec_as_stack_pop_n (cx, 2);}static voidswfdec_action_define_local2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue val = { 0, }; SwfdecAsObject *target; const char *name; name = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 1)); if (cx->frame->is_local) { target = SWFDEC_AS_OBJECT (cx->frame); } else { target = cx->frame->target; } swfdec_as_object_set_variable (target, name, &val); swfdec_as_stack_pop (cx);}static voidswfdec_action_return (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ swfdec_as_frame_return (cx->frame, swfdec_as_stack_pop (cx));}static voidswfdec_action_delete (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *val; const char *name; gboolean success = FALSE; name = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 1)); val = swfdec_as_stack_peek (cx, 2); if (SWFDEC_AS_VALUE_IS_OBJECT (val)) { success = swfdec_as_object_delete_variable ( SWFDEC_AS_VALUE_GET_OBJECT (val), name) == SWFDEC_AS_DELETE_DELETED; } SWFDEC_AS_VALUE_SET_BOOLEAN (val, success); swfdec_as_stack_pop_n (cx, 1);}static voidswfdec_action_delete2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len){ SwfdecAsValue *val; const char *name; gboolean success = FALSE; val = swfdec_as_stack_peek (cx, 1); name = swfdec_as_value_to_string (cx, val); success = swfdec_as_frame_delete_variable (cx->frame, name) == SWFDEC_AS_DELETE_DELETED; SWFDEC_AS_VALUE_SET_BOOLEAN (val, success);}static void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -