4 #include "swf_action.h"
6 swf_action_info_t swf_action_info_table[] = {
8 /* nothing 0x01 - 0x03 */
9 { 0x04, "Next Frame" },
10 { 0x05, "Previous Frame" },
13 { 0x08, "Toggle Quality" },
14 { 0x09, "Stop Sound" },
20 { 0x0F, "Less Than" },
21 { 0x10, "Logical And" },
22 { 0x11, "Logical Or " },
23 { 0x12, "Logical Not" },
24 { 0x13, "String Equal" },
25 { 0x14, "String Length" },
26 { 0x15, "SubString" },
29 { 0x18, "Integral Part"},
30 /* nothing 0x19 - 0x1B */
31 { 0x1C, "Get Variable"},
32 { 0x1D, "Set Variable"},
33 /* nothing 0x1E - 0x1F */
34 { 0x20, "Set Target" },
35 { 0x21, "Concatenate Strings"},
36 { 0x22, "Get Property" },
37 { 0x23, "Set Property" },
38 { 0x24, "Duplicate Sprite" },
39 { 0x25, "Remove Sprite" },
41 { 0x27, "Start Drag" },
42 { 0x28, "Stop Drag" },
43 { 0x29, "String Less Than"},
45 { 0x2B, "Cast Object" },
46 { 0x2C, "implements" },
47 { 0x2D, "FSCommand2" },
50 { 0x31, "String Length(multibyte)" },
53 { 0x34, "Get Timer" },
54 { 0x35, "SubString(multibyte)" },
55 { 0x36, "Ord(multibyte)" },
56 { 0x37, "Chr(multibyte)" },
59 { 0x3B, "Delete All" },
60 { 0x3C, "Set Local Variable" },
61 { 0x3D, "Call Function" },
65 { 0x41, "Declare Local Variable" },
66 { 0x42, "Declare Array" },
67 { 0x43, "Declare Object" },
69 { 0x45, "Get Targer" },
70 { 0x46, "Enumerate" },
71 { 0x47, "Add(typed)" },
72 { 0x48, "Less Than(typed)" },
73 { 0x49, "Equal(typed)" },
76 { 0x4C, "Duplicate" },
78 { 0x4E, "Get Member" },
79 { 0x4F, "Set Member" },
80 { 0x50, "Increment" },
81 { 0x51, "Decrement" },
82 { 0x52, "Call Method" },
83 { 0x53, "New Method" },
84 { 0x54, "Instance Of" },
85 { 0x55, "Enumerate Object" },
86 /* nothing 0x56 - 0x5F */
90 { 0x63, "Shift Left" },
91 { 0x64, "Shift Right" },
92 { 0x65, "Shift Right Unsigned" },
93 { 0x66, "Strict Equal" },
94 { 0x67, "Greater Than(typed)" },
95 { 0x68, "String Greater Than(typed)" },
97 /* nothing 0x6A - 0x80 */
98 { 0x81, "Goto Frame" },
101 /* nothing 0x84 - 0x86 */
102 { 0x87, "Store Register" },
103 { 0x88, "Declare Dictionary" },
104 { 0x89, "Strict Mode" },
105 { 0x8A, "Wait For Frame" },
106 { 0x8B, "Set Target" },
107 { 0x8C, "Goto Label" },
108 { 0x8D, "Wait For Frame(dynamic)" },
109 { 0x8E, "Declare Function (with 256 registers)"},
111 /* nothing 0x90 - 0x93 */
114 { 0x96, "Push Data" },
115 /* nothing 0x97 - 0x98 */
116 { 0x99, "Branch Always" },
117 { 0x9A, "Get URL2" },
118 { 0x9B, "Declare Function" },
120 { 0x9D, "Branch If True" },
121 { 0x9E, "Call Frame" },
122 { 0x9F, "Goto Expression" },
126 get_swf_action_info(int action_id) {
127 int i, action_info_num = NumOfTable(swf_action_info_table);
128 for (i=0 ; i < action_info_num; i++) {
129 if (action_id == swf_action_info_table[i].id) {
130 return &(swf_action_info_table[i]);
137 swf_action_parse(bitstream_t *bs, swf_action_t *act) {
138 unsigned long offset;
140 act->action_id = bitstream_getbyte(bs);
141 if (act->action_id & 0x80) {
142 act->action_length = bitstream_getbytesLE(bs, 2);
143 offset = bitstream_getbytepos(bs);
144 act->action_data = malloc(act->action_length);
145 if (act->action_data == NULL) {
146 fprintf(stderr, "Can't alloc memory for act->action_data\n");
149 bitstream_getstring(bs, act->action_data, act->action_length);
155 swf_action_build(bitstream_t *bs, swf_action_t *act) {
157 bitstream_putbyte(bs, act->action_id);
158 if (act->action_id & 0x80) {
159 if (act->action_data == NULL) {
162 bitstream_putbytesLE(bs, act->action_length, 2);
163 bitstream_putstring(bs, act->action_data, act->action_length);
169 swf_action_print(swf_action_t *act, int indent_depth) {
170 swf_action_info_t *act_info = get_swf_action_info(act->action_id);
171 if (act_info && act_info->name) {
172 print_indent(indent_depth);
173 printf("%s", act_info->name);
175 print_indent(indent_depth);
176 printf("0x%02x", act->action_id);
178 if (act->action_id & 0x80) {
181 switch(act->action_id) {
182 case 0x83: // Get URL
183 printf(" (String)%s", act->action_data);
184 printf(" (String)%s",
185 act->action_data + strlen((char*) act->action_data) + 1);
187 case 0x88: // Declare Dictionary
188 d = act->action_data;
189 n = GetUShortLE(act->action_data); d += 2;
191 print_indent(indent_depth);
192 for (i=0 ; i < n ; i++) {
193 printf("\t\t[%d]'", i);
194 d += printf("%s", d) + 1;
198 case 0x96: // Push Data
199 swf_action_data_print(act->action_data, act->action_length);
202 printf(" len=%d", act->action_length);
211 swf_action_list_create(void) {
212 swf_action_list_t *action_list;
213 action_list = calloc(sizeof(*action_list), 1);
214 if (action_list == NULL) {
215 fprintf(stderr, "Can't alloc memory for action_list\n");
218 action_list->head = NULL;
219 action_list->tail = NULL;
224 swf_action_list_parse(bitstream_t *bs, swf_action_list_t *action_list) {
225 swf_action_t *action;
227 action = calloc(sizeof(*action), 1);
228 if (action == NULL) {
229 fprintf(stderr, "Can't alloc memory for action\n");
232 if (swf_action_parse(bs, action)) {
233 fprintf(stderr, "swf_action_list_parse: swf_action_parse failed");
236 if (action_list->head == NULL) {
237 action_list->head = action_list->tail = action;
239 action_list->tail->next = action;
240 action_list->tail = action;
243 if (action->action_id == 0) { // End Action;
251 swf_action_list_build(bitstream_t *bs, swf_action_list_t *list) {
252 swf_action_t *action;
253 for (action=list->head ; action ; action=action->next) {
254 if (swf_action_build(bs, action) != 0) {
255 fprintf(stderr, "swf_action_list_build: swf_action_build failed\n");
256 bitstream_putbyte(bs, 0);
264 swf_action_list_destroy(swf_action_list_t *action_list) {
267 swf_action_t *action = action_list->head;
269 swf_action_t *action_next = action->next;
270 if (action->action_data) {
271 free(action->action_data);
274 action = action_next;
281 swf_action_list_print(swf_action_list_t *action_list, int indent_depth) {
284 swf_action_t *action = action_list->head;
285 print_indent(indent_depth);
286 printf("action list:\n");
288 swf_action_print(action, indent_depth);
289 action = action->next;
295 swf_action_data_print(unsigned char *action_data, unsigned short action_data_len) {
297 unsigned char *data = action_data+1;
298 unsigned short data_len = action_data_len - 1;
300 while (data < action_data + action_data_len) {
305 printf("(String)%s", data);
306 data += strlen((char*) data) + 1; // text + \0
309 printf("(Float)%f", GetFloatIEEE(data));
315 case 0x03: // Undefined
316 printf("(Undefined)");
318 case 0x04: // Register
319 printf("(Register)%d", (data[0]&0xff));
322 case 0x05: // Boolean
323 printf("(Boolean)%s", (data[0]&0xff)?"true":"false");
327 printf("(Double)%f", GetDoubleIEEE(data));
330 case 0x07: // Integer
331 printf("(Integer)%ld", GetULongLE(data));
334 case 0x08: // Dictionary Lookup
335 printf("(Dictionary Lookup)%d", data[0] & 0xff);
338 case 0x09: // Large Dictionary Lookup
339 printf("(Large Dictionary Lookup)%d", GetUShortLE(data) & 0xffff);
343 printf("type=0x%02x len=%d", type, data_len);
351 swf_action_list_replace_strings(swf_action_list_t *action_list,
352 int *modified, y_keyvalue_t *kv) {
353 swf_action_t *action;
357 for (action=action_list->head ; action ; action=action->next) {
358 if (action->action_id < 0x80) {
359 continue; // skip (no string)
361 switch(action->action_id) {
363 unsigned char *token;
371 case 0x83: // Get URL
373 bs = bitstream_open();
374 token = action->action_data;
375 token_len = strlen((char *) token);
376 value = y_keyvalue_get(kv, (char *)token, token_len, &value_len);
378 bitstream_putstring(bs, (unsigned char *) value, value_len);
379 bitstream_putbyte(bs, '\0');
382 bitstream_putstring(bs, (unsigned char *) token, token_len);
383 bitstream_putbyte(bs, '\0');
385 token += token_len + 1;
386 token_len = strlen((char *) token);
387 value = y_keyvalue_get(kv, (char *)token, token_len, &value_len);
389 bitstream_putstring(bs, (unsigned char *)value, value_len);
390 bitstream_putbyte(bs, '\0');
393 bitstream_putstring(bs, (unsigned char *)token, token_len);
394 bitstream_putbyte(bs, '\0');
397 unsigned long length;
398 free(action->action_data);
399 action->action_data = bitstream_steal(bs, &length);
400 action->action_length = length;
407 case 0x88: // ActionConstantPool
409 count = action->action_data[0] + 0x100 * action->action_data[1];
410 token = action->action_data + 2;
411 bs = bitstream_open();
412 bitstream_putbytesLE(bs, count, 2);
413 for (i = 0 ; i < count ; i++) {
414 token_len = strlen((char *) token);
415 value = y_keyvalue_get(kv, (char *)token, token_len, &value_len);
417 bitstream_putstring(bs, (unsigned char *)value, value_len);
418 bitstream_putbyte(bs, '\0');
421 bitstream_putstring(bs, (unsigned char *)token , token_len);
422 bitstream_putbyte(bs, '\0');
424 token += token_len + 1;
427 unsigned long length;
428 free(action->action_data);
429 action->action_data = bitstream_steal(bs, &length);
430 action->action_length = length;
437 case 0x96: // Push Data
439 token = action->action_data;
440 bs = bitstream_open();
441 while (token < action->action_data + action->action_length) {
442 static const int action_value_type_size[] = {
451 1, // 8: Dictionary Lookup
452 2, // 9: Large Dictionary Lookup
455 bitstream_putbyte(bs, type);
457 if (type == 0) { // String
458 token_len = strlen((char *) token);
459 value = y_keyvalue_get(kv, (char *)token, token_len, &value_len);
461 bitstream_putstring(bs, (unsigned char *)value, value_len);
462 bitstream_putbyte(bs, '\0');
465 bitstream_putstring(bs, (unsigned char *)token , token_len);
466 bitstream_putbyte(bs, '\0');
468 token += token_len + 1;
469 } else if (type < 10) { // else String
470 bitstream_putstring(bs, token, action_value_type_size[type]);
471 token += action_value_type_size[type];
473 fprintf(stderr, "swf_action_list_replace_strings: illegal type=%d\n", type);
479 unsigned long length;
480 free(action->action_data);
481 action->action_data = bitstream_steal(bs, &length);
482 action->action_length = length;
495 swf_action_list_append_top(swf_action_list_t *list, int action_id,
496 unsigned char *action_data, int action_data_length) {
497 swf_action_t *action;
498 action = calloc(sizeof(*action), 1);
499 action->action_id = action_id;
500 if (action_id >= 0x80) {
501 action->action_data = malloc(action_data_length);
502 memcpy(action->action_data, action_data, action_data_length);
503 action->action_length = action_data_length;
505 action->action_data = NULL;
506 action->action_length = action_data_length;
508 action->next = list->head;
510 if (list->tail == NULL) {