X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=src%2Fswfextract.c;h=79ebf058868ac868d8d973a6522eb7170bfd5c7e;hp=f66dd83ffae1660a6d5ef4d5f88a46455ff78872;hb=5e60b81690ac5883abe4f68b61814b8764604fd1;hpb=cccb7ad998a2f0c6677fffabbb1c849e837b9eb6 diff --git a/src/swfextract.c b/src/swfextract.c index f66dd83..79ebf05 100644 --- a/src/swfextract.c +++ b/src/swfextract.c @@ -42,6 +42,8 @@ char* extractjpegids = 0; char* extractfontids = 0; char* extractpngids = 0; char* extractsoundids = 0; +char* extractbinaryids = 0; +char* extractanyids = 0; char extractmp3 = 0; char* extractname = 0; @@ -51,6 +53,7 @@ char originalplaceobjects = 0; char movetozero = 0; int numextracts = 0; +char *outputformat = NULL; struct options_t options[] = { @@ -60,6 +63,7 @@ struct options_t options[] = {"i","id"}, {"j","jpegs"}, {"p","pngs"}, + {"a","any"}, {"P","placeobject"}, {"0","movetozero"}, {"m","mp3"}, @@ -68,6 +72,8 @@ struct options_t options[] = {"f","frame"}, {"F","font"}, {"V","version"}, + {"b","binary"}, + {"O","outputformat"}, {0,0} }; @@ -137,6 +143,15 @@ int args_callback_option(char*name,char*val) extractsoundids = val; return 1; } + else if(!strcmp(name, "b")) { + if(extractbinaryids) { + fprintf(stderr, "Only one --binary argument is allowed. (Try to use a range, e.g. -s 1,2,3)\n"); + exit(1); + } + numextracts++; + extractbinaryids = val; + return 1; + } #ifdef _ZLIB_INCLUDED_ else if(!strcmp(name, "p")) { if(extractpngids) { @@ -148,6 +163,11 @@ int args_callback_option(char*name,char*val) return 1; } #endif + else if(!strcmp(name, "a")) { + numextracts++; + extractanyids = val; + return 1; + } else if(!strcmp(name, "f")) { numextracts++; extractframes = val; @@ -165,6 +185,10 @@ int args_callback_option(char*name,char*val) hollow = 1; return 0; } + else if (!strcmp(name, "O")) { + outputformat = val; + return 1; + } else { printf("Unknown option: -%s\n", name); exit(1); @@ -212,6 +236,23 @@ int args_callback_command(char*name,char*val) return 0; } +void prepare_name(char *buf, size_t len, const char *prefix, + const char *suffix, int idx) { + if (outputformat!=NULL) { + // override default file name formatting + // make sure single-file behavior is not used + numextracts = -1; + // Other parts of codebase use vsnprintf, so I assume snprintf + // is available on all platforms that swftools currently works on. + // We need to check for buffer overflows now that the user is + // supplying the format string. + snprintf(buf,len,outputformat,idx,suffix); + } else { + // use default file name formatting, unchanged + sprintf(buf,"%s%d.%s",prefix,idx,suffix); + } +} + U8 mainr,maing,mainb; /* 1 = used, not expanded, 3 = used, expanded @@ -483,9 +524,12 @@ int isOfType(int t, TAG*tag) if(t == 4 && (tag->id == ST_DEFINESOUND)) { show = 1; } - if(t == 5 && (tag->id == ST_DEFINEFONT || tag->id == ST_DEFINEFONT2)) { + if(t == 5 && (tag->id == ST_DEFINEFONT || tag->id == ST_DEFINEFONT2 || tag->id == ST_DEFINEFONT3)) { show = 1; } + if (t== 6 && (tag->id == ST_DEFINEBINARY)) { + show = 1; + } return show; } @@ -495,8 +539,8 @@ void listObjects(SWF*swf) char first; int t; int frame = 0; - char*names[] = {"Shape", "MovieClip", "JPEG", "PNG", "Sound", "Font"}; - char*options[] = {"-i", "-i", "-j", "-p", "-s", "-F"}; + char*names[] = {"Shape", "MovieClip", "JPEG", "PNG", "Sound", "Font", "Binary"}; + char*options[] = {"-i", "-i", "-j", "-p", "-s", "-F","-b"}; int mp3=0; printf("Objects in file %s:\n",filename); swf_FoldAll(swf); @@ -567,7 +611,7 @@ void listObjects(SWF*swf) printf(" [-m] 1 MP3 Soundstream\n"); } -void handlefont(SWF*swf, TAG*tag) +int handlefont(SWF*swf, TAG*tag) { SWFFONT* f=0; U16 id; @@ -576,21 +620,22 @@ void handlefont(SWF*swf, TAG*tag) int t; id = swf_GetDefineID(tag); - sprintf(name, "font%d.swf", id); + prepare_name(name, sizeof(name), "font", "swf", id); if(numextracts==1) { filename = destfilename; } swf_FontExtract(swf, id, &f); if(!f) { - printf("Couldn't extract font %d\n", id); - return; + if (!extractanyids) { + printf("Couldn't extract font %d\n", id); + } + return 0; } - if(!f->layout) - swf_FontCreateLayout(f); swf_WriteFont(f, filename); swf_FontFree(f); + return 1; } static char has_jpegtables=0; @@ -632,13 +677,13 @@ int findjpegboundary(U8*data, int len) } /* extract jpeg data out of a tag */ -void handlejpeg(TAG*tag) +int handlejpeg(TAG*tag) { char name[80]; char*filename = name; FILE*fi; - sprintf(name, "pic%d.jpg", GET16(tag->data)); + prepare_name(name, sizeof(name), "pic", "jpg", GET16(tag->data)); if(numextracts==1) { filename = destfilename; if(!strcmp(filename,"output.swf")) @@ -675,19 +720,27 @@ void handlejpeg(TAG*tag) else if(tag->id == ST_DEFINEBITSJPEG3 && tag->len>6) { U32 end = GET32(&tag->data[2])+6; int pos = findjpegboundary(&tag->data[6], tag->len-6); - if(pos<0) - return; - pos+=6; - fi = save_fopen(filename, "wb"); - fwrite(&tag->data[6], pos-6, 1, fi); - fwrite(&tag->data[pos+4], end-(pos+4), 1, fi); - fclose(fi); + if(pos<0) { + fi = save_fopen(filename, "wb"); + fwrite(&tag->data[6], end-6, 1, fi); + fclose(fi); + } else { + pos+=6; + fi = save_fopen(filename, "wb"); + fwrite(&tag->data[6], pos-6, 1, fi); + fwrite(&tag->data[pos+4], end-(pos+4), 1, fi); + fclose(fi); + } } else { int id = GET16(tag->data); - fprintf(stderr, "Object %d is not a JPEG picture!\n",id, jpegtables); - exit(1); + if (!extractanyids) { + fprintf(stderr, "Object %d is not a JPEG picture!\n", id); + exit(1); + } + return 0; } + return 1; } #ifdef _ZLIB_INCLUDED_ @@ -751,7 +804,7 @@ static void png_end_chunk(FILE*fi) This routine was originally meant to be a one-pager. I just didn't know png is _that_ much fun. :) -mk */ -void handlelossless(TAG*tag) +int handlelossless(TAG*tag) { char name[80]; char*filename = name; @@ -782,8 +835,11 @@ void handlelossless(TAG*tag) if(tag->id != ST_DEFINEBITSLOSSLESS && tag->id != ST_DEFINEBITSLOSSLESS2) { int id = GET16(tag->data); - fprintf(stderr, "Object %d is not a PNG picture!\n",id); - exit(1); + if (!extractanyids) { + fprintf(stderr, "Object %d is not a PNG picture!\n",id); + exit(1); + } + return 0; } id =swf_GetU16(tag); @@ -796,7 +852,7 @@ void handlelossless(TAG*tag) fprintf(stderr, "Can't handle 16-bit palette images yet (image %d)\n",id); else fprintf(stderr, "Unknown image type %d in image %d\n", format, id); - return; + return 0; } width = swf_GetU16(tag); height = swf_GetU16(tag); @@ -823,11 +879,11 @@ void handlelossless(TAG*tag) } while(error == Z_BUF_ERROR); if(error != Z_OK) { fprintf(stderr, "Zlib error %d (image %d)\n", error, id); - return; + return 0; } msg(" Uncompressed image is %d bytes (%d colormap)", datalen, (3+alpha)*cols); pos = 0; - datalen2 = datalen; + datalen2 = datalen+16; data2 = malloc(datalen2); palette = (RGBA*)malloc(cols*sizeof(RGBA)); @@ -840,7 +896,7 @@ void handlelossless(TAG*tag) } } - sprintf(name, "pic%d.png", id); + prepare_name(name, sizeof(name), "pic", "png", id); if(numextracts==1) { filename = destfilename; if(!strcmp(filename,"output.swf")) @@ -859,7 +915,7 @@ void handlelossless(TAG*tag) png_write_byte(fi,2); //rgb else if(format == 5 && alpha==1) png_write_byte(fi,6); //rgba - else return; + else return 0; png_write_byte(fi,0); //compression mode png_write_byte(fi,0); //filter mode @@ -925,7 +981,7 @@ void handlelossless(TAG*tag) if(compress (data2, &datalen2, data3, datalen3) != Z_OK) { fprintf(stderr, "zlib error in pic %d\n", id); - return; + return 0; } msg(" Compressed data is %d bytes", datalen2); png_start_chunk(fi, "IDAT", datalen2); @@ -937,6 +993,7 @@ void handlelossless(TAG*tag) free(data); free(data2); free(data3); + return 1; } #endif @@ -973,7 +1030,7 @@ void handlesoundstream(TAG*tag) } } -void handledefinesound(TAG*tag) +int handledefinesound(TAG*tag) { U8 flags; U32 samples; @@ -1007,8 +1064,10 @@ void handledefinesound(TAG*tag) } else if(format == 1) { // adpcm printf("Sound is ADPCM, format: %s samples/sec, %d bit, %s\n", rates[rate], bits, stereo?"stereo":"mono"); extension = "adpcm"; + } else { + return 0; } - sprintf(buf, "sound%d.%s", id, extension); + prepare_name(buf, sizeof(buf), "sound", extension, id); if(numextracts==1) { filename = destfilename; if(!strcmp(filename,"output.swf")) { @@ -1019,6 +1078,34 @@ void handledefinesound(TAG*tag) fi = save_fopen(filename, "wb"); fwrite(&tag->data[tag->pos], tag->len - tag->pos, 1, fi); fclose(fi); + return 1; +} + +int handlebinary(TAG*tag) { + FILE *fout = NULL; + char buf[100]; + char *filename = buf; + int len = tag->memsize; + int dx = 6; // offset to binary data + if (tag->id!=ST_DEFINEBINARY) { + if (!extractanyids) { + fprintf(stderr, "Object %d is not a binary entity!\n", + GET16(tag->data)); + } + return 0; + } + prepare_name(buf, sizeof(buf), "binary", "bin", GET16(tag->data)); + if(numextracts==1) { + filename = destfilename; + if(!strcmp(filename,"output.swf")) { + sprintf(buf, "output.bin"); + filename = buf; + } + } + fout = fopen(filename, "wb"); + fwrite(tag->data+dx,len-dx,1,fout); + fclose(fout); + return 1; } int main (int argc,char ** argv) @@ -1034,7 +1121,7 @@ int main (int argc,char ** argv) processargs(argc, argv); if(!extractframes && !extractids && ! extractname && !extractjpegids && !extractpngids - && !extractmp3 && !extractsoundids && !extractfontids) + && !extractmp3 && !extractsoundids && !extractfontids && !extractbinaryids && !extractanyids) listavailable = 1; if(!originalplaceobjects && movetozero) { @@ -1139,11 +1226,32 @@ int main (int argc,char ** argv) if(extractsoundids && is_in_range(id, extractsoundids)) { handledefinesound(tag); } + if(extractbinaryids && is_in_range(id, extractbinaryids)) { + handlebinary(tag); + } #ifdef _ZLIB_INCLUDED_ if(extractpngids && is_in_range(id, extractpngids)) { handlelossless(tag); } #endif + if(extractanyids && is_in_range(id, extractanyids)) { + if (handlefont(&swf,tag)) { + // pass + } else if (handlejpeg(tag)) { + // pass + } else if (handlebinary(tag)) { + // pass +#ifdef _ZLIB_INCLUDED_ + } else if (handlelossless(tag)) { + // pass +#endif + } else if (handledefinesound(tag)) { + // Not sure if sound code checks carefully for type. + // pass + } else { + printf("#%d not processed\n", id); + } + } } else if (tag->id == ST_SETBACKGROUNDCOLOR) { mainr = tag->data[0];