OSDN Git Service

delete png_set_gAMA
[swfed/swfed.git] / src / swf_action.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "bitstream.h"
4 #include "swf_action.h"
5
6 swf_action_info_t swf_action_info_table[] = {
7     { 0x00, "End" },
8     /* nothing 0x01 - 0x03 */
9     { 0x04, "Next Frame" },
10     { 0x05, "Previous Frame" },
11     { 0x06, "Play" },
12     { 0x07, "Stop" },
13     { 0x08, "Toggle Quality" },
14     { 0x09, "Stop Sound" },
15     { 0x0A, "Add" },
16     { 0x0B, "Subtract" },
17     { 0x0C, "Multiply" },
18     { 0x0D, "Divide" },
19     { 0x0E, "Equal" },
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" },
27     /* nothing 0x16 */
28     { 0x17, "Pop"},
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" },
40     { 0x26, "Trace" },
41     { 0x27, "Start Drag" },
42     { 0x28, "Stop Drag" },
43     { 0x29, "String Less Than"},
44     { 0x2A, "Throw" },
45     { 0x2B, "Cast Object" },
46     { 0x2C, "implements" },
47     { 0x2D, "FSCommand2" },
48     /* nothing 0x2E-2F */
49     { 0x30, "Random" },
50     { 0x31, "String Length(multibyte)" },
51     { 0x32, "Ord" },
52     { 0x33, "Chr"},
53     { 0x34, "Get Timer" },
54     { 0x35, "SubString(multibyte)" },
55     { 0x36, "Ord(multibyte)" },
56     { 0x37, "Chr(multibyte)" },
57     /* nothing 0x28-29 */
58     { 0x3A, "Delete" },
59     { 0x3B, "Delete All" },
60     { 0x3C, "Set Local Variable" },
61     { 0x3D, "Call Function" },
62     { 0x3E, "Return" },
63     { 0x3F, "Modulo" },
64     { 0x40, "New" },
65     { 0x41, "Declare Local Variable" },
66     { 0x42, "Declare Array" },
67     { 0x43, "Declare Object" },
68     { 0x44, "Type Of" },
69     { 0x45, "Get Targer" },
70     { 0x46, "Enumerate" },
71     { 0x47, "Add(typed)" },
72     { 0x48, "Less Than(typed)" },
73     { 0x49, "Equal(typed)" },
74     { 0x4A, "Number" },
75     { 0x4B, "String" },
76     { 0x4C, "Duplicate" },
77     { 0x4D, "Swap" },
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 */
87     { 0x60, "And" },
88     { 0x61, "Or" },
89     { 0x62, "XOr" },
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)" },
96     { 0x69, "Extends" },
97     /* nothing 0x6A - 0x80 */
98     { 0x81, "Goto Frame" },
99     /* nothing 0x82 */
100     { 0x83, "Get URL" },
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)"},
110     { 0x8F, "Try"},
111     /* nothing 0x90 - 0x93 */
112     { 0x94, "With"},
113     /* nothing 0x95 */
114     { 0x96, "Push Data" },
115      /* nothing 0x97 - 0x98 */
116     { 0x99, "Branch Always" },
117     { 0x9A, "Get URL2" },
118     { 0x9B, "Declare Function" },
119     /* nothing 0x9C */
120     { 0x9D, "Branch If True" },
121     { 0x9E, "Call Frame" },
122     { 0x9F, "Goto Expression" },
123 };
124
125 swf_action_info_t *
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]);
131         }
132     }
133     return NULL;
134 }
135
136 int
137 swf_action_parse(bitstream_t *bs, swf_action_t *act) {
138     unsigned long offset;
139     bitstream_align(bs);
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");
147             return 1;
148         }
149         bitstream_getstring(bs, act->action_data, act->action_length);
150     }
151     return 0;
152 }
153
154 int
155 swf_action_build(bitstream_t *bs, swf_action_t *act) {
156     bitstream_align(bs);
157     bitstream_putbyte(bs, act->action_id);
158     if (act->action_id & 0x80) {
159         if (act->action_data == NULL) {
160             return 1; // error
161         }
162         bitstream_putbytesLE(bs, act->action_length, 2);
163         bitstream_putstring(bs, act->action_data, act->action_length);
164     }
165     return 0;
166 }
167
168 int
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);
174     } else {
175         print_indent(indent_depth);
176         printf("0x%02x", act->action_id);
177     }
178     if (act->action_id & 0x80) {
179         int i, n;
180         unsigned char *d;
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);
186             break;
187         case 0x88: // Declare Dictionary
188             d = act->action_data;
189             n = GetUShortLE(act->action_data);  d += 2;
190             printf(":\n");
191             print_indent(indent_depth);
192             for (i=0 ; i < n ; i++) {
193                 printf("\t\t[%d]'", i);
194                 d += printf("%s", d) + 1;
195                 printf("'\n");
196             }
197             break;
198         case 0x96: // Push Data
199             swf_action_data_print(act->action_data, act->action_length);
200             break;
201         default:
202             printf(" len=%d", act->action_length);
203             break;
204         }
205     }
206     printf("\n");
207     return 0;
208 }
209
210 swf_action_list_t *
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");
216         return NULL;
217     }
218     action_list->head = NULL;
219     action_list->tail = NULL;
220     return action_list;
221 }
222
223 int
224 swf_action_list_parse(bitstream_t *bs, swf_action_list_t *action_list) {
225     swf_action_t *action;
226     while (1) {
227         action = calloc(sizeof(*action), 1);
228         if (action == NULL) {
229             fprintf(stderr, "Can't alloc memory for action\n");
230             break;
231         }
232         if (swf_action_parse(bs, action)) {
233             fprintf(stderr, "swf_action_list_parse: swf_action_parse failed");
234             return 1; // NG
235         }
236         if (action_list->head == NULL) {
237             action_list->head = action_list->tail = action;
238         } else {
239             action_list->tail->next = action;
240             action_list->tail = action;
241         }
242         action->next = NULL;
243         if (action->action_id == 0) { // End Action;
244             break;
245         }
246     }
247     return 0;
248 }
249
250 int
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);
257             return 1;
258         }
259     }
260     return 0;
261 }
262
263 void
264 swf_action_list_destroy(swf_action_list_t *action_list) {
265
266     if (action_list) {
267         swf_action_t *action = action_list->head;
268         while (action) {
269             swf_action_t *action_next = action->next;
270             if (action->action_data) {
271                 free(action->action_data);
272             }
273             free(action);
274             action = action_next;
275         }
276         free(action_list);
277     }
278 }
279
280 void
281 swf_action_list_print(swf_action_list_t *action_list, int indent_depth) {
282     
283     if (action_list) {
284         swf_action_t *action = action_list->head;
285         print_indent(indent_depth);
286         printf("action list:\n");
287         while(action) {
288             swf_action_print(action, indent_depth);
289             action = action->next;
290         }
291     }
292 }
293
294 int
295 swf_action_data_print(unsigned char *action_data, unsigned short action_data_len) {
296   unsigned char type;
297     unsigned char *data = action_data+1;
298     unsigned short data_len = action_data_len - 1;
299     data = action_data;
300     while (data < action_data + action_data_len) {
301         type = data[0];
302         data += 1;
303         switch (type) {
304           case 0x00: // String
305             printf("(String)%s", data);
306             data += strlen((char*) data) + 1; // text + \0
307             break;
308           case 0x01: // Float
309             printf("(Float)%f", GetFloatIEEE(data));
310             data += 4;
311             break;
312           case 0x02: // NULL
313             printf("(NULL)");
314             break;
315           case 0x03: // Undefined
316             printf("(Undefined)");
317             break;
318           case 0x04: // Register
319             printf("(Register)%d", (data[0]&0xff));
320             data += 1;
321             break;
322           case 0x05: // Boolean
323             printf("(Boolean)%s", (data[0]&0xff)?"true":"false");
324             data += 1;
325             break;
326           case 0x06: // Double
327             printf("(Double)%f", GetDoubleIEEE(data));
328             data += 8;
329             break;
330           case 0x07: // Integer
331             printf("(Integer)%ld", GetULongLE(data));
332             data += 4;
333             break;
334           case 0x08: // Dictionary Lookup
335             printf("(Dictionary Lookup)%d", data[0] & 0xff);
336             data += 1;
337             break;
338           case 0x09: // Large Dictionary Lookup
339             printf("(Large Dictionary Lookup)%d", GetUShortLE(data) & 0xffff);
340             data += 2;
341             break;
342           default:
343             printf("type=0x%02x len=%d", type, data_len);
344             break;
345         }
346     }
347     return 0;
348 }
349
350 int
351 swf_action_list_replace_strings(swf_action_list_t *action_list,
352                                 int *modified, y_keyvalue_t *kv) {
353     swf_action_t *action;
354     if (modified) {
355         *modified = 0;
356     }
357     for (action=action_list->head ; action ; action=action->next) {
358         if (action->action_id < 0x80) {
359             continue; // skip (no string)
360         }
361         switch(action->action_id) {
362           int type;
363           unsigned char *token;
364           int token_len;
365           bitstream_t *bs;
366           char *value;
367           int value_len;
368           int count;
369           int m = 0;
370           int i;
371         case 0x83: // Get URL
372             m = 0;
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);
377             if (value) {
378                 bitstream_putstring(bs, (unsigned char *) value, value_len);
379                 bitstream_putbyte(bs, '\0');
380                 m = 1;
381             } else {
382                 bitstream_putstring(bs, (unsigned char *) token, token_len);
383                 bitstream_putbyte(bs, '\0');
384             }
385             token +=  token_len + 1;
386             token_len = strlen((char *) token);
387             value = y_keyvalue_get(kv, (char *)token, token_len, &value_len);
388             if (value) {
389                 bitstream_putstring(bs, (unsigned char *)value, value_len);
390                 bitstream_putbyte(bs, '\0');
391                 m = 1;
392             } else {
393                 bitstream_putstring(bs, (unsigned char *)token, token_len);
394                 bitstream_putbyte(bs, '\0');
395             }
396             if (m) {
397                 unsigned long length;
398                 free(action->action_data);
399                 action->action_data = bitstream_steal(bs, &length);
400                 action->action_length = length;
401                 if (modified) {
402                     *modified = 1;
403                 }
404             }
405             bitstream_close(bs);
406             break;
407         case 0x88: // ActionConstantPool
408             m = 0;
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);
416                 if (value) {
417                     bitstream_putstring(bs, (unsigned char *)value, value_len);
418                     bitstream_putbyte(bs, '\0');
419                     m = 1;
420                 } else {
421                     bitstream_putstring(bs, (unsigned char *)token , token_len);
422                     bitstream_putbyte(bs, '\0');
423                 }
424                 token +=  token_len + 1;
425             }
426             if (m) {
427                 unsigned long length;
428                 free(action->action_data);
429                 action->action_data = bitstream_steal(bs, &length);
430                 action->action_length = length;
431                 if (modified) {
432                     *modified = 1;
433                 }
434             }
435             bitstream_close(bs);
436             break;
437         case 0x96: // Push Data
438             m = 0;
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[] = {
443                 -1, // 0: String
444                 4,  // 1: Float
445                 0,  // 2: NULL
446                 0,  // 3: Undefined
447                 1,  // 4: Register
448                 1,  // 5: Boolean
449                 8,  // 6: Double
450                 4,  // 7: Integer
451                 1,  // 8: Dictionary Lookup
452                 2,  // 9: Large Dictionary Lookup
453               };
454               type = token[0];
455               bitstream_putbyte(bs, type);
456               token += 1;
457               if (type == 0) { // String
458                 token_len = strlen((char *) token);
459                 value = y_keyvalue_get(kv, (char *)token, token_len, &value_len);
460                 if (value) {
461                     bitstream_putstring(bs, (unsigned char *)value, value_len);
462                     bitstream_putbyte(bs, '\0');
463                     m = 1;
464                 } else {
465                     bitstream_putstring(bs, (unsigned char *)token , token_len);
466                     bitstream_putbyte(bs, '\0');
467                 }
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];
472               } else {
473                 fprintf(stderr, "swf_action_list_replace_strings: illegal type=%d\n", type);
474                 bitstream_close(bs);
475                 return 1; // FAILURE
476               }
477             }
478             if (m) {
479                 unsigned long length;
480                 free(action->action_data);
481                 action->action_data = bitstream_steal(bs, &length);
482                 action->action_length = length;
483                 if (modified) {
484                     *modified = 1;
485                 }
486             }
487             bitstream_close(bs);
488             break;
489         }
490     }
491     return 0;
492 }
493
494 int
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;
504     } else {
505         action->action_data = NULL;
506         action->action_length = action_data_length;
507     }
508     action->next = list->head;
509     list->head = action;
510     if (list->tail == NULL) {
511         list->tail = action;
512     }
513     return 0;
514 }
515