3 Actionscript generation and parsing routines
5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
10 This file is distributed under the GPL, see file COPYING for details
14 #include "../rfxswf.h"
29 c: constant pool (string)
30 s: skip (byte) (number of actions)
31 m: method (byte) GetUrl2:(0=none, 1=get, 2=post)/GotoFrame2:(1=play)
32 b: branch (word) (number of bytes)
33 p (push): type(byte), type=0:string, type=1:double
34 {: define function (name (string), num (word), params (num strings), codesize (word)
39 {3,"GotoFrame", 0x81, "f"},
40 {4,"GotoFrame2", 0x9f, "m"}, // -1 (/Movieclip:3)
41 {3,"GetUrl", 0x83, "ul"},
42 {4,"GetUrl2", 0x9a, "m"}, //-2
43 {3,"NextFrame", 0x04, ""},
44 {3,"PreviousFrame", 0x05, ""},
47 {3,"ToggleQuality", 0x08, ""},
48 {3,"StopSounds", 0x09, ""},
49 {3,"WaitForFrame", 0x8a, "fs"},
50 {4,"WaitForFrame2", 0x8d, "s"}, // -1
51 {3,"SetTarget", 0x8b, "t"},
52 {4,"SetTarget2", 0x20, ""}, //-1
53 {3,"GotoLabel", 0x8c, "l"},
54 {4,"Add", 0x0a, ""}, // -2, +1
55 {4,"Multiply", 0x0c, ""}, // -2, +1
56 {4,"Divide", 0x0d, ""}, // -2, +1
57 {4,"Subtract", 0x0b, ""}, // -2, +1
58 {4,"Less", 0x0f, ""}, // -2, +1
59 {4,"Equals", 0x0e, ""}, // -2, +1
60 {4,"And", 0x10, ""}, // -2, +1
61 {4,"Or", 0x11, ""}, // -2, +1
62 {4,"Not", 0x12, ""}, // -1, +1
63 {4,"StringAdd", 0x21, ""}, // -2,+1
64 {4,"StringLength", 0x14, ""}, // -1, +1
65 {4,"MBStringLength", 0x31}, // -1, +1
66 {4,"StringEquals", 0x13, ""}, // -2, +1
67 {4,"StringLess", 0x29, ""}, //-2, +1
68 {4,"StringExtract", 0x15, ""}, // -3, +1
69 {4,"MBStringExtract", 0x35, ""}, //-3 +1
70 {4,"Push", 0x96, "p"}, // +1
71 {4,"Pop", 0x17, ""}, // -1
72 {4,"ToInteger", 0x18, ""}, // -1, +1
73 {4,"CharToAscii", 0x32, ""}, // -1, +1
74 {4,"AsciiToChar", 0x33, ""}, // -1, +1
75 {4,"MBCharToAscii", 0x36, ""}, // -1, +1
76 {4,"MBAsciiToChar", 0x37, ""}, // -1, +1
77 {4,"Jump", 0x99, "b"},
78 {4,"If", 0x9d, "b"}, // -1
79 {4,"Call", 0x9e, ""}, //-1 (frame label/number)
80 {4,"GetVariable", 0x1c,""}, // -1, +1
81 {4,"SetVariable", 0x1d,""}, // -2
82 {4,"GetProperty", 0x22,""}, //-2, +1
83 {4,"SetProperty", 0x23, ""}, // -3
84 {4,"RemoveSprite", 0x25, ""}, //-1
85 {4,"StartDrag", 0x27, ""}, // -2, -1, (-4)
86 {4,"EndDrag", 0x28, ""},
87 {4,"CloneSprite", 0x24, ""}, // -3
88 {4,"Trace", 0x26, ""}, //-1
89 {4,"GetTime", 0x34, ""}, //+1
90 {4,"RandomNumber", 0x30, ""}, //-1,+1
91 {5,"Modulo", 0x3f,""},
92 {5,"BitAnd", 0x60,""},
93 {5,"BitLShift", 0x63,""},
95 {5,"BitRShift", 0x64,""},
96 {5,"BitURShift", 0x65,""},
97 {5,"BitXor", 0x62,""},//66?
98 {5,"Decrement", 0x51,""},
99 {5,"Increment", 0x50,""},
100 {5,"PushDuplicate", 0x4c,""},
101 {5,"StackSwap", 0x4d,""}, //?
102 {5,"StoreRegister", 0x87,"r"},
103 {5,"CallFunction", 0x3d,""},
104 {5,"DefineFunction", 0x9b, "{"},
105 {5,"Return", 0x3e,""},
106 {5,"GetMember", 0x4e,""},
107 {5,"SetMember", 0x4f,""},
108 {5,"CallMethod", 0x52,""},
109 {5,"Constantpool", 0x88, "c"},
110 {5,"DefineLocal", 0x3c,""},
111 {5,"DefineLocal2", 0x41,""},
112 {5,"Makehash", 0x43, ""}, //??
113 {5,"Delete", 0x3a,""}, //?
114 {5,"Delete2", 0x3b,""},
115 {5,"Enumerate", 0x46,""},
116 {5,"Equals2", 0x49,""},
117 {5,"InitArray", 0x42,""}, // InitObject?
118 {5,"NewMethod", 0x53,""}, //?
119 {5,"NewObject", 0x40,""},
120 {5,"TargetPath", 0x45,""}, //?
121 {5,"With", 0x94, "o"},
122 {5,"ToNumber", 0x4a,""}, //?
123 {5,"ToString", 0x4b,""}, //?
124 {5,"TypeOf", 0x44,""},
128 static int definedactions = sizeof(actions)/sizeof(struct Action);
130 ActionTAG* swf_GetActions(TAG*tag)
135 ActionTAG*action = &tmp;
140 action->next = (ActionTAG*)malloc(sizeof(ActionTAG));
141 action->next->prev = action;
142 action->next->next = 0;
143 action = action->next;
149 length = swf_GetU16(tag);
153 data = malloc(length);
154 for(t=0;t<length;t++)
155 data[t] = swf_GetU8(tag);
160 action->len = length;
162 action->parent = tag;
167 void swf_SetActions(TAG*tag, ActionTAG*action)
171 swf_SetU8(tag, action->op);
173 swf_SetU16(tag, action->len);
175 swf_SetBlock(tag, action->data, action->len);
177 action = action->next;
181 int swf_OpAdvance(char c, char*data)
188 return strlen(data)+1;
190 return strlen(data)+1;
192 return strlen(data)+1;
194 return strlen(data)+1;
204 return 1+strlen(data)+1; //string
205 } else if (type == 1) {
207 } else if (type == 2) {
209 } else if (type == 4) {
210 return 1+1; //register
211 } else if (type == 5) {
213 } else if (type == 6) {
215 } else if (type == 7) {
217 } else if (type == 8) {
224 /* TODO: this should be in swfdump.c */
225 void swf_DumpActions(ActionTAG*atag, char*prefix)
235 for(t=0;t<definedactions;t++)
236 if(actions[t].op == atag->op)
239 if(t==definedactions) {
240 printf("%s (%5d bytes) action: %02x\n", prefix, atag->len, op);
244 printf("%s (%5d bytes) action: %s", prefix, atag->len, actions[t].name);
245 cp = actions[t].flags;
247 if(atag->len) //TODO: check for consistency: should we have a length?
253 printf(" %d", *(U16*)data); //FIXME: le/be
256 printf(" URL:\"%s\"", data);
259 printf(" Target:\"%s\"", data);
262 printf(" Label:\"%s\"", data);
265 printf(" Constant Pool:\"%s\"", data);
268 printf(" +%d", data);
271 //m: method (byte) url:(0=none, 1=get, 2=datat)/gf2:(1=play)
275 printf(" %d", *(U16*)data);
281 printf(" String:\"%s\"", value);
282 } else if (type == 1) {
283 printf(" Float:\"%f\"", *(float*)value);
284 } else if (type == 2) {
286 } else if (type == 4) {
287 printf(" register:%d", value);
288 } else if (type == 5) {
289 printf(" %s", *value?"true":"false");
290 } else if (type == 6) {
291 printf(" %f", *(double*)value);
292 } else if (type == 7) {
293 printf(" %d", *(int*)value);
294 } else if (type == 8) {
295 printf(" Lookup:%d", *value);
299 data += swf_OpAdvance(*cp, data);
303 if(data < atag->data + atag->len)
305 int nl = ((atag->data+atag->len)-data);
307 printf(" remainder of %d bytes:\"", nl);
310 printf("\\%d",data[t]);
312 printf("%c", data[t]);
321 int swf_ActionEnumerateURLs(ActionTAG*atag, char*(*callback)(char*))
331 for(t=0;t<definedactions;t++)
332 if(actions[t].op == atag->op)
335 if(t==definedactions) {
340 cp = actions[t].flags;
346 char * replacepos = 0;
352 replacelen = strlen(data);
354 replacement = callback(data); // may be null
356 /* everything below may very well
357 contain an URL, too. However, to extract
358 these, we would have to call callback also for
359 strings which might not contain an url.
360 TODO: should we check for Strings which start
362 Nope: user can force it by reg.ex. if he wants to /r
370 char*value = &data[1];
371 if(type == 0) { //string
372 } else if (type == 8) { //lookup
376 data += swf_OpAdvance(*cp, data);
379 //TODO: apply replacement here.