📄 actions.c
字号:
#include <ctype.h>#include <string.h>#include <math.h>#include "swfdec_internal.h"#define DEBUG printftypedef struct { void *SwfdecDecoder;} SwfdecActionContext;typedef struct { int type; char *s; double num;} SwfdecActionVal;enum { ACTIONVAL_TYPE_UNKNOWN = 0, ACTIONVAL_TYPE_BOOLEAN, ACTIONVAL_TYPE_INTEGER, ACTIONVAL_TYPE_DOUBLE, ACTIONVAL_TYPE_STRING,};#define ACTIONVAL_IS_BOOLEAN(val) ((val)->type == ACTIONVAL_TYPE_BOOLEAN)#define ACTIONVAL_IS_INTEGER(val) ((val)->type == ACTIONVAL_TYPE_INTEGER)#define ACTIONVAL_IS_DOUBLE(val) ((val)->type == ACTIONVAL_TYPE_DOUBLE)#define ACTIONVAL_IS_STRING(val) ((val)->type == ACTIONVAL_TYPE_STRING)#define ACTIONVAL_IS_NUM(val) (ACTIONVAL_IS_BOOLEAN(val) || \ ACTIONVAL_IS_INTEGER(val) || ACTIONVAL_IS_DOUBLE(val))typedef int SwfdecActionFunc(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2);static SwfdecActionFunc action_add, action_subtract, action_multiply, action_divide, action_equal, action_less_than, action_logical_and, action_logical_or, action_logical_not, action_string_equal, action_string_length, action_substring, action_int, action_string_concat;struct action_struct { int action; char * name; SwfdecActionFunc *func; int n_src; int n_dest;};static struct action_struct actions[] = { { 0x04, "next frame", NULL, 0, 0 }, { 0x05, "prev frame", NULL, 0, 0 }, { 0x06, "play", NULL, 0, 0 }, { 0x07, "stop", NULL, 0, 0 }, { 0x08, "toggle quality", NULL, 0, 0 }, { 0x09, "stop sounds", NULL, 0, 0 }, { 0x0a, "add", action_add, 2, 1 }, { 0x0b, "subtract", action_subtract, 2, 1 }, { 0x0c, "multiply", action_multiply, 2, 1 }, { 0x0d, "divide", action_divide, 2, 1 }, { 0x0e, "equal", action_equal, 2, 1 }, { 0x0f, "less than", action_less_than, 2, 1 }, { 0x10, "and", action_logical_and, 2, 1 }, { 0x11, "or", action_logical_or, 2, 1 }, { 0x12, "not", action_logical_not, 1, 1 }, { 0x13, "string equal", action_string_equal, 2, 1 }, { 0x14, "string length", action_string_length, 1, 1 }, { 0x15, "substring", action_substring, 3, 1 },// { 0x17, "unknown", NULL }, { 0x18, "int", action_int, 1, 1 }, { 0x1c, "eval", NULL, 1, 1 }, { 0x1d, "set variable", NULL, 2, 0 }, { 0x20, "set target expr", NULL, 1, 0 }, { 0x21, "string concat", action_string_concat, 2, 1 }, { 0x22, "get property", NULL, 2, 1 }, { 0x23, "set property", NULL, 3, 0 }, { 0x24, "duplicate clip", NULL, 3, 0 }, { 0x25, "remove clip", NULL, 1, 0 }, { 0x26, "trace", NULL, 0, 0 }, { 0x27, "start drag movie", NULL, 3, 0 }, /* 3 or 7 */ { 0x28, "stop drag movie", NULL, 0, 0 }, { 0x29, "string compare", NULL, 2, 1 }, { 0x30, "random", NULL, 1, 1 }, { 0x31, "mb length", NULL, 1, 1 }, { 0x32, "ord", NULL, 1, 1 }, { 0x33, "chr", NULL, 1, 1 }, { 0x34, "get timer", NULL, 0, 1 }, { 0x35, "mb substring", NULL, 3, 1 }, { 0x36, "mb ord", NULL, 1, 1 }, { 0x37, "mb chr", NULL, 1, 1 }, { 0x3b, "call function", NULL }, { 0x3a, "delete", NULL }, { 0x3c, "declare local var", NULL },// { 0x3d, "unknown", NULL }, { 0x3e, "return from function", NULL }, { 0x3f, "modulo", NULL }, { 0x40, "instantiate", NULL },// { 0x41, "unknown", NULL }, { 0x44, "typeof", NULL }, { 0x46, "unknown", NULL }, { 0x47, "add", NULL }, { 0x48, "less than", NULL }, { 0x49, "equals", NULL }, { 0x4c, "make boolean", NULL }, { 0x4e, "get member", NULL }, { 0x4f, "set member", NULL }, { 0x50, "increment", NULL }, { 0x52, "call method", NULL }, { 0x60, "bitwise and", NULL }, { 0x61, "bitwise or", NULL }, { 0x62, "bitwise xor", NULL }, { 0x63, "shift left", NULL }, { 0x64, "shift right", NULL }, { 0x65, "rotate right", NULL },// { 0x67, "unknown", NULL }, { 0x81, "goto frame", NULL }, { 0x83, "get url", NULL }, { 0x87, "get next dict member", NULL }, { 0x88, "declare dictionary", NULL }, { 0x8a, "wait for frame", NULL },// { 0x8b, "unknown", NULL },// { 0x8c, "unknown", NULL }, { 0x8d, "wait for frame expr", NULL, 1, 0 }, { 0x94, "with", NULL }, { 0x96, "push data", NULL }, { 0x99, "branch", NULL, 0, 0 }, { 0x9a, "get url2", NULL, 2, 0 }, { 0x9b, "declare function", NULL }, { 0x9d, "branch if", NULL, 1, 0 }, { 0x9e, "call frame", NULL, 1, 0 }, { 0x9f, "goto expr", NULL, 1, 0 },// { 0xb7, "unknown", NULL },/* in 1394C148d01.swf */ { 0x8b, "unknown", NULL }, { 0x8c, "unknown", NULL },};static int n_actions = sizeof(actions)/sizeof(actions[0]);static void hexdump(unsigned char *data, int len){ int i; int j; while(len>0){ printf(" "); j = (len<16)?len:16; for(i=0;i<j;i++){ printf("%02x ",data[i]); } for(;i<16;i++){ printf(" "); } for(i=0;i<j;i++){ printf("%c",isprint(data[i])?data[i]:'.'); } printf("\n"); data += j; len -= j; }}void get_actions(SwfdecDecoder *s,bits_t *bits){ int action; int len; //int index; //int skip_count; int i; SWF_DEBUG(0,"get_actions\n"); while(1){ action = get_u8(bits); if(action==0)break; if(action&0x80){ len = get_u16(bits); }else{ len = 0; } for(i=0;i<n_actions;i++){ if(actions[i].action == action){ if(s->debug<1){ printf(" [%02x] %s\n",action, actions[i].name); } break; } } if(i==n_actions){ if(s->debug<3){ printf(" [%02x] *** unknown action\n",action); } } if(s->debug<1){ hexdump(bits->ptr, len); } bits->ptr += len; }}int tag_func_do_action(SwfdecDecoder *s){ get_actions(s,&s->b); return SWF_OK;}int swfdec_action_script_execute(SwfdecDecoder *s, bits_t *bits){ int action; int len; //int index; //int skip_count; int i; SWF_DEBUG(0,"swfdec_action_script_execute\n"); while(1){ action = get_u8(bits); if(action==0)break; if(action&0x80){ len = get_u16(bits); }else{ len = 0; } for(i=0;i<n_actions;i++){ if(actions[i].action == action){ if(s->debug<1){ printf(" [%02x] %s\n",action, actions[i].name); } break; } } if(i==n_actions){ if(s->debug<3){ printf(" [%02x] *** unknown action\n",action); } } hexdump(bits->ptr, len); bits->ptr += len; } return SWF_OK;}static int action_promote(SwfdecActionVal *src1, SwfdecActionVal *src2){ if(ACTIONVAL_IS_DOUBLE(src1))return ACTIONVAL_TYPE_DOUBLE; if(ACTIONVAL_IS_DOUBLE(src2))return ACTIONVAL_TYPE_DOUBLE; if(ACTIONVAL_IS_INTEGER(src1))return ACTIONVAL_TYPE_INTEGER; if(ACTIONVAL_IS_INTEGER(src2))return ACTIONVAL_TYPE_INTEGER; return ACTIONVAL_TYPE_BOOLEAN;}static SwfdecActionVal *action_pop(SwfdecActionContext *context){ /* FIXME unimplemented */ return NULL;}static int action_add(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_NUM(src1) && ACTIONVAL_IS_NUM(src2)){ dest->type = action_promote(src1,src2); dest->num = src1->num + src2->num; }else if(ACTIONVAL_IS_STRING(src1) && ACTIONVAL_IS_STRING(src2)){ dest->type = ACTIONVAL_TYPE_STRING; dest->s = malloc(strlen(src1->s) + strlen(src2->s) + 1); strcpy(dest->s, src1->s); strcat(dest->s, src2->s); }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_subtract(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_NUM(src1) && ACTIONVAL_IS_NUM(src2)){ dest->type = action_promote(src1,src2); dest->num = src1->num - src2->num; }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_multiply(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_NUM(src1) && ACTIONVAL_IS_NUM(src2)){ dest->type = action_promote(src1,src2); dest->num = src1->num * src2->num; }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_divide(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_NUM(src1) && ACTIONVAL_IS_NUM(src2)){ dest->type = action_promote(src1,src2); dest->num = src1->num / src2->num; }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_equal(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_NUM(src1) && ACTIONVAL_IS_NUM(src2)){ dest->type = ACTIONVAL_TYPE_BOOLEAN; dest->num = (src1->num == src2->num); }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_less_than(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_NUM(src1) && ACTIONVAL_IS_NUM(src2)){ dest->type = ACTIONVAL_TYPE_BOOLEAN; dest->num = (src1->num < src2->num); }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_logical_and(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_BOOLEAN(src1) && ACTIONVAL_IS_BOOLEAN(src2)){ dest->type = ACTIONVAL_TYPE_BOOLEAN; dest->num = (src1->num && src2->num); }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_logical_or(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_BOOLEAN(src1) && ACTIONVAL_IS_BOOLEAN(src2)){ dest->type = ACTIONVAL_TYPE_BOOLEAN; dest->num = (src1->num || src2->num); }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_logical_not(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2==NULL); if(ACTIONVAL_IS_BOOLEAN(src1)){ dest->type = ACTIONVAL_TYPE_BOOLEAN; dest->num = !src1->num; }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_string_equal(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_STRING(src1) && ACTIONVAL_IS_STRING(src2)){ dest->type = ACTIONVAL_TYPE_BOOLEAN; dest->num = (strcmp(src1->s,src2->s)==0); }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_string_length(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2==NULL); if(ACTIONVAL_IS_STRING(src1)){ dest->type = ACTIONVAL_TYPE_INTEGER; dest->num = strlen(src1->s); }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_substring(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ unsigned int len; unsigned int slen; unsigned int offset; SwfdecActionVal *src3; g_assert(dest); g_assert(src1); g_assert(src2); src3 = action_pop(context); g_assert(src3); if(ACTIONVAL_IS_STRING(src1) && ACTIONVAL_IS_NUM(src2) && ACTIONVAL_IS_NUM(src3)){ dest->type = ACTIONVAL_TYPE_STRING; slen = strlen(src1->s); offset = src2->num; if(offset>slen)offset = slen; len = src3->num; if(len>slen - offset)len = slen - offset; dest->s = malloc(len + 1); memcpy(dest->s, src1->s + offset, len); dest->s[len] = 0; }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_int(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2==NULL); if(ACTIONVAL_IS_NUM(src1)){ dest->type = ACTIONVAL_TYPE_INTEGER; dest->num = floor(src1->num); }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}static int action_string_concat(SwfdecActionContext *context, SwfdecActionVal *dest, SwfdecActionVal *src1, SwfdecActionVal *src2){ g_assert(dest); g_assert(src1); g_assert(src2); if(ACTIONVAL_IS_STRING(src1) && ACTIONVAL_IS_STRING(src2)){ dest->type = ACTIONVAL_TYPE_STRING; dest->s = malloc(strlen(src1->s) + strlen(src2->s) + 1); strcpy(dest->s, src1->s); strcat(dest->s, src2->s); }else{ DEBUG("incompatible types\n"); return SWF_ERROR; } return SWF_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -