X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswfaction.c;h=6b59ca0046c4fc0008ae687a580856e51e3299df;hb=e2ac6fca142e8f7f81b971bd873d1c7c783f1142;hp=301c4c94ff4ffa2d1f16790905de6c7c5cb20c51;hpb=2275b63cc1e60eb913a939f4cc773763eef5f8cf;p=swftools.git diff --git a/lib/modules/swfaction.c b/lib/modules/swfaction.c index 301c4c9..6b59ca0 100644 --- a/lib/modules/swfaction.c +++ b/lib/modules/swfaction.c @@ -13,6 +13,8 @@ #include "../rfxswf.h" +#define MAX_LOOKUP 1024 // make cross references in dumps + struct Action { int version; @@ -33,7 +35,7 @@ m: method (byte) swf_GetUrl2:(0=none, 1=get, 2=post)/GotoFrame2:(1=play) b: branch (word) (number of bytes) p (push): type(byte), type=0:string, type=1:double {: define function (name (string), num (word), params (num strings), codesize (word) -o: object (string) +o: codesize (word) object (string) r: register (byte) */ {3,"End", 0x00, ""}, @@ -124,11 +126,13 @@ r: register (byte) {5,"ToString", 0x4b,""}, //? {5,"TypeOf", 0x44,""}, {5,"Add2", 0x47,""}, -{5,"Less2", 0x48,""} +{5,"Less2", 0x48,""}, +{5/*6?*/,"Less3?", 0x67,""}, +{5/*6?*/,"GetMembers?", 0x55,""} }; static int definedactions = sizeof(actions)/sizeof(struct Action); -ActionTAG* swf_GetActions(TAG*tag) +ActionTAG* swf_ActionGet(TAG*tag) { U8 op = 1; int length; @@ -149,10 +153,8 @@ ActionTAG* swf_GetActions(TAG*tag) length = swf_GetU16(tag); if(length) { - int t; data = malloc(length); - for(t=0;tdata && action->data != action->tmp) + free(action->data); + tmp = action; + action=action->next; + free(tmp); + } +} + +void swf_ActionSet(TAG*tag, ActionTAG*action) { while(action) { @@ -178,7 +193,7 @@ void swf_SetActions(TAG*tag, ActionTAG*action) } } -int OpAdvance(char c, char*data) +int OpAdvance(char c, U8*data) { switch (c) { @@ -200,6 +215,8 @@ int OpAdvance(char c, char*data) return 1; case 'b': return 2; + case 'r': + return 1; case 'p': { U8 type = *data++; if(type == 0) { @@ -218,115 +235,249 @@ int OpAdvance(char c, char*data) return 1+4; //int } else if (type == 8) { return 1+1; //lookup - } + } else return 1; break; } + case 'o': { + return 2; + } + case '{': { + U16 num; + U16 codesize; + U8* odata = data; + int t; + while(*data++); //name + num = (*data++)*256; //num + num += (*data++); + for(t=0;tlen + 1 + ((atag)->op&0x80?2:0)) +#define MAX_LEVELS 16 +/* TODO: * this should be in swfdump.c */ void swf_DumpActions(ActionTAG*atag, char*prefix) { int t; U8*data; char* cp; - if(!prefix) - prefix=""; + int entry = 0; + char spaces[MAX_LEVELS*4+1]; + struct { + char*text; + int count; + } counter[MAX_LEVELS]; + int countpos = 0; +#ifdef MAX_LOOKUP + char * lookup[MAX_LOOKUP]; + memset(lookup,0x00,sizeof(lookup)); +#endif + memset(spaces, 32, sizeof(spaces)); + spaces[sizeof(spaces)-1] = 0; + + if (!prefix) + prefix=""; + while(atag) { + char*indent = &spaces[sizeof(spaces)-1-countpos*4]; U8 poollen = 0; for(t=0;top) break; if(t==definedactions) { - printf("%s (%5d bytes) action: %02x\n", prefix, atag->len, atag->op); - atag = atag->next; - continue; + printf("%s (%5d bytes) action:%s unknown[%02x]", prefix, atag->len, indent, atag->op); + } else { + printf("%s (%5d bytes) action:%s %s", prefix, atag->len, indent, actions[t].name); } - printf("%s (%5d bytes) action: %s", prefix, atag->len, actions[t].name); - cp = actions[t].flags; data = atag->data; - if(atag->len) //TODO: check for consistency: should we have a length? - while(*cp) + if(atag->len && t!=definedactions) //TODO: check for consistency: should we have a length? { - switch(*cp) - { - case 'f': { - printf(" %d", *(U16*)data); //FIXME: le/be - } break; - case 'u': { - printf(" URL:\"%s\"", data); - } break; - case 't': { - printf(" Target:\"%s\"", data); - } break; - case 'l': { - printf(" Label:\"%s\"", data); - } break; - case 'c': { - printf(" String:\"%s\"", data); - } break; - case 'C': { - poollen = *data; - printf("(%d entries)", poollen); - } break; - case 's': { - printf(" +%d", *data); - } break; - case 'm': { - //m: method (byte) url:(0=none, 1=get, 2=datat)/gf2:(1=play) - printf(" %d", *data); - } break; - case 'b': { - printf(" %d", *(U16*)data); - } break; - case 'p': { - U8 type = *data; - char*value = data+1; - if(type == 0) { - printf(" String:\"%s\"", value); - } else if (type == 1) { - printf(" Float:\"%f\"", *(float*)value); - } else if (type == 2) { - printf(" NULL"); - } else if (type == 4) { - printf(" register:%d", *value); - } else if (type == 5) { - printf(" %s", *value?"true":"false"); - } else if (type == 6) { - printf(" %f", *(double*)value); - } else if (type == 7) { - printf(" %d", *(int*)value); - } else if (type == 8) { - printf(" Lookup:%d", *value); - } - } break; - } - data += OpAdvance(*cp, data); - if(*cp!='c' || !poollen) - cp++; - if(poollen) - poollen--; + cp = actions[t].flags; + while(*cp) + { + switch(*cp) + { + case 'f': { //frame + printf(" %d", data[0]+256*data[1]); + } break; + case 'u': { + printf(" URL:\"%s\"", data); + } break; + case 't': { + printf(" Target:\"%s\"", data); + } break; + case 'l': { + printf(" Label:\"%s\"", data); + } break; + case 'c': { + printf(" String:\"%s\"", data); +#ifdef MAX_LOOKUP + if (entry=15) { + printf("Error: nested too deep\n"); + continue; + } + counter[countpos].text = "}"; + counter[countpos].count = codesize + ATAG_FULLLENGTH(atag); + countpos++; + } break; + case 'o': { + int t; + U16 codesize = data[0]+256*data[1]; + printf(" codesize:%d ", codesize); + + /* the following tries to find the "string" + the flash documentation speaks of- I've + never actually seen one yet. -mk */ + for(t=2;tlen;t++) + printf("[%02x]", atag->data[t]); + + printf("\n%s %s{", prefix, indent); + if(countpos>=15) { + printf("Error: nested too deep\n"); + continue; + } + counter[countpos].text = "}"; + counter[countpos].count = codesize + ATAG_FULLLENGTH(atag); + countpos++; + } break; + case 'b': { + printf(" %d", data[0]+256*(signed char)data[1]); + } break; + case 'r': { + printf(" %d", data[0]); + } break; + case 'p': { + U8 type = *data; + unsigned char*value = data+1; + if(type == 0) { + printf(" String:\"%s\"", value); + } else if (type == 1) { + U32 f = value[0]+(value[1]<<8)+ + (value[2]<<16)+(value[3]<<24); + printf(" Float:%f", *(float*)&f); + } else if (type == 2) { + printf(" NULL"); + } else if (type == 4) { + printf(" register:%d", *value); + } else if (type == 5) { + printf(" bool:%s", *value?"true":"false"); + } else if (type == 6) { + U8 a[8]; + int t; + memcpy(&a[4],value,4); + memcpy(a,&value[4],4); +#ifdef WORDS_BIGENDIAN + for(t=0;t<4;t++) { + U8 tmp = a[t]; + a[t]=a[7-t]; + a[7-t] = tmp; + } +#endif + printf(" double:%f", *(double*)a); + } else if (type == 7) { + printf(" int:%d", value[0]+(value[1]<<8)+ + (value[2]<<16)+(value[3]<<24)); + } else if (type == 8) { + printf(" Lookup:%d", *value); +#ifdef MAX_LOOKUP + if (lookup[*value]) + printf(" (\"%s\")",lookup[*value]); +#endif + } else { + printf(" UNKNOWN[%02x]",type); + } + } break; + } + data += OpAdvance(*cp, data); + if((*cp!='c' || !poollen) && + (*cp!='p' || !(data<&atag->data[atag->len]))) + cp++; + if(poollen) + poollen--; + } } if(data < atag->data + atag->len) { int nl = ((atag->data+atag->len)-data); int t; - printf(" remainder of %d bytes:\"", nl); + printf(" (remainder of %d bytes:\"", nl); for(t=0;tnext; } + +#ifdef MAX_LOOKUP + for (t=0;tnext; } +ActionMarker action_setMarker() +{ + ActionMarker m; + m.atag = currentatag; + return m; +} + +int inline ActionTagSize(ActionTAG*atag) +{ + return (atag->op&0x80)?3+(atag->len):1+0; +} + + #define ACTION_END 0x00 #define ACTION_NEXTFRAME 0x04 #define ACTION_PREVIOUSFRAME 0x05 @@ -563,6 +727,55 @@ void swf_AddActionTAG(U8 op, U8*data, U16 len) #define ACTION_CALL 0x9e #define ACTION_GOTOFRAME2 0x9f +void action_fixjump(ActionMarker m1, ActionMarker m2) +{ + ActionTAG* a1 = m1.atag; + ActionTAG* a2 = m2.atag; + ActionTAG* a; + int len = 0; + int oplen = 0; + a = a1; + + a = a->next; //first one is free + while(a && a!=a2) + { + len += ActionTagSize(a); + oplen ++; + a = a->next; + } + if(!a) + { len = 0; + oplen = 0; + a = a2; + while(a && a!=a1) { + len -= ActionTagSize(a); + oplen --; + a = a->next; + } + if(!a) { + fprintf(stderr, "action_fixjump: couldn't find second tag\n"); + return; + } + len -= ActionTagSize(a); + oplen --; + } + + if (a1->op == ACTION_IF || a1->op == ACTION_JUMP) + { + *(U16*)(a1->data) = SWAP16(len); + } + else if(a1->op == ACTION_WAITFORFRAME) + { + ((U8*)(a1->data))[2] = oplen; + } + else if(a1->op == ACTION_WAITFORFRAME2) + { + ((U8*)(a1->data))[0] = oplen; + } + +} + + void action_NextFrame() {swf_AddActionTAG(ACTION_NEXTFRAME, 0, 0);} void action_PreviousFrame() {swf_AddActionTAG(ACTION_PREVIOUSFRAME, 0, 0);} void action_Play() {swf_AddActionTAG(ACTION_PLAY, 0, 0);} @@ -639,17 +852,17 @@ void action_Call() {swf_AddActionTAG(ACTION_CALL, 0, 0);} void action_End() {swf_AddActionTAG(ACTION_END, 0, 0);} void action_GotoFrame(U16 frame) { - *(U16*)currentatag->tmp = frame; + *(U16*)currentatag->tmp = SWAP16(frame); swf_AddActionTAG(ACTION_GOTOFRAME, (U8*)currentatag->tmp, 2); } void action_Jump(U16 branch) { - *(U16*)currentatag->tmp = branch; + *(U16*)currentatag->tmp = SWAP16(branch); swf_AddActionTAG(ACTION_JUMP, (U8*)currentatag->tmp, 2); } void action_If(U16 branch) { - *(U16*)currentatag->tmp = branch; + *(U16*)currentatag->tmp = SWAP16(branch); swf_AddActionTAG(ACTION_IF, (U8*)currentatag->tmp, 2); } void action_StoreRegister(U8 reg) @@ -674,7 +887,7 @@ void action_WaitForFrame2(U8 skip) } void action_WaitForFrame(U16 frame, U8 skip) { - *(U16*)currentatag->tmp = frame; + *(U16*)currentatag->tmp = SWAP16(frame); *(U8*)¤tatag->tmp[2] = skip; swf_AddActionTAG(ACTION_WAITFORFRAME, (U8*)currentatag->tmp, 3); } @@ -717,21 +930,39 @@ void action_PushString(char*str) void action_PushFloat(float f) { char*ptr = (char*)malloc(5); + U32 fd = *(U32*)&f; ptr[0] = 1; //float - *(float*)&ptr[1] = f; + ptr[1] = fd; + ptr[2] = fd>>8; + ptr[3] = fd>>16; + ptr[4] = fd>>24; swf_AddActionTAG(ACTION_PUSH, (U8*)ptr, 5); } void action_PushDouble(double d) { char*ptr = (char*)malloc(9); + U8*dd = (U8*)&d; ptr[0] = 6; //double - *(double*)&ptr[1] = d; +#ifdef WORDS_BIGENDIAN + ptr[1] = dd[7];ptr[2] = dd[6]; + ptr[3] = dd[5];ptr[4] = dd[4]; + ptr[5] = dd[3];ptr[6] = dd[2]; + ptr[7] = dd[1];ptr[8] = dd[0]; +#else + ptr[1] = dd[0];ptr[2] = dd[1]; + ptr[3] = dd[2];ptr[4] = dd[3]; + ptr[5] = dd[4];ptr[6] = dd[5]; + ptr[7] = dd[6];ptr[8] = dd[7]; +#endif swf_AddActionTAG(ACTION_PUSH, (U8*)ptr, 9); } void action_PushInt(int i) { *(U8*)currentatag->tmp = 7; //int - *(U8*)¤tatag->tmp[1] = i; + currentatag->tmp[1] = i; + currentatag->tmp[2] = i>>8; + currentatag->tmp[3] = i>>16; + currentatag->tmp[4] = i>>24; swf_AddActionTAG(ACTION_PUSH, (U8*)currentatag->tmp, 5); } void action_GotoLabel(char* label) @@ -745,10 +976,37 @@ void action_GetUrl(char* url, char* label) int l2= strlen(label); char*ptr = malloc(l1+l2+2); strcpy(ptr, url); - strcat(&ptr[l2+1], label); - swf_AddActionTAG(ACTION_GETURL, ptr, strlen(ptr)); + strcpy(&ptr[l1+1], label); + swf_AddActionTAG(ACTION_GETURL, ptr, l1+l2+2); } //TODO: void action_DefineFunction(U8*data, int len) {} void action_Constantpool(char* constantpool) {} void action_With(char*object) {} + +/* + Properties: + + _X 0 + _Y 1 + _xscale 2 + _yscale 3 + _currentframe 4 + _totalframes 5 + _alpha 6 + _visible 7 + _width 8 + _height 9 + _rotation 10 + _target 11 + _framesloaded 12 + _name 13 + _droptarget 14 + _url 15 + _highquality 16 + _focusrect 17 + _soundbuftime 18 + _quality* 19 + _xmouse* 20 + _ymouse* 21 +*/