2 A tool for modifying swfs on the tag level
4 Part of the swftools package.
6 Copyright (c) 2008/2009 Matthias Kramm <kramm@quiss.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
22 #include "../config.h"
27 #include "../lib/rfxswf.h"
28 #include "../lib/args.h"
30 static char * filename
= 0;
32 static char* output_filename
= "output.swf";
34 static struct options_t options
[] = {
41 int args_callback_option(char*name
,char*val
)
43 if(!strcmp(name
, "V")) {
44 printf("swfedit - part of %s %s\n", PACKAGE
, VERSION
);
46 } else if(!strcmp(name
, "v")) {
49 } else if(!strcmp(name
, "o")) {
50 output_filename
= val
;
53 printf("Unknown option: -%s\n", name
);
58 int args_callback_longoption(char*name
,char*val
)
60 return args_long2shortoption(options
, name
, val
);
62 void args_callback_usage(char *name
)
65 printf("Usage: %s [-v] file.swf > file.hexdump\n", name
);
66 printf("OR: %s file.hexdump\n", name
);
68 printf("-h , --help Print help and exit\n");
69 printf("-v , --verbose Be more verbose\n");
70 printf("-V , --version Print program version and exit\n");
73 int args_callback_command(char*name
,char*val
)
76 fprintf(stderr
, "Only one file allowed. You supplied at least two. (%s and %s)\n", filename
, name
);
82 void dumpTag(FILE*fo
, char*prefix
, TAG
*tag
)
85 for(t
=0;t
<tag
->len
;t
++) {
87 fprintf(fo
, "%s| ", prefix
);
88 fprintf(fo
, "%02x ", tag
->data
[t
]);
89 if((t
&& ((t
&15)==15)) || (t
==tag
->len
-1)) {
95 void dumpFile(SWF
*swf
, FILE*fo
)
97 TAG
* tag
= swf
->firstTag
;
103 memset(whitespace
, 32, 32); whitespace
[32] = 0;
105 fprintf(fo
, "Version: %d\n", swf
->fileVersion
);
106 fprintf(fo
, "FrameRate: %f\n",swf
->frameRate
/256.0);
107 fprintf(fo
, "FrameCount: %d\n",swf
->frameCount
);
108 fprintf(fo
, "Width: %.2f\n",(swf
->movieSize
.xmax
-swf
->movieSize
.xmin
)/20.0);
109 fprintf(fo
, "X-Offset: %.2f\n", swf
->movieSize
.xmin
/20.0);
110 fprintf(fo
, "Height: %.2f\n",(swf
->movieSize
.ymax
-swf
->movieSize
.ymin
)/20.0);
111 fprintf(fo
, "Y-Offset: %.2f\n", swf
->movieSize
.ymin
/20.0);
116 if(swf_isDefiningTag(tag
)) {
117 fprintf(fo
, "%s%s <%d>\n", prefix
, swf_TagGetName(tag
), swf_GetDefineID(tag
));
118 swf_SetTagPos(tag
, 2);
119 dumpTag(fo
, prefix
, tag
);
120 } else if(swf_isPseudoDefiningTag(tag
)) {
121 fprintf(fo
, "%s%s <%d>\n", prefix
, swf_TagGetName(tag
), swf_GetDefineID(tag
));
122 swf_SetTagPos(tag
, 2);
123 dumpTag(fo
, prefix
, tag
);
124 } else if(tag
->id
== ST_PLACEOBJECT
|| tag
->id
== ST_PLACEOBJECT2
) {
126 swf_GetPlaceObject(tag
, &po
);
127 fprintf(fo
, "%s%s <%d>\n", prefix
,swf_TagGetName(tag
), po
.id
);
129 swf_SetTagPos(tag
, 0);
130 dumpTag(fo
, prefix
, tag
);
131 swf_PlaceObjectFree(&po
);
133 fprintf(fo
, "%s%s\n", prefix
, swf_TagGetName(tag
));
134 dumpTag(fo
, prefix
, tag
);
137 if(tag
->id
== ST_DEFINESPRITE
) {
141 prefix
= &whitespace
[32-indent
];
142 } else if(tag
->id
== ST_END
) {
146 prefix
= &whitespace
[32-indent
];
153 static void readline(FILE*fi
, char*line
, int maxlen
) {
156 if(!fread(&line
[pos
],1,1,fi
))
159 /* cut of preceding whitespace */
160 if(pos
== 0 && (line
[0] == 32 || line
[0] == '\t'))
163 if(line
[pos
] == 13 || line
[pos
]==10)
170 /* cut off comments */
171 char*x
=strchr(line
,'#');
177 /* cut off trailing whitespace */
178 while(pos
>=1 && (line
[pos
-1]==32 || line
[pos
-1]==9)) {
188 while(*s
==32 || *s
=='\t') s
++;
189 sscanf(s
, "%f%n", &x
, &n
);
191 fprintf(stderr
, "Not a float: %s\n", s
);
198 while(*s
==32 || *s
=='\t') s
++;
199 sscanf(s
, "%d%n", &i
, &n
);
201 fprintf(stderr
, "Not an integer: %s\n", s
);
206 return (int)(getFloat(x
)*20);
211 int swf_TagNameToID(char*name
)
215 memset(&tag
, 0, sizeof(tag
));
217 lookup
= (char**)malloc(sizeof(char*)*65536);
218 for(t
=0;t
<65536;t
++) {
220 lookup
[t
] = swf_TagGetName(&tag
);
223 for(t
=0;t
<65536;t
++) {
224 if(lookup
[t
] && !strcasecmp(name
, lookup
[t
]))
227 fprintf(stderr
, "Not a tag name: \"%s\"\n", name
);
231 void parseFile(FILE*fi
, SWF
*swf
)
235 memset(swf
, 0, sizeof(SWF
));
238 readline(fi
, line
, 1024);
241 colon
= strchr(line
, ':');
243 int num
= colon
- line
;
245 if(num
== 9 && !strncmp(line
, "FrameRate", num
)) {
246 swf
->frameRate
= getFloat(colon
+1)*256;
247 } else if(num
== 10 && !strncmp(line
, "FrameCount", num
)) {
248 swf
->frameCount
= getInt(colon
+1);
249 } else if(num
== 7 && !strncmp(line
, "Version", num
)) {
250 swf
->fileVersion
= getInt(colon
+1);
251 } else if(num
== 5 && !strncmp(line
, "Width", num
)) {
252 int width
= getTwip(colon
+1);
253 swf
->movieSize
.xmax
+= width
;
254 } else if(num
== 6 && !strncmp(line
, "Height", num
)) {
255 int height
= getTwip(colon
+1);
256 swf
->movieSize
.ymax
+= height
;
257 } else if(num
== 8 && !strncmp(line
, "X-Offset", num
)) {
258 int xoffset
= getTwip(colon
+1);
259 swf
->movieSize
.xmin
+= xoffset
;
260 swf
->movieSize
.xmax
+= xoffset
;
261 } else if(num
== 8 && !strncmp(line
, "Y-Offset", num
)) {
262 int yoffset
= getTwip(colon
+1);
263 swf
->movieSize
.ymin
+= yoffset
;
264 swf
->movieSize
.ymax
+= yoffset
;
266 fprintf(stderr
, "Ignored line \"%s\"\n", line
);
273 readline(fi
, line
, 1024);
276 s
= strchr(line
, ' ');
277 br
= strchr(line
, '|');
280 /* DEFINESHAPE <id> ... type line */
282 tagname
= strdup(line
);
284 tagname
= strdup(line
);
287 id
= swf_TagNameToID(tagname
);
290 fprintf(stderr
, "Ignored line \"%s\"\n", line
);
293 tag
= swf_InsertTag(tag
, id
);
297 /* | 00 34 fe c7 ... type line */
303 fprintf(stderr
, "Discarded unassignable data %s\n", line
);
309 if((*p
>='a' && *p
<='f') ||
310 (*p
>='A' && *p
<='F')) {
315 else if(*p
>='0' && *p
<='9') {
332 char swf_IsSWF(char*filename
)
334 int fi
= open(filename
,O_RDONLY
|O_BINARY
);
340 if((buf
[0] == 'F' || buf
[0] == 'C') && buf
[1] == 'W' && buf
[2] == 'S')
345 int main (int argc
,char ** argv
)
351 processargs(argc
, argv
);
354 fprintf(stderr
, "You must supply a filename.\n");
357 if(swf_IsSWF(filename
)) {
358 fi
= open(filename
,O_RDONLY
|O_BINARY
);
360 perror("Couldn't open file: ");
363 if FAILED(swf_ReadSWF(fi
,&swf
)) {
364 fprintf(stderr
, "%s is not a valid SWF file or contains errors.\n",filename
);
368 dumpFile(&swf
, stdout
);
372 FILE*fi
= fopen(filename
, "rb");
373 parseFile(fi
, &newswf
);
376 char*sname
= output_filename
;
377 f
= open(sname
,O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
, 0644);
378 if FAILED(swf_WriteSWF(f
,&newswf
)) {
379 fprintf(stderr
, "Unable to write output file: %s\n", sname
);