X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswfabc.c;h=c1cbdedc11c0ab4f609fa17ddd0dd1c94b2d9416;hb=db09f56c8f648428f2019acbb40298fe987d6e97;hp=00af1ba408ec7a9fa83a948002a1ec9bdb495a94;hpb=ea678d107c942d40c3b46248ce7077b867e4c61d;p=swftools.git diff --git a/lib/modules/swfabc.c b/lib/modules/swfabc.c index 00af1ba..c1cbded 100644 --- a/lib/modules/swfabc.c +++ b/lib/modules/swfabc.c @@ -373,6 +373,34 @@ int swf_GetU30(TAG*tag) return s; } +int swf_GetS30(TAG*tag) +{ + U32 shift = 0; + U32 s = 0; + while(1) { + U8 b = swf_GetU8(tag); + s|=(b&127)<pos+len; @@ -630,10 +765,21 @@ static int parse_code(TAG*tag, int len, abc_file_t*pool, char*prefix) } else if(*p == 'b') { int b = swf_GetU8(tag); printf("%02x", b); + } else if(*p == 'j') { + printf("%d", swf_GetU24(tag)); } else if(*p == 's') { const char*s = dict_getstr(pool->strings, swf_GetU30(tag)); printf("\"%s\"", s); - } + } else if(*p == 'S') { + swf_GetU24(tag); //default + int num = swf_GetU30(tag)+1; + int t; + for(t=0;tstrings, swf_GetU30(tag)); + int num = swf_GetU30(tag); + int s; + DEBUG printf(" %s\n", name); + for(s=0;sstrings, swf_GetU30(tag)); + const char*value = dict_getstr(pool->strings, swf_GetU30(tag)); + DEBUG printf(" %s=%s\n", key, value); + } + } +} + #define TRAIT_SLOT 0 #define TRAIT_METHOD 1 #define TRAIT_GETTER 2 @@ -689,6 +853,9 @@ static dict_t* parse_traits(char*prefix, TAG*tag, abc_file_t*pool, char print) int num_traits = swf_GetU30(tag); dict_t*traits = dict_new(); int t; + if(num_traits) { + DEBUG printf("%d traits\n", num_traits); + } for(t=0;tmultinames, name_index); U8 kind = swf_GetU8(tag); - DEBUG printf("trait %d) %s type=%02x\n", t, name, kind); + U8 attributes = kind&0xf0; + kind&=0x0f; + DEBUG printf(" trait %d) %s type=%02x\n", t, name, kind); if(kind == 1 || kind == 2 || kind == 3) { // method / getter / setter int disp_id = swf_GetU30(tag); int nr = swf_GetU30(tag); - DEBUG printf("%smethod %d %d %s\n", prefix, nr, disp_id, ((abc_method_t*)dict_getdata(pool->methods, nr))->paramstr); + DEBUG printf(" %smethod %d %d %s\n", prefix, nr, disp_id, ((abc_method_t*)dict_getdata(pool->methods, nr))->paramstr); if(print) dump_method(prefix, kind==1?"method":(kind==2?"getter":"setter"), name, nr, pool); } else if(kind == 5) { // function int slot_id = swf_GetU30(tag); @@ -709,19 +878,26 @@ static dict_t* parse_traits(char*prefix, TAG*tag, abc_file_t*pool, char print) } else if(kind == 4) { // class int slot_id = swf_GetU30(tag); int cls = swf_GetU30(tag); - if(print) printf("%sclass %s %d %d\n", prefix, name, slot_id, cls); - } else if(kind == 0) { // slot + if(print) printf(" %sclass %s %d %d\n", prefix, name, slot_id, cls); + } else if(kind == 0 || kind == 6) { // slot, const int slot_id = swf_GetU30(tag); const char*type_name = dict_getstr(pool->multinames, swf_GetU30(tag)); int vindex = swf_GetU30(tag); if(vindex) { U8 vkind = swf_GetU8(tag); } - if(print) printf("%sslot %s %d %s (vindex=%d)\n", prefix, name, slot_id, type_name, vindex); + if(print) printf(" %sslot %s %d %s (vindex=%d)\n", prefix, name, slot_id, type_name, vindex); } else { printf(" can't parse trait type %d\n", kind); return 0; } + if(attributes&0x40) { + int num = swf_GetU30(tag); + int s; + for(s=0;sints = dict_new(); - f->ints = dict_new(); + dict_append(f->ints, 0, (void*)(ptroff_t)0); f->uints = dict_new(); + dict_append(f->uints, 0, (void*)(ptroff_t)0); f->floats = dict_new(); + dict_append(f->floats, 0, 0); f->strings = dict_new(); dict_append(f->strings, "----", 0); f->namespaces = dict_new(); dict_append(f->namespaces, "----", 0); + f->namespace_sets = dict_new(); + dict_append(f->namespace_sets, "----", 0); f->sets = dict_new(); dict_append(f->sets, "----", 0); f->multinames = dict_new(); @@ -780,27 +960,39 @@ void swf_DissassembleABC(TAG*tag) swf_SetTagPos(tag, 0); U32 flags = swf_GetU32(tag); + int t; DEBUG printf("flags=%08x\n", flags); char*classname = swf_GetString(tag); U32 version = swf_GetU32(tag); + if(version!=0x002e0010) { + fprintf(stderr, "Warning: unknown AVM2 version %08x\n", version); + } - pool->ints->num = swf_GetU30(tag)-1; - if(pool->ints->num>0) { - printf("can't parse ints yet\n"); - return; + int num_ints = swf_GetU30(tag); + DEBUG printf("%d ints\n", num_ints); + for(t=1;tints, 0, (void*)(ptroff_t)v); } - pool->uints->num = swf_GetU30(tag)-1; - if(pool->uints->num>0) { - printf("can't parse uints yet\n"); - return; + + int num_uints = swf_GetU30(tag); + DEBUG printf("%d uints\n", num_uints); + for(t=1;tuints, 0, (void*)(ptroff_t)v); } - pool->floats->num = swf_GetU30(tag)-1; - if(pool->floats->num>0) { - printf("can't parse floats yet\n"); - return; + + int num_floats = swf_GetU30(tag); + DEBUG printf("%d floats\n", num_floats); + for(t=1;tfloats, 0, 0); } + int num_strings = swf_GetU30(tag); - int t; DEBUG printf("%d strings\n", num_strings); for(t=1;tstrings, namenr); - dict_append(pool->namespaces, name, (void*)(int)type); + dict_append(pool->namespaces, name, (void*)(ptroff_t)type); int w = 0; DEBUG w=1; if(w) { @@ -834,18 +1026,37 @@ void swf_DissassembleABC(TAG*tag) } } int num_sets = swf_GetU30(tag); - if(num_sets>0) { - printf("can't parse namespace sets yet\n"); - return; + DEBUG printf("%d namespace sets\n", num_namespaces); + for(t=1;tnamespaces, nsnr); + l += strlen(name[s])+1; + } + char*desc = malloc(l+16); + strcpy(desc, "{"); + for(s=0;snamespace_sets, desc, 0); + DEBUG printf("set %d) %s\n", t, desc); } + int num_multinames = swf_GetU30(tag); + DEBUG printf("%d multinames\n", num_multinames); for(t=1;tnamespaces, nr1); - U8 access = (U8)(int)dict_getdata(pool->namespaces, nr1); + U8 access = (U8)(ptroff_t)dict_getdata(pool->namespaces, nr1); const char*methodname = dict_getstr(pool->strings, swf_GetU30(tag)); DEBUG printf("multiname %d) <%s> %s:%s\n", t, access2str(access), namespace, methodname); mname = malloc(strlen(namespace)+strlen(methodname)+300); @@ -858,9 +1069,17 @@ void swf_DissassembleABC(TAG*tag) mname = strdup(methodname); } else if(type==0x11 || type==0x12) { mname = strdup(""); - } else if(type==0x09 || type==0x0e || type==0x1b || type==0x1c) { - printf("no support for namespace sets yet\n", type); - return; + } else if(type==0x09 || type==0x0e) { + const char*methodname = dict_getstr(pool->strings, swf_GetU30(tag)); + const char*namespace = dict_getstr(pool->namespace_sets, swf_GetU30(tag)); + DEBUG printf("multiname %d) %s:%s\n", t, namespace, methodname); + mname = malloc(strlen(namespace)+strlen(methodname)+16); + strcpy(mname, namespace); + strcat(mname, ":"); + strcat(mname, methodname); + } else if(type==0x1b || type==0x1c) { + const char*nsset = dict_getstr(pool->namespace_sets, swf_GetU30(tag)); + mname = strdup(nsset); } else { printf("can't parse type %d multinames yet\n", type); return; @@ -870,6 +1089,7 @@ void swf_DissassembleABC(TAG*tag) } int num_methods = swf_GetU30(tag); + DEBUG printf("%d methods\n", num_methods); for(t=0;treturn_type_index = swf_GetU30(tag); m->index = t; int s; - char params[256]; + int params_len = 256; + char* params = malloc(params_len); params[0]='('; params[1]=0; for(s=0;sparam_count;s++) { - if(s) - strcat(params, ", "); int typenr = swf_GetU30(tag); if(s < sizeof(m->params)/sizeof(m->params[0])) m->params[s] = typenr; const char*type = dict_getstr(pool->multinames, typenr); + while(strlen(type)+strlen(params)>params_len-4) { + params_len+=256; + params = realloc(params, params_len); + } + if(s) + strcat(params, ", "); strcat(params, type); } strcat(params, ")"); @@ -895,38 +1120,53 @@ void swf_DissassembleABC(TAG*tag) if(namenr) m->name = dict_getstr(pool->strings, namenr); m->paramstr=strdup(params); - DEBUG printf("method %d) %s\n", t, m->paramstr); + free(params);params = 0; m->flags = swf_GetU8(tag); - if(m->flags&0x88) { - printf("can't parse optional or params names yet\n"); + + DEBUG printf("method %d) %s flags=%02x\n", t, m->paramstr, m->flags); + + if(m->flags&0x08) { + /* optional parameters */ + int num = swf_GetU30(tag); + int s; + for(s=0;sflags&0x80) { + printf("can't parse param names yet\n"); return; } dict_append(pool->methods, m->name, m); } - int num_metadata = swf_GetU30(tag); - for(t=0;tpos; DEBUG printf("%d classes\n", num_classes); for(t=0;tmultinames, swf_GetU30(tag)); + DEBUG printf(" class %d interface: %s\n", t, interface); + } + swf_GetU30(tag); //iinit if(!parse_traits("", tag, pool, 0)) return; } for(t=0;ttag, tag, code_length); int exception_count = swf_GetU30(tag); + int s; + for(s=0;straits = parse_traits("", tag, pool, 1); if(!c->traits) { return; @@ -986,6 +1234,7 @@ void swf_DissassembleABC(TAG*tag) memset(cls, 0, sizeof(abc_class_t)); const char* classname = dict_getstr(pool->multinames, swf_GetU30(tag)); const char* supername = dict_getstr(pool->multinames, swf_GetU30(tag)); + cls->name = classname; U8 flags = swf_GetU8(tag); const char*ns = ""; if(flags&8) { @@ -994,11 +1243,12 @@ void swf_DissassembleABC(TAG*tag) } printf("class %s extends %s, %s, flags=%02x\n", classname, supername, ns, flags); printf("{\n"); - int num_interfaces = swf_GetU30(tag); - if(num_interfaces>0) { - printf("can't parse interfaces yet\n"); - return; - } + + int num_interfaces = swf_GetU30(tag); //interface count + int s; + for(s=0;siinit = swf_GetU30(tag); dump_method(" ","constructor", classname, cls->iinit, pool); cls->traits = parse_traits(" ",tag, pool, 1); @@ -1053,13 +1303,13 @@ static int registerNameSpace(abc_file_t*file, U8 access, char*name) { int t; for(t=0;tnamespaces->num;t++) { const char*name2 = dict_getstr(file->namespaces, t); - U8 access2 = (U8)(int)dict_getdata(file->namespaces, t); + U8 access2 = (U8)(ptroff_t)dict_getdata(file->namespaces, t); if(access == access2 && !strcmp(name, name2)) { return t; } } dict_update(file->strings, name, 0); - return dict_append(file->namespaces, name, (void*)(int)access); + return dict_append(file->namespaces, name, (void*)(ptroff_t)access); } int abc_RegisterNameSpace(abc_file_t*file, char*name) { return registerNameSpace(file, 0x08, name); @@ -1113,9 +1363,12 @@ abc_class_t* abc_NewClass(abc_file_t*abc, char*classname, char*superclass) { memset(c, 0, sizeof(abc_class_t)); c->index = dict_append(abc->classes, 0, c); c->abc = abc; + c->name = strdup(classname); c->classname_index = multiname_index(abc, classname); c->superclass_index = multiname_index(abc, superclass); c->ns_index = abc_RegisterProtectedNameSpace(abc, classname); + c->iinit = -1; + c->cinit = -1; c->traits = dict_new(); return c; @@ -1279,7 +1532,7 @@ void swf_WriteABC(TAG*tag, abc_file_t*abc) } swf_SetU30(tag, abc->namespaces->num>1?abc->namespaces->num:0); for(t=1;tnamespaces->num;t++) { - U8 type = (U8)(int)dict_getdata(abc->namespaces, t); + U8 type = (U8)(ptroff_t)dict_getdata(abc->namespaces, t); const char*name = dict_getstr(abc->namespaces, t); int i = dict_find(abc->strings, name); if(i<0) { @@ -1327,11 +1580,19 @@ void swf_WriteABC(TAG*tag, abc_file_t*abc) swf_SetU30(tag, c->ns_index); swf_SetU30(tag, 0); // no interfaces + if(c->iinit<0) { + fprintf(stderr, "Error: Class %s has no constructor\n", c->name); + return; + } swf_SetU30(tag, c->iinit); write_traits(abc, tag, c->traits); } for(t=0;tclasses->num;t++) { abc_class_t*c = (abc_class_t*)dict_getdata(abc->classes, t); + if(c->cinit<0) { + fprintf(stderr, "Error: Class %s has no constructor\n", c->name); + return; + } swf_SetU30(tag, c->cinit); swf_SetU30(tag, 0); // no traits } @@ -1384,19 +1645,6 @@ void swf_AddButtonLinks(TAG*tag) c->max_scope_depth = 11; abc_getlocal_0(c); abc_pushscope(c); - - abc_getlex(c,":MyButton1"); - abc_getlex(c,"flash.events:MouseEvent"); - abc_getproperty(c, ":CLICK"); - abc_getlex(c, ":gotoPage1"); - abc_callpropvoid(c, ":addEventListener" ,2); - - abc_getlex(c,":MyButton2"); - abc_getlex(c,"flash.events:MouseEvent"); - abc_getproperty(c, ":CLICK"); - abc_getlex(c,":gotoPage2"); - abc_callpropvoid(c,":addEventListener",2); - abc_returnvoid(c); abc_AddSlot(maintimeline, ":MyButton1", 0, "flash.display:SimpleButton"); @@ -1435,14 +1683,29 @@ void swf_AddButtonLinks(TAG*tag) c->local_count = 1; c->init_scope_depth = 10; c->max_scope_depth = 11; + abc_getlocal_0(c); abc_pushscope(c); + abc_getlocal_0(c); abc_constructsuper(c,0); abc_findpropstrict(c,":addFrameScript"); abc_pushbyte(c,0x00); abc_getlex(c,"[packageinternal]buttonmitlink_fla:frame1"); abc_callpropvoid(c,":addFrameScript",2); + + abc_getlex(c,":MyButton1"); + abc_getlex(c,"flash.events:MouseEvent"); + abc_getproperty(c, ":CLICK"); + abc_getlex(c, ":gotoPage1"); + abc_callpropvoid(c, ":addEventListener" ,2); + + abc_getlex(c,":MyButton2"); + abc_getlex(c,"flash.events:MouseEvent"); + abc_getproperty(c, ":CLICK"); + abc_getlex(c,":gotoPage2"); + abc_callpropvoid(c,":addEventListener",2); + abc_returnvoid(c); c = abc_AddInitScript(abc, 0, 0);