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* 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 = GetU16(tag);
153 data = malloc(length);
154 for(t=0;t<length;t++)
155 data[t] = GetU8(tag);
160 action->len = length;
162 action->parent = tag;
167 void SetActions(TAG*tag, ActionTAG*action)
171 SetU8(tag, action->op);
173 SetU16(tag, action->len);
175 SetBlock(tag, action->data, action->len);
177 action = action->next;
181 int 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 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 += 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 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
369 char*value = &data[1];
370 if(type == 0) { //string
371 } else if (type == 8) { //lookup
375 data += OpAdvance(*cp, data);
378 //TODO: apply replacement here.