📄 swfdec_script.c
字号:
cx->fp->sp--; movie = swfdec_action_get_target (cx); if (movie) { int frame = swfdec_value_to_frame (cx, movie, val); guint jump = data[2]; guint loaded; if (frame < 0) return JS_TRUE; if (SWFDEC_IS_ROOT_MOVIE (movie)) { SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie)->decoder; loaded = dec->frames_loaded; g_assert (loaded <= movie->n_frames); } else { loaded = movie->n_frames; } if (loaded < (guint) frame) swfdec_script_skip_actions (cx, jump); } else { SWFDEC_ERROR ("no movie to WaitForFrame2 on"); } return JS_TRUE;}static JSBoolswfdec_action_wait_for_frame (JSContext *cx, guint action, const guint8 *data, guint len){ SwfdecMovie *movie = swfdec_action_get_target (cx); guint frame, jump, loaded; if (len != 3) { SWFDEC_ERROR ("WaitForFrame action length invalid (is %u, should be 3", len); return JS_TRUE; } if (movie == NULL) { SWFDEC_ERROR ("no movie for WaitForFrame"); return JS_TRUE; } frame = GUINT16_FROM_LE (*((guint16 *) data)); jump = data[2]; if (SWFDEC_IS_ROOT_MOVIE (movie)) { SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie)->decoder; loaded = dec->frames_loaded; g_assert (loaded <= movie->n_frames); } else { loaded = movie->n_frames; } if (loaded < frame) swfdec_script_skip_actions (cx, jump); return JS_TRUE;}static JSBoolswfdec_action_constant_pool (JSContext *cx, guint action, const guint8 *data, guint len){ SwfdecConstantPool *pool; pool = swfdec_constant_pool_new_from_action (data, len); if (pool == NULL) return JS_FALSE; if (cx->fp->constant_pool) swfdec_constant_pool_free (cx->fp->constant_pool); cx->fp->constant_pool = pool; return JS_TRUE;}static JSBoolswfdec_action_push (JSContext *cx, guint action, const guint8 *data, guint len){ /* FIXME: supply API for this */ SwfdecBits bits; guint stackspace = cx->fp->spend - cx->fp->sp; swfdec_bits_init_data (&bits, data, len); while (swfdec_bits_left (&bits) && stackspace-- > 0) { guint type = swfdec_bits_get_u8 (&bits); SWFDEC_LOG ("push type %u", type); switch (type) { case 0: /* string */ { const char *s = swfdec_bits_skip_string (&bits); if (!swfdec_action_push_string (cx, s)) return JS_FALSE; break; } case 1: /* float */ { double d = swfdec_bits_get_float (&bits); if (!JS_NewDoubleValue (cx, d, cx->fp->sp)) return JS_FALSE; cx->fp->sp++; break; } case 2: /* null */ *cx->fp->sp++ = JSVAL_NULL; break; case 3: /* undefined */ *cx->fp->sp++ = JSVAL_VOID; break; case 4: /* register */ { guint regnum = swfdec_bits_get_u8 (&bits); if (!swfdec_action_has_register (cx, regnum)) { SWFDEC_ERROR ("cannot Push register %u: not enough registers", regnum); return JS_FALSE; } *cx->fp->sp++ = cx->fp->vars[regnum]; break; } case 5: /* boolean */ *cx->fp->sp++ = swfdec_bits_get_u8 (&bits) ? JSVAL_TRUE : JSVAL_FALSE; break; case 6: /* double */ { double d = swfdec_bits_get_double (&bits); if (!JS_NewDoubleValue (cx, d, cx->fp->sp)) return JS_FALSE; cx->fp->sp++; break; } case 7: /* 32bit int */ { int i = swfdec_bits_get_u32 (&bits); *cx->fp->sp++ = INT_TO_JSVAL (i); break; } case 8: /* 8bit ConstantPool address */ { guint i = swfdec_bits_get_u8 (&bits); SwfdecConstantPool *pool = cx->fp->constant_pool; if (pool == NULL) { SWFDEC_ERROR ("no constant pool to push from"); return JS_FALSE; } if (i >= swfdec_constant_pool_size (pool)) { SWFDEC_ERROR ("constant pool index %u too high - only %u elements", i, swfdec_constant_pool_size (pool)); return JS_FALSE; } if (!swfdec_action_push_string (cx, swfdec_constant_pool_get (pool, i))) return JS_FALSE; break; } case 9: /* 16bit ConstantPool address */ { guint i = swfdec_bits_get_u16 (&bits); SwfdecConstantPool *pool = cx->fp->constant_pool; if (pool == NULL) { SWFDEC_ERROR ("no constant pool to push from"); return JS_FALSE; } if (i >= swfdec_constant_pool_size (pool)) { SWFDEC_ERROR ("constant pool index %u too high - only %u elements", i, swfdec_constant_pool_size (pool)); return JS_FALSE; } if (!swfdec_action_push_string (cx, swfdec_constant_pool_get (pool, i))) return JS_FALSE; break; } default: SWFDEC_ERROR ("Push: type %u not implemented", type); return JS_FALSE; } } return swfdec_bits_left (&bits) ? JS_FALSE : JS_TRUE;}static JSBoolswfdec_action_get_variable (JSContext *cx, guint action, const guint8 *data, guint len){ const char *s; s = swfdec_js_to_string (cx, cx->fp->sp[-1]); if (s == NULL) return JS_FALSE; cx->fp->sp[-1] = swfdec_js_eval (cx, NULL, s);#ifdef SWFDEC_WARN_MISSING_PROPERTIES if (cx->fp->sp[-1] == JSVAL_VOID) { SWFDEC_WARNING ("no variable named %s", s); }#endif return JS_TRUE;}static JSBoolswfdec_action_set_variable (JSContext *cx, guint action, const guint8 *data, guint len){ const char *s; s = swfdec_js_to_string (cx, cx->fp->sp[-2]); if (s == NULL) return JS_FALSE; swfdec_js_eval_set (cx, NULL, s, cx->fp->sp[-1]); cx->fp->sp -= 2; return JS_TRUE;}static JSBoolswfdec_action_trace (JSContext *cx, guint action, const guint8 *data, guint len){ SwfdecPlayer *player = JS_GetContextPrivate (cx); const char *bytes; bytes = swfdec_js_to_string (cx, cx->fp->sp[-1]); cx->fp->sp--; if (bytes == NULL) return JS_TRUE; swfdec_player_trace (player, bytes); return JS_TRUE;}/** * swfdec_action_invoke: * @cx: the #JSContext * @n_args: number of arguments * * This function is similar to js_Invoke, however it uses a reversed stack * order. sp[-1] has to be the function to call, sp[-2] will be the object the * function is called on, sp[-3] is the first argument, followed by the rest of * the arguments. The function removes all of these argumends from the stack * and pushes the return value on top. * * Returns: JS_TRUE on success, JS_FALSE on failure. **/static JSBoolswfdec_action_call (JSContext *cx, guint n_args, guint flags){ JSStackFrame *fp = cx->fp; int i, j; jsval tmp; guint stacksize; stacksize = fp->sp - fp->spbase; g_assert (stacksize >= 2); if (n_args + 2 > stacksize) { SWFDEC_WARNING ("broken script. Want %u arguments, only got %u", n_args, stacksize - 2); n_args = stacksize - 2; if (!swfdec_script_ensure_stack (cx, n_args + 2)) return JS_FALSE; } j = -1; i = - (n_args + 2); while (i < j) { tmp = fp->sp[j]; fp->sp[j] = fp->sp[i]; fp->sp[i] = tmp; j--; i++; } return js_Invoke (cx, n_args, flags);}/* FIXME: lots of overlap with swfdec_action_call_method */static JSBoolswfdec_action_call_function (JSContext *cx, guint action, const guint8 *data, guint len){ JSStackFrame *fp = cx->fp; const char *s; guint32 n_args; JSObject *obj, *pobj; JSProperty *prop; jsval fun; JSAtom *atom; if (!swfdec_script_ensure_stack (cx, 2)) return JS_FALSE; s = swfdec_js_to_string (cx, fp->sp[-1]); if (s == NULL) return JS_FALSE; if (!JS_ValueToECMAUint32 (cx, fp->sp[-2], &n_args)) return JS_FALSE; if (!(atom = js_Atomize (cx, s, strlen (s), 0)) || !js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop)) return JS_FALSE; if (!JS_GetProperty (cx, obj, s, &fun)) return JS_FALSE; if (!JSVAL_IS_OBJECT (fun)) { /* FIXME: figure out what class we operate on */ SWFDEC_WARNING ("%s is not a function", s); } fp->sp[-1] = fun; fp->sp[-2] = OBJECT_TO_JSVAL (obj); swfdec_action_call (cx, n_args, 0); return JS_TRUE;}static JSBoolswfdec_action_call_method (JSContext *cx, guint action, const guint8 *data, guint len){ JSStackFrame *fp = cx->fp; const char *s; guint32 n_args; JSObject *obj; jsval fun; if (!swfdec_script_ensure_stack (cx, 3)) return JS_FALSE; if (fp->sp[-1] == JSVAL_VOID) { s = ""; } else { s = swfdec_js_to_string (cx, fp->sp[-1]); if (s == NULL) return JS_FALSE; } if (!JS_ValueToECMAUint32 (cx, fp->sp[-3], &n_args)) return JS_FALSE; if (!JS_ValueToObject (cx, fp->sp[-2], &obj)) return JS_FALSE; if (obj == NULL) goto fail; if (s[0] == '\0') { fun = OBJECT_TO_JSVAL (obj); } else { if (!JS_GetProperty (cx, obj, s, &fun)) return JS_FALSE; if (!JSVAL_IS_OBJECT (fun)) { SWFDEC_WARNING ("%s:%s is not a function", JS_GetClass (obj)->name, s); } } fp->sp--; fp->sp[-1] = fun; fp->sp[-2] = OBJECT_TO_JSVAL (obj); swfdec_action_call (cx, n_args, 0); return JS_TRUE;fail: fp->sp -= 2 + n_args; fp->sp[-1] = JSVAL_VOID; return JS_TRUE;}static JSBoolswfdec_action_pop (JSContext *cx, guint action, const guint8 *data, guint len){ cx->fp->sp--; return JS_TRUE;}static const char *swfdec_eval_jsval (JSContext *cx, JSObject *obj, jsval *val){ if (JSVAL_IS_STRING (*val)) { const char *bytes = swfdec_js_to_string (cx, *val); if (bytes == NULL) return NULL; *val = swfdec_js_eval (cx, obj, bytes); return bytes; } else { if (obj == NULL) { obj = OBJ_THIS_OBJECT (cx, cx->fp->scopeChain); } *val = OBJECT_TO_JSVAL (obj); return "."; }}static const char *properties[22] = { "_x", "_y", "_xscale", "_yscale", "_currentframe", "_totalframes", "_alpha", "_visible", "_width", "_height", "_rotation", "_target", "_framesloaded", "_name", "_droptarget", "_url", "_highquality", "_focusrect", "_soundbuftime", "_quality", "_xmouse", "_ymouse"};static JSBoolswfdec_action_get_property (JSContext *cx, guint action, const guint8 *data, guint len){ jsval val; SwfdecMovie *movie; JSObject *jsobj; guint32 id; const char *bytes; if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-1], &id)) return JS_FALSE; val = cx->fp->sp[-2]; bytes = swfdec_eval_jsval (cx, NULL, &val); if (id > (((SwfdecScript *) cx->fp->swf)->version > 4 ? 21 : 18)) { SWFDEC_WARNING ("trying to SetProperty %u, not allowed", id); goto out; } if (bytes == NULL) return JS_FALSE; if (*bytes == '\0') { JSObject *pobj; JSProperty *prop; JSAtom *atom = js_Atomize (cx, properties[id], strlen (properties[id]), 0); if (atom == NULL) return JS_FALSE; if (!js_FindProperty (cx, (jsid) atom, &jsobj, &pobj, &prop)) return JS_FALSE; if (!prop) return JS_FALSE; if (!OBJ_GET_PROPERTY (cx, jsobj, (jsid) prop->id, &val)) return JS_FALSE; } else { movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("specified target does not reference a movie clip"); goto out; } jsobj = JSVAL_TO_OBJECT (val); val = JSVAL_VOID; if (!JS_GetProperty (cx, jsobj, properties[id], &val)) return JS_FALSE; }out: cx->fp->sp -= 1; cx->fp->sp[-1] = val; return JS_TRUE;}static JSBoolswfdec_action_set_property (JSContext *cx, guint action, const guint8 *data, guint len){ jsval val; SwfdecMovie *movie; JSObject *jsobj; guint32 id; const char *bytes; val = cx->fp->sp[-3]; if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-2], &id)) return JS_FALSE; bytes = swfdec_eval_jsval (cx, NULL, &val); if (!bytes) return JS_FALSE; if (id > (((SwfdecScript *) cx->fp->swf)->version > 4 ? 21 : 18)) { SWFDEC_WARNING ("trying to SetProperty %u, not allowed", id); goto out; } if (*bytes == '\0' || *bytes == '.') val = OBJECT_TO_JSVAL (cx->fp->varobj); movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("specified target does not reference a movie clip"); goto out; } jsobj = JSVAL_TO_OBJECT (val); if (!JS_SetProperty (cx, jsobj, properties[id], &cx->fp->sp[-1])) return JS_FALSE;out: cx->fp->sp -= 3; return JS_TRUE;}static JSBoolswfdec_action_binary (JSContext *cx, guint action, const guint8 *data, guint len){ jsval lval, rval; double l, r; rval = cx->fp->sp[-1]; lval = cx->fp->sp[-2]; if (((SwfdecScript *) cx->fp->swf)->version < 7) { l = swfdec_value_to_number (cx, lval); r = swfdec_value_to_number (cx, rval); } else { if (!swfdec_value_to_number_7 (cx, lval, &l) || !swfdec_value_to_number_7 (cx, rval, &r)) return JS_FALSE; } cx->fp->sp--; switch (action) { case 0x0a: l = l + r; break; case 0x0b: l = l - r; break; case 0x0c: l = l * r; break; case 0x0d: if (((SwfdecScript *) cx->fp->swf)->version < 5) { if (r == 0) { JSString *str = JS_InternString (cx, "#ERROR#"); if (str == NULL) return JS_FALSE; cx->fp->sp[-1] = STRING_TO_JSVAL (str); return JS_TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -