From 02b067c2aaa52b8b1d379ce977e9330744b34d97 Mon Sep 17 00:00:00 2001 From: yoya Date: Fri, 10 Oct 2008 10:04:34 +0000 Subject: [PATCH] =?utf8?q?=E4=BB=8A=E3=81=82=E3=82=8B=E3=83=95=E3=82=A1?= =?utf8?q?=E3=82=A4=E3=83=AB=E3=82=92=E5=85=A8=E3=81=A6=20trunk=20?= =?utf8?q?=E3=81=AB=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/swfed/trunk@64 7c90b180-03d5-4157-b861-58a559ae9d1e --- doc/install.txt | 8 + doc/readme.txt | 43 +++ sample/swfcompress.phps | 27 ++ sample/swfdump.phps | 13 + sample/swfgeteditstring.phps | 15 + sample/swfgetjpegalphadata.phps | 12 + sample/swfgetjpegdata.phps | 15 + sample/swfgetpngdata.phps | 15 + sample/swfgetsounddata.phps | 15 + sample/swfreplaceeditstring.phps | 24 ++ sample/swfreplacejpegdata.phps | 41 +++ sample/swfreplacemlddata.phps | 21 ++ sample/swfreplacepngdata.phps | 27 ++ src/bitstream.c | 360 ++++++++++++++++++ src/bitstream.h | 64 ++++ src/config.m4 | 63 ++++ src/jpeg_segment.c | 315 ++++++++++++++++ src/jpeg_segment.h | 46 +++ src/php_swfed.h | 105 ++++++ src/swf_action.c | 330 +++++++++++++++++ src/swf_action.h | 42 +++ src/swf_argb.c | 28 ++ src/swf_argb.h | 21 ++ src/swf_debug.c | 141 +++++++ src/swf_define.h | 51 +++ src/swf_header.c | 66 ++++ src/swf_header.h | 36 ++ src/swf_jpeg.c | 143 ++++++++ src/swf_jpeg.h | 21 ++ src/swf_object.c | 409 +++++++++++++++++++++ src/swf_object.h | 53 +++ src/swf_png.c | 395 ++++++++++++++++++++ src/swf_png.h | 19 + src/swf_rect.c | 67 ++++ src/swf_rect.h | 22 ++ src/swf_rgb.c | 26 ++ src/swf_rgb.h | 21 ++ src/swf_rgba.c | 28 ++ src/swf_rgba.h | 21 ++ src/swf_tag.c | 530 +++++++++++++++++++++++++++ src/swf_tag.h | 89 +++++ src/swf_tag_action.c | 117 ++++++ src/swf_tag_action.h | 36 ++ src/swf_tag_edit.c | 295 +++++++++++++++ src/swf_tag_edit.h | 76 ++++ src/swf_tag_jpeg.c | 315 ++++++++++++++++ src/swf_tag_jpeg.h | 60 +++ src/swf_tag_lossless.c | 428 ++++++++++++++++++++++ src/swf_tag_lossless.h | 67 ++++ src/swf_tag_sound.c | 212 +++++++++++ src/swf_tag_sound.h | 50 +++ src/swf_test.c | 33 ++ src/swf_xrgb.c | 28 ++ src/swf_xrgb.h | 21 ++ src/swfed.c | 769 +++++++++++++++++++++++++++++++++++++++ 55 files changed, 6295 insertions(+) create mode 100644 doc/install.txt create mode 100644 doc/readme.txt create mode 100644 sample/swfcompress.phps create mode 100644 sample/swfdump.phps create mode 100644 sample/swfgeteditstring.phps create mode 100644 sample/swfgetjpegalphadata.phps create mode 100644 sample/swfgetjpegdata.phps create mode 100644 sample/swfgetpngdata.phps create mode 100644 sample/swfgetsounddata.phps create mode 100644 sample/swfreplaceeditstring.phps create mode 100644 sample/swfreplacejpegdata.phps create mode 100644 sample/swfreplacemlddata.phps create mode 100644 sample/swfreplacepngdata.phps create mode 100644 src/bitstream.c create mode 100644 src/bitstream.h create mode 100644 src/config.m4 create mode 100644 src/jpeg_segment.c create mode 100644 src/jpeg_segment.h create mode 100644 src/php_swfed.h create mode 100644 src/swf_action.c create mode 100644 src/swf_action.h create mode 100644 src/swf_argb.c create mode 100644 src/swf_argb.h create mode 100644 src/swf_debug.c create mode 100644 src/swf_define.h create mode 100644 src/swf_header.c create mode 100644 src/swf_header.h create mode 100644 src/swf_jpeg.c create mode 100644 src/swf_jpeg.h create mode 100644 src/swf_object.c create mode 100644 src/swf_object.h create mode 100644 src/swf_png.c create mode 100644 src/swf_png.h create mode 100644 src/swf_rect.c create mode 100644 src/swf_rect.h create mode 100644 src/swf_rgb.c create mode 100644 src/swf_rgb.h create mode 100644 src/swf_rgba.c create mode 100644 src/swf_rgba.h create mode 100644 src/swf_tag.c create mode 100644 src/swf_tag.h create mode 100644 src/swf_tag_action.c create mode 100644 src/swf_tag_action.h create mode 100644 src/swf_tag_edit.c create mode 100644 src/swf_tag_edit.h create mode 100644 src/swf_tag_jpeg.c create mode 100644 src/swf_tag_jpeg.h create mode 100644 src/swf_tag_lossless.c create mode 100644 src/swf_tag_lossless.h create mode 100644 src/swf_tag_sound.c create mode 100644 src/swf_tag_sound.h create mode 100644 src/swf_test.c create mode 100644 src/swf_xrgb.c create mode 100644 src/swf_xrgb.h create mode 100644 src/swfed.c diff --git a/doc/install.txt b/doc/install.txt new file mode 100644 index 0000000..31b3305 --- /dev/null +++ b/doc/install.txt @@ -0,0 +1,8 @@ +% tar xvfz swfed-?.??.tar.gz +% cd src +% phpize +% ./configure +% make +% su +Password: +# cp modules/swfed.so /. diff --git a/doc/readme.txt b/doc/readme.txt new file mode 100644 index 0000000..f41cde5 --- /dev/null +++ b/doc/readme.txt @@ -0,0 +1,43 @@ + SWF Editor for PHP + 2008/08/08- yoya@awm.jp + +* introduce + + this is php extension for edit SWF file. + +* require + + - php on unix + - zlib and libpng + + +* sample + + - replace image id = 1 jpeg data + $swf = new SWFEditor(); + $swf->input($swfdata); + $swf->replaceJpegData(1, $jpegdata); + echo $swf->output(); + + - other sample code + http://svn.sourceforge.jp/svnroot/swfed/sample/ + +* demo + + - http://awm.jp/~yoya/php/flash/swfdump/ + - http://diary.awm.jp/~yoya/?20080331#200803311 + - http://diary.awm.jp/~yoya/?20080514#200805141 + + +* download + + - http://sourceforge.jp/projects/swfed/files/ release + - http://svn.sourceforge.jp/svnroot/swfed/ current + +* install + + - see install.txt + +* more information + + - http://sourceforge.jp/projects/swfed/wiki/ diff --git a/sample/swfcompress.phps b/sample/swfcompress.phps new file mode 100644 index 0000000..6630826 --- /dev/null +++ b/sample/swfcompress.phps @@ -0,0 +1,27 @@ +\n"); + exit(1); +} + +$swf_data = file_get_contents($swf_filename); + +$swf = new SWFEditor(); +$swf->input($swf_data); +$info = array('compress' => $compress); +$swf->setHeaderInfo($info); + +echo $swf->output(); diff --git a/sample/swfdump.phps b/sample/swfdump.phps new file mode 100644 index 0000000..536b576 --- /dev/null +++ b/sample/swfdump.phps @@ -0,0 +1,13 @@ +\n"); + exit(1); +} + +$swf_filename = $argv[1]; +$swfdata = file_get_contents($swf_filename); + +$obj = new SWFEditor(); +$obj->input($swfdata); +$obj->swfInfo(); diff --git a/sample/swfgeteditstring.phps b/sample/swfgeteditstring.phps new file mode 100644 index 0000000..5d824bd --- /dev/null +++ b/sample/swfgeteditstring.phps @@ -0,0 +1,15 @@ + \n"); + exit(1); +} + +$swf_filename = $argv[1]; +$var_name = $argv[2]; +$swfdata = file_get_contents($swf_filename); + +$obj = new SWFEditor(); +$obj->input($swfdata); + +echo $obj->getEditString($var_name) . "\n"; diff --git a/sample/swfgetjpegalphadata.phps b/sample/swfgetjpegalphadata.phps new file mode 100644 index 0000000..9fd8540 --- /dev/null +++ b/sample/swfgetjpegalphadata.phps @@ -0,0 +1,12 @@ + \n"); + exit(1); +} +$swf_filename = $argv[1]; +$image_id = $argv[2]; +$swfdata = file_get_contents($swf_filename); +$obj = new SWFEditor(); +$obj->input($swfdata); +echo $obj->getJpegAlpha($image_id); diff --git a/sample/swfgetjpegdata.phps b/sample/swfgetjpegdata.phps new file mode 100644 index 0000000..cc8ad19 --- /dev/null +++ b/sample/swfgetjpegdata.phps @@ -0,0 +1,15 @@ + \n"); + exit(1); +} + +$swf_filename = $argv[1]; +$image_id = $argv[2]; +$swfdata = file_get_contents($swf_filename); + +$obj = new SWFEditor(); +$obj->input($swfdata); + +echo $obj->getJpegData($image_id); diff --git a/sample/swfgetpngdata.phps b/sample/swfgetpngdata.phps new file mode 100644 index 0000000..47d9569 --- /dev/null +++ b/sample/swfgetpngdata.phps @@ -0,0 +1,15 @@ + \n"); + exit(1); +} + +$swf_filename = $argv[1]; +$image_id = $argv[2]; +$swfdata = file_get_contents($swf_filename); + +$obj = new SWFEditor(); +$obj->input($swfdata); + +echo $obj->getPNGData($image_id); diff --git a/sample/swfgetsounddata.phps b/sample/swfgetsounddata.phps new file mode 100644 index 0000000..1c3060e --- /dev/null +++ b/sample/swfgetsounddata.phps @@ -0,0 +1,15 @@ + \n"); + exit(1); +} + +$swf_filename = $argv[1]; +$sound_id = $argv[2]; +$swfdata = file_get_contents($swf_filename); + +$obj = new SWFEditor(); +$obj->input($swfdata); + +echo $obj->getSoundData($sound_id); diff --git a/sample/swfreplaceeditstring.phps b/sample/swfreplaceeditstring.phps new file mode 100644 index 0000000..c12361f --- /dev/null +++ b/sample/swfreplaceeditstring.phps @@ -0,0 +1,24 @@ + \n"); + exit(1); +} + +$swf_filename = $argv[1]; +$variable_name = $argv[2]; +$initial_text = $argv[3]; +$swfdata = file_get_contents($swf_filename); + +$obj = new SWFEditor(); +if ($obj->input($swfdata) == false) { + fprintf(STDERR, "input failed\n"); + exit (1); +} +if ($obj->replaceEditString($variable_name, $initial_text) == false) { + fprintf(STDERR, "replaceEditString($variable_name, ...) failed\n"); + exit (1); + +} + +echo $obj->output(); diff --git a/sample/swfreplacejpegdata.phps b/sample/swfreplacejpegdata.phps new file mode 100644 index 0000000..f4008af --- /dev/null +++ b/sample/swfreplacejpegdata.phps @@ -0,0 +1,41 @@ + [alpha_file]\n"); + exit(1); +} + +if ($argc > 3) { + $swf_filename = $argv[1]; + $image_id = $argv[2]; + $jpeg_filename = $argv[3]; + if ($argc > 4) { + $alpha_filename = $argv[4]; + } +} + +$swfdata = file_get_contents($swf_filename); +$jpegdata = file_get_contents($jpeg_filename); + +if (! empty($alpha_filename)) { + $alphadata = file_get_contents($alpha_filename); +} + +$obj = new SWFEditor(); +if ($obj->input($swfdata) == false) { + fprintf(STDERR, "input failed\n"); + exit (1); +} + +if (empty($alphadata)) { + $result = $obj->replaceJpegData($image_id, $jpegdata); +} else { + $result = $obj->replaceJpegData($image_id, $jpegdata, $alphadata); +} + +if ($result == false) { + fprintf(STDERR, "replaceJpegdata($image_id, ...) failed\n"); + exit (1); +} + +echo $obj->output(); diff --git a/sample/swfreplacemlddata.phps b/sample/swfreplacemlddata.phps new file mode 100644 index 0000000..b969114 --- /dev/null +++ b/sample/swfreplacemlddata.phps @@ -0,0 +1,21 @@ + [ [...]]\n"); + exit(1); +} + +$swf_filename = $argv[1]; + +$swfdata = file_get_contents($swf_filename); +$obj = new SWFEditor(); +$obj->input($swfdata); + +for ($i=2 ; $i< $argc ; $i += 2) { + $sound_id = $argv[$i]; + $mld_filename = $argv[$i+1]; + $mlddata = file_get_contents($mld_filename); + $obj->replaceMLDData($sound_id, $mlddata); +} + +echo $obj->output(); diff --git a/sample/swfreplacepngdata.phps b/sample/swfreplacepngdata.phps new file mode 100644 index 0000000..9a93131 --- /dev/null +++ b/sample/swfreplacepngdata.phps @@ -0,0 +1,27 @@ + [ [...]]\n"); + exit(1); +} + +$swf_filename = $argv[1]; + +$swfdata = file_get_contents($swf_filename); +$obj = new SWFEditor(); +if ($obj->input($swfdata) == false) { + fprintf(STDERR, "input failed\n"); + exit (1); +} + +for ($i=2 ; $i< $argc ; $i += 2) { + $image_id = $argv[$i]; + $png_filename = $argv[$i+1]; + $pngdata = file_get_contents($png_filename); + if ($obj->replacePNGData($image_id, $pngdata) == false) { + fprintf(STDERR, "replacePNGdata($image_id, ...) failed\n"); + exit (1); + } +} + +echo $obj->output(); diff --git a/src/bitstream.c b/src/bitstream.c new file mode 100644 index 0000000..eab51fc --- /dev/null +++ b/src/bitstream.c @@ -0,0 +1,360 @@ +/* + * bit stream routine + * (C) 2008/03/09- yoya@awm.jp + */ + +#include +#include +#include +#include "bitstream.h" + +static void bitstream_clear(bitstream_t *bs); + +bitstream_t * +bitstream_open(void) { + bitstream_t *bs = (bitstream_t *) calloc(sizeof(*bs), 1); + bs->data = NULL; + bs->data_len = 0; + bs->data_alloc_len = 0; + bs->byte_offset = 0; + bs->bit_offset = 0; + return bs; +} + +void +bitstream_close(bitstream_t * bs) { + if (bs->data) { + free(bs->data); + } + free(bs); + return ; +} + +static void +bitstream_clear(bitstream_t *bs) { + if (bs->data) { + free(bs->data); + bs->data = NULL; + } + bs->data_len = 0; + bs->data_alloc_len = 0; + bs->byte_offset = 0; + bs->bit_offset = 0; + return ; +} + +int +bitstream_realloc(bitstream_t *bs) { + unsigned char *data; + bs->data_alloc_len *= 2; + if (bs->data_alloc_len < BITSTREAM_DATA_LEN_MIN) { + bs->data_alloc_len = BITSTREAM_DATA_LEN_MIN; + } + data = (unsigned char *) realloc(bs->data, bs->data_alloc_len); + if (! data) { + fprintf(stderr, "bitstream_realloc: Can't realloc memory (%p, %ld)\n", + data, bs->data_alloc_len); + return 1; + } + bs->data = data; + return 0; +} + +int +bitstream_input(bitstream_t *bs, unsigned char *data, + unsigned long data_len) { + bitstream_clear(bs); + bs->data_alloc_len = data_len; + bs->data = malloc(bs->data_alloc_len); + memcpy(bs->data, data, data_len); + bs->data_len = data_len; + return 0; +} + +unsigned char * +bitstream_steal(bitstream_t *bs, unsigned long *length) { + unsigned char *data, *tmp; + *length = 0; + if (! bs) { + return NULL; + } + data = bs->data; + *length = bs->data_len; + if ((tmp = realloc(data, *length)) == NULL) { + fprintf(stderr, "Can't realloc\n"); + } + bs->data = NULL; + bs->data_len = 0; + bs->data_alloc_len = 0; + return data; +} + +unsigned char * +bitstream_output_sub(bitstream_t *bs, unsigned long offset, unsigned long length) { + unsigned char *data; + if (! bs) { + fprintf(stderr, "bs == NULL"); + return NULL; + } + if (bs->data_len < offset + length ) { + fprintf(stderr, "bitstream_output_sub: bs->data_len(%lu) < offset(%lu)+length(%lu)\n", + bs->data_len, offset, length); + return NULL; + } + data = malloc(length); + if (data == NULL) { + fprintf(stderr, "bitstream_output_sub: Can't malloc\n"); + return NULL; + } + memcpy(data, bs->data + offset, length); + return data; +} + +/* + * byte stream + */ + +int +bitstream_putbyte(bitstream_t *bs, int byte) { + bitstream_align(bs); + if (bs->data_len < bs->byte_offset ) { + return 1; + } + if (bs->data_len == bs->byte_offset ) { + if (bs->data_alloc_len <= bs->byte_offset ) { + bitstream_realloc(bs); + } + bs->data_len ++; + } + byte &= 0xff; + bs->data[bs->byte_offset] = (unsigned char) byte ; + bs->byte_offset++; + return 0; +} + +int +bitstream_getbyte(bitstream_t *bs) { + int byte; + bitstream_align(bs); + if (bs->data_len <= bs->byte_offset) { + return -1; /* End of Stream */ + } + byte = bs->data[bs->byte_offset] & 0xff; + bs->byte_offset++; + return byte; +} + +int +bitstream_putstring(bitstream_t *bs, + unsigned char *data, signed long data_len) { + bitstream_align(bs); + if (bs->data_len < bs->byte_offset ) { + return 1; + } + while(bs->data_alloc_len < bs->byte_offset + data_len) { + bitstream_realloc(bs); + } + bs->data_len = bs->byte_offset + data_len; + memcpy(bs->data + bs->byte_offset, data, data_len); + bs->byte_offset += data_len; + return 0; +} + +int +bitstream_getstring(bitstream_t *bs, + unsigned char *data, signed long data_len) { + bitstream_align(bs); + if (bs->data_len < bs->byte_offset + data_len) { + return -1; /* End of Stream */ + } + memcpy(data, bs->data + bs->byte_offset, data_len); + bs->byte_offset += data_len; + return 0; +} + +unsigned char * +bitstream_outputstring(bitstream_t *bs) { + unsigned char *data; + unsigned long data_len; + bitstream_align(bs); + data_len = strlen((char *) bs->data + bs->byte_offset); + data_len += 1; // + '\0' + if (bs->data_len < bs->byte_offset + data_len) { + return NULL; /* End of Stream */ + } + data = malloc(data_len); + if (data == NULL) { + fprintf(stderr, "bitstream_outputstring: can't malloc\n"); + return NULL; + } + memcpy(data, bs->data + bs->byte_offset, data_len); + bs->byte_offset += data_len; + return data; +} + +int +bitstream_putbytesLE(bitstream_t *bs, unsigned long bytes, int byte_width) { + int i; + unsigned long byte; + for (i=0; i < byte_width; i++) { + byte = bytes & 0xff; + bitstream_putbyte(bs, byte); + bytes >>= 8; + } + return 0; +} + +int +bitstream_putbytesBE(bitstream_t *bs, unsigned long bytes, int byte_width) { + int i; + unsigned long byte; + for (i=0; i < byte_width; i++) { + byte = bytes >> ( 8 * (byte_width - 1 - i)); + bitstream_putbyte(bs, byte & 0xff); + } + return 0; +} + +unsigned long +bitstream_getbytesLE(bitstream_t *bs, int byte_width) { + int i; + unsigned long byte, bytes = 0; + for (i=0; i < byte_width; i++) { + byte = bitstream_getbyte(bs); + byte <<= 8 * i; + bytes |= byte; + } + return bytes; +} + +unsigned long +bitstream_getbytesBE(bitstream_t *bs, int byte_width) { + int i; + unsigned long byte, bytes = 0; + for (i=0; i < byte_width; i++) { + bytes <<= 8; + byte = bitstream_getbyte(bs); + bytes |= byte; + } + return bytes; +} + +/* + * bit stream + */ + +int +bitstream_putbit(bitstream_t *bs, int bit) { + int byte; + if (bs->data_len <= bs->byte_offset) { +// fprintf(stderr, "bs->data_len(%ld) <= bs->byte_offset(%ld)\n", +// bs->data_len, bs->byte_offset); + if (bs->data_alloc_len <= bs->byte_offset) { + fprintf(stderr, "bitstream_putbit: alloc_len=%lu\n", bs->data_alloc_len); + bitstream_realloc(bs); + } + bs->data[bs->byte_offset] = 0; + bs->data_len ++; +// return 1; + } + bit &= 1; + byte = bs->data[bs->byte_offset]; + byte |= bit << (7 - bs->bit_offset); + bs->data[bs->byte_offset] = byte; + bitstream_incrpos(bs, 0, 1); + return 0; +} +int +bitstream_getbit(bitstream_t *bs) { + int bit, byte; + if (bs->data_len <= bs->byte_offset) { + fprintf(stderr, "bitstream_getbit: bs->data_len(%ld) <= bs->byte_offset(%ld)\n", + bs->data_len, bs->byte_offset); + return -1; /* End of Stream */ + } + byte = bs->data[bs->byte_offset]; + bit = byte >> (7 - bs->bit_offset); + bitstream_incrpos(bs, 0, 1); + return bit & 1; +} + +int +bitstream_putbits(bitstream_t *bs, unsigned long bits, int bit_width) { + int i, bit; + for (i=0; i < bit_width; i++) { + bit = bits >> (bit_width - 1 - i); + bit &= 1; + bitstream_putbit(bs, bit); + } + return 0; +} + +unsigned long +bitstream_getbits(bitstream_t *bs, int bit_width) { + int i; + int bit; + unsigned long bits = 0; + for (i=0; i < bit_width; i++) { + bit = bitstream_getbit(bs); + if (bit == -1) { + return -1; + } + bits |= bit << (bit_width - 1 - i); + } + return bits; +} + +void +bitstream_align(bitstream_t *bs) { + if (bs->bit_offset > 0) { + bs->byte_offset++; + bs->bit_offset = 0; + } +} + +/* + * stream seek + */ + +int +bitstream_incrpos(bitstream_t *bs, signed long byte_incr, + unsigned long bit_incr) { + bs->byte_offset += byte_incr; + bs->bit_offset += bit_incr; + while (bs->bit_offset >= 8) { + bs->bit_offset -= 8; + bs->byte_offset ++; + } + return 0; +} + +int +bitstream_setpos(bitstream_t *bs, unsigned long byte_offset, + unsigned long bit_offset) { + if (bs->data_len <= byte_offset ) { + fprintf(stderr, "bitstream_setpos: bs->data_len(%ld) <= byte_offset(%ld)\n", + bs->data_len, byte_offset); + } + bs->byte_offset = byte_offset; + bs->bit_offset = bit_offset; + return 0; +} + +unsigned long +bitstream_getbytepos(bitstream_t *bs) { + return bs->byte_offset; +} + +/* + * stream info + */ + +unsigned char * +bitstream_buffer(bitstream_t *bs, unsigned long byte_offset) { + return bs->data + byte_offset; +} + +unsigned long +bitstream_length(bitstream_t *bs) { + return bs->data_len; +} diff --git a/src/bitstream.h b/src/bitstream.h new file mode 100644 index 0000000..26a0d72 --- /dev/null +++ b/src/bitstream.h @@ -0,0 +1,64 @@ +#ifndef __BITSTREAM_H__ +#define __BITSTREAM_H__ + +#include "swf_define.h" /* for malloc */ + +/* + * bit stream routine + * (C) 2008/03/09- yoya@awm.jp + */ + +typedef struct bitstream_ { + /* raw data */ + unsigned char *data; + unsigned long data_len; + unsigned long data_alloc_len; + /* seek position */ + unsigned long byte_offset; + unsigned long bit_offset; +} bitstream_t; + +#define BITSTREAM_DATA_LEN_MIN 0x100 + +extern bitstream_t *bitstream_open(void); +extern void bitstream_close(bitstream_t * bs); + +/* load/save */ +extern int bitstream_input(bitstream_t *bs, unsigned char *data, + unsigned long data_len); +extern unsigned char *bitstream_steal(bitstream_t *bs, unsigned long *length); +extern unsigned char *bitstream_output_sub(bitstream_t *bs, unsigned long offset, unsigned long length); + +/* put/get */ +extern int bitstream_putbyte(bitstream_t *bs, int byte); +extern int bitstream_getbyte(bitstream_t *bs); +extern int bitstream_putstring(bitstream_t *bs, + unsigned char *data, signed long data_len); +extern int bitstream_getstring(bitstream_t *bs, + unsigned char *data, signed long data_len); +extern unsigned char *bitstream_outputstring(bitstream_t *bs); + +extern int bitstream_putbytesLE(bitstream_t *bs, unsigned long bytes, int byte_width); +extern int bitstream_putbytesBE(bitstream_t *bs, unsigned long bytes, int byte_width); +extern unsigned long bitstream_getbytesLE(bitstream_t *bs, int byte_width); +extern unsigned long bitstream_getbytesBE(bitstream_t *bs, int byte_width); +extern int bitstream_putbit(bitstream_t *bs, int bit); +extern int bitstream_getbit(bitstream_t *bs); +extern int bitstream_putbits(bitstream_t *bs, unsigned long bits, int bit_width); +extern unsigned long bitstream_getbits(bitstream_t *bs, int bit_width); +extern void bitstream_align(bitstream_t *bs); + +/* seeking */ +extern int bitstream_incrpos(bitstream_t *bs, signed long byte_incr, + unsigned long bit_incr); +extern int bitstream_setpos(bitstream_t *bs, unsigned long byte_offset, + unsigned long bit_offset); +extern unsigned long bitstream_getbytepos(bitstream_t *bs); + +extern int bitstream_realloc(bitstream_t *bs); + +/* direct access */ +extern unsigned char *bitstream_buffer(bitstream_t *bs, unsigned long byte_offset); +extern unsigned long bitstream_length(bitstream_t *bs); + +#endif /* __BITSTREAM_H__ */ diff --git a/src/config.m4 b/src/config.m4 new file mode 100644 index 0000000..69d20f6 --- /dev/null +++ b/src/config.m4 @@ -0,0 +1,63 @@ +dnl $Id$ +dnl config.m4 for extension swfed + +dnl Comments in this file start with the string 'dnl'. +dnl Remove where necessary. This file will not work +dnl without editing. + +dnl If your extension references something external, use with: + +dnl PHP_ARG_WITH(swfed, for swfed support, +dnl Make sure that the comment is aligned: +dnl [ --with-swfed Include swfed support]) + +dnl Otherwise use enable: + +PHP_ARG_ENABLE(swfed, whether to enable swfed support, +Make sure that the comment is aligned: +[ --enable-swfed Enable swfed support]) + +if test "$PHP_SWFED" != "no"; then + dnl Write more examples of tests here... + + dnl # --with-swfed -> check with-path + dnl SEARCH_PATH="/usr/local /usr" # you might want to change this + dnl SEARCH_FOR="/include/swfed.h" # you most likely want to change this + dnl if test -r $PHP_SWFED/$SEARCH_FOR; then # path given as parameter + dnl SWFED_DIR=$PHP_SWFED + dnl else # search default path list + dnl AC_MSG_CHECKING([for swfed files in default path]) + dnl for i in $SEARCH_PATH ; do + dnl if test -r $i/$SEARCH_FOR; then + dnl SWFED_DIR=$i + dnl AC_MSG_RESULT(found in $i) + dnl fi + dnl done + dnl fi + dnl + dnl if test -z "$SWFED_DIR"; then + dnl AC_MSG_RESULT([not found]) + dnl AC_MSG_ERROR([Please reinstall the swfed distribution]) + dnl fi + + dnl # --with-swfed -> add include path + dnl PHP_ADD_INCLUDE($SWFED_DIR/include) + + dnl # --with-swfed -> check for lib and symbol presence + dnl LIBNAME=swfed # you may want to change this + dnl LIBSYMBOL=swfed # you most likely want to change this + + dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, + dnl [ + dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SWFED_DIR/lib, SWFED_SHARED_LIBADD) + dnl AC_DEFINE(HAVE_SWFEDLIB,1,[ ]) + dnl ],[ + dnl AC_MSG_ERROR([wrong swfed lib version or lib not found]) + dnl ],[ + dnl -L$SWFED_DIR/lib -lm -ldl + dnl ]) + dnl + dnl PHP_SUBST(SWFED_SHARED_LIBADD) + + PHP_NEW_EXTENSION(swfed, swfed.c swf_object.c swf_header.c swf_rect.c swf_tag.c swf_tag_jpeg.c swf_tag_edit.c swf_tag_action.c swf_tag_lossless.c swf_tag_sound.c swf_rgb.c swf_rgba.c swf_argb.c swf_xrgb.c swf_action.c swf_jpeg.c bitstream.c jpeg_segment.c swf_png.c swf_debug.c, $ext_shared) +fi diff --git a/src/jpeg_segment.c b/src/jpeg_segment.c new file mode 100644 index 0000000..16d7e8a --- /dev/null +++ b/src/jpeg_segment.c @@ -0,0 +1,315 @@ +/* + ref code) http://diary.awm.jp/~yoya/data/2008/02/03/jpegdump.phps + + gcc -W -Wall -D__COMPONENT_DEBUG__ jpeg_segment.c bitstream.c +*/ + +#include +#include +#include "bitstream.h" +#include "jpeg_segment.h" +#include "swf_define.h" + +typedef struct jpeg_marker_name_ { + int marker; + char *name; +} jpeg_marker_name_t; + +jpeg_marker_name_t jpeg_marker_name_table[] = { + {0xD8, "SOI"}, + {0xE0, "APP0"}, {0xE1, "APP1"}, {0xE2, "APP2"}, {0xE3, "APP3"}, + {0xE4, "APP4"}, {0xE5, "APP5"}, {0xE6, "APP6"}, {0xE7, "APP7"}, + {0xE8, "APP8"}, {0xE9, "APP9"}, {0xEA, "APP10"},{0xEB, "APP11"}, + {0xEC, "APP12"},{0xED, "APP13"},{0xEE, "APP14"},{0xEF, "APP15"}, + {0xFE, "COM"}, + {0xDB, "DQT"}, + {0xC0, "SOF0"}, {0xC1, "SOF1"}, {0xC21, "SOF2"}, + {0xC4, "DHT"}, + {0xDA, "SOS"}, + {0xD0, "RST0"}, {0xD1, "RST1"}, {0xD2, "RST2"}, {0xD3, "RST3"}, + {0xD4, "RST4"} ,{0xD5, "RST5"}, {0xD6, "RST6"}, {0xD7, "RST7"}, + {0xDD, "DRI"}, + {0xD9, "EOI"}, +}; + +#define NumOfTable(t) (sizeof(t) / sizeof(*t)) + +char *jpeg_segment_get_marker_name(int marker) { + int i, marker_name_num = NumOfTable(jpeg_marker_name_table); + for(i=0; i < marker_name_num; i++) { + if (marker == jpeg_marker_name_table[i].marker) { + return jpeg_marker_name_table[i].name; + } + } + return "Unknown"; +} + +jpeg_segment_t *jpeg_segment_create(void) { + jpeg_segment_t *jpeg_seg = calloc(sizeof(*jpeg_seg), 1); + if (jpeg_seg == NULL) { + fprintf(stderr, "jpeg_segment_create: Can't alloc memory\n"); + return NULL; + } + jpeg_seg->head = NULL; + jpeg_seg->tail = NULL; + return jpeg_seg; +} + +void jpeg_segment_append(jpeg_segment_t *jpeg_seg, + int marker, + unsigned char *data_ref, unsigned long data_len) { + jpeg_segment_node_t *node = jpeg_seg->head; + jpeg_segment_node_t *new_node; + new_node = calloc(sizeof(*node), 1); + if (new_node == NULL) { + fprintf(stderr, "jpeg_segment_append: jpeg_segment_create failed\n"); + return ; + } + if (jpeg_seg->head == NULL) { + jpeg_seg->head = new_node; + } else { + jpeg_seg->tail->next = new_node; + } + jpeg_seg->tail = new_node; + new_node->marker = marker; + new_node->data_ref = data_ref; + new_node->data_len = data_len; + return ; +} + +jpeg_segment_t *jpeg_segment_parse(unsigned char *data, + unsigned long data_len) { + bitstream_t *bs; + jpeg_segment_t *jpeg_seg; + int marker1; + unsigned len; + bs = bitstream_open(); + bitstream_input(bs, data, data_len); + jpeg_seg = jpeg_segment_create(); + + while((marker1 = bitstream_getbyte(bs)) >= 0) { + if (marker1 != 0xFF) { + fprintf(stderr, "marker1=0x%02X", marker1); + jpeg_segment_destroy(jpeg_seg); + bitstream_close(bs); + return NULL; + } + int marker2 = bitstream_getbyte(bs); + int next_marker2; + switch(marker2) { + unsigned long sos_offset; + case -1: + /* removed segment */ + break; + case 0xD8: // SOI (Start of Image) + case 0xD9: // EOI (End of Image) + jpeg_segment_append(jpeg_seg, marker2, NULL, 0); + break; + case 0xDA: // SOS + case 0xD0: case 0xD1: case 0xD2: case 0xD3: // RST + case 0xD4: case 0xD5: case 0xD6: case 0xD7: // RST + sos_offset = bitstream_getbytepos(bs); + while((marker1 = bitstream_getbyte(bs)) >= 0) { + if (marker1 != 0xFF) { + continue; + } + next_marker2 = bitstream_getbyte(bs); + if (next_marker2 == 0x00) { + continue; + } + bitstream_incrpos(bs, -2, 0); + jpeg_segment_append(jpeg_seg, marker2, data + sos_offset, + bitstream_getbytepos(bs) - sos_offset); + break; + } + break; + default: + len = bitstream_getbytesBE(bs, 2) - 2; + jpeg_segment_append(jpeg_seg, marker2, + data + bitstream_getbytepos(bs), + len); + bitstream_incrpos(bs, len, 0); + break; + } + } + bitstream_close(bs); + return jpeg_seg; +} + +int jpeg_segment_contain(jpeg_segment_t *jpeg_seg, int marker) { + jpeg_segment_node_t *node; + for (node = jpeg_seg->head; node; node = node->next) { + if (node->marker == marker) { + return 1; + } + } + return 0; +} + +unsigned char *jpeg_segment_steal_node(jpeg_segment_t *jpeg_seg, + int marker, + unsigned long *length) { + jpeg_segment_node_t *node; + unsigned char *data; + *length = 0; + for (node = jpeg_seg->head; node; node = node->next) { + if (node->marker == marker) { + data = node->data_ref; + *length = node->data_len; + node->marker = -1; // remove mark; + node->data_ref = NULL; + node->data_len = 0; + return data; + } + } + return NULL; +} + +int +jpeg_segment_delete_node(jpeg_segment_t *jpeg_seg, int marker) { + jpeg_segment_node_t *node; + int count = 0; + for (node = jpeg_seg->head; node; node = node->next) { + if (node->marker == marker) { + node->marker = -1; // remove mark; + if (node->data_ref) { + free(node->data_ref); + node->data_ref = NULL; + } + node->data_len = 0; + count ++; + } + } + return count; +} +int +jpeg_segment_peek_marker(jpeg_segment_t *jpeg_seg) { + jpeg_segment_node_t *node; + for (node = jpeg_seg->head; node; node = node->next) { + if (node->marker != -1) { + return node->marker; + } + } + return -1; +} + +void jpeg_segment_print(jpeg_segment_t *jpeg_seg) { + int i; + jpeg_segment_node_t *node; + if (jpeg_seg == NULL) { + fprintf(stderr, "jpeg_segment_print: jpeg_seg == NULL\n"); + return ; + } + node = jpeg_seg->head; + for (i=0; node; i++) { + char *marker_name; + if (node->marker >= 0) { + marker_name = jpeg_segment_get_marker_name(node->marker); + printf("(%d) marker=%s(FF%02X): length=%lu\n", + i, marker_name?marker_name:"Unknown", + node->marker, node->data_len); + } + node = node->next; + } +} + +extern unsigned char *jpeg_segment_output(jpeg_segment_t *jpeg_seg, + unsigned long *length) { + bitstream_t *bs; + unsigned char *data; + jpeg_segment_node_t *node; + *length = 0; + node = jpeg_seg->head; + bs = bitstream_open(); + for (; node; node = node->next) { + int marker2 = node->marker; + if (marker2 == -1) { + continue; + } + bitstream_putbyte(bs, 0xFF); // marker1 + bitstream_putbyte(bs, marker2); // marker2 + switch(marker2) { + case 0xD8: // SOI (Start of Image) + case 0xD9: // EOI (End of Image) + /* nothing to do */ + break; + default: + bitstream_putbytesBE(bs, node->data_len + 2, 2); + /* no break */ + case 0xDA: // SOS + case 0xD0: case 0xD1: case 0xD2: case 0xD3: // RST + case 0xD4: case 0xD5: case 0xD6: case 0xD7: // RST + bitstream_putstring(bs, node->data_ref, node->data_len); + break; + } + } + data = bitstream_steal(bs, length); + bitstream_close(bs); + return data; +} +void jpeg_segment_destroy(jpeg_segment_t *jpeg_seg) { + jpeg_segment_node_t *node, *next_node; + if (jpeg_seg == NULL) { + return ; + } + node = jpeg_seg->head; + while(node) { + next_node = node->next; + /* node->data_ref no free!! */ + free(node); + node = next_node; + } + free(jpeg_seg); +} + +#ifdef __COMPONENT_DEBUG__ /* for component debug */ + +#include + +int main(int argc, char **argv) { + char *filename; + struct stat sbuf; + FILE *fp, *fp_out = NULL; + unsigned char *data, *output_data; + unsigned long data_len, output_data_len; + jpeg_segment_t *jpeg_seg; + if ((argc != 2) && (argc != 3)) { + fprintf(stderr, "Usage: %s []\n", argv[0]); + return EXIT_FAILURE; + } + filename = argv[1]; + if (stat(filename, &sbuf)) { + fprintf(stderr, "Can't stat file(%s)\n", filename); + return EXIT_FAILURE; + } + data_len = sbuf.st_size; + fp = fopen(filename, "rb"); + if (fp == NULL) { + fprintf(stderr, "Can't open infile(%s)\n", filename); + return EXIT_FAILURE; + } + data = malloc(data_len); + if (fread(data, 1, data_len, fp) != data_len) { + fclose(fp); + return 1; + } + fclose(fp); + jpeg_seg = jpeg_segment_parse(data, data_len); + jpeg_segment_print(jpeg_seg); + if (argc == 3) { + fp_out = fopen(argv[2], "wb"); + if (fp_out == NULL) { + fprintf(stderr, "Can't open outfile(%s)\n", argv[2]); + return EXIT_FAILURE; + } + output_data = jpeg_segment_output(jpeg_seg, &output_data_len); + fwrite(output_data, output_data_len, 1, fp_out); + fclose(fp_out); + free(output_data); + } + jpeg_segment_destroy(jpeg_seg); + free(data); + return EXIT_SUCCESS; +} + +#endif diff --git a/src/jpeg_segment.h b/src/jpeg_segment.h new file mode 100644 index 0000000..f412ab8 --- /dev/null +++ b/src/jpeg_segment.h @@ -0,0 +1,46 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + + +#ifndef __JPEG_SEGMENT_H__ +#define __JPEG_SEGMENT_H__ + +typedef struct jpeg_segment_node_ { + int marker; + unsigned char *data_ref; /* do NOT free! */ + unsigned long data_len; + struct jpeg_segment_node_ *next; +} jpeg_segment_node_t; + +typedef struct jpeg_segment_ { + jpeg_segment_node_t *head, *tail; +} jpeg_segment_t; + +extern jpeg_segment_t *jpeg_segment_create(void); + +extern void jpeg_segment_append(jpeg_segment_t *jpeg_seg_head, + int marker, + unsigned char *data, + unsigned long data_len); + +extern jpeg_segment_t *jpeg_segment_parse(unsigned char *data, + unsigned long data_len); + +extern int jpeg_segment_contain(jpeg_segment_t *jpeg_seg, int marker); +extern unsigned char *jpeg_segment_steal_node(jpeg_segment_t *jpeg_seg, + int marker, + unsigned long *length); +extern int jpeg_segment_delete_node(jpeg_segment_t *jpeg_seg, int marker); +extern int jpeg_segment_peek_marker(jpeg_segment_t *jpeg_seg); + +extern void jpeg_segment_print(jpeg_segment_t *jpeg_seg); +extern unsigned char *jpeg_segment_output(jpeg_segment_t *jpeg_seg, + unsigned long *length); +extern void jpeg_segment_destroy(jpeg_segment_t *jpeg_seg); + +extern char *jpeg_segment_get_marker_name(int marker); + +#endif /* __JPEG_SEGMENT_H__ */ diff --git a/src/php_swfed.h b/src/php_swfed.h new file mode 100644 index 0000000..f1948b7 --- /dev/null +++ b/src/php_swfed.h @@ -0,0 +1,105 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2006 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +/* $Id: header,v 1.16.2.1 2006/01/01 12:50:00 sniper Exp $ */ + +#ifndef PHP_SWFED_H +#define PHP_SWFED_H + +extern zend_module_entry swfed_module_entry; +#define phpext_swfed_ptr &swfed_module_entry + +#ifdef PHP_WIN32 +#define PHP_SWFED_API __declspec(dllexport) +#else +#define PHP_SWFED_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +PHP_MINIT_FUNCTION(swfed); +PHP_MSHUTDOWN_FUNCTION(swfed); +PHP_RINIT_FUNCTION(swfed); +PHP_RSHUTDOWN_FUNCTION(swfed); +PHP_MINFO_FUNCTION(swfed); + +PHP_FUNCTION(confirm_swfed_compiled); /* For testing, remove later. */ + +static zend_class_entry *swfeditor_ce; + +PHP_METHOD(swfed, __construct); +PHP_METHOD(swfed, input); +PHP_METHOD(swfed, output); +PHP_METHOD(swfed, getHeaderInfo); +PHP_METHOD(swfed, setHeaderInfo); +PHP_METHOD(swfed, getTagList); +PHP_METHOD(swfed, getTagDetail); +PHP_METHOD(swfed, getTagInfo); +PHP_METHOD(swfed, getTagData); +PHP_METHOD(swfed, getJpegData); +PHP_METHOD(swfed, getJpegAlpha); +PHP_METHOD(swfed, replaceJpegData); +PHP_METHOD(swfed, getPNGData); +PHP_METHOD(swfed, replacePNGData); +PHP_METHOD(swfed, getSoundData); +PHP_METHOD(swfed, replaceMLDData); +PHP_METHOD(swfed, getEditString); +PHP_METHOD(swfed, replaceEditString); +PHP_METHOD(swfed, getActionData); +PHP_METHOD(swfed, disasmActionData); +PHP_METHOD(swfed, swfInfo); + +/* + Declare any global variables you may need between the BEGIN + and END macros here: + +ZEND_BEGIN_MODULE_GLOBALS(swfed) + long global_value; + char *global_string; +ZEND_END_MODULE_GLOBALS(swfed) +*/ + +/* In every utility function you add that needs to use variables + in php_swfed_globals, call TSRMLS_FETCH(); after declaring other + variables used by that function, or better yet, pass in TSRMLS_CC + after the last function argument and declare your utility function + with TSRMLS_DC after the last declared argument. Always refer to + the globals in your function as SWFED_G(variable). You are + encouraged to rename these macros something shorter, see + examples in any other php module directory. +*/ + +#ifdef ZTS +#define SWFED_G(v) TSRMG(swfed_globals_id, zend_swfed_globals *, v) +#else +#define SWFED_G(v) (swfed_globals.v) +#endif + +#endif /* PHP_SWFED_H */ + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/src/swf_action.c b/src/swf_action.c new file mode 100644 index 0000000..6242844 --- /dev/null +++ b/src/swf_action.c @@ -0,0 +1,330 @@ +#include +#include +#include "bitstream.h" +#include "swf_action.h" + +swf_action_info_t swf_action_info_table[] = { + { 0x00, "End" }, + /* nothing 0x01 - 0x03 */ + { 0x04, "Next Frame" }, + { 0x05, "Previous Frame" }, + { 0x06, "Play" }, + { 0x07, "Stop" }, + { 0x08, "Toggle Quality" }, + { 0x09, "Stop Sound" }, + { 0x0A, "Add" }, + { 0x0B, "Subtract" }, + { 0x0C, "Multiply" }, + { 0x0D, "Divide" }, + { 0x0E, "Equal" }, + { 0x0F, "Less Than" }, + { 0x10, "Logical And" }, + { 0x11, "Logical Or " }, + { 0x12, "Logical Not" }, + { 0x13, "String Equal" }, + { 0x14, "String Length" }, + { 0x15, "SubString" }, + /* nothing 0x16 */ + { 0x17, "Pop"}, + { 0x18, "Integral Part"}, + /* nothing 0x19 - 0x1B */ + { 0x1C, "Get Variable"}, + { 0x1D, "Set Variable"}, + /* nothing 0x1E - 0x1F */ + { 0x20, "Set Target" }, + { 0x21, "Concatenate Strings"}, + { 0x22, "Get Property" }, + { 0x23, "Set Property" }, + { 0x24, "Duplicate Sprite" }, + { 0x25, "Remove Sprite" }, + { 0x26, "Trace" }, + { 0x27, "Start Drag" }, + { 0x28, "Stop Drag" }, + { 0x29, "String Less Than"}, + { 0x2A, "Throw" }, + { 0x2B, "Cast Object" }, + { 0x2C, "implements" }, + { 0x2D, "FSCommand2" }, + /* nothing 0x2E-2F */ + { 0x30, "Random" }, + { 0x31, "String Length(multibyte)" }, + { 0x32, "Ord" }, + { 0x33, "Chr"}, + { 0x34, "Get Timer" }, + { 0x35, "SubString(multibyte)" }, + { 0x36, "Ord(multibyte)" }, + { 0x37, "Chr(multibyte)" }, + /* nothing 0x28-29 */ + { 0x3A, "Delete" }, + { 0x3B, "Delete All" }, + { 0x3C, "Set Local Variable" }, + { 0x3D, "Call Function" }, + { 0x3E, "Return" }, + { 0x3F, "Modulo" }, + { 0x40, "New" }, + { 0x41, "Declare Local Variable" }, + { 0x42, "Declare Array" }, + { 0x43, "Declare Object" }, + { 0x44, "Type Of" }, + { 0x45, "Get Targer" }, + { 0x46, "Enumerate" }, + { 0x47, "Add(typed)" }, + { 0x48, "Less Than(typed)" }, + { 0x49, "Equal(typed)" }, + { 0x4A, "Number" }, + { 0x4B, "String" }, + { 0x4C, "Duplicate" }, + { 0x4D, "Swap" }, + { 0x4E, "Get Member" }, + { 0x4F, "Set Member" }, + { 0x50, "Increment" }, + { 0x51, "Decrement" }, + { 0x52, "Call Method" }, + { 0x53, "New Method" }, + { 0x54, "Instance Of" }, + { 0x55, "Enumerate Object" }, + /* nothing 0x56 - 0x5F */ + { 0x60, "And" }, + { 0x61, "Or" }, + { 0x62, "XOr" }, + { 0x63, "Shift Left" }, + { 0x64, "Shift Right" }, + { 0x65, "Shift Right Unsigned" }, + { 0x66, "Strict Equal" }, + { 0x67, "Greater Than(typed)" }, + { 0x68, "String Greater Than(typed)" }, + { 0x69, "Extends" }, + /* nothing 0x6A - 0x80 */ + { 0x81, "Goto Frame" }, + /* nothing 0x82 */ + { 0x83, "Get URL" }, + /* nothing 0x84 - 0x86 */ + { 0x87, "Store Register" }, + { 0x88, "Declare Dictionary" }, + { 0x89, "Strict Mode" }, + { 0x8A, "Wait For Frame" }, + { 0x8B, "Set Target" }, + { 0x8C, "Goto Label" }, + { 0x8D, "Wait For Frame(dynamic)" }, + { 0x8E, "Declare Function (with 256 registers)"}, + { 0x8F, "Try"}, + /* nothing 0x90 - 0x93 */ + { 0x94, "With"}, + /* nothing 0x95 */ + { 0x96, "Push Data" }, + /* nothing 0x97 - 0x98 */ + { 0x99, "Branch Always" }, + { 0x9A, "Get URL2" }, + { 0x9B, "Declare Function" }, + /* nothing 0x9C */ + { 0x9D, "Branch If True" }, + { 0x9E, "Call Frame" }, + { 0x9F, "Goto Expression" }, +}; + +swf_action_info_t * +get_swf_action_info(int action_id) { + int i, action_info_num = NumOfTable(swf_action_info_table); + for (i=0; i < action_info_num; i++) { + if (action_id == swf_action_info_table[i].id) { + return &(swf_action_info_table[i]); + } + } + return NULL; +} + +int +swf_action_parse(bitstream_t *bs, swf_action_t *act) { + unsigned long offset; + bitstream_align(bs); + act->action_id = bitstream_getbyte(bs); + if (act->action_id & 0x80) { + act->action_has_length = 1; + } else { + act->action_has_length = 0; + } + if (act->action_has_length) { + act->action_length = bitstream_getbytesLE(bs, 2); + offset = bitstream_getbytepos(bs); + act->action_data = malloc(act->action_length); + if (act->action_data == NULL) { + fprintf(stderr, "Can't alloc memory for act->action_data\n"); + return 1; + } + bitstream_getstring(bs, act->action_data, act->action_length); + } + return 0; +} + +int +swf_action_build(bitstream_t *bs, swf_action_t *act) { + bitstream_align(bs); + /* bitstream_putbits(bs, act->action_has_length, 1); no need */ + bitstream_putbyte(bs, act->action_id); + if (act->action_has_length) { + if (act->action_data == NULL) { + return 1; // error + } + bitstream_putbytesLE(bs, act->action_length, 2); + bitstream_putstring(bs, act->action_data, act->action_length); + } + return 0; +} + +int +swf_action_print(swf_action_t *act) { + swf_action_info_t *act_info = get_swf_action_info(act->action_id); + if (act_info && act_info->name) { + printf("%s", act_info->name); + } else { + printf("0x%02x", act->action_id); + } + if (act->action_has_length) { + int i, n; + unsigned char *d; + switch(act->action_id) { + case 0x83: // Get URL + printf(" (String)%s", act->action_data); + printf(" (String)%s", + act->action_data + strlen(act->action_data) + 1); + break; + case 0x88: // Declare Dictionary + d = act->action_data; + n = GetUShortLE(act->action_data); d += 2; + printf(":\n"); + for(i=0; iaction_data, act->action_length); + break; + default: + printf(" len=%d", act->action_length); + break; + } + } + printf("\n"); + return 0; +} + + +swf_action_list_t * +swf_action_list_create(bitstream_t *bs) { + swf_action_list_t *action_list; + swf_action_t *action; + action_list = calloc(sizeof(*action_list), 1); + if (action_list == NULL) { + fprintf(stderr, "Can't alloc memory for action_list\n"); + return NULL; + } + do { + action = calloc(sizeof(*action), 1); + if (action == NULL) { + fprintf(stderr, "Can't alloc memory for action\n"); + break; + } + swf_action_parse(bs, action); + if (action_list->head == NULL) { + action_list->head = action_list->tail = action; + } else { + action_list->tail->next = action; + action_list->tail = action; + } + action->next = NULL; + } while(action->action_id != 0); // End Action; + return action_list; +} +unsigned char * +swf_action_list_output(swf_action_list_t *list, unsigned long *length) { + swf_action_t *action; + bitstream_t *bs; + unsigned char *data; + *length = 0; + bs = bitstream_open(); + for (action = list->head; action ; action = action->next) { + swf_action_build(bs, action); + } + data = bitstream_steal(bs, length); + bitstream_close(bs); + return data; +} +void +swf_action_list_destroy(swf_action_list_t *action_list) { + + if (action_list) { + swf_action_t *action = action_list->head; + while (action) { + swf_action_t *action_next = action->next; + if (action->action_data) { + free(action->action_data); + } + free(action); + action = action_next; + } + free(action_list); + } +} + +void +swf_action_list_print(swf_action_list_t *action_list) { + + if (action_list) { + swf_action_t *action = action_list->head; + while(action) { + printf("\t"); + swf_action_print(action); + action = action->next; + } + } +} + +int swf_action_data_print(unsigned char *action_data, unsigned short action_data_len) { + unsigned char type = action_data[0] & 0xff; + unsigned char *data = action_data+1; + unsigned short data_len = action_data_len - 1; + int result = 1; // type field + switch (type) { + case 0x00: // String + printf("(String)%*s", data_len, data); + result += strlen((char*) data) + 1; // text + \0 + break; + case 0x01: // Float + printf("(Float)XXX"); + break; + case 0x02: // NULL + printf("(NULL)"); + break; + case 0x03: // Undefined + printf("(Undefined)"); + break; + case 0x04: // Register + printf("(Register)%d", (data[0]&0xff)); + break; + case 0x05: // Boolean + printf("(Boolean)%s", (data[0]&0xff)?"true":"false"); + result += 1; + break; + case 0x06: // Double + printf("(Double)%f", GetDoubleIEEE(data)); + break; + case 0x07: // Integer + printf("(Integer)%ld", GetULongLE(data)); + result += 4; + break; + case 0x08: // Dictionary Lookup + printf("(Dictionary Lookup)%d", data[0] & 0xff); + result += 1; + break; + case 0x09: // Large Dictionary Lookup + printf("(Large Dictionary Lookup)%d", GetUShortLE(data) & 0xffff); + result += 2; + break; + default: + printf("type=0x%02x len=%d", type, data_len); + break; + } + return result; +} diff --git a/src/swf_action.h b/src/swf_action.h new file mode 100644 index 0000000..2c262da --- /dev/null +++ b/src/swf_action.h @@ -0,0 +1,42 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_ACTION_H__ +#define __SWF_ACTION_H__ + +typedef struct swf_action_ { + unsigned char action_has_length; + unsigned char action_id; + unsigned short action_length; + unsigned char *action_data; + struct swf_action_ *next; // self reference structure +} swf_action_t; + +typedef struct swf_action_list_ { + swf_action_t *head, *tail; +} swf_action_list_t; + +typedef struct swf_action_info_ { + int id; + char *name; +} swf_action_info_t; + +extern swf_action_info_t *get_swf_action_info(int action_id); + +extern int swf_action_parse(bitstream_t *bs, swf_action_t *act); +extern int swf_action_build(bitstream_t *bs, swf_action_t *act); +extern int swf_action_print(swf_action_t *act); + +extern swf_action_list_t *swf_action_list_create(bitstream_t *bs); +extern unsigned char *swf_action_list_output(swf_action_list_t *list, + unsigned long *length); +extern void swf_action_list_destroy(swf_action_list_t *act_list); +extern void swf_action_list_print(swf_action_list_t *act_list); + +extern int swf_action_data_print(unsigned char *action_data, + unsigned short action_data_len); + +#endif /* __SWF_ACTION_H__ */ diff --git a/src/swf_argb.c b/src/swf_argb.c new file mode 100644 index 0000000..13e7efa --- /dev/null +++ b/src/swf_argb.c @@ -0,0 +1,28 @@ +#include +#include "bitstream.h" +#include "swf_argb.h" + +int +swf_argb_parse(bitstream_t *bs, swf_argb_t *color) { + color->alpha = bitstream_getbyte(bs); + color->red = bitstream_getbyte(bs); + color->green = bitstream_getbyte(bs); + color->blue = bitstream_getbyte(bs); + return 0; +} + +int +swf_argb_build(bitstream_t *bs, swf_argb_t *color) { + bitstream_putbyte(bs, color->alpha); + bitstream_putbyte(bs, color->red); + bitstream_putbyte(bs, color->green); + bitstream_putbyte(bs, color->blue); + return 0; +} + +int +swf_argb_print(swf_argb_t *color) { + printf("alpha=0x%02x red=0x%02x green=0x%02X blue=0x%02x\n", + color->alpha, color->red, color->green, color->blue); + return 0; +} diff --git a/src/swf_argb.h b/src/swf_argb.h new file mode 100644 index 0000000..5d3c9dd --- /dev/null +++ b/src/swf_argb.h @@ -0,0 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_ARGB_H__ +#define __SWF_ARGB_H__ + +typedef struct swf_argb_ { + unsigned char alpha; + unsigned char red; + unsigned char green; + unsigned char blue; +} swf_argb_t; + +extern int swf_argb_parse(bitstream_t *bs, swf_argb_t *color); +extern int swf_argb_build(bitstream_t *bs, swf_argb_t *color); +extern int swf_argb_print(swf_argb_t *color); + +#endif /* __SWF_ARGB_H__ */ diff --git a/src/swf_debug.c b/src/swf_debug.c new file mode 100644 index 0000000..78a2356 --- /dev/null +++ b/src/swf_debug.c @@ -0,0 +1,141 @@ +#include +#include + +// #include "swf_define.h" no include + +int swf_debug = 0; + +#define MALLOC_DEBUG_TABLE_NUM 0x20000 + +static struct malloc_debug_ { + void *ptr; + char *filename; + int linenum; +} malloc_debug_table[MALLOC_DEBUG_TABLE_NUM]; + + +void malloc_debug_start(void) { + int i; + for(i=0; i new_ptr=%p (%s,%d)\n", +// ptr, new_ptr, filename, linenum); + for(i=0; i=0; j--) { + printf("%d", (c >> j) & 1); + + } + printf("\n"); + } while(0); +#endif + } + printf("\n"); + return ; +} diff --git a/src/swf_define.h b/src/swf_define.h new file mode 100644 index 0000000..9aa67b1 --- /dev/null +++ b/src/swf_define.h @@ -0,0 +1,51 @@ +#ifndef __SWF_DEFINE__H__ +#define __SWF_DEFINE__H__ + +#include + +#define SWF_TWIPS 20 +#define SWF_MAGIC_SIZE 4 +#define SWF_FILE_LENGTH_SIZE 4 +#define SWF_HEADER_SIZE 8 + +extern int swf_debug; + +extern void malloc_debug_start(void); +extern void malloc_debug_end(void); + +#ifdef MALLOC_DEBUG /* malloc debug */ +extern void *calloc_debug(size_t nmemb, size_t size, char *filename, int linenum); +extern void *malloc_debug(size_t size, char *filename, int linenum); +extern void free_debug(void *ptr, char *filename, int linenum); +extern void *realloc_debug(void *ptr, size_t size, char *filename, int linenum); + +#define calloc(n,s) calloc_debug(n,s,__FILE__,__LINE__) +#define malloc(s) malloc_debug(s,__FILE__,__LINE__) +#define free(p) free_debug(p,__FILE__,__LINE__) +#define realloc(p,s) realloc_debug(p,s,__FILE__,__LINE__) + +extern void print_hexbin(unsigned char *data, int data_len); + +#endif + +#if 0 /* PHP Extension */ +#define calloc(n,s) ecalloc(n,s) +#define malloc(s) emalloc(s) +#define free(p) efree(p) +#define realloc(p,s) erealloc(p,s) +#endif + +#define NumOfTable(t) (sizeof(t) / sizeof(*t)) + + +#define GV2B(a,b) ((a << 8) + b) +#define GV4B(a,b,c,d) GV2B(GV2B(GV2B(a,b),c),d) +#define GV8B(a,b,c,d,e,f,g,h) GV2B(GV2B(GV2B(GV2B(GV2B(GV2B(GV2B(a,b),c),d),e),f),g),h) + +#define GetUShortLE(data) ((unsigned short) GV2B(data[1], data[0])) + +#define GetULongLE(data) ((unsigned long) GV4B(data[3], data[2], data[1], data[0])) +#define GetDoubleIEEE(data) ((double) GV8B(data[4], data[5], data[6], data[7], data[0], data[1], data[2], data[3])) + +#endif /* __SWF_DEFINE__H__ */ + diff --git a/src/swf_header.c b/src/swf_header.c new file mode 100644 index 0000000..4e37c1d --- /dev/null +++ b/src/swf_header.c @@ -0,0 +1,66 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include "swf_define.h" +#include "swf_header.h" + +int +swf_header_parse(bitstream_t *bs, swf_header_t *header) { + bitstream_getstring(bs, header->magic, 3); + header->version = bitstream_getbyte(bs); + header->file_length = bitstream_getbytesLE(bs, 4); + return 0; +} +int +swf_header_build(bitstream_t *bs, swf_header_t *header) { + if (bitstream_putstring(bs, header->magic, 3)) { + return 1; + } + if (bitstream_putbyte(bs, header->version)) { + return 1; + } + if (bitstream_putbytesLE(bs, header->file_length, 4)) { + return 1; + } + return 0; +} + +int +swf_header_movie_parse(bitstream_t *bs, + swf_header_movie_t *header_movie) { + swf_rect_parse(bs, &header_movie->frame_size); + header_movie->frame_rate_decimal = bitstream_getbyte(bs); + header_movie->frame_rate_integral = bitstream_getbyte(bs); + header_movie->frame_count = bitstream_getbytesLE(bs, 2); + return 0; +} + +int +swf_header_movie_build(bitstream_t *bs, + swf_header_movie_t *header_movie) { + swf_rect_build(bs, &header_movie->frame_size); + bitstream_putbyte(bs, header_movie->frame_rate_decimal); + bitstream_putbyte(bs, header_movie->frame_rate_integral); + bitstream_putbytesLE(bs, header_movie->frame_count, 2); + return 0; +} + +int swf_header_print(swf_header_t *header) { + printf("magic=%s version=%d file_length=%lu\n", + header->magic, header->version, header->file_length); + return 0; +} + +int swf_header_movie_print(swf_header_movie_t *header_movie) { + swf_rect_print(&header_movie->frame_size); + printf("frame_rate=%d.%d frame_count=%d\n", + header_movie->frame_rate_integral, + header_movie->frame_rate_decimal, + header_movie->frame_count); + return 0; +} + diff --git a/src/swf_header.h b/src/swf_header.h new file mode 100644 index 0000000..a75c885 --- /dev/null +++ b/src/swf_header.h @@ -0,0 +1,36 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_HEADER_H__ +#define __SWF_HEADER_H__ + +#include "bitstream.h" +#include "swf_rect.h" + +typedef struct swf_header_ { + unsigned char magic[4]; // 'FWS' or 'CWS' + '\0'; + unsigned char version; + unsigned long file_length; +} swf_header_t; + + +typedef struct swf_header_movie_ { + swf_rect_t frame_size; + unsigned short frame_rate_integral; + unsigned short frame_rate_decimal; + unsigned short frame_count; +} swf_header_movie_t; + +extern int swf_header_parse(bitstream_t *bs, swf_header_t *header); +extern int swf_header_build(bitstream_t *bs, swf_header_t *header); +extern int swf_header_print(swf_header_t *header); + +extern int swf_header_movie_parse(bitstream_t *bs, swf_header_movie_t *header_movie); +extern int swf_header_movie_build(bitstream_t *bs, swf_header_movie_t *header_movie); +extern int swf_header_movie_print(swf_header_movie_t *header_movie); + +#endif /* __SWF_HEADER_H__ */ + diff --git a/src/swf_jpeg.c b/src/swf_jpeg.c new file mode 100644 index 0000000..831d993 --- /dev/null +++ b/src/swf_jpeg.c @@ -0,0 +1,143 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include "bitstream.h" +#include "swf_jpeg.h" +#include "jpeg_segment.h" + +unsigned char * +jpegconv_std2swf(unsigned char *data, unsigned long data_len, + unsigned long *length) { + jpeg_segment_t *jpeg_data = NULL; + jpeg_segment_t *jpeg_output; + unsigned char *d; + unsigned long d_len; + int m; + unsigned char *ret_data; + jpeg_data = jpeg_segment_parse(data, data_len); + if (jpeg_data == NULL) { + fprintf(stderr, "jpegconv_std2swf: Can't create jpeg segment for data\n"); + return NULL; + } + jpeg_output = jpeg_segment_create(); + if (jpeg_output == NULL) { + fprintf(stderr, + "jpegconv_std2swf: Can't create jpeg segment for output\n"); + jpeg_segment_destroy(jpeg_data); + return NULL; + } + /* 並び替え */ + // 圧縮テーブル部 + jpeg_segment_append(jpeg_output, 0xD8, NULL, 0); // SOI + while ((d = jpeg_segment_steal_node(jpeg_data, 0xDB, &d_len)) != NULL) { + jpeg_segment_append(jpeg_output, 0xDB, d, d_len); // DQT + } + while ((d = jpeg_segment_steal_node(jpeg_data, 0xC4, &d_len)) != NULL) { + jpeg_segment_append(jpeg_output, 0xC4, d, d_len); // DHT + } + jpeg_segment_append(jpeg_output, 0xD9, NULL, 0); // EOI + // 画像実データ部 (APP 等も含む) + while((m = jpeg_segment_peek_marker(jpeg_data)) >= 0) { + d = jpeg_segment_steal_node(jpeg_data, m, &d_len); + jpeg_segment_append(jpeg_output, m, d, d_len); + } + ret_data = jpeg_segment_output(jpeg_output, length); + jpeg_segment_destroy(jpeg_data); + jpeg_segment_destroy(jpeg_output); + return ret_data; +} + +unsigned char * +jpegconv_swf2std(unsigned char *data, unsigned long data_len, + unsigned long *length, unsigned char *table_data, + unsigned long table_data_len) { + jpeg_segment_t *jpeg_data, *jpeg_table = NULL; + jpeg_segment_t *jpeg_output; + int m; + unsigned char *d; + unsigned long d_len; + unsigned char *ret_data; + *length = 0; + jpeg_data = jpeg_segment_parse(data, data_len); + if (jpeg_data == NULL) { + fprintf(stderr, "jpegconv_swf2std: Can't create jpeg segment for data\n"); + return NULL; + } + if (jpeg_segment_contain(jpeg_data, 0xDB)) { + /* 圧縮テーブルが含まれている場合 */ + jpeg_table = jpeg_segment_create(); + if (jpeg_table == NULL) { + fprintf(stderr, + "jpegconv_swf2std: Can't create jpeg segment for table\n"); + jpeg_segment_destroy(jpeg_data); + return NULL; + } + while ((d = jpeg_segment_steal_node(jpeg_data, 0xDB, &d_len)) != NULL) { + jpeg_segment_append(jpeg_table, 0xDB, d, d_len); // DQT + } + while ((d = jpeg_segment_steal_node(jpeg_data, 0xC4, &d_len)) != NULL) { + jpeg_segment_append(jpeg_table, 0xC4, d, d_len); // DHT + } + } else if (table_data && table_data_len) { + /* 圧縮テーブルが入っていない場合は JPEGTables を参照 */ + jpeg_table = jpeg_segment_parse(table_data, table_data_len); + if (jpeg_table == NULL) { + fprintf(stderr, "Can't create jpeg segment for table\n"); + jpeg_segment_destroy(jpeg_data); + return NULL; + } + } else { + fprintf(stderr, "jpegconv_swf2std: not found jpeg table segment\n"); + jpeg_segment_destroy(jpeg_data); + return NULL; + } + /* 並び替え */ + jpeg_segment_delete_node(jpeg_data, 0xD8); // SOI + jpeg_segment_delete_node(jpeg_data, 0xD9); // EOI + jpeg_output = jpeg_segment_create(); + if (jpeg_output == NULL) { + fprintf(stderr, "jpegconv_swf2std: Can't create jpeg segment for output\n"); + jpeg_segment_destroy(jpeg_data); + jpeg_segment_destroy(jpeg_table); + return NULL; + } + jpeg_segment_append(jpeg_output, 0xD8, NULL, 0); // SOI + /* 圧縮テーブルを退避 */ + /* SOF0,1,2 マーカーの手前まで構成 */ + while((m = jpeg_segment_peek_marker(jpeg_data)) >= 0) { + if ((m == 0xC0) || (m == 0xC1) || (m == 0xC2)) { // SOF0,1,2 + break; + } + d = jpeg_segment_steal_node(jpeg_data, m, &d_len); + jpeg_segment_append(jpeg_output, m, d, d_len); + }; + while ((d = jpeg_segment_steal_node(jpeg_table, 0xDB, &d_len)) != NULL) { + jpeg_segment_append(jpeg_output, 0xDB, d, d_len); // DQT + } + /* SOF0,1,2 を構成 */ + while((m = jpeg_segment_peek_marker(jpeg_data)) >= 0) { + if ((m != 0xC0) && (m != 0xC1) && (m != 0xC2)) { // SOF0,1,2 + break; + } + d = jpeg_segment_steal_node(jpeg_data, m, &d_len); + jpeg_segment_append(jpeg_output, m, d, d_len); + } + while ((d = jpeg_segment_steal_node(jpeg_table, 0xC4, &d_len)) != NULL) { + jpeg_segment_append(jpeg_output, 0xC4, d, d_len); // DHT + } + while((m = jpeg_segment_peek_marker(jpeg_data)) >= 0) { + d = jpeg_segment_steal_node(jpeg_data, m, &d_len); + jpeg_segment_append(jpeg_output, m, d, d_len); + } + jpeg_segment_append(jpeg_output, 0xD9, NULL, 0); // EOI + ret_data = jpeg_segment_output(jpeg_output, length); + jpeg_segment_destroy(jpeg_data); + jpeg_segment_destroy(jpeg_table); + jpeg_segment_destroy(jpeg_output); + return ret_data; +} diff --git a/src/swf_jpeg.h b/src/swf_jpeg.h new file mode 100644 index 0000000..69af038 --- /dev/null +++ b/src/swf_jpeg.h @@ -0,0 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_JPEG__H__ +#define __SWF_JPEG__H__ + +/* for DefineBitsJPEG2,3*/ +extern unsigned char *jpegconv_std2swf(unsigned char *data, + unsigned long data_len, + unsigned long *length); +/* for DefineBitsJPEG(1),2,3*/ +extern unsigned char *jpegconv_swf2std(unsigned char *data, + unsigned long data_len, + unsigned long *length, + unsigned char *table_data, + unsigned long table_data_len); + +#endif /* __SWF_JPEG__H__ */ diff --git a/src/swf_object.c b/src/swf_object.c new file mode 100644 index 0000000..e995ad2 --- /dev/null +++ b/src/swf_object.c @@ -0,0 +1,409 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include // memcmp +#include +#include "bitstream.h" +#include "swf_define.h" +#include "swf_tag_action.h" +#include "swf_tag_jpeg.h" +#include "swf_tag_lossless.h" +#include "swf_action.h" +#include "swf_object.h" + +swf_object_t * +swf_object_open(void) { + swf_object_t *swf; + malloc_debug_start(); /* DEBUG XXX */ + swf = (swf_object_t *) calloc(sizeof(*swf), 1); + return swf; +} + +void +swf_object_close(swf_object_t *swf) { + swf_tag_t *tag, *next_tag; + if (! swf) { + return ; + } + for(tag = swf->tag; tag; tag = next_tag) { + next_tag = tag->next; + swf_tag_destroy(tag); + } + free(swf); + malloc_debug_end(); /* DEBUG XXX */ + return ; +} +int +swf_object_input(swf_object_t *swf, unsigned char *data, + unsigned long data_len) { + int result; + bitstream_t *bs = bitstream_open(); + swf_tag_t **tag; + bitstream_input(bs, data, data_len); + result = swf_header_parse(bs, &swf->header); + if (result) { + bitstream_close(bs); + return result; + } + if (memcmp(swf->header.magic, "FWS", 3) == 0) { + ; // OK + } else if (memcmp(swf->header.magic, "CWS", 3) == 0) { + int result; + unsigned char *old_buff, *new_buff; + unsigned long origsize; + old_buff = bitstream_buffer(bs, SWF_HEADER_SIZE); + origsize = swf->header.file_length - SWF_HEADER_SIZE; + new_buff = malloc(origsize); + result = uncompress(new_buff, &origsize, old_buff, bs->data_len - SWF_HEADER_SIZE); + if (result != Z_OK) { + if (result == Z_MEM_ERROR) { + fprintf(stderr, "swf_object_input: uncompress Z_MEM_ERROR: can't malloc\n"); + } else if (result == Z_BUF_ERROR) { + fprintf(stderr, "swf_object_input: uncompress Z_BUF_ERROR: not enough buff size\n"); + } else { + fprintf(stderr, "swf_object_input: uncompress failed by unknown reason\n"); + } + free(new_buff); + bitstream_close(bs); + return 1; // FAILURE + } + bitstream_putstring(bs, new_buff, origsize); + free(new_buff); + bitstream_setpos(bs, SWF_HEADER_SIZE, 0); + } else { + fprintf(stderr, "swf_object_input: unknown magic %s\n", swf->header.magic); + bitstream_close(bs); + return 1; // FAILURE + } + result = swf_header_movie_parse(bs, &swf->header_movie); + if (result) { + bitstream_close(bs); + return result; + } + tag = &swf->tag; + while(1) { + long pos; + pos = bitstream_getbytepos(bs); + if ((pos == -1) || ((long) swf->header.file_length <= pos)) { + break; + } + *tag = swf_tag_create(bs); + if (tag == NULL) { + fprintf(stderr, "swf_object_input: swf_tag_create failed\n"); + } + tag = &((*tag)->next); + } + bitstream_close(bs); + return 0; +} + +unsigned char * +swf_object_output(swf_object_t *swf, unsigned long *length) { + int result; + swf_tag_t *tag; + unsigned char *data; + bitstream_t *bs = bitstream_open(); + *length = 0; + result = swf_header_build(bs, &swf->header); + if (result) { + bitstream_close(bs); + return NULL; + } + result = swf_header_movie_build(bs, &swf->header_movie); + if (result) { + bitstream_close(bs); + return NULL; + } + for (tag = swf->tag; tag; tag = tag->next) { + swf_tag_build(bs, tag, swf); + } + swf->header.file_length = bitstream_getbytepos(bs); + bitstream_setpos(bs, SWF_MAGIC_SIZE, 0); + bitstream_putbytesLE(bs, swf->header.file_length, + SWF_FILE_LENGTH_SIZE); + if (memcmp(swf->header.magic, "FWS", SWF_MAGIC_SIZE) == 0) { + ; // OK + } else if (memcmp(swf->header.magic, "CWS", SWF_MAGIC_SIZE) == 0) { + int result; + unsigned long compsize; + unsigned char *new_buff, *old_buff; + bitstream_setpos(bs, SWF_HEADER_SIZE, 0); + old_buff = bitstream_buffer(bs, SWF_HEADER_SIZE); + new_buff = malloc(swf->header.file_length - SWF_HEADER_SIZE); + result = compress(new_buff, &compsize, old_buff, + bs->data_len - SWF_HEADER_SIZE); + if (result != Z_OK) { + if (result == Z_MEM_ERROR) { + fprintf(stderr, "swf_object_output: compress Z_MEM_ERROR: can't malloc\n"); + } else if (result == Z_BUF_ERROR) { + fprintf(stderr, "swf_object_output: compress Z_BUF_ERROR: not enough buff size\n"); + } else { + fprintf(stderr, "swf_object_output: compress failed by unknown reason\n"); + } + bitstream_close(bs); + return NULL; // FAILURE + } + bitstream_putstring(bs, new_buff, compsize); + free(new_buff); + } else { + fprintf(stderr, "swf_object_output: unknown magic %s\n", swf->header.magic); + bitstream_close(bs); + return NULL; // FAILURE + } + data = bitstream_steal(bs, length); + bitstream_close(bs); + return data; +} +void +swf_object_print(swf_object_t *swf) { + int i; + swf_tag_t *tag; + swf_header_print(&swf->header); + swf_header_movie_print(&swf->header_movie); + tag = swf->tag; + for (i=0; tag; i++) { + printf("[%d] ", i); + swf_tag_print(tag, swf); + if (tag->tag == 0) { // END Tag + break; + } + tag = tag->next; + } +} + + +/* --- */ + +unsigned char * +swf_object_get_jpegdata(swf_object_t *swf, unsigned long *length, int image_id) { + swf_tag_t *tag, *tag_jpegtables = NULL; + unsigned char *data = NULL; + *length = 0; + if (swf == NULL) { + fprintf(stderr, "swf_object_get_jpegdata: swf == NULL\n"); + return NULL; + } + for (tag = swf->tag; tag; tag = tag->next) { + if (tag->tag == 8) { // JPEGTables + tag_jpegtables = tag; + break; + } + } + for (tag = swf->tag; tag; tag = tag->next) { + if (tag->tag == 8) { + tag_jpegtables = tag; + continue; + } + // DefineBitsJPEG(1),2,3 + if ((tag->tag != 6) && (tag->tag != 21) && (tag->tag != 35)) { + continue; + } + data = swf_tag_get_jpeg_data(tag, length, image_id, tag_jpegtables); + if (data) { + break; + } + } + return data; +} + +unsigned char * +swf_object_get_alphadata(swf_object_t *swf, unsigned long *length, int image_id) { + swf_tag_t *tag; + unsigned char *data = NULL; + *length = 0; + if (swf == NULL) { + fprintf(stderr, "swf_object_get_alphadata: swf == NULL\n"); + return NULL; + } + for (tag = swf->tag; tag; tag = tag->next) { + if (tag->tag != 35) { // ! DefineBitsJPEG3 + continue; + } + data = swf_tag_get_alpha_data(tag, length, image_id); + if (data) { + break; + } + } + return data; +} + + +int +swf_object_replace_jpegdata(swf_object_t *swf, int image_id, + unsigned char *jpeg_data, + unsigned long jpeg_data_len, + unsigned char *alpha_data, + unsigned long alpha_data_len) { + int result = 1; + swf_tag_t *tag; + if (swf == NULL) { + fprintf(stderr, "swf_object_replace_jpegdata: swf == NULL\n"); + return 1; + } + for (tag = swf->tag; tag; tag = tag->next) { + result = swf_tag_replace_jpeg_data(tag, image_id, + jpeg_data, jpeg_data_len, + alpha_data, alpha_data_len); + if (! result) { + break; + } + } + return result; +} + + +unsigned char * +swf_object_get_pngdata(swf_object_t *swf, unsigned long *length, int image_id) { + swf_tag_t *tag; + unsigned char *data = NULL; + *length = 0; + if (swf == NULL) { + fprintf(stderr, "swf_object_get_pngdata: swf == NULL\n"); + return NULL; + } + for (tag = swf->tag; tag; tag = tag->next) { + // DefineBitsLossless(1),2 + if ((tag->tag != 20) && (tag->tag != 36)) { + continue; + } + data = swf_tag_get_png_data(tag, length, image_id); + if (data) { + break; + } + } + return data; +} + +int +swf_object_replace_pngdata(swf_object_t *swf, int image_id, + unsigned char *png_data, + unsigned long png_data_len) { + int result = 1; + swf_tag_t *tag; + if (swf == NULL) { + fprintf(stderr, "swf_object_replace_pngdata: swf == NULL\n"); + return 1; + } + for (tag = swf->tag; tag; tag = tag->next) { + result = swf_tag_replace_png_data(tag, image_id, + png_data, png_data_len); + if (! result) { + break; + } + } + return result; +} + +unsigned char * +swf_object_get_sounddata(swf_object_t *swf, unsigned long *length, int sound_id) { + swf_tag_t *tag; + unsigned char *data = NULL; + *length = 0; + if (swf == NULL) { + fprintf(stderr, "swf_object_get_sounddata: swf == NULL\n"); + return NULL; + } + for (tag = swf->tag; tag; tag = tag->next) { + // DefineSound + if (tag->tag != 14) { + continue; + } + data = swf_tag_get_sound_data(tag, length, sound_id); + if (data) { + break; + } + } + return data; +} + +int +swf_object_replace_melodata(swf_object_t *swf, int sound_id, + unsigned char *melo_data, + unsigned long melo_data_len) { + int result = 1; + swf_tag_t *tag; + if (swf == NULL) { + fprintf(stderr, "swf_object_replace_melodata: swf == NULL\n"); + return 1; + } + for (tag = swf->tag; tag; tag = tag->next) { + result = swf_tag_replace_melo_data(tag, sound_id, + melo_data, melo_data_len); + if (! result) { + break; + } + } + return result; +} + +char * +swf_object_get_editstring(swf_object_t *swf, + char *variable_name, + int variable_name_len) { + swf_tag_t *tag; + char *data = NULL; + if (swf == NULL) { + fprintf(stderr, "swf_object_get_editstring: swf == NULL\n"); + return NULL; + } + for (tag = swf->tag; tag; tag = tag->next) { + data = swf_tag_get_edit_string(tag, variable_name, + variable_name_len, swf); + if (data) { + break; + } + } + return data; +} +int +swf_object_replace_editstring(swf_object_t *swf, + char *variable_name, + int variable_name_len, + char *initial_text, + int initial_text_len) { + int result = 1; + swf_tag_t *tag; + if (swf == NULL) { + fprintf(stderr, "swf_object_replace_editstring: swf == NULL\n"); + return 1; + } + for (tag = swf->tag; tag; tag = tag->next) { + result = swf_tag_replace_edit_string(tag, variable_name, + variable_name_len, + initial_text, + initial_text_len, + swf); + if (! result) { + break; + } + } + return result; +} + +unsigned char * +swf_object_get_actiondata(swf_object_t *swf, unsigned long *length, int tag_seqno) { + swf_tag_t *tag; + swf_tag_action_detail_t *swf_tag_action; + int i = 0; + for(tag = swf->tag; tag; tag = tag->next) { + if (i == tag_seqno) { + break; + } + i++; + } + if (tag == NULL) { + return NULL; + } + if ((tag->tag != 12) && (tag->tag != 59)) { // DoAction, DoInitAction + return NULL; + } + swf_tag_create_detail(tag, swf); + swf_tag_action = (swf_tag_action_detail_t *) tag->detail; + *length = swf_tag_action->action_record_len; + return swf_tag_action->action_record; +} diff --git a/src/swf_object.h b/src/swf_object.h new file mode 100644 index 0000000..34c497f --- /dev/null +++ b/src/swf_object.h @@ -0,0 +1,53 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_OBJECT_H__ +#define __SWF_OBJECT_H__ + +#include "swf_header.h" +#include "swf_header.h" +#include "swf_tag.h" + +typedef struct swf_object_ { + swf_header_t header; + swf_header_movie_t header_movie; + swf_tag_t *tag; +} swf_object_t; + + +extern swf_object_t *swf_object_open(void); +extern void swf_object_close(swf_object_t *swf); +extern int swf_object_input(swf_object_t *swf, unsigned char *data, unsigned long data_len); +extern unsigned char *swf_object_output(swf_object_t *swf, unsigned long *length); +extern void swf_object_print(swf_object_t *swf); + +/* --- */ +extern unsigned char *swf_object_get_jpegdata(swf_object_t *swf, unsigned long *length, int image_id); +extern unsigned char *swf_object_get_alphadata(swf_object_t *swf, unsigned long *length, int image_id); +extern int swf_object_replace_jpegdata(swf_object_t *swf, int image_id, + unsigned char *jpeg_data, + unsigned long jpeg_data_len, + unsigned char *alpha_data, + unsigned long alpha_data_len); +extern unsigned char *swf_object_get_pngdata(swf_object_t *swf, unsigned long *length, int image_id); +extern int swf_object_replace_pngdata(swf_object_t *swf, int image_id, + unsigned char *png_data, + unsigned long png_data_len); +extern unsigned char *swf_object_get_sounddata(swf_object_t *swf, unsigned long *length, int sound_id); +extern int swf_object_replace_melodata(swf_object_t *swf, int sound_id, + unsigned char *melo_data, + unsigned long melo_data_len); +extern char *swf_object_get_editstring(swf_object_t *swf, + char *variable_name, + int variable_name_len); +extern int swf_object_replace_editstring(swf_object_t *swf, + char *variable_name, + int variable_name_len, + char *initial_text, + int initial_text_len); +extern unsigned char *swf_object_get_actiondata(swf_object_t *swf, unsigned long *length, int tag_seqno); + +#endif /* __SWF_OBJECT_H__ */ diff --git a/src/swf_png.c b/src/swf_png.c new file mode 100644 index 0000000..04cdce8 --- /dev/null +++ b/src/swf_png.c @@ -0,0 +1,395 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include +#include "bitstream.h" +#include "swf_rgb.h" // Lossless format=3 +#include "swf_rgba.h" // Lossless2 format=3 +#include "swf_xrgb.h" // Lossless format=5 +#include "swf_argb.h" // Lossless2 format=5 +#include "swf_png.h" + +typedef struct my_png_buffer_ { + unsigned char *data; + unsigned long data_len; + unsigned long data_offset; +} my_png_buffer; + +/* + * png read + */ + +static void png_data_read_func(png_structp png_ptr, png_bytep buf, png_size_t size){ + my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr); + if (png_buff->data_offset + size <= png_buff->data_len) { + memcpy(buf, png_buff->data + png_buff->data_offset, size); + png_buff->data_offset += size; + } else { + fprintf(stderr, "png_data_read_func: ! png_buff->data_offset(%lu) + size(%d) <= png_buff->data_len(%lu)\n", + png_buff->data_offset, size, png_buff->data_len); + png_error(png_ptr,"png_read_read_func failed"); + } +} + +static void png_data_read(png_structp png_ptr, my_png_buffer *png_buff) { + png_set_read_fn(png_ptr, (png_voidp) png_buff, + (png_rw_ptr)png_data_read_func); +} + +/* + * png write + */ + +void png_data_write_func(png_structp png_ptr, png_bytep buf, png_size_t size){ + my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr); + unsigned long new_data_len; + if (png_buff->data_offset + size > png_buff->data_len) { + new_data_len = 2 * png_buff->data_len; + if (png_buff->data_offset + size > new_data_len) { + new_data_len = png_buff->data_offset + size; + } + png_buff->data = realloc(png_buff->data, new_data_len); + if (png_buff->data == NULL) { + fprintf(stderr, "png_data_write_func: can't realloc: new_data_len(%lu), data_len(%lu)\n", + new_data_len, png_buff->data_len); + png_error(png_ptr,"png_data_write_func failed"); + + } + png_buff->data_len = new_data_len; + } + memcpy(png_buff->data + png_buff->data_offset, buf, size); + png_buff->data_offset += size; +} + +void png_data_write(png_structp png_ptr, my_png_buffer *png_buff) { + png_set_write_fn(png_ptr, (png_voidp) png_buff, + (png_rw_ptr)png_data_write_func, NULL); +} + +/* + * + */ + +void * +pngconv_png2lossless(unsigned char *png_data, unsigned long png_data_len, + int *tag_no, int *format, + unsigned short *width, unsigned short *height, + void **colormap, int *colormap_count) { + volatile png_structp png_ptr = NULL; + volatile png_infop png_info_ptr = NULL; + my_png_buffer png_buff; + int is_png; + int bpp, color_type; + png_uint_32 png_width = 0, png_height = 0; + volatile png_bytepp png_image_data = NULL; + png_uint_32 x, y; + void *image_data; + png_color *palette = NULL; + int palette_num = 0; + png_bytep trans = NULL; + int num_trans = 0; + png_color_16p trans_values = NULL; + + is_png = png_check_sig((png_bytep)png_data, 8); + if (! is_png) { + fprintf(stderr, "pngconv_png2lossless: is not PNG!\n"); + return NULL; + } + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); + if (! png_ptr) { + fprintf(stderr, "pngconv_png2lossless: can't create read_struct\n"); + return NULL; + } + if (setjmp(png_jmpbuf(png_ptr))) { + fprintf(stderr, "pngconv_png2lossless: libpng error jump occured\n"); + png_destroy_read_struct((png_structpp) &png_ptr, + (png_infopp) &png_info_ptr, NULL); + if (png_image_data) { + for ( y = 0 ; y < png_height ; y++) { + free(png_image_data[y]); + } + free(png_image_data); + } + return NULL; + } + png_info_ptr = png_create_info_struct(png_ptr); + if (! png_info_ptr) { + fprintf(stderr, "pngconv_png2lossless: can't create info_struct\n"); + png_destroy_read_struct ((png_structpp)&png_ptr, NULL, NULL); + return NULL; + } + png_buff.data = png_data; + png_buff.data_len = png_data_len; + png_buff.data_offset = 0; + + png_data_read(png_ptr, &png_buff); + png_read_info(png_ptr, png_info_ptr); + png_get_IHDR(png_ptr, png_info_ptr, + &png_width, &png_height, &bpp, &color_type, + NULL, NULL, NULL); + *width = (unsigned short) png_width; + *height = (unsigned short) png_height; + switch(color_type) { + case PNG_COLOR_TYPE_PALETTE: + *format = 3; + png_get_PLTE(png_ptr, png_info_ptr, &palette, &palette_num); + if (png_get_tRNS(png_ptr, png_info_ptr, &trans, &num_trans, + &trans_values) && (num_trans > 0)) { + *tag_no = 36; // DefineBitsLossless2 + } else { + *tag_no = 20; // DefineBitsLossless + } + break; + case PNG_COLOR_TYPE_RGB: + *format = 5; + *tag_no = 20; /* DefineBitsLossless */ + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + *format = 5; + *tag_no = 36; /* DefineBitsLossless2 */ + if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + break; + default: + fprintf(stderr, "pngconv_png2lossless: color_type=%d not implemented yet.\n", color_type); + png_destroy_read_struct((png_structpp)&png_ptr, + (png_infopp)&png_info_ptr, NULL); + return NULL; + } + if (bpp != 8) { + fprintf(stderr, "pngconv_png2lossless: bpp=%d not implemented yet. accept only bpp=8\n", bpp); + png_destroy_read_struct((png_structpp)&png_ptr, + (png_infopp)&png_info_ptr, NULL); + return NULL; + } + + png_image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep)); + for (y=0; y < png_height; y++) { + png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr)); + } + png_read_image(png_ptr, png_image_data); + /* + * image copy + */ + if (color_type == PNG_COLOR_TYPE_PALETTE) { + int i; + *colormap_count = palette_num; + if (num_trans == 0) { + swf_rgb_t *result_colormap = malloc(sizeof(swf_rgb_t) * palette_num); // Lossless + for (i = 0 ; i < palette_num ; i++) { + result_colormap[i].red = palette[i].red; + result_colormap[i].green = palette[i].green; + result_colormap[i].blue = palette[i].blue; + } + *colormap = result_colormap; + } else { + swf_rgba_t *result_colormap = malloc(sizeof(swf_rgba_t) * palette_num); // Lossless2 + for (i = 0 ; i < palette_num ; i++) { + result_colormap[i].red = palette[i].red; + result_colormap[i].green = palette[i].green; + result_colormap[i].blue = palette[i].blue; + if (i <= num_trans) { + result_colormap[i].alpha = trans[i]; + } else { + result_colormap[i].alpha = 0xff; // XXX + } + } + *colormap = result_colormap; + } + unsigned char *indices_data = malloc(((png_width+ 3) & -4) * png_height); + for (y=0; y < png_height; y++) { + for (x=0; x < png_width; x++) { + indices_data[x+y*((png_width + 3) & -4)] = png_image_data[y][x]; // XXX + } + } + image_data = indices_data; + } else if (color_type == PNG_COLOR_TYPE_RGB) { + swf_xrgb_t *xrgb_list; + xrgb_list = malloc(sizeof(swf_xrgb_t) * png_width * png_height); + for (y=0; y < png_height; y++) { + for (x=0; x < png_width; x++) { + xrgb_list[x+y*png_width].red = png_image_data[y][3*x + 0]; + xrgb_list[x+y*png_width].green = png_image_data[y][3*x + 1]; + xrgb_list[x+y*png_width].blue = png_image_data[y][3*x + 2]; + } + } + image_data = xrgb_list; + } else { // PNG_COLOR_TYPE_RGB_ALPHA + swf_argb_t *argb_list; + argb_list = malloc(sizeof(swf_argb_t) * png_width * png_height); + for (y=0; y < png_height; y++) { + for (x=0; x < png_width; x++) { + argb_list[x+y*png_width].red = png_image_data[y][4*x + 0]; + argb_list[x+y*png_width].green = png_image_data[y][4*x + 1]; + argb_list[x+y*png_width].blue = png_image_data[y][4*x + 2]; + argb_list[x+y*png_width].alpha = png_image_data[y][4*x + 3]; + } + } + image_data = argb_list; + } + for (y=0; y < png_height; y++) { + free(png_image_data[y]); + } + free(png_image_data); + /* + * destruct + */ + png_destroy_read_struct((png_structpp) &png_ptr, + (png_infopp) &png_info_ptr, NULL); + return image_data; +} + +unsigned char * +pngconv_lossless2png(void *image_data, + unsigned short width, unsigned short height, + void *index_data, + unsigned short index_data_count, + int tag_no, int format, + unsigned long *length) { + volatile png_structp png_ptr = NULL; + volatile png_infop png_info_ptr = NULL; + volatile my_png_buffer png_buff; + png_uint_32 png_width = 0, png_height = 0; + int bpp, color_type; + volatile png_bytepp png_image_data = NULL; + png_uint_32 x, y; + volatile png_colorp png_palette = NULL; + if ((format != 3) && (format != 5)) { + fprintf(stderr, "jpegconv_lossless2png: format=%d not implemented yes.\n", format); + return NULL; + } + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); + if (! png_ptr) { + fprintf(stderr, "jpegconv_lossless2png: can't create write_struct\n"); + return NULL; + } + if (setjmp(png_jmpbuf(png_ptr))) { + fprintf(stderr, "pngconv_lossless2png: libpng error jump occured\n"); + free(png_palette); + if (png_image_data) { + for ( y = 0; y < png_height ; y++) { + free(png_image_data[y]); + } + free(png_image_data); + } + free(png_buff.data); + png_destroy_write_struct((png_structpp) &png_ptr, + (png_infopp) &png_info_ptr); + return NULL; + } + png_info_ptr = png_create_info_struct(png_ptr); + if (! png_info_ptr) { + fprintf(stderr, "jpegconv_lossless2png: can't create info_struct\n"); + png_destroy_write_struct((png_structpp) &png_ptr, NULL); + return NULL; + } + // + png_width = width; + png_height = height; + bpp = 8; + if (format == 3) { + color_type = PNG_COLOR_TYPE_PALETTE; + } else if (tag_no == 20) { /* DefineBitsLossless */ + color_type = PNG_COLOR_TYPE_RGB; + } else if (tag_no == 36) { /* DefineBitsLossless2 */ + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + } else { + fprintf(stderr, "jpegconv_lossless2png: format!=3 and tag_no=%d not implemented.\n", + tag_no); + png_destroy_write_struct((png_structpp) &png_ptr, + (png_infopp) &png_info_ptr); + return NULL; + } + png_set_filter(png_ptr, 0, PNG_ALL_FILTERS); + png_set_IHDR(png_ptr, png_info_ptr, + png_width, png_height, bpp, color_type, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + if (format == 3) { + int i; + if (index_data_count == 0) { + fprintf(stderr, "jpegconv_lossless2png: index_data_count == 0 at line(%d)\n", __LINE__); + png_destroy_write_struct((png_structpp) &png_ptr, + (png_infopp) &png_info_ptr); + return NULL; + } + png_palette = (png_colorp) malloc(sizeof(png_color)*index_data_count); + png_set_packing(png_ptr); + if (tag_no == 20) { + swf_rgb_t *rgb_list = index_data; + for (i=0; i +#include "bitstream.h" +#include "swf_rect.h" + + +int two_negative(int num, int size) { + int msb = 1 << (size - 1); + int mask = msb - 1; + if (num & msb) { + return - ((num^mask) & mask) - 1; + } + return num; +} + +int two_negative_reverse(int num, int size) { // dummy + int msb = 1 << (size - 1); + int mask = msb - 1; + if (num < 0) { + return - ((num^mask) & mask) - 1; + } + return num; +} + +int +swf_rect_parse(bitstream_t *bs, swf_rect_t *rect) { + unsigned char size; + bitstream_align(bs); + size = bitstream_getbits(bs, 5); + rect->size = size; + rect->x_min = bitstream_getbits(bs, size); + rect->x_max = bitstream_getbits(bs, size); + rect->y_min = bitstream_getbits(bs, size); + rect->y_max = bitstream_getbits(bs, size); + // + rect->x_min = two_negative(rect->x_min, size); + rect->x_max = two_negative(rect->x_max, size); + rect->y_min = two_negative(rect->y_min, size); + rect->y_max = two_negative(rect->y_max, size); + return 0; +} + +int +swf_rect_build(bitstream_t *bs, swf_rect_t *rect) { + unsigned char size = rect->size; // XXX + int x_min = two_negative_reverse(rect->x_min, size); + int x_max = two_negative_reverse(rect->x_max, size); + int y_min = two_negative_reverse(rect->y_min, size); + int y_max = two_negative_reverse(rect->y_max, size); + bitstream_align(bs); + bitstream_putbits(bs, size, 5); + bitstream_putbits(bs, x_min, size); + bitstream_putbits(bs, x_max, size); + bitstream_putbits(bs, y_min, size); + bitstream_putbits(bs, y_max, size); + return 0; +} + +int +swf_rect_print(swf_rect_t *rect) { + printf("rect=(%d, %d)-(%d, %d) (f_size=%d)\n", + rect->x_min / SWF_TWIPS, + rect->y_min / SWF_TWIPS, + rect->x_max / SWF_TWIPS, + rect->y_max / SWF_TWIPS, + rect->size); + return 0; +} diff --git a/src/swf_rect.h b/src/swf_rect.h new file mode 100644 index 0000000..debb522 --- /dev/null +++ b/src/swf_rect.h @@ -0,0 +1,22 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_RECT_H__ +#define __SWF_RECT_H__ + +typedef struct swf_rect_ { + unsigned char size; + int x_min; + int x_max; + int y_min; + int y_max; +} swf_rect_t; + +extern int swf_rect_parse(bitstream_t *bs, swf_rect_t *rect); +extern int swf_rect_build(bitstream_t *bs, swf_rect_t *rect); +extern int swf_rect_print(swf_rect_t *rect); + +#endif /* __SWF_RECT_H__ */ diff --git a/src/swf_rgb.c b/src/swf_rgb.c new file mode 100644 index 0000000..314fc93 --- /dev/null +++ b/src/swf_rgb.c @@ -0,0 +1,26 @@ +#include +#include "bitstream.h" +#include "swf_rgb.h" + +int +swf_rgb_parse(bitstream_t *bs, swf_rgb_t *color) { + color->red = bitstream_getbyte(bs); + color->green = bitstream_getbyte(bs); + color->blue = bitstream_getbyte(bs); + return 0; +} + +int +swf_rgb_build(bitstream_t *bs, swf_rgb_t *color) { + bitstream_putbyte(bs, color->red); + bitstream_putbyte(bs, color->green); + bitstream_putbyte(bs, color->blue); + return 0; +} + +int +swf_rgb_print(swf_rgb_t *color) { + printf("red=0x%02x green=0x%02X blue=0x%02x\n", + color->red, color->green, color->blue); + return 0; +} diff --git a/src/swf_rgb.h b/src/swf_rgb.h new file mode 100644 index 0000000..201c656 --- /dev/null +++ b/src/swf_rgb.h @@ -0,0 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_RGB_H__ +#define __SWF_RGB_H__ + +typedef struct swf_rgb_ { + unsigned char red; + unsigned char green; + unsigned char blue; +} swf_rgb_t; + + +extern int swf_rgb_parse(bitstream_t *bs, swf_rgb_t *color); +extern int swf_rgb_build(bitstream_t *bs, swf_rgb_t *color); +extern int swf_rgb_print(swf_rgb_t *color); + +#endif /* __SWF_RGB_H__ */ diff --git a/src/swf_rgba.c b/src/swf_rgba.c new file mode 100644 index 0000000..a7632a9 --- /dev/null +++ b/src/swf_rgba.c @@ -0,0 +1,28 @@ +#include +#include "bitstream.h" +#include "swf_rgba.h" + +int +swf_rgba_parse(bitstream_t *bs, swf_rgba_t *color) { + color->red = bitstream_getbyte(bs); + color->green = bitstream_getbyte(bs); + color->blue = bitstream_getbyte(bs); + color->alpha = bitstream_getbyte(bs); + return 0; +} + +int +swf_rgba_build(bitstream_t *bs, swf_rgba_t *color) { + bitstream_putbyte(bs, color->red); + bitstream_putbyte(bs, color->green); + bitstream_putbyte(bs, color->blue); + bitstream_putbyte(bs, color->alpha); + return 0; +} + +int +swf_rgba_print(swf_rgba_t *color) { + printf("red=0x%02x green=0x%02X blue=0x%02x alpha=0x%02x\n", + color->red, color->green, color->blue, color->alpha); + return 0; +} diff --git a/src/swf_rgba.h b/src/swf_rgba.h new file mode 100644 index 0000000..72c7018 --- /dev/null +++ b/src/swf_rgba.h @@ -0,0 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_RGBA_H__ +#define __SWF_RGBA_H__ + +typedef struct swf_rgba_ { + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned char alpha; +} swf_rgba_t; + +extern int swf_rgba_parse(bitstream_t *bs, swf_rgba_t *color); +extern int swf_rgba_build(bitstream_t *bs, swf_rgba_t *color); +extern int swf_rgba_print(swf_rgba_t *color); + +#endif /* __SWF_RGBA_H__ */ diff --git a/src/swf_tag.c b/src/swf_tag.c new file mode 100644 index 0000000..3b00094 --- /dev/null +++ b/src/swf_tag.c @@ -0,0 +1,530 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include "bitstream.h" +#include "swf_define.h" +#include "swf_tag.h" +#include "swf_tag_jpeg.h" +#include "swf_tag_lossless.h" +#include "swf_tag_edit.h" +#include "swf_tag_action.h" +#include "swf_tag_sound.h" + +swf_tag_info_t swf_tag_info_table[] = { + { 0, "End", NULL }, + { 1, "ShowFrame", NULL }, + { 2, "DefineShape", NULL }, + { 3, "FreeCharacter", NULL}, + { 4, "PlaceObject", NULL}, + { 5, "RemoveObject", NULL}, + { 6, "DefineBitsJPEG", swf_tag_jpeg_detail_handler }, + { 7, "DefineButton", NULL}, + { 8, "JPEGTables", NULL }, + { 9, "SetBackgroundColor", NULL }, + { 10, "DefineFont ", NULL}, + { 11, "DefineText", NULL }, + { 12, "DoAction", swf_tag_action_detail_handler }, + { 13, "DefineFontInfo", NULL }, + { 14, "DefineSound", swf_tag_sound_detail_handler }, + { 15, "StartSound", NULL }, + { 16, "DefineButtonSound", NULL }, + { 17, "DefineButtonSound", NULL }, + { 18, "SoundStreamHead", NULL }, + { 19, "SoundStreamBlock", NULL }, + { 20, "DefineBitsLossless", swf_tag_lossless_detail_handler }, + { 21, "DefineBitsJPEG2", swf_tag_jpeg_detail_handler }, + { 22, "DefineShape2", NULL }, + { 26, "PlaceObject2", NULL }, + { 28, "RemoveObject2", NULL }, + { 32, "DefineShape3", NULL }, + { 33, "DefineText2", NULL }, + { 34, "DefineButton2", NULL }, + { 35, "DefineBitsJPEG3", swf_tag_jpeg3_detail_handler }, + { 36, "DefineBitsLossless2", swf_tag_lossless_detail_handler }, + { 37, "DefineEditText", swf_tag_edit_detail_handler }, + { 39, "DefineSprite", NULL } , + { 43, "FrameLabel", NULL } , + { 48, "DefineFont2", NULL } , + { 69, "FileAttributes", NULL }, + { 73, "DefineFontAlignZones", NULL }, + { 74, "CSMTextSettings", NULL }, + { 75, "DefineFont3", NULL } , + { 83, "DefineShape4", NULL }, + { 88, "DefineFontName", NULL } , + { 777,"Reflex", NULL } , +}; + +swf_tag_info_t *get_swf_tag_info(int tag_id) { + int i, tag_info_num = NumOfTable(swf_tag_info_table); + for(i=0; i < tag_info_num; i++) { + if (tag_id == swf_tag_info_table[i].id) { + return &(swf_tag_info_table[i]); + } + } + return NULL; +} + +swf_tag_t *swf_tag_create(bitstream_t *bs) { + swf_tag_t *tag = calloc(sizeof(*tag), 1); + unsigned short tag_and_length; + if (bs == NULL) { + fprintf(stderr, "swf_tag_create: bs == NULL\n"); + return NULL; + } + tag_and_length = bitstream_getbytesLE(bs, 2); + if (tag_and_length == (unsigned short) -1) { + free(tag); + return NULL; + } + tag->tag = tag_and_length >> 6; + tag->length = tag_and_length & 0x3f; + tag->length_longformat = 0; + if (tag->length == 0x3f) { + tag->length = bitstream_getbytesLE(bs, 4); + if (tag_and_length == (unsigned short) -1) { + free(tag); + return NULL; + } + tag->length_longformat = 1; + } +// printf("XXX: malloc length=%d\n", tag->length); + tag->data = malloc(tag->length); + bitstream_getstring(bs, tag->data, tag->length); + tag->detail = NULL; + return tag; +} + +void swf_tag_destroy(swf_tag_t *tag) { + if (! tag) { + return; + } + if (tag->data) { + free(tag->data); + } + if (tag->detail) { + swf_tag_info_t *tag_info = get_swf_tag_info(tag->tag); + if (tag_info && tag_info->detail_handler) { + swf_tag_detail_handler_t * detail_handler = tag_info->detail_handler(); + if (detail_handler->destroy) { + detail_handler->destroy(tag->detail); + } else { + fprintf(stderr, "detail_handler->destroy == NULL (tag=%d)\n", + tag->tag); + } + } else { + fprintf(stderr, "not impremented yet. destroy tag detail\n"); + } + } + free(tag); +} + +static int swf_tag_and_length_build(bitstream_t *bs, swf_tag_t *tag) { + signed short tag_and_length; + if (bs == NULL) { + fprintf(stderr, "swf_tag_and_length_build: bs == NULL\n"); + return 1; + } + if (tag->length >= 0x3f) { + tag->length_longformat = 1; + } else { + switch (tag->tag) { + case 6: // DefineBitsJPEG + case 21: // DefineBitsJPEG2 + case 35: // DefineBitsJPEG3 + case 20: // DefineBitsLossless + case 36: // DefineBitsLossless2 + case 19: // SoundStreamBlock + tag->length_longformat = 1; + break; + default: + tag->length_longformat = 0; + break; + } + } + if (tag->length_longformat) { + tag_and_length = (tag->tag << 6) | 0x3f; + bitstream_putbytesLE(bs, tag_and_length, 2); + bitstream_putbytesLE(bs, tag->length, 4); + } else { + tag_and_length = (tag->tag << 6) | tag->length; + bitstream_putbytesLE(bs, tag_and_length, 2); + } + return 0; +} +extern int swf_tag_build(bitstream_t *bs, swf_tag_t *tag, struct swf_object_ *swf) { + swf_tag_info_t *tag_info; + unsigned char *data; + unsigned long data_len = 0; + swf_tag_detail_handler_t * detail_handler; + if (bs == NULL) { + fprintf(stderr, "swf_tag_and_length_build: bs == NULL\n"); + return 1; + } +// fprintf(stderr, "XXX: swf_tag_build: tag->tag=%d\n",tag->tag); + if (tag->data) { + swf_tag_and_length_build(bs, tag); + bitstream_putstring(bs, tag->data, tag->length); + } else if (tag->detail){ + tag_info = get_swf_tag_info(tag->tag); + if ((tag_info == NULL) || (tag_info->detail_handler == NULL)) { + fprintf(stderr, "swf_tag_build: not implemented yet. detail build tag->tag=%d\n", + tag->tag); + return 1; + } + detail_handler = tag_info->detail_handler(); + if (detail_handler->output == NULL) { + fprintf(stderr, "swf_tag_build: detail_handler->output == NULL: tag->tag=%d\n", + tag->tag); + return 1; + } + data = detail_handler->output(tag->detail, &data_len, tag, swf); + if (data == NULL) { + fprintf(stderr, "swf_tag_build: Can't output: data=%p data_len=%lu\n", + data, data_len); + } + tag->length = data_len; + swf_tag_and_length_build(bs, tag); + bitstream_putstring(bs, data, data_len); + free(data); + } else { + fprintf(stderr, "ERROR: not found tag data and detail\n"); + return 1; + } + return 0; +} + +void +swf_tag_print(swf_tag_t *tag, struct swf_object_ *swf) { + swf_tag_info_t *tag_info; + const char *tag_name; + if (tag == NULL) { + fprintf(stderr, "swf_tag_print: tag == NULL\n"); + return ; + } + tag_info = get_swf_tag_info(tag->tag); + tag_name = (tag_info)?tag_info->name:"Unknown"; + printf("tag=%s(%d)", tag_name, tag->tag); + if (tag->length > 0) { + printf(" length=%lu", tag->length); + } + printf("\n"); + if (tag_info && tag_info->detail_handler) { + if (tag->detail == NULL) { + swf_tag_create_detail(tag, swf); + } + swf_tag_detail_handler_t * detail_handler = tag_info->detail_handler(); + if (detail_handler->print) { + detail_handler->print(tag->detail, tag, swf); + } + } +} + +int swf_tag_create_detail(swf_tag_t *tag, struct swf_object_ *swf) { + swf_tag_info_t *tag_info; + if (tag == NULL) { + fprintf(stderr, "swf_tag_create_detail: tag == NULL\n"); + return 1; + } + tag_info = get_swf_tag_info(tag->tag); + if (tag_info && tag_info->detail_handler) { + swf_tag_detail_handler_t * detail_handler = tag_info->detail_handler(); + if (detail_handler->create == NULL) { + fprintf(stderr, "detail_handler->create == NULL (tag=%d)\n", + tag->tag); + return 1; + } + tag->detail = detail_handler->create(tag->data, tag->length, tag, swf); + if (tag->detail == NULL) { + fprintf(stderr, "can't create tag detail (tag=%d)\n", tag->tag); + return 1; + } + } + return 1; +} + +unsigned char * +swf_tag_get_jpeg_data(swf_tag_t *tag, unsigned long *length, int image_id, swf_tag_t *tag_jpegtables) { + swf_tag_info_t *tag_info; + *length = 0; + if (tag == NULL) { + fprintf(stderr, "swf_tag_get_jpeg_data: tag == NULL\n"); + return NULL; + } + tag_info = get_swf_tag_info(tag->tag); + if ((tag->tag != 6) && (tag->tag != 21) && (tag->tag != 35)) { + return NULL; + } + if (! tag->detail) { + swf_tag_create_detail(tag, NULL); + } + if (! tag->detail) { + fprintf(stderr, "swf_tag_get_jpeg_data: Can't create tag\n"); + return NULL; + } + if (tag_jpegtables) { + return swf_tag_jpeg_get_jpeg_data(tag->detail, length, image_id, + tag_jpegtables->data, + tag_jpegtables->length); + } else { + return swf_tag_jpeg_get_jpeg_data(tag->detail, length, image_id, + NULL, 0); + } +} + +unsigned char * +swf_tag_get_alpha_data(swf_tag_t *tag, unsigned long *length, int image_id) { + swf_tag_info_t *tag_info; + *length = 0; + if (tag == NULL) { + fprintf(stderr, "swf_tag_get_alpha_data: tag == NULL\n"); + return NULL; + } + if (tag->tag != 35) { // ! DefineBitsJPEG3 + return NULL; + } + tag_info = get_swf_tag_info(tag->tag); + if (tag_info && tag_info->detail_handler) { + swf_tag_detail_handler_t * detail_handler = tag_info->detail_handler(); + if (detail_handler->identity) { + if (detail_handler->identity(tag->data, image_id, tag)) { + return NULL; + } + } + } + if (! tag->detail) { + swf_tag_create_detail(tag, NULL); + } + if (! tag->detail) { + fprintf(stderr, "swf_tag_get_alpha_data: Can't create tag\n"); + return NULL; + } + return swf_tag_jpeg_get_alpha_data(tag->detail, length, image_id); +} + +int +swf_tag_replace_jpeg_data(swf_tag_t *tag, int image_id, + unsigned char *jpeg_data, + unsigned long jpeg_data_len, + unsigned char *alpha_data, + unsigned long alpha_data_len) { + swf_tag_info_t *tag_info; + int result; + if (tag == NULL) { + fprintf(stderr, "swf_tag_replace_jpeg_data: tag == NULL\n"); + return 1; + } + if ((tag->tag != 6) && (tag->tag != 21) && (tag->tag != 35)) { // DefineBitsJPEG or 2 or 3 + return 1; + } + tag_info = get_swf_tag_info(tag->tag); + if (tag_info && tag_info->detail_handler) { + swf_tag_detail_handler_t * detail_handler = tag_info->detail_handler(); + if (detail_handler->identity) { + if (detail_handler->identity(tag->data, image_id, tag)) { + return 1; + } + } + } + if (! tag->detail) { + swf_tag_create_detail(tag, NULL); + } + if (! tag->detail) { + fprintf(stderr, "swf_tag_replace_jpeg_data: Can't create tag\n"); + return 1; + } + result= swf_tag_jpeg_replace_jpeg_data(tag->detail, image_id, + jpeg_data, jpeg_data_len, + alpha_data, alpha_data_len, tag); + if (result == 0) { + free(tag->data); + tag->data = NULL; + tag->length = 0; + } + return result; +} + +unsigned char * +swf_tag_get_png_data(swf_tag_t *tag, unsigned long *length, int image_id) { + swf_tag_info_t *tag_info; + *length = 0; + if (tag == NULL) { + fprintf(stderr, "swf_tag_get_png_data: tag == NULL\n"); + return NULL; + } + tag_info = get_swf_tag_info(tag->tag); + if ((tag->tag != 20) && (tag->tag != 36)) { + return NULL; + } + if (! tag->detail) { + swf_tag_create_detail(tag, NULL); + } + if (! tag->detail) { + fprintf(stderr, "swf_tag_get_png_data: Can't create tag\n"); + return NULL; + } + return swf_tag_lossless_get_png_data(tag->detail, length, image_id, tag); +} + +int +swf_tag_replace_png_data(swf_tag_t *tag, int image_id, + unsigned char *png_data, + unsigned long png_data_len) { + swf_tag_info_t *tag_info; + int result; + if (tag == NULL) { + fprintf(stderr, "swf_tag_replace_png_data: tag == NULL\n"); + return 1; + } + if ((tag->tag != 20) && (tag->tag != 36)) { // DefineBitsLossless or 2 + return 1; + } + tag_info = get_swf_tag_info(tag->tag); + if (tag_info && tag_info->detail_handler) { + swf_tag_detail_handler_t * detail_handler = tag_info->detail_handler(); + if (detail_handler->identity) { + if (detail_handler->identity(tag->data, image_id, tag)) { + return 1; + } + } + } + if (! tag->detail) { + swf_tag_create_detail(tag, NULL); + } + if (! tag->detail) { + fprintf(stderr, "swf_tag_replace_png_data: Can't create tag\n"); + return 1; + } + result= swf_tag_lossless_replace_png_data(tag->detail, image_id, + png_data, png_data_len, tag); + if (result == 0) { + free(tag->data); + tag->data = NULL; + tag->length = 0; + } + return result; +} + +/* + * DefineSound + */ + +unsigned char * +swf_tag_get_sound_data(swf_tag_t *tag, unsigned long *length, int sound_id) { + swf_tag_info_t *tag_info; + *length = 0; + if (tag == NULL) { + fprintf(stderr, "swf_tag_get_sound_data: tag == NULL\n"); + return NULL; + } + tag_info = get_swf_tag_info(tag->tag); + if (tag->tag != 14) { // DefineSound + return NULL; + } + if (! tag->detail) { + swf_tag_create_detail(tag, NULL); + } + if (! tag->detail) { + fprintf(stderr, "swf_tag_get_sound_data: Can't create tag detail\n"); + return NULL; + } + return swf_tag_sound_get_sound_data(tag->detail, length, sound_id); +} + +int +swf_tag_replace_melo_data(swf_tag_t *tag, int sound_id, + unsigned char *melo_data, + unsigned long melo_data_len) { + swf_tag_info_t *tag_info; + int result; + if (tag == NULL) { + fprintf(stderr, "swf_tag_replace_melo_data: tag == NULL\n"); + return 1; + } + if (tag->tag != 14) { // DefineSound + return 1; + } + tag_info = get_swf_tag_info(tag->tag); + if (tag_info && tag_info->detail_handler) { + swf_tag_detail_handler_t * detail_handler = tag_info->detail_handler(); + if (detail_handler->identity) { + if (detail_handler->identity(tag->data, sound_id, tag)) { + return 1; + } + } + } + if (! tag->detail) { + swf_tag_create_detail(tag, NULL); + } + if (! tag->detail) { + fprintf(stderr, "swf_tag_replace_melog_data: Can't create tag\n"); + return 1; + } + result= swf_tag_sound_replace_melo_data(tag->detail, sound_id, + melo_data, melo_data_len); + if (result == 0) { + free(tag->data); + tag->data = NULL; + tag->length = 0; + } + return result; +} + +char * +swf_tag_get_edit_string(swf_tag_t *tag, + char *variable_name, int variable_name_len, + struct swf_object_ *swf) { + if (tag == NULL) { + fprintf(stderr, "swf_tag_get_edit_string: tag == NULL\n"); + return NULL; + } + if (tag->tag != 37) { // DefineEditText + return NULL; + } + if (! tag->detail) { + swf_tag_create_detail(tag, swf); + } + if (! tag->detail) { + fprintf(stderr, "Can't create tag\n"); + return NULL; + } + return swf_tag_edit_get_string(tag->detail, + variable_name, variable_name_len); +} + + +int +swf_tag_replace_edit_string(swf_tag_t *tag, + char *variable_name, int variable_name_len, + char *initial_text, int initial_text_len, + struct swf_object_ *swf) { + int result; + if (tag == NULL) { + fprintf(stderr, "swf_tag_replace_edit_string: tag == NULL\n"); + return 1; + } + if (tag->tag != 37) { // DefineEditText + return 1; + } + + if (! tag->detail) { + swf_tag_create_detail(tag, swf); + } + if (! tag->detail) { + fprintf(stderr, "swf_tag_replace_edit_string: Can't create tag\n"); + return 1; + } + result = swf_tag_edit_replace_string(tag->detail, + variable_name, variable_name_len, + initial_text, initial_text_len); + if (result == 0) { + free(tag->data); + tag->data = NULL; + tag->length = 0; + } + return result; +} diff --git a/src/swf_tag.h b/src/swf_tag.h new file mode 100644 index 0000000..e14dd3a --- /dev/null +++ b/src/swf_tag.h @@ -0,0 +1,89 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_TAG_H__ +#define __SWF_TAG_H__ + +#include "bitstream.h" +struct swf_object_; // swf_object.h + +typedef struct swf_tag_ { + int tag; + unsigned long length; + int length_longformat; + // + unsigned char *data; + void *detail; + // + struct swf_tag_ *next; +} swf_tag_t; + +typedef struct swf_tag_detail_handler_ { + void * (*create) (unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf); + int (*identity) (unsigned char *data, int id, + swf_tag_t *tag); + unsigned char * (*output) (void *detail, unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf); + void (*print) (void *detail, + swf_tag_t *tag, + struct swf_object_ *swf); + void (*destroy) (void *); +} swf_tag_detail_handler_t; + +typedef struct swf_tag_info_ { + int id; + const char *name; + swf_tag_detail_handler_t *(*detail_handler)(void); +} swf_tag_info_t; + +extern swf_tag_info_t *get_swf_tag_info(int tag_id); + +extern swf_tag_t *swf_tag_create(bitstream_t *bs); +extern void swf_tag_destroy(swf_tag_t *tag); +extern int swf_tag_build(bitstream_t *bs, swf_tag_t *tag, struct swf_object_ *swf); +extern void swf_tag_print(swf_tag_t *tag, struct swf_object_ *swf); + +/* image */ + +extern unsigned char *swf_tag_get_jpeg_data(swf_tag_t *tag, unsigned long *length, int image_id, swf_tag_t *tag_jpegtables); +extern unsigned char *swf_tag_get_alpha_data(swf_tag_t *tag, unsigned long *length, int image_id); +extern int swf_tag_replace_jpeg_data(swf_tag_t *tag, int image_id, + unsigned char *jpeg_data, + unsigned long jpeg_data_len, + unsigned char *alpha_data, + unsigned long alpha_data_len); + +extern unsigned char *swf_tag_get_png_data(swf_tag_t *tag, unsigned long *length, int image_id); +extern int swf_tag_replace_png_data(swf_tag_t *tag, int image_id, + unsigned char *png_data, + unsigned long png_data_len); +/* sound */ +extern unsigned char *swf_tag_get_sound_data(swf_tag_t *tag, + unsigned long *length, + int sound_id); +extern int swf_tag_replace_melo_data(swf_tag_t *tag, int sound_id, + unsigned char *melo_data, + unsigned long melo_data_len); +/* edit text */ + +extern char *swf_tag_get_edit_string(swf_tag_t *tag, + char *variable_name, + int variable_name_len, + struct swf_object_ *swf); +extern int swf_tag_replace_edit_string(swf_tag_t *tag, + char *variable_name, + int variable_name_len, + char *initial_text, + int initial_text_len, + struct swf_object_ *swf); + +extern int swf_tag_create_detail(swf_tag_t *tag, struct swf_object_ *swf); + +#endif /* __SWF_TAG_H__ */ diff --git a/src/swf_tag_action.c b/src/swf_tag_action.c new file mode 100644 index 0000000..7e0b9e5 --- /dev/null +++ b/src/swf_tag_action.c @@ -0,0 +1,117 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include "bitstream.h" +#include "swf_tag_action.h" +#include "swf_object.h" + +swf_tag_detail_handler_t action_detail_handler; + +swf_tag_detail_handler_t * +swf_tag_action_detail_handler(void) { + action_detail_handler.create = swf_tag_action_create_detail; + action_detail_handler.identity = swf_tag_action_identity_detail; + action_detail_handler.output = swf_tag_action_output_detail; + action_detail_handler.print = swf_tag_action_print_detail; + action_detail_handler.destroy = swf_tag_action_destroy_detail; + return &action_detail_handler; +} + +void * +swf_tag_action_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_action_detail_t *swf_tag_action; + bitstream_t *bs; + unsigned long pos, len; + (void) swf; + swf_tag_action = calloc(sizeof(*swf_tag_action), 1); + if (swf_tag_action == NULL) { + fprintf(stderr, "ERROR: swf_tag_action_create_detail: can't calloc\n"); + return NULL; + } + bs = bitstream_open(); + bitstream_input(bs, data, length); + + if (tag->tag == 59) { // DoInitAction + swf_tag_action->action_sprite = bitstream_getbytesLE(bs, 2); + } else { // DoAction + swf_tag_action->action_sprite = 0; // fail safe + } + pos = bitstream_getbytepos(bs); + len = bitstream_length(bs) - pos; + swf_tag_action->action_record = bitstream_output_sub(bs, pos, len); + swf_tag_action->action_record_len = len; + bitstream_close(bs); + return (void *) swf_tag_action; +} + +int swf_tag_action_identity_detail(unsigned char *data, int id, + swf_tag_t *tag) { + (void) data; + (void) id; + (void) tag; + return 1; +} + +unsigned char * +swf_tag_action_output_detail(void *detail, unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_action_detail_t *swf_tag_action = (swf_tag_action_detail_t *) detail; + bitstream_t *bs; + unsigned char *data; + *length = 0; + + (void) swf; + bs = bitstream_open(); + if (tag->tag == 59) { // DoInitAction + bitstream_putbytesLE(bs, swf_tag_action->action_sprite, 2); + } else { // DoAction + ; // nothing + } + bitstream_putstring(bs, swf_tag_action->action_record, + swf_tag_action->action_record_len); + data = bitstream_steal(bs, length); + bitstream_close(bs); + return data; +} + +void +swf_tag_action_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf) { + bitstream_t *bs; + swf_action_list_t *action_list; + swf_tag_action_detail_t *swf_tag_action = (swf_tag_action_detail_t *) detail; + (void) swf; + if (tag->tag == 59) { // DoInitAction + printf("action_sprite=%d ", swf_tag_action->action_sprite); + } + printf("action_record =\n"); + bs = bitstream_open(); + bitstream_input(bs, swf_tag_action->action_record, + swf_tag_action->action_record_len); + action_list = swf_action_list_create(bs); + bitstream_close(bs); + swf_action_list_print(action_list); + swf_action_list_destroy(action_list); + return ; +} + +void +swf_tag_action_destroy_detail(void *detail) { + swf_tag_action_detail_t *swf_tag_action = (swf_tag_action_detail_t *) detail; + if (swf_tag_action) { + free(swf_tag_action->action_record); + swf_tag_action->action_record = NULL; + free(swf_tag_action); + } + return ; +} diff --git a/src/swf_tag_action.h b/src/swf_tag_action.h new file mode 100644 index 0000000..f785baf --- /dev/null +++ b/src/swf_tag_action.h @@ -0,0 +1,36 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_TAG_ACTION__H__ +#define __SWF_TAG_ACTION__H__ + +#include "swf_tag.h" +#include "swf_action.h" + +typedef struct swf_tag_action_detail_ { + unsigned short action_sprite; + unsigned char *action_record; + unsigned long action_record_len; +} swf_tag_action_detail_t; + +extern swf_tag_detail_handler_t *swf_tag_action_detail_handler(void); + +extern void *swf_tag_action_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern int swf_tag_action_identity_detail(unsigned char *data, int id, + swf_tag_t *tag); +extern unsigned char *swf_tag_action_output_detail(void *detail, + unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_action_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_action_destroy_detail(void *detail); + +#endif /* __SWF_TAG_ACTION__H__ */ diff --git a/src/swf_tag_edit.c b/src/swf_tag_edit.c new file mode 100644 index 0000000..15c9917 --- /dev/null +++ b/src/swf_tag_edit.c @@ -0,0 +1,295 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include "bitstream.h" +#include "swf_tag_edit.h" +#include "swf_object.h" +#include "swf_rgba.h" + +swf_tag_detail_handler_t edit_detail_handler; + +swf_tag_detail_handler_t * +swf_tag_edit_detail_handler(void) { + edit_detail_handler.create = swf_tag_edit_create_detail; + edit_detail_handler.identity = swf_tag_edit_identity_detail; + edit_detail_handler.output = swf_tag_edit_output_detail; + edit_detail_handler.print = swf_tag_edit_print_detail; + edit_detail_handler.destroy = swf_tag_edit_destroy_detail; + return &edit_detail_handler; +} + +void * +swf_tag_edit_create_detail(unsigned char *data, unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_edit_detail_t *swf_tag_edit; + bitstream_t *bs; + (void) tag; + swf_tag_edit = calloc(sizeof(*swf_tag_edit), 1); + if (swf_tag_edit == NULL) { + fprintf(stderr, "ERROR: swf_tag_edit_create_detail: can't calloc\n"); + return NULL; + } + bs = bitstream_open(); + bitstream_input(bs, data, length); + swf_tag_edit->edit_id = bitstream_getbytesLE(bs, 2); + swf_rect_parse(bs, &swf_tag_edit->rect); + bitstream_align(bs); + swf_tag_edit->edit_has_text = bitstream_getbit(bs); + swf_tag_edit->edit_word_wrap = bitstream_getbit(bs); + swf_tag_edit->edit_multiline = bitstream_getbit(bs); + swf_tag_edit->edit_password = bitstream_getbit(bs); + swf_tag_edit->edit_readonly = bitstream_getbit(bs); + swf_tag_edit->edit_has_color = bitstream_getbit(bs); + swf_tag_edit->edit_has_max_length = bitstream_getbit(bs); + swf_tag_edit->edit_has_font = bitstream_getbit(bs); + if (swf && (swf->header.version >= 6)) { + (void) bitstream_getbit(bs); // reserved; + swf_tag_edit->edit_auto_size = bitstream_getbit(bs); + } else { + (void) bitstream_getbit(bs); // reserved; + (void) bitstream_getbit(bs); // reserved; + } + swf_tag_edit->edit_has_layout = bitstream_getbit(bs); + swf_tag_edit->edit_no_select = bitstream_getbit(bs); + swf_tag_edit->edit_border = bitstream_getbit(bs); + (void) bitstream_getbit(bs); // reserved; + swf_tag_edit->edit_html = bitstream_getbit(bs); + swf_tag_edit->edit_use_outlines = bitstream_getbit(bs); + if (swf_tag_edit->edit_has_font) { + swf_tag_edit->edit_font_id_ref = bitstream_getbytesLE(bs, 2); + swf_tag_edit->edit_font_height = bitstream_getbytesLE(bs, 2); + } + if (swf_tag_edit->edit_has_color) { + swf_rgba_parse(bs, &swf_tag_edit->edit_color); + } + if (swf_tag_edit->edit_has_max_length) { + swf_tag_edit->edit_max_length = bitstream_getbytesLE(bs, 2); + } + if (swf_tag_edit->edit_has_layout) { + swf_tag_edit->edit_align = bitstream_getbyte(bs); + swf_tag_edit->edit_left_margine = bitstream_getbytesLE(bs, 2); + swf_tag_edit->edit_right_margine = bitstream_getbytesLE(bs, 2); + swf_tag_edit->edit_indent = (signed) bitstream_getbytesLE(bs, 2); + swf_tag_edit->edit_leading = (signed) bitstream_getbytesLE(bs, 2); + } + swf_tag_edit->edit_variable_name = (char *) bitstream_outputstring(bs); + if (swf_tag_edit->edit_has_text) { + swf_tag_edit->edit_initial_text = (char *) bitstream_outputstring(bs); + } else { + swf_tag_edit->edit_initial_text = NULL; + } + + bitstream_close(bs); + return (void *) swf_tag_edit; +} + +int swf_tag_edit_identity_detail(unsigned char *data, int id, + swf_tag_t *tag) { + bitstream_t *bs; + int edit_id; + (void) tag; + bs = bitstream_open(); + bitstream_input(bs, data, 2); + edit_id = bitstream_getbytesLE(bs, 2); + bitstream_close(bs); + if (id == edit_id) { + return 0; + } + return 1; +} + +unsigned char * +swf_tag_edit_output_detail(void *detail, unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_edit_detail_t *swf_tag_edit = (swf_tag_edit_detail_t *) detail; + bitstream_t *bs; + unsigned char *data; + (void) tag; + *length = 0; + bs = bitstream_open(); + bitstream_putbytesLE(bs, swf_tag_edit->edit_id, 2); + swf_rect_build(bs, &swf_tag_edit->rect); + bitstream_align(bs); + bitstream_putbit(bs, swf_tag_edit->edit_has_text); + bitstream_putbit(bs, swf_tag_edit->edit_word_wrap); + bitstream_putbit(bs, swf_tag_edit->edit_multiline); + bitstream_putbit(bs, swf_tag_edit->edit_password ); + bitstream_putbit(bs, swf_tag_edit->edit_readonly); + bitstream_putbit(bs, swf_tag_edit->edit_has_color ); + bitstream_putbit(bs, swf_tag_edit->edit_has_max_length); + bitstream_putbit(bs, swf_tag_edit->edit_has_font); + if (swf && (swf->header.version >= 6)) { + bitstream_putbit(bs, 0); // reserved; + bitstream_putbit(bs, swf_tag_edit->edit_auto_size); + } else { + bitstream_putbit(bs, 0); // reserved; + bitstream_putbit(bs, 0); // reserved; + } + bitstream_putbit(bs, swf_tag_edit->edit_has_layout); + bitstream_putbit(bs, swf_tag_edit->edit_no_select); + bitstream_putbit(bs, swf_tag_edit->edit_border); + bitstream_putbit(bs, 0); // reserved; + bitstream_putbit(bs, swf_tag_edit->edit_html); + bitstream_putbit(bs, swf_tag_edit->edit_use_outlines); + if (swf_tag_edit->edit_has_font) { + bitstream_putbytesLE(bs, swf_tag_edit->edit_font_id_ref, 2); + bitstream_putbytesLE(bs, swf_tag_edit->edit_font_height, 2); + } + if (swf_tag_edit->edit_has_color) { + swf_rgba_build(bs, &swf_tag_edit->edit_color); + } + if (swf_tag_edit->edit_has_max_length) { + bitstream_putbytesLE(bs, swf_tag_edit->edit_max_length, 2); + } + if (swf_tag_edit->edit_has_layout) { + bitstream_putbyte(bs, swf_tag_edit->edit_align); + bitstream_putbytesLE(bs, swf_tag_edit->edit_left_margine, 2); + bitstream_putbytesLE(bs, swf_tag_edit->edit_right_margine, 2); + bitstream_putbytesLE(bs, swf_tag_edit->edit_indent, 2); + bitstream_putbytesLE(bs, swf_tag_edit->edit_leading, 2); + } + bitstream_putstring(bs, + (unsigned char *) swf_tag_edit->edit_variable_name, + strlen(swf_tag_edit->edit_variable_name) + 1); + if (swf_tag_edit->edit_has_text) { + bitstream_putstring(bs, + (unsigned char *)swf_tag_edit->edit_initial_text, + strlen(swf_tag_edit->edit_initial_text) + 1); + } + data = bitstream_steal(bs, length); + bitstream_close(bs); + return data; +} + +void +swf_tag_edit_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_edit_detail_t *swf_tag_edit = (swf_tag_edit_detail_t *) detail; + (void) tag; + printf("\tedit_id=%d\n", swf_tag_edit->edit_id); + printf("\t"); + swf_rect_print(&swf_tag_edit->rect); + printf("\ttext=%d wwrap=%d multi=%d pass=%d ro=%d col=%d maxlen=%d font=%d\n", + swf_tag_edit->edit_has_text?1:0, + swf_tag_edit->edit_word_wrap?1:0, + swf_tag_edit->edit_multiline?1:0, + swf_tag_edit->edit_password?1:0, + swf_tag_edit->edit_readonly?1:0, + swf_tag_edit->edit_has_color?1:0, + swf_tag_edit->edit_has_max_length?1:0, + swf_tag_edit->edit_has_font?1:0); + if (swf->header.version >= 6) { + printf("\tauto_size=%d\n", swf_tag_edit->edit_auto_size); + } + printf("\tlayout=%d no_sel=%d border=%d\n", + swf_tag_edit->edit_has_layout?1:0, + swf_tag_edit->edit_no_select?1:0, + swf_tag_edit->edit_border?1:0); + if (swf_tag_edit->edit_has_font) { + printf("\tfont_id=%d font_height=%d\n", + swf_tag_edit->edit_font_id_ref, + swf_tag_edit->edit_font_height / SWF_TWIPS); + } + if (swf_tag_edit->edit_has_color) { + printf("\t"); + swf_rgba_print(&swf_tag_edit->edit_color); + } + if (swf_tag_edit->edit_has_max_length) { + printf("\tmax_length=%d\n", + swf_tag_edit->edit_max_length); + } + if (swf_tag_edit->edit_has_layout) { + printf("\talign=%d (left,right)_margine=(%d,%d) indent=%d leading=%d\n", + swf_tag_edit->edit_align, + swf_tag_edit->edit_left_margine, + swf_tag_edit->edit_right_margine, + swf_tag_edit->edit_indent, + swf_tag_edit->edit_leading); + } + if (swf_tag_edit->edit_variable_name) { + printf("\tvariable_name=%s\n", + swf_tag_edit->edit_variable_name); + } + if (swf_tag_edit->edit_initial_text) { + printf("\tinitial_text=%s\n", + swf_tag_edit->edit_initial_text); + } + return ; +} + +void +swf_tag_edit_destroy_detail(void *detail) { + swf_tag_edit_detail_t *swf_tag_edit = (swf_tag_edit_detail_t *) detail; + if (swf_tag_edit) { + free(swf_tag_edit->edit_variable_name); + free(swf_tag_edit->edit_initial_text); + swf_tag_edit->edit_variable_name = NULL; + swf_tag_edit->edit_initial_text = NULL; + free(swf_tag_edit); + } + return ; +} + +char * +swf_tag_edit_get_string(void *detail, + char *variable_name, int variable_name_len) { + swf_tag_edit_detail_t *swf_tag_edit = (swf_tag_edit_detail_t *) detail; + char *data, *initial_text; + if (strcmp(swf_tag_edit->edit_variable_name, variable_name)) { + if (atoi(variable_name) != swf_tag_edit->edit_id) { + return NULL; + } + } + initial_text = swf_tag_edit->edit_initial_text; + data = malloc(variable_name_len + 1); + if (data == NULL) { + fprintf(stderr, "swf_tag_edit_get_string: Can't malloc\n"); + return NULL; + } + memcpy(data, initial_text, variable_name_len + 1); + return data; +} + +int +swf_tag_edit_replace_string(void *detail, + char *variable_name, int variable_name_len, + char *initial_text, int initial_text_len) { + char *new_str; + swf_tag_edit_detail_t *swf_tag_edit = (swf_tag_edit_detail_t *) detail; + if (((int) strlen(swf_tag_edit->edit_variable_name) != variable_name_len) + || memcmp(swf_tag_edit->edit_variable_name, variable_name, + variable_name_len)) { + if (atoi(variable_name) != swf_tag_edit->edit_id) { + return 1; + } + } + if (initial_text_len == 0) { + swf_tag_edit->edit_has_text = 0; + if (swf_tag_edit->edit_initial_text) { + free(swf_tag_edit->edit_initial_text); + swf_tag_edit->edit_initial_text = NULL; + } + return 0; + } + swf_tag_edit->edit_has_text = 1; + new_str = malloc(initial_text_len + 1); + if (new_str == NULL) { + fprintf(stderr, "swf_tag_edit_replace_string: Can't malloc\n"); + return 1; + } + memcpy(new_str, initial_text, initial_text_len); + new_str[initial_text_len] = '\0'; + if (swf_tag_edit->edit_initial_text) { + free(swf_tag_edit->edit_initial_text); + } + swf_tag_edit->edit_initial_text = new_str; + return 0; +} diff --git a/src/swf_tag_edit.h b/src/swf_tag_edit.h new file mode 100644 index 0000000..977acf7 --- /dev/null +++ b/src/swf_tag_edit.h @@ -0,0 +1,76 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_TAG_EDIT__H__ +#define __SWF_TAG_EDIT__H__ + +#include "swf_tag.h" +#include "swf_rect.h" +#include "swf_rgba.h" + +typedef struct swf_tag_edit_detail_ { + int edit_id; + swf_rect_t rect; + int edit_has_text:1; + int edit_word_wrap:1; + int edit_multiline:1; + int edit_password:1; + int edit_readonly:1; + int edit_has_color:1; + int edit_has_max_length:1; + int edit_has_font:1; +/* unsigned char edit_reserved; */ + unsigned char edit_auto_size; // version >= 6 + int edit_has_layout:1; + int edit_no_select:1; + int edit_border:1; +/* int edit_researved:1; */ + int edit_html:1; + int edit_use_outlines:1; + // edit has font -- begin + unsigned short edit_font_id_ref; + unsigned short edit_font_height; + // edit has font -- end + swf_rgba_t edit_color; // edit has color + unsigned short edit_max_length; // edit has max length + // edit has layout -- begin + unsigned char edit_align; + unsigned short edit_left_margine; + unsigned short edit_right_margine; + signed short edit_indent; + signed short edit_leading; + // edit has layout -- end + char *edit_variable_name; + char *edit_initial_text; // edit_has text +} swf_tag_edit_detail_t; + +extern swf_tag_detail_handler_t *swf_tag_edit_detail_handler(void); + +extern void *swf_tag_edit_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern int swf_tag_edit_identity_detail(unsigned char *data, int id, + swf_tag_t *tag); +extern unsigned char *swf_tag_edit_output_detail(void *detail, + unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_edit_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_edit_destroy_detail(void *detail); + +extern char *swf_tag_edit_get_string(void *detail, + char *variable_name, + int variable_name_len); +extern int swf_tag_edit_replace_string(void *detail, + char *variable_name, + int variable_name_len, + char *initial_text, + int initial_text_len); + +#endif /* __SWF_TAG_EDIT__H__ */ diff --git a/src/swf_tag_jpeg.c b/src/swf_tag_jpeg.c new file mode 100644 index 0000000..b6c1c66 --- /dev/null +++ b/src/swf_tag_jpeg.c @@ -0,0 +1,315 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include /* strndup */ +#include +#include "bitstream.h" +#include "swf_define.h" +#include "swf_tag_jpeg.h" +// #include "swf_tag.h" +#include "swf_jpeg.h" +#include "jpeg_segment.h" + +swf_tag_detail_handler_t jpeg_detail_handler; + +swf_tag_detail_handler_t *swf_tag_jpeg_detail_handler(void) { + jpeg_detail_handler.create = swf_tag_jpeg_create_detail; + jpeg_detail_handler.identity = swf_tag_jpeg_identity_detail; + jpeg_detail_handler.output = swf_tag_jpeg_output_detail; + jpeg_detail_handler.print = swf_tag_jpeg_print_detail; + jpeg_detail_handler.destroy = swf_tag_jpeg_destroy_detail; + return &jpeg_detail_handler; +} + +swf_tag_detail_handler_t *swf_tag_jpeg3_detail_handler(void) { + jpeg_detail_handler.create = swf_tag_jpeg3_create_detail; + jpeg_detail_handler.identity = swf_tag_jpeg_identity_detail; + jpeg_detail_handler.output = swf_tag_jpeg3_output_detail; + jpeg_detail_handler.print = swf_tag_jpeg_print_detail; + jpeg_detail_handler.destroy = swf_tag_jpeg_destroy_detail; + return &jpeg_detail_handler; +} + +void * +swf_tag_jpeg_create_detail(unsigned char *data, unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_jpeg_detail_t *swf_tag_jpeg; + bitstream_t *bs; + (void) tag; + (void) swf; + swf_tag_jpeg = calloc(sizeof(*swf_tag_jpeg), 1); + if (swf_tag_jpeg == NULL) { + fprintf(stderr, "ERROR: swf_tag_jpeg_create_detail: can't calloc\n"); + return NULL; + } + bs = bitstream_open(); + bitstream_input(bs, data, length); + swf_tag_jpeg->image_id = bitstream_getbytesLE(bs, 2); + swf_tag_jpeg->jpeg_data = bitstream_output_sub(bs, 2, length - 2); + swf_tag_jpeg->jpeg_data_len = length - 2; + swf_tag_jpeg->alpha_data = NULL; + swf_tag_jpeg->alpha_data_len = 0; + bitstream_close(bs); + return (void *) swf_tag_jpeg; +} + +void * +swf_tag_jpeg3_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_jpeg_detail_t *swf_tag_jpeg; + unsigned long offset_to_alpha; + bitstream_t *bs; + unsigned long offset, alpha_data_len; + unsigned char *old_buff_ref, *new_buff; + unsigned long origsize; + int result; + (void) tag; + (void) swf; + swf_tag_jpeg = calloc(sizeof(*swf_tag_jpeg), 1); + if (swf_tag_jpeg == NULL) { + fprintf(stderr, "swf_tag_jpeg_create_detail: can't calloc\n"); + return NULL; + } + bs = bitstream_open(); + bitstream_input(bs, data, length); + swf_tag_jpeg->image_id = bitstream_getbytesLE(bs, 2); + offset_to_alpha = bitstream_getbytesLE(bs, 4); + swf_tag_jpeg->offset_to_alpha = offset_to_alpha; + swf_tag_jpeg->jpeg_data = bitstream_output_sub(bs, 2 + 4 , offset_to_alpha); + if (swf_tag_jpeg->jpeg_data == NULL) { + free(swf_tag_jpeg); + bitstream_close(bs); + fprintf(stderr, "swf_tag_jpeg3_create_detail: swf_tag_jpeg->jpeg_data\n"); + return NULL; + } + + swf_tag_jpeg->jpeg_data_len = offset_to_alpha; + offset = 2 + 4 + offset_to_alpha; + alpha_data_len = length - offset; + origsize = 256 * alpha_data_len; + new_buff = malloc(origsize); + old_buff_ref = bitstream_buffer(bs, offset); + result = uncompress(new_buff, &origsize, old_buff_ref, alpha_data_len); + if (result == Z_OK) { + swf_tag_jpeg->alpha_data = realloc(new_buff, origsize); + swf_tag_jpeg->alpha_data = new_buff; + swf_tag_jpeg->alpha_data_len = origsize; + } else { + if (result == Z_MEM_ERROR) { + fprintf(stderr, "swf_tag_jpeg3_create_detail: uncompress: Z_MEM_ERROR: can't malloc\n"); + } else if (result == Z_BUF_ERROR) { + fprintf(stderr, "swf_tag_jpeg3_create_detail: uncompress: Z_BUF_ERROR: not enough buff size\n"); + } else if (result == Z_DATA_ERROR) { + fprintf(stderr, "swf_tag_jpeg3_create_detail: uncompress: Z_DATA_ERROR: corrupted or imcomplete data\n"); + } else { + fprintf(stderr, "swf_tag_jpeg3_create_detail: uncompress: failed by unknown reason (%d)\n", result); + } + free(new_buff); + } + bitstream_close(bs); + return (void *) swf_tag_jpeg; +} + +int +swf_tag_jpeg_identity_detail(unsigned char *data, int id, swf_tag_t *tag) { + int image_id; + if (tag->detail) { + swf_tag_jpeg_detail_t *swf_tag_jpeg = (swf_tag_jpeg_detail_t *) tag->detail; + if (swf_tag_jpeg->image_id == id) { + return 0; + } + return 1; + } + if (data == NULL) { + fprintf(stderr, "swf_tag_jpeg_identity_detail: data==NULL\n"); + return 1; + } + image_id = GetUShortLE(data); + if (id == image_id) { + return 0; + } + return 1; +} + +unsigned char * +swf_tag_jpeg_output_detail(void *detail, unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_jpeg_detail_t *swf_tag_jpeg = (swf_tag_jpeg_detail_t *) detail; + bitstream_t *bs; + unsigned char *data; + (void) tag; + (void) swf; + *length = 0; + bs = bitstream_open(); + bitstream_putbytesLE(bs, swf_tag_jpeg->image_id, 2); + bitstream_putstring(bs, swf_tag_jpeg->jpeg_data, swf_tag_jpeg->jpeg_data_len); + data = bitstream_steal(bs, length); + bitstream_close(bs); + return data; +} + +unsigned char * +swf_tag_jpeg3_output_detail(void *detail, unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_jpeg_detail_t *swf_tag_jpeg = (swf_tag_jpeg_detail_t *) detail; + bitstream_t *bs; + unsigned char *data, *new_buff; + unsigned long offset_to_alpha; + unsigned long compsize; + (void) tag; + (void) swf; + *length = 0; + bs = bitstream_open(); + bitstream_putbytesLE(bs, swf_tag_jpeg->image_id, 2); + bitstream_putbytesLE(bs, swf_tag_jpeg->jpeg_data_len, 4); + bitstream_putstring(bs, swf_tag_jpeg->jpeg_data, swf_tag_jpeg->jpeg_data_len); + offset_to_alpha = swf_tag_jpeg->jpeg_data_len; + new_buff = malloc(swf_tag_jpeg->alpha_data_len); // too enough memory + compress(new_buff, &compsize, swf_tag_jpeg->alpha_data, swf_tag_jpeg->alpha_data_len); + bitstream_putstring(bs, new_buff, compsize); + free(new_buff); + data = bitstream_steal(bs, length); + bitstream_close(bs); + return data; +} + +void +swf_tag_jpeg_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_jpeg_detail_t *swf_tag_jpeg = (swf_tag_jpeg_detail_t *) detail; + jpeg_segment_t *jpeg_seg; + jpeg_segment_node_t *node; + (void) tag; + (void) swf; + if (detail == NULL) { + fprintf(stderr, "swf_tag_jpeg_print_detail: detail == NULL\n"); + return ; + } + printf("\timage_id=%d jpeg_data_size=%lu\n", + swf_tag_jpeg->image_id, swf_tag_jpeg->jpeg_data_len); + jpeg_seg = jpeg_segment_parse(swf_tag_jpeg->jpeg_data, + swf_tag_jpeg->jpeg_data_len); + if (jpeg_seg) { + for(node = jpeg_seg->head ; node ; node = node->next) { + char *name = jpeg_segment_get_marker_name(node->marker); + printf("\t\t%s(0x%02X): len=%lu\n", name?name:"Unknwon", + node->marker, node->data_len); + } + jpeg_segment_destroy(jpeg_seg); + } else { + printf("\t\t(invalid jpeg data)\n"); + } + if (swf_tag_jpeg->alpha_data) { + printf(" alpha_data_size=%lu\n", + swf_tag_jpeg->alpha_data_len); + } +} + +void +swf_tag_jpeg_destroy_detail(void *detail) { + swf_tag_jpeg_detail_t *swf_tag_jpeg = (swf_tag_jpeg_detail_t *) detail; + if (swf_tag_jpeg) { + free(swf_tag_jpeg->jpeg_data); + free(swf_tag_jpeg->alpha_data); + swf_tag_jpeg->jpeg_data = NULL; + swf_tag_jpeg->alpha_data = NULL; + free(swf_tag_jpeg); + } + return ; +} + +unsigned char *swf_tag_jpeg_get_jpeg_data(void *detail, + unsigned long *length, + int image_id, + unsigned char *jpeg_table_data, + unsigned long jpeg_table_data_len) { + swf_tag_jpeg_detail_t *swf_tag_jpeg = (swf_tag_jpeg_detail_t *) detail; + unsigned char *data; + *length = 0; + if (detail == NULL) { + fprintf(stderr, "swf_tag_jpeg_get_jpeg_data: detail == NULL\n"); + } + if (swf_tag_jpeg->image_id != image_id) { + return NULL; + } + if (swf_tag_jpeg->jpeg_data_len == 0) { + fprintf(stderr, "swf_tag_jpeg_get_jpeg_data: swf_tag_jpeg->jpeg_data_len\n"); + return NULL; + } + data = jpegconv_swf2std(swf_tag_jpeg->jpeg_data, + swf_tag_jpeg->jpeg_data_len, + length, + jpeg_table_data, + jpeg_table_data_len); + return data; +} + +unsigned char *swf_tag_jpeg_get_alpha_data(void *detail, unsigned long *length, int image_id) { + swf_tag_jpeg_detail_t *swf_tag_jpeg = (swf_tag_jpeg_detail_t *) detail; + unsigned char *data; + *length = 0; + if (detail == NULL) { + fprintf(stderr, "swf_tag_jpeg_get_alpha_data: detail == NULL\n"); + return NULL; + } + if (swf_tag_jpeg->image_id != image_id) { + return NULL; + } + *length = swf_tag_jpeg->alpha_data_len; + if (*length == 0) { + return NULL; + } + data = malloc(*length); + memcpy(data, swf_tag_jpeg->alpha_data, *length); + return data; +} + +int +swf_tag_jpeg_replace_jpeg_data(void *detail, int image_id, + unsigned char *jpeg_data, + unsigned long jpeg_data_len, + unsigned char *alpha_data, + unsigned long alpha_data_len, + swf_tag_t *tag) { + swf_tag_jpeg_detail_t *swf_tag_jpeg = (swf_tag_jpeg_detail_t *) detail; + if (detail == NULL) { + fprintf(stderr, "swf_tag_jpeg_replace_jpeg_data: detail == NULL\n"); + return 1; + } + if (swf_tag_jpeg->image_id != image_id) { + return 1; + } + if (tag->tag == 6) { // DefineBitsJPEG + free(swf_tag_jpeg->jpeg_data); + swf_tag_jpeg->jpeg_data = malloc(jpeg_data_len); + memcpy(swf_tag_jpeg->jpeg_data, jpeg_data, jpeg_data_len); + swf_tag_jpeg->jpeg_data_len = jpeg_data_len; + } else { + if (jpeg_data) { + unsigned long length; + free(swf_tag_jpeg->jpeg_data); + swf_tag_jpeg->jpeg_data = jpegconv_std2swf(jpeg_data, jpeg_data_len, + &length); + swf_tag_jpeg->jpeg_data_len = length; + } + if (alpha_data) { + free(swf_tag_jpeg->alpha_data); + swf_tag_jpeg->alpha_data = malloc(alpha_data_len); + memcpy(swf_tag_jpeg->alpha_data, alpha_data, alpha_data_len); + swf_tag_jpeg->alpha_data_len = alpha_data_len; + } + } + + return 0; +} diff --git a/src/swf_tag_jpeg.h b/src/swf_tag_jpeg.h new file mode 100644 index 0000000..f208fb0 --- /dev/null +++ b/src/swf_tag_jpeg.h @@ -0,0 +1,60 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_TAG_JPEG__H__ +#define __SWF_TAG_JPEG__H__ + +#include "swf_tag.h" + +typedef struct swf_tag_jpeg_detail_ { + int image_id; + unsigned char *jpeg_data; + unsigned long jpeg_data_len; + unsigned long offset_to_alpha; + unsigned char *alpha_data; + unsigned long alpha_data_len; +} swf_tag_jpeg_detail_t; + +extern swf_tag_detail_handler_t *swf_tag_jpeg_detail_handler(void); +extern swf_tag_detail_handler_t *swf_tag_jpeg3_detail_handler(void); + +extern void *swf_tag_jpeg_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern int swf_tag_jpeg_identity_detail(unsigned char *data, int id, + swf_tag_t *tag); +extern void *swf_tag_jpeg3_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern unsigned char *swf_tag_jpeg_output_detail(void *detail, + unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern unsigned char *swf_tag_jpeg3_output_detail(void *detail, + unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_jpeg_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_jpeg_destroy_detail(void *detail); + +extern unsigned char *swf_tag_jpeg_get_jpeg_data(void *detail, + unsigned long *length, + int image_id, + unsigned char *jpeg_table_data, + unsigned long jpeg_table_data_len); +extern unsigned char *swf_tag_jpeg_get_alpha_data(void *detail, unsigned long *length, int image_id); +extern int swf_tag_jpeg_replace_jpeg_data(void *detail, int image_id, + unsigned char *jpeg_data, + unsigned long jpeg_data_len, + unsigned char *alpha_data, + unsigned long alpha_data_len, + swf_tag_t *tag); + +#endif /* __SWF_TAG_JPEG__H__ */ diff --git a/src/swf_tag_lossless.c b/src/swf_tag_lossless.c new file mode 100644 index 0000000..ef6d360 --- /dev/null +++ b/src/swf_tag_lossless.c @@ -0,0 +1,428 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include /* strndup */ +#include +#include "bitstream.h" +#include "swf_define.h" +#include "swf_tag_lossless.h" +#include "swf_png.h" + +swf_tag_detail_handler_t lossless_detail_handler; + +swf_tag_detail_handler_t *swf_tag_lossless_detail_handler(void) { + lossless_detail_handler.create = swf_tag_lossless_create_detail; + lossless_detail_handler.identity = swf_tag_lossless_identity_detail; + lossless_detail_handler.output = swf_tag_lossless_output_detail; + lossless_detail_handler.print = swf_tag_lossless_print_detail; + lossless_detail_handler.destroy = swf_tag_lossless_destroy_detail; + return &lossless_detail_handler; +} + +void * +swf_tag_lossless_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_lossless_detail_t *swf_tag_lossless; + bitstream_t *bs, *bs2; + (void) swf; + unsigned long i; + unsigned char *tmp_buff, *old_buff_ref; + unsigned long origsize, old_size, offset; + int result; + + swf_tag_lossless = calloc(sizeof(*swf_tag_lossless), 1); + if (swf_tag_lossless == NULL) { + fprintf(stderr, "swf_tag_lossless_create_detail: can't calloc swf_tag_lossless\n"); + return NULL; + } + bs = bitstream_open(); + bitstream_input(bs, data, length); + swf_tag_lossless->image_id = bitstream_getbytesLE(bs, 2); + swf_tag_lossless->format = bitstream_getbyte(bs); + swf_tag_lossless->width = bitstream_getbytesLE(bs, 2); + swf_tag_lossless->height = bitstream_getbytesLE(bs, 2); + if (swf_tag_lossless->format == 3) { + unsigned long indices_len; + int bytes_per_color; + swf_tag_lossless->colormap_count = bitstream_getbyte(bs) + 1; + indices_len = ((swf_tag_lossless->width + 3) & -4) * swf_tag_lossless->height; + if (tag->tag == 20) { // Lossless => rgb (3 bytes) + bytes_per_color = 3; + } else { // Lossless2 => rgba (4 bytes) + bytes_per_color = 4; + } + origsize = bytes_per_color * swf_tag_lossless->colormap_count + indices_len; + tmp_buff = malloc(origsize); + offset = bitstream_getbytepos(bs); + old_buff_ref = bitstream_buffer(bs, offset); + old_size = bitstream_length(bs) - offset; + result = uncompress(tmp_buff, &origsize, old_buff_ref, old_size); + if (result != Z_OK) { + if (result == Z_MEM_ERROR) { + fprintf(stderr, "swf_tag_lossless_create_detail: uncompress: Z_MEM_ERROR: can't malloc at line(%d)\n", __LINE__); + } else if (result == Z_BUF_ERROR) { + fprintf(stderr, "swf_tag_lossless_create_detail: uncompress: Z_BUF_ERROR: not enough buff size at line(%d)\n", __LINE__); + } else if (result == Z_DATA_ERROR) { + fprintf(stderr, "swf_tag_lossless_create_detail: uncompress: Z_DATA_ERROR: corrupted or imcomplete data at line(%d)\n", __LINE__); + } else { + fprintf(stderr, "swf_tag_lossless_create_detail: uncompress: failed byunknown reason (%d) at line(%d)\n", result, __LINE__); + } + free(tmp_buff); + bitstream_close(bs); + return NULL; + } + if (indices_len != origsize - bytes_per_color * swf_tag_lossless->colormap_count) { + fprintf(stderr, "swf_tag_lossless_create_detail: indices_len(%lu) != origsize(%lu) - %d * swf_tag_lossless->colormap_count(%d) at line(%d)\n", + indices_len, origsize, bytes_per_color, + swf_tag_lossless->colormap_count, __LINE__); + free(tmp_buff); + bitstream_close(bs); + return NULL; + } + bs2 = bitstream_open(); + bitstream_input(bs2, tmp_buff, origsize); + if (tag->tag == 20) { // Lossless + swf_tag_lossless->colormap = malloc(sizeof(swf_rgb_t) * swf_tag_lossless->colormap_count); + for (i=0 ; i < swf_tag_lossless->colormap_count ; i++) { + swf_rgb_t *rgb = swf_tag_lossless->colormap + i; + swf_rgb_parse(bs2, rgb); + } + } else { // tag == 36 (Lossless2) + swf_tag_lossless->colormap2 = malloc(sizeof(swf_rgba_t) * swf_tag_lossless->colormap_count); + for (i=0; icolormap_count; i++) { + swf_rgba_t *rgba = swf_tag_lossless->colormap2 + i; + swf_rgba_parse(bs2, rgba); + } + } + swf_tag_lossless->indices = malloc(indices_len); + bitstream_getstring(bs2, swf_tag_lossless->indices, indices_len); + bitstream_close(bs2); + free(tmp_buff); + } else { // format != 3 + unsigned long bitmap_count; + bitmap_count = swf_tag_lossless->width * swf_tag_lossless->height; + origsize = 4 * bitmap_count; // xrgb or argb (4 bytes) + tmp_buff = malloc(origsize); + offset = bitstream_getbytepos(bs); + old_buff_ref = bitstream_buffer(bs, offset); + old_size = bitstream_length(bs) - offset; + result = uncompress(tmp_buff, &origsize, old_buff_ref, old_size); + if (result != Z_OK) { + if (result == Z_MEM_ERROR) { + fprintf(stderr, "swf_tag_lossless_create_detail: uncompress: Z_MEM_ERROR: can't malloc (origsize=%lu, old_size=%lu) at line(%d)\n", + origsize, old_size, __LINE__); + } else if (result == Z_BUF_ERROR) { + fprintf(stderr, "swf_tag_lossless_create_detail: uncompress: Z_BUF_ERROR: not enough buff size(origsize=%lu, old_size=%lu) at line(%d)\n", + origsize, old_size, __LINE__); + } else if (result == Z_DATA_ERROR) { + fprintf(stderr, "swf_tag_lossless_create_detail: uncompress: Z_DATA_ERROR: corrupted or imcomplete data at line(%d)\n", __LINE__); + } else { + fprintf(stderr, "swf_tag_lossless_create_detail: uncompress: failed byunknown reason (%d) at line(%d)\n", result, __LINE__); + } + free(tmp_buff); + bitstream_close(bs); + return NULL; + } + bs2 = bitstream_open(); + bitstream_input(bs2, tmp_buff, origsize); + if (tag->tag == 20) { // Lossless + swf_tag_lossless->bitmap = malloc(bitmap_count * sizeof(swf_xrgb_t)); + for (i=0; ibitmap + i; + swf_xrgb_parse(bs2, xrgb); + } + } else { // tag == 36 (Lossless2) + swf_tag_lossless->bitmap2 = malloc(bitmap_count * sizeof(swf_argb_t)); + for (i=0; ibitmap2 + i; + swf_argb_parse(bs2, argb); + } + } + bitstream_close(bs2); + free(tmp_buff); + } + bitstream_close(bs); + return (void *) swf_tag_lossless; +} + +int +swf_tag_lossless_identity_detail(unsigned char *data, int id, swf_tag_t *tag) { + int image_id; + if (tag->detail) { + swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) tag->detail; + if (swf_tag_lossless->image_id == id) { + return 0; + } + return 1; + } + if (data == NULL) { + fprintf(stderr, "swf_tag_lossless_identity_detail: data==NULL at line(%d)\n", __LINE__); + return 1; + } + image_id = GetUShortLE(data); + if (id == image_id) { + return 0; + } + return 1; +} + +unsigned char * +swf_tag_lossless_output_detail(void *detail, unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) detail; + bitstream_t *bs, *bs2; + unsigned char *data; + unsigned long i; + unsigned char *tmp_buff, *old_buff_ref; + unsigned long compsize, old_size; + (void) swf; + *length = 0; + bs = bitstream_open(); + bitstream_putbytesLE(bs, swf_tag_lossless->image_id, 2); + bitstream_putbyte(bs, swf_tag_lossless->format); + bitstream_putbytesLE(bs, swf_tag_lossless->width, 2); + bitstream_putbytesLE(bs, swf_tag_lossless->height, 2); + if (swf_tag_lossless->format == 3) { + unsigned long indices_len; + bitstream_putbyte(bs, swf_tag_lossless->colormap_count - 1); /* XXX */ + bs2 = bitstream_open(); + if (tag->tag == 20) { // Lossless + for (i=0; icolormap_count; i++) { + swf_rgb_t *rgb = swf_tag_lossless->colormap + i; + swf_rgb_build(bs2, rgb); + } + } else { // tag == 36 (Lossless2) + for (i=0; icolormap_count; i++) { + swf_rgba_t *rgba = swf_tag_lossless->colormap2 + i; + swf_rgba_build(bs2, rgba); + } + } + indices_len = ((swf_tag_lossless->width + 3) & -4) * swf_tag_lossless->height; + bitstream_putstring(bs2, swf_tag_lossless->indices, + indices_len); + old_buff_ref = bitstream_buffer(bs2, 0); + old_size = bitstream_length(bs2); + tmp_buff = malloc(old_size); // too enough size + compress(tmp_buff, &compsize, old_buff_ref, old_size); + bitstream_putstring(bs, tmp_buff, compsize); + bitstream_close(bs2); + free(tmp_buff); + } else { + unsigned long bitmap_size; + bs2 = bitstream_open(); + if (tag->tag == 20) { // Lossless + bitmap_size = swf_tag_lossless->width * swf_tag_lossless->height; + for (i=0; ibitmap + i; + swf_xrgb_build(bs2, xrgb); + } + } else { // tag == 36 (Lossless2) + bitmap_size = swf_tag_lossless->width * swf_tag_lossless->height; + for (i=0; ibitmap2 + i; + swf_argb_build(bs2, argb); + } + } + old_buff_ref = bitstream_buffer(bs2, 0); + old_size = bitstream_length(bs2); + compsize = old_size; // too enough size + tmp_buff = malloc(compsize); + compress(tmp_buff, &compsize, old_buff_ref, old_size); + bitstream_putstring(bs, tmp_buff, compsize); + bitstream_close(bs2); + free(tmp_buff); + } + data = bitstream_steal(bs, length); + bitstream_close(bs); + return data; +} + +void +swf_tag_lossless_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) detail; + (void) tag; + (void) swf; + if (detail == NULL) { + fprintf(stderr, "swf_tag_lossless_print_detail: detail == NULL\n"); + return ; + } + printf("\timage_id=%d format=%d width=%u height=%u\n", + swf_tag_lossless->image_id, swf_tag_lossless->format, + swf_tag_lossless->width, swf_tag_lossless->height); + if (swf_tag_lossless->colormap || + swf_tag_lossless->colormap2) { + printf("\tcolormap_count=%d", + swf_tag_lossless->colormap_count); + if (swf_tag_lossless->colormap) { + printf(" rgb colormap exists"); + } else { + printf(" rgba colormap exists"); + } + if (swf_tag_lossless->indices) { + printf(" indices exists"); + } + printf("\n"); + } + if (swf_tag_lossless->bitmap) { + printf("\txrgb bitmap exists\n"); + } + if (swf_tag_lossless->bitmap2) { + printf("\targb bitmap exists\n"); + } +} + +void +swf_tag_lossless_destroy_detail(void *detail) { + swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) detail; + if (swf_tag_lossless) { + free(swf_tag_lossless->colormap); + free(swf_tag_lossless->colormap2); + free(swf_tag_lossless->indices); + free(swf_tag_lossless->bitmap); + free(swf_tag_lossless->bitmap2); + swf_tag_lossless->colormap = NULL; + swf_tag_lossless->colormap2 = NULL; + swf_tag_lossless->indices = NULL; + swf_tag_lossless->bitmap = NULL; + swf_tag_lossless->bitmap2 = NULL; + free(swf_tag_lossless); + } + return ; +} + +unsigned char *swf_tag_lossless_get_png_data(void *detail, + unsigned long *length, + int image_id, + swf_tag_t *tag) { + swf_tag_lossless_detail_t *swf_tag_lossless; + unsigned char *data; + *length = 0; + void *index_data = NULL; + void *image_data = NULL; + if (detail == NULL) { + fprintf(stderr, "swf_tag_lossless_get_lossless_data: detail == NULL at line(%d)\n", __LINE__); + } + swf_tag_lossless = (swf_tag_lossless_detail_t *) detail; + if (swf_tag_lossless->image_id != image_id) { + return NULL; + } + if ((swf_tag_lossless->format != 3) && (swf_tag_lossless->format != 5)) { + fprintf(stderr, "swf_tag_lossless_get_lossless_data: format=%d not implemented yet\n", + swf_tag_lossless->format); + return NULL; + } + if (tag->tag == 20) { + if (swf_tag_lossless->format == 3) { + index_data = (void *) swf_tag_lossless->colormap; + image_data = (void *) swf_tag_lossless->indices; + } else { + image_data = (void *) swf_tag_lossless->bitmap; + } + } else { // 36 + if (swf_tag_lossless->format == 3) { + index_data = (void *) swf_tag_lossless->colormap2; + image_data = (void *) swf_tag_lossless->indices; + } else { + image_data = (void *) swf_tag_lossless->bitmap2; + } + } + if (image_data == NULL) { + fprintf(stderr, "swf_tag_lossless_get_lossless_data: image_data == NULL at line(%d)\n", __LINE__); + return NULL; + } + data = pngconv_lossless2png(image_data, + swf_tag_lossless->width, + swf_tag_lossless->height, + index_data, + swf_tag_lossless->colormap_count, + tag->tag, swf_tag_lossless->format, + length); + return data; +} + +int +swf_tag_lossless_replace_png_data(void *detail, int image_id, + unsigned char *png_data, + unsigned long png_data_len, swf_tag_t *tag) { + int tag_no, format; + unsigned short width, height; + unsigned char *result_data; + void *colormap = NULL; + int colormap_count = 0; + swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) detail; + if (detail == NULL) { + fprintf(stderr, "swf_tag_lossless_replace_lossless_data: detail == NULL at line(%d)\n", __LINE__); + return 1; + } + if (swf_tag_lossless->image_id != image_id) { + return 1; + } + result_data = pngconv_png2lossless(png_data, png_data_len, + &tag_no, &format, + &width, &height, + &colormap, &colormap_count); + + if (result_data == NULL) { + fprintf(stderr, "swf_tag_lossless_replace_lossless_data: pngconv_png2lossless failed at line(%d)\n", __LINE__); + return 1; + } + tag->tag = tag_no; + swf_tag_lossless->format = format; + swf_tag_lossless->width = width; + swf_tag_lossless->height = height; + if (format == 3) { + free(swf_tag_lossless->colormap); + free(swf_tag_lossless->colormap2); + free(swf_tag_lossless->indices); + free(swf_tag_lossless->bitmap); + free(swf_tag_lossless->bitmap2); + swf_tag_lossless->colormap = NULL; + swf_tag_lossless->colormap2 = NULL; + swf_tag_lossless->indices = NULL; + swf_tag_lossless->bitmap = NULL; + swf_tag_lossless->bitmap2 = NULL; + if (tag_no == 20) { + swf_tag_lossless->colormap = (swf_rgb_t*) colormap; + } else if (tag_no == 36) { + swf_tag_lossless->colormap2 = (swf_rgba_t*) colormap; + } else { + fprintf(stderr, "swf_tag_lossless_replace_lossless_data: internal error tag_no(%d) at line(%d).\n", tag_no, __LINE__); + return 1; + } + swf_tag_lossless->colormap_count = colormap_count; + swf_tag_lossless->indices = (unsigned char *) result_data; + } else if (format == 5) { + free(swf_tag_lossless->colormap); + free(swf_tag_lossless->colormap2); + free(swf_tag_lossless->indices); + free(swf_tag_lossless->bitmap); + free(swf_tag_lossless->bitmap2); + swf_tag_lossless->colormap = NULL; + swf_tag_lossless->colormap2 = NULL; + swf_tag_lossless->indices = NULL; + swf_tag_lossless->bitmap = NULL; + swf_tag_lossless->bitmap2 = NULL; + if (tag_no == 20) { + swf_tag_lossless->bitmap = (swf_xrgb_t*) result_data; + } else if (tag_no == 36) { + swf_tag_lossless->bitmap2 = (swf_argb_t*) result_data; + } else { + fprintf(stderr, "swf_tag_lossless_replace_lossless_data: internal error tag_no(%d) at line(%d).\n", tag_no, __LINE__); + return 1; + } + } else { + fprintf(stderr, "swf_tag_lossless_replace_lossless_data: format(%d) not implemented yet. at line(%d)\n", format, __LINE__); + return 1; + } + return 0; +} diff --git a/src/swf_tag_lossless.h b/src/swf_tag_lossless.h new file mode 100644 index 0000000..11a4156 --- /dev/null +++ b/src/swf_tag_lossless.h @@ -0,0 +1,67 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_TAG_LOSSLESS__H__ +#define __SWF_TAG_LOSSLESS__H__ + +#include "swf_rgb.h" +#include "swf_rgba.h" +#include "swf_xrgb.h" +#include "swf_argb.h" +#include "swf_tag.h" + +typedef struct swf_tag_lossless_detail_ { + int image_id; + unsigned char format; + unsigned short width, height; + // format: 3 + unsigned short colormap_count; + swf_rgb_t *colormap; // Lossless + swf_rgba_t *colormap2; // Lossless2 + unsigned char *indices; + // format: 4,5 + swf_xrgb_t *bitmap; // Lossless + swf_argb_t *bitmap2; // Lossless2 +} swf_tag_lossless_detail_t; + +extern swf_tag_detail_handler_t *swf_tag_lossless_detail_handler(void); + +extern void *swf_tag_lossless_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void *swf_tag_lossless2_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern int swf_tag_lossless_identity_detail(unsigned char *data, int id, + swf_tag_t *tag); +extern unsigned char *swf_tag_lossless_output_detail(void *detail, + unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern unsigned char *swf_tag_lossless2_output_detail(void *detail, + unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_lossless_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_lossless2_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_lossless_destroy_detail(void *detail); + +extern unsigned char *swf_tag_lossless_get_png_data(void *detail, + unsigned long *length, + int image_id, + swf_tag_t *tag); +extern int swf_tag_lossless_replace_png_data(void *detail, int image_id, + unsigned char *png_data, + unsigned long png_data_len, + swf_tag_t *tag); + +#endif /* __SWF_TAG_LOSSLESS__H__ */ diff --git a/src/swf_tag_sound.c b/src/swf_tag_sound.c new file mode 100644 index 0000000..db2a58a --- /dev/null +++ b/src/swf_tag_sound.c @@ -0,0 +1,212 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include "bitstream.h" +#include "swf_tag_sound.h" +#include "swf_object.h" + +swf_tag_detail_handler_t sound_detail_handler; + +swf_tag_detail_handler_t * +swf_tag_sound_detail_handler(void) { + sound_detail_handler.create = swf_tag_sound_create_detail; + sound_detail_handler.identity = swf_tag_sound_identity_detail; + sound_detail_handler.output = swf_tag_sound_output_detail; + sound_detail_handler.print = swf_tag_sound_print_detail; + sound_detail_handler.destroy = swf_tag_sound_destroy_detail; + return &sound_detail_handler; +} + +void * +swf_tag_sound_create_detail(unsigned char *data, unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_sound_detail_t *swf_tag_sound; + bitstream_t *bs; + unsigned long sound_data_len; + unsigned char *sound_data; + (void) tag; + (void) swf; + swf_tag_sound = calloc(sizeof(*swf_tag_sound), 1); + if (swf_tag_sound == NULL) { + fprintf(stderr, "ERROR: swf_tag_sound_create_detail: can't calloc\n"); + return NULL; + } + bs = bitstream_open(); + bitstream_input(bs, data, length); + swf_tag_sound->sound_id = bitstream_getbytesLE(bs, 2); + swf_tag_sound->sound_format = bitstream_getbits(bs, 4); + swf_tag_sound->sound_rate = bitstream_getbits(bs, 2); + swf_tag_sound->sound_is_16bits = bitstream_getbit(bs); + swf_tag_sound->sound_is_stereo = bitstream_getbit(bs); + swf_tag_sound->sound_samples_count = bitstream_getbytesLE(bs, 4); + sound_data_len = bitstream_length(bs) - bitstream_getbytepos(bs); + swf_tag_sound->sound_data = malloc(sound_data_len); + if (swf_tag_sound->sound_data == NULL) { + fprintf(stderr, "swf_tag_sound_create_detail: swf_tag_sound->sound_data == NULL at line(%d): sound_data_len=%lu\n", + __LINE__, sound_data_len); + bitstream_close(bs); + return NULL; + } + sound_data = bitstream_buffer(bs, bitstream_getbytepos(bs)); + memcpy(swf_tag_sound->sound_data, sound_data, sound_data_len); + swf_tag_sound->sound_data_len = sound_data_len; + bitstream_close(bs); + return (void *) swf_tag_sound; +} + +int +swf_tag_sound_identity_detail(unsigned char *data, int id, swf_tag_t *tag) { + int sound_id; + if (tag->detail) { + swf_tag_sound_detail_t *swf_tag_sound = (swf_tag_sound_detail_t *) tag->detail; + if (swf_tag_sound->sound_id == id) { + return 0; + } + return 1; + } + if (data == NULL) { + fprintf(stderr, "swf_tag_sound_identity_detail: data==NULL\n"); + return 1; + } + sound_id = GetUShortLE(data); + if (id == sound_id) { + return 0; + } + return 1; +} + +unsigned char * +swf_tag_sound_output_detail(void *detail, unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_sound_detail_t *swf_tag_sound = (swf_tag_sound_detail_t *) detail; + bitstream_t *bs; + unsigned char *data; + (void) tag; + (void) swf; + *length = 0; + bs = bitstream_open(); + bitstream_putbytesLE(bs, swf_tag_sound->sound_id, 2); + bitstream_putbits(bs, swf_tag_sound->sound_format, 4); + bitstream_putbits(bs, swf_tag_sound->sound_rate, 2); + bitstream_putbit(bs, swf_tag_sound->sound_is_16bits); + bitstream_putbit(bs, swf_tag_sound->sound_is_stereo); + bitstream_putbytesLE(bs, swf_tag_sound->sound_samples_count, 4); + bitstream_putstring(bs, swf_tag_sound->sound_data, + swf_tag_sound->sound_data_len); + data = bitstream_steal(bs, length); + bitstream_close(bs); + return data; +} + +void +swf_tag_sound_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf) { + swf_tag_sound_detail_t *swf_tag_sound = (swf_tag_sound_detail_t *) detail; + char *format_name = "Unknown"; + (void) tag; + (void) swf; + switch(swf_tag_sound->sound_format & 0x0f) { + case 0: + format_name = "Raw"; + break; + case 1: + format_name = "ADPCM"; + break; + case 2: + format_name = "MP3"; + break; + case 3: + format_name = "Uncompressed"; + break; + case 6: + format_name = "Nellymoser"; + break; + + } + printf("\tsound_id=%d\n", swf_tag_sound->sound_id); + + printf("\tformat=%u(%s) rate=%u is_16bits=%u is_stereo=%u samples_count=%lu\n", + swf_tag_sound->sound_format & 0x0f, format_name, + swf_tag_sound->sound_rate & 0x03, + swf_tag_sound->sound_is_16bits?1:0, + swf_tag_sound->sound_is_stereo?1:0, + swf_tag_sound->sound_samples_count); + printf("\tsound_data(length=%lu)\n", + swf_tag_sound->sound_data_len); + return ; +} + +void +swf_tag_sound_destroy_detail(void *detail) { + swf_tag_sound_detail_t *swf_tag_sound = (swf_tag_sound_detail_t *) detail; + if (swf_tag_sound) { + free(swf_tag_sound->sound_data); + swf_tag_sound->sound_data = NULL; + free(swf_tag_sound); + } + return ; +} + +unsigned char * +swf_tag_sound_get_sound_data(void *detail, unsigned long *length, + int sound_id) { + swf_tag_sound_detail_t *swf_tag_sound = (swf_tag_sound_detail_t *) detail; + unsigned char *data; + *length = 0; + if (detail == NULL) { + fprintf(stderr, "swf_tag_sound_get_sound_data: detail == NULL\n"); + return NULL; + } + if (swf_tag_sound->sound_id != sound_id) { + return NULL; + } + *length = swf_tag_sound->sound_data_len; + data = malloc(*length); + memcpy(data, swf_tag_sound->sound_data, *length); + return data; +} + +int +swf_tag_sound_replace_mp3_data(void *detail, int sound_id, + unsigned char *mp3_data, + unsigned long mp3_data_len) { + (void) detail; + (void) sound_id; + (void) mp3_data; + (void) mp3_data_len; + // dummy + return -1; +} + +int +swf_tag_sound_replace_melo_data(void *detail, int sound_id, + unsigned char *melo_data, + unsigned long melo_data_len) { + swf_tag_sound_detail_t *swf_tag_sound = (swf_tag_sound_detail_t *) detail; + (void) melo_data; + (void) melo_data_len; + swf_tag_sound->sound_id = sound_id; + swf_tag_sound->sound_format = 15; + swf_tag_sound->sound_rate = 0; + swf_tag_sound->sound_is_16bits = 0; + swf_tag_sound->sound_is_stereo = 0; + swf_tag_sound->sound_samples_count = 0; + free(swf_tag_sound->sound_data); + swf_tag_sound->sound_data = malloc(melo_data_len); + if (swf_tag_sound->sound_data == NULL) { + fprintf(stderr, "swf_tag_sound_replace_melo_data: swf_tag_sound->sound_data == NULL\n"); + return 1; + } + memcpy(swf_tag_sound->sound_data, melo_data, melo_data_len); + swf_tag_sound->sound_data_len = melo_data_len; + // dummy + return 0; +} diff --git a/src/swf_tag_sound.h b/src/swf_tag_sound.h new file mode 100644 index 0000000..c9d7d3c --- /dev/null +++ b/src/swf_tag_sound.h @@ -0,0 +1,50 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_TAG_SOUND__H__ +#define __SWF_TAG_SOUND__H__ + +#include "swf_tag.h" + +typedef struct swf_tag_sound_detail_ { + int sound_id; + int sound_format:4; + int sound_rate:2; + int sound_is_16bits:1; + int sound_is_stereo:1; + unsigned long sound_samples_count; + unsigned char *sound_data; + unsigned long sound_data_len; +} swf_tag_sound_detail_t; + +extern swf_tag_detail_handler_t *swf_tag_sound_detail_handler(void); + +extern void *swf_tag_sound_create_detail(unsigned char *data, + unsigned long length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern int swf_tag_sound_identity_detail(unsigned char *data, int id, + swf_tag_t *tag); +extern unsigned char *swf_tag_sound_output_detail(void *detail, + unsigned long *length, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_sound_print_detail(void *detail, + swf_tag_t *tag, + struct swf_object_ *swf); +extern void swf_tag_sound_destroy_detail(void *detail); + +extern unsigned char *swf_tag_sound_get_sound_data(void *detail, unsigned long *length, + int sound_id); +extern int swf_tag_sound_replace_mp3_data(void *detail, int sound_id, + unsigned char *mp3_data, + unsigned long mp3_data_len); + +extern int swf_tag_sound_replace_melo_data(void *detail, int sound_id, + unsigned char *sound_data, + unsigned long sound_data_len); + +#endif /* __SWF_TAG_SOUND__H__ */ diff --git a/src/swf_test.c b/src/swf_test.c new file mode 100644 index 0000000..01d4b9b --- /dev/null +++ b/src/swf_test.c @@ -0,0 +1,33 @@ +#include +#include +#include "swf_object.h" + +typedef struct _binedit_string { + unsigned char *ptr; + unsigned long len; +} binedit_string_t; + +int loadfile(binedit_string_t *str, char *filename) { + FILE *fp; + struct stat sbuf; + if (stat(filename, &sbuf)) { + return 1; + } + str->len = sbuf.st_size; + str->ptr = calloc(str->len, 1); + fp = fopen(filename, "rb"); + if (fread(str->ptr, 1, str->len, fp) != str->len) { + return 1; + } + fclose(fp); + return 0; +} + +int main(int argc, char **argv) { + swf_object_t *swf; + binedit_string_t str; + loadfile(&str, "saitama.swf"); + swf = swf_object_open(); + swf = swf_object_set(str.ptr, str.len); + return 0; +} diff --git a/src/swf_xrgb.c b/src/swf_xrgb.c new file mode 100644 index 0000000..138f07b --- /dev/null +++ b/src/swf_xrgb.c @@ -0,0 +1,28 @@ +#include +#include "bitstream.h" +#include "swf_xrgb.h" + +int +swf_xrgb_parse(bitstream_t *bs, swf_xrgb_t *color) { + (void) bitstream_getbyte(bs); // pad + color->red = bitstream_getbyte(bs); + color->green = bitstream_getbyte(bs); + color->blue = bitstream_getbyte(bs); + return 0; +} + +int +swf_xrgb_build(bitstream_t *bs, swf_xrgb_t *color) { + bitstream_putbyte(bs, 0); // pad + bitstream_putbyte(bs, color->red); + bitstream_putbyte(bs, color->green); + bitstream_putbyte(bs, color->blue); + return 0; +} + +int +swf_xrgb_print(swf_xrgb_t *color) { + printf("pad=0xXX red=0x%02x green=0x%02X blue=0x%02x\n", + color->red, color->green, color->blue); + return 0; +} diff --git a/src/swf_xrgb.h b/src/swf_xrgb.h new file mode 100644 index 0000000..72eab97 --- /dev/null +++ b/src/swf_xrgb.h @@ -0,0 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +#ifndef __SWF_XRGB_H__ +#define __SWF_XRGB_H__ + +typedef struct swf_xrgb_ { +// unsigned char pad; + unsigned char red; + unsigned char green; + unsigned char blue; +} swf_xrgb_t; + +extern int swf_xrgb_parse(bitstream_t *bs, swf_xrgb_t *color); +extern int swf_xrgb_build(bitstream_t *bs, swf_xrgb_t *color); +extern int swf_xrgb_print(swf_xrgb_t *color); + +#endif /* __SWF_XRGB_H__ */ diff --git a/src/swfed.c b/src/swfed.c new file mode 100644 index 0000000..345108d --- /dev/null +++ b/src/swfed.c @@ -0,0 +1,769 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2006 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: yoya@awm.jp | + +----------------------------------------------------------------------+ +*/ + +/* $Id: header,v 1.16.2.1 2006/01/01 12:50:00 sniper Exp $ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_swfed.h" + +#include "swf_define.h" +#include "swf_tag_jpeg.h" +#include "swf_tag_lossless.h" +#include "swf_tag_edit.h" +#include "swf_tag_sound.h" +#include "swf_tag_action.h" +#include "swf_tag.h" +#include "swf_object.h" + +/* If you declare any globals in php_swfed.h uncomment this: +ZEND_DECLARE_MODULE_GLOBALS(swfed) +*/ + +/* True global resources - no need for thread safety here */ +static int le_swfed; + +/* {{{ swfed_functions[] + * + * Every user visible function must have an entry in swfed_functions[]. + */ +zend_function_entry swfed_functions[] = { + PHP_FE(confirm_swfed_compiled, NULL) /* For testing, remove later. */ + PHP_ME(swfed, __construct, NULL, 0) + PHP_ME(swfed, input, NULL, 0) + PHP_ME(swfed, output, NULL, 0) + PHP_ME(swfed, getHeaderInfo, NULL, 0) + PHP_ME(swfed, setHeaderInfo, NULL, 0) + PHP_ME(swfed, getTagList, NULL, 0) + PHP_ME(swfed, getTagDetail, NULL, 0) + PHP_ME(swfed, getTagData, NULL, 0) + PHP_ME(swfed, getJpegData, NULL, 0) + PHP_ME(swfed, getJpegAlpha, NULL, 0) + PHP_ME(swfed, replaceJpegData, NULL, 0) + PHP_ME(swfed, getPNGData, NULL, 0) + PHP_ME(swfed, replacePNGData, NULL, 0) + PHP_ME(swfed, getSoundData, NULL, 0) + PHP_ME(swfed, replaceMLDData, NULL, 0) + PHP_ME(swfed, getEditString, NULL, 0) + PHP_ME(swfed, replaceEditString, NULL, 0) + PHP_ME(swfed, getActionData, NULL, 0) + PHP_ME(swfed, disasmActionData, NULL, 0) + PHP_ME(swfed, swfInfo, NULL, 0) + {NULL, NULL, NULL} /* Must be the last line in swfed_functions[] */ +}; +/* }}} */ + +/* {{{ swfed_module_entry + */ +zend_module_entry swfed_module_entry = { +#if ZEND_MODULE_API_NO >= 20010901 + STANDARD_MODULE_HEADER, +#endif + "swfed", + swfed_functions, + PHP_MINIT(swfed), + PHP_MSHUTDOWN(swfed), + PHP_RINIT(swfed), /* Replace with NULL if there's nothing to do at request start */ + PHP_RSHUTDOWN(swfed), /* Replace with NULL if there's nothing to do at request end */ + PHP_MINFO(swfed), +#if ZEND_MODULE_API_NO >= 20010901 + "0.1", /* Replace with version number for your extension */ +#endif + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +#ifdef COMPILE_DL_SWFED +ZEND_GET_MODULE(swfed) +#endif + +/* {{{ PHP_INI + */ +/* Remove comments and fill if you need to have entries in php.ini +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("swfed.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_swfed_globals, swfed_globals) + STD_PHP_INI_ENTRY("swfed.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_swfed_globals, swfed_globals) +PHP_INI_END() +*/ +/* }}} */ + +/* {{{ php_swfed_init_globals + */ +/* Uncomment this function if you have INI entries +static void php_swfed_init_globals(zend_swfed_globals *swfed_globals) +{ + swfed_globals->global_value = 0; + swfed_globals->global_string = NULL; +} +*/ +/* }}} */ + + +static void free_swfed_resource(zend_rsrc_list_entry *resource TSRMLS_DC); +static swf_object_t *get_swf_object(zval *obj TSRMLS_DC); + +/* {{{ PHP_MINIT_FUNCTION + */ +PHP_MINIT_FUNCTION(swfed) +{ + /* If you have INI entries, uncomment these lines + ZEND_INIT_MODULE_GLOBALS(swfed, php_swfed_init_globals, NULL); + REGISTER_INI_ENTRIES(); + */ + zend_class_entry ce; + INIT_CLASS_ENTRY(ce, "SWFEditor", swfed_functions); + swfeditor_ce = zend_register_internal_class(&ce TSRMLS_CC); + le_swfed = zend_register_list_destructors_ex(free_swfed_resource, NULL, "SWFEditor", module_number); + + zend_declare_property_stringl(swfeditor_ce, + "swf_object", strlen("swf_object"), + "", 0, ZEND_ACC_PUBLIC); + return SUCCESS; +} + +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(swfed) +{ + /* uncomment this line if you have INI entries + UNREGISTER_INI_ENTRIES(); + */ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request start */ +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(swfed) +{ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request end */ +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(swfed) +{ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION + */ +PHP_MINFO_FUNCTION(swfed) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "swfed support", "enabled"); + php_info_print_table_end(); + + /* Remove comments if you have entries in php.ini + DISPLAY_INI_ENTRIES(); + */ +} +/* }}} */ + + +/* Remove the following function when you have succesfully modified config.m4 + so that your module can be compiled into PHP, it exists only for testing + purposes. */ + +/* Every user-visible function in PHP should document itself in the source */ +/* {{{ proto string confirm_swfed_compiled(string arg) + Return a string to confirm that the module is compiled in */ +PHP_FUNCTION(confirm_swfed_compiled) +{ + char *arg = NULL; + int arg_len, len; + char string[256]; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { + return; + } + + len = sprintf(string, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "swfed", arg); +// RETURN_STRINGL(string, len, 0); + RETURN_STRINGL(string, len, 1); +} +/* }}} */ +/* The previous line is meant for vim and emacs, so it can correctly fold and + unfold functions in source code. See the corresponding marks just before + function definition, where the functions purpose is also documented. Please + follow this convention for the convenience of others editing your code. +*/ + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ + +PHP_METHOD(swfed, __construct) { + swf_object_t *swf = swf_object_open(); + int ret; + if (swf == NULL) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Couldn't create swf object"); + } + ret = zend_list_insert(swf, le_swfed); + object_init_ex(getThis(), swfeditor_ce); + add_property_resource(getThis(), "swfed", ret); + zend_list_addref(ret); +} + +PHP_METHOD(swfed, input) { + char *data; + int data_len; + swf_object_t *swf; + zval *obj = getThis(); + int result; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, + "s", &data, &data_len) == FAILURE) { + RETURN_FALSE; + } + swf = get_swf_object(obj TSRMLS_CC); + result = swf_object_input(swf, (unsigned char *) data, data_len); + if (result) { + RETURN_FALSE; + } + RETURN_TRUE; +} + +PHP_METHOD(swfed, output) { + unsigned long len = 0; + unsigned char *data, *new_buff; + swf_object_t *swf; + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT; + RETURN_FALSE; /* XXX */ + } + swf = get_swf_object(getThis()); + data = swf_object_output(swf, &len); + new_buff = emalloc(len); + if (new_buff == NULL) { + fprintf(stderr, "output: Can't emalloc new_buff\n"); + free(data); + RETURN_FALSE; + } + memcpy(new_buff, data, len); + free(data); + RETURN_STRINGL(new_buff, len, 0); +} + +PHP_METHOD(swfed, getHeaderInfo) { + swf_object_t *swf = get_swf_object(getThis()); + array_init(return_value); + if (memcmp(swf->header.magic, "CWS", 3) == 0) { + add_assoc_bool(return_value, "compress", 1); + } else { // FWS + add_assoc_bool(return_value, "compress", 0); + } + add_assoc_long(return_value, "version", swf->header.version); +} + +PHP_METHOD(swfed, setHeaderInfo) { + zval *header_info; + swf_object_t *swf; + HashTable *header_table; + zval **tmp; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", + &header_info) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters"); + } + swf = get_swf_object(getThis()); + header_table = Z_ARRVAL_P(header_info); + if (zend_hash_find(header_table, "compress", sizeof("compress"), (void**)&tmp) == SUCCESS) { + convert_to_boolean_ex(tmp); + if (Z_LVAL_PP(tmp) != 0) { + memcpy(swf->header.magic, "CWS", 3); + } else { + memcpy(swf->header.magic, "FWS", 3); + } + } + + if (zend_hash_find(header_table, "version", sizeof("version"), (void**)&tmp) == SUCCESS) { + convert_to_long_ex(tmp); + swf->header.version = Z_LVAL_PP(tmp); + } + RETURN_TRUE; +} + +PHP_METHOD(swfed, getTagList) { + int i = 0; + zval *data; + swf_object_t *swf; + swf_tag_t *tag; + swf_tag_info_t *tag_info; + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT; + RETURN_FALSE; /* XXX */ + } + swf = get_swf_object(getThis()); + tag = swf->tag; + array_init(return_value); + for(tag = swf->tag; tag; tag=tag->next) { + ALLOC_INIT_ZVAL(data); + array_init(data); + add_assoc_long(data, "tag", tag->tag); + tag_info = get_swf_tag_info(tag->tag); + if (tag_info && tag_info->name) { + add_assoc_string_ex(data, + "tagName", sizeof("tagName"), + (char *)tag_info->name, 1); + } + add_assoc_long(data, "length", tag->length); + if (tag_info && tag_info->detail_handler) { + add_assoc_bool(data, "detail", 1); + } + add_index_zval(return_value, i, data); + i++; + } +} + +PHP_METHOD(swfed, getTagDetail) { + long tag_seqno; + swf_object_t *swf; + swf_tag_t *tag; + swf_tag_info_t *tag_info; + int i; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, + "l", &tag_seqno) == FAILURE) { + RETURN_FALSE; + } + swf = get_swf_object(getThis()); + i = 0; + for(tag = swf->tag; tag; tag = tag->next) { + if (i == tag_seqno) { + break; + } + i++; + } + if (tag == NULL) { + RETURN_FALSE; + } + tag_info = get_swf_tag_info(tag->tag); + if ((tag_info == NULL) || (tag_info->detail_handler == NULL)) { + RETURN_FALSE; + } + swf_tag_create_detail(tag, swf); + switch (tag->tag) { + swf_tag_jpeg_detail_t *tag_jpeg; + swf_tag_lossless_detail_t *tag_lossless; + swf_tag_edit_detail_t *tag_edit; + swf_tag_sound_detail_t *tag_sound; + swf_tag_action_detail_t *tag_action; + case 6: // DefineBitsJPEG + case 21: // DefineBitsJPEG2 + case 35: // DefineBitsJPEG3 + tag_jpeg = tag->detail; + array_init(return_value); + add_assoc_long(return_value, "image_id", tag_jpeg->image_id); + add_assoc_long(return_value, "jpeg_data_len", tag_jpeg->jpeg_data_len); + if ((tag_jpeg->alpha_data != NULL) && + (tag_jpeg->alpha_data_len > 0)) { + add_assoc_long(return_value, "alpha_data_len", tag_jpeg->alpha_data_len); + } + break; + case 20: // DefineBitsLossless + case 36: // DefineBitsLossless2 + tag_lossless = tag->detail; + array_init(return_value); + add_assoc_long(return_value, "image_id", tag_lossless->image_id); + add_assoc_long(return_value, "format", tag_lossless->format); + add_assoc_long(return_value, "width", tag_lossless->width); + add_assoc_long(return_value, "height", tag_lossless->height); + if (tag_lossless->format == 3) { + add_assoc_long(return_value, "colormap_count", tag_lossless->colormap_count); + } + break; + case 14: // DefineSound + tag_sound = tag->detail; + array_init(return_value); + add_assoc_long(return_value, "sound_id", tag_sound->sound_id); + add_assoc_long(return_value, "format", (unsigned long) tag_sound->sound_format); + add_assoc_long(return_value, "rate", (unsigned long) tag_sound->sound_rate); + add_assoc_long(return_value, "is_16bits", tag_sound->sound_is_16bits?1:0); + add_assoc_long(return_value, "is_stereo", tag_sound->sound_is_stereo?1:0); + add_assoc_long(return_value, "sound_samples_count", tag_sound->sound_samples_count); + add_assoc_long(return_value, "sound_data_len", tag_sound->sound_data_len); + break; + case 12: // DoAction + case 59: // DoInitAction + tag_action = tag->detail; + array_init(return_value); + if (tag->tag == 59) { // DoInitAction + add_assoc_long(return_value, "action_sprite", tag_action->action_sprite); + } + if (tag_action->action_record && tag_action->action_record_len) { + add_assoc_long(return_value, "action_record_len", tag_action->action_record_len); + } + break; + case 37: // DefineEditText; + tag_edit = tag->detail; + array_init(return_value); + add_assoc_long(return_value, "edit_id", tag_edit->edit_id); + if (tag_edit->edit_variable_name && tag_edit->edit_variable_name[0]){ + add_assoc_string_ex(return_value, "variable_name", + sizeof("variable_name"), + (char *)tag_edit->edit_variable_name, 1); + } + if (tag_edit->edit_initial_text && tag_edit->edit_initial_text[0]) { + add_assoc_string_ex(return_value, "initial_text", + sizeof("initial_text"), + (char *)tag_edit->edit_initial_text, 1); + } + break; + default: + RETURN_FALSE; + } + /* return_value */ +} + +PHP_METHOD(swfed, getTagData) { + printf("not implemented yet.\n"); + RETURN_FALSE; +} + +PHP_METHOD(swfed, getJpegData) { + unsigned long image_id = 0; + unsigned long len = 0; + unsigned char *data, *new_buff; + zval *obj = getThis(); + swf_object_t *swf; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, + "l", &image_id) == FAILURE) { + RETURN_FALSE; + } + swf = get_swf_object(getThis()); + data = swf_object_get_jpegdata(swf, &len, image_id); + if (data == NULL) { + RETURN_FALSE; + } + new_buff = emalloc(len); + if (new_buff == NULL) { + fprintf(stderr, "getJpegData Can't emalloc new_buff\n"); + free(data); + RETURN_FALSE; + } + memcpy(new_buff, data, len); + free(data); + RETURN_STRINGL(new_buff, (int) len, 0); +} + +PHP_METHOD(swfed, getJpegAlpha) { + unsigned long image_id = 0; + unsigned long len = 0; + unsigned char *data, *new_buff; + zval *obj = getThis(); + swf_object_t *swf; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, + "l", &image_id) == FAILURE) { + RETURN_FALSE; + } + swf = get_swf_object(getThis()); + data = swf_object_get_alphadata(swf, &len, image_id); + if (data == NULL) { + RETURN_FALSE; + } + new_buff = emalloc(len); + if (new_buff == NULL) { + fprintf(stderr, "getJpegAlpha Can't emalloc new_buff\n"); + free(data); + RETURN_FALSE; + } + memcpy(new_buff, data, len); + free(data); + RETURN_STRINGL(new_buff, len, 0); +} + +PHP_METHOD(swfed, replaceJpegData) { + char *data = NULL, *alpha_data = NULL; + int data_len = 0 , alpha_data_len = 0; + int image_id; + swf_object_t *swf; + int result = 0; + switch (ZEND_NUM_ARGS()) { + default: + WRONG_PARAM_COUNT; + RETURN_FALSE; /* XXX */ + case 2: + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &image_id, &data, &data_len) == FAILURE) { + RETURN_FALSE; + } + break; + case 3: + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lss", &image_id, &data, &data_len, &alpha_data, &alpha_data_len) == FAILURE) { + RETURN_FALSE; + } + break; + } + swf = get_swf_object(getThis()); + result = swf_object_replace_jpegdata(swf, image_id, + (unsigned char *)data, + (unsigned long) data_len, + (unsigned char *)alpha_data, + (unsigned long) alpha_data_len); + if (result) { + RETURN_FALSE; + } + RETURN_TRUE; +} + +PHP_METHOD(swfed, getPNGData) { + unsigned long image_id = 0; + unsigned long len = 0; + unsigned char *data, *new_buff; + zval *obj = getThis(); + swf_object_t *swf; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, + "l", &image_id) == FAILURE) { + RETURN_FALSE; + } + swf = get_swf_object(getThis()); + data = swf_object_get_pngdata(swf, &len, image_id); + if (data == NULL) { + RETURN_FALSE; + } + new_buff = emalloc(len); + if (new_buff == NULL) { + fprintf(stderr, "getPNGData: Can't emalloc new_buff\n"); + free(data); + RETURN_FALSE; + } + memcpy(new_buff, data, len); + free(data); + RETURN_STRINGL(new_buff, (int) len, 0); +} + +PHP_METHOD(swfed, replacePNGData) { + char *data = NULL; + int data_len = 0; + int image_id; + swf_object_t *swf; + int result = 0; + switch (ZEND_NUM_ARGS()) { + default: + WRONG_PARAM_COUNT; + RETURN_FALSE; /* XXX */ + case 2: + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &image_id, &data, &data_len) == FAILURE) { + RETURN_FALSE; + } + break; + } + swf = get_swf_object(getThis()); + result = swf_object_replace_pngdata(swf, image_id, + (unsigned char *)data, + (unsigned long) data_len); + if (result) { + RETURN_FALSE; + } + RETURN_TRUE; +} + +PHP_METHOD(swfed, getSoundData) { + unsigned long sound_id = 0; + unsigned long len = 0; + unsigned char *data, *new_buff; + zval *obj = getThis(); + swf_object_t *swf; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, + "l", &sound_id) == FAILURE) { + RETURN_FALSE; + } + swf = get_swf_object(getThis()); + data = swf_object_get_sounddata(swf, &len, sound_id); + if (data == NULL) { + RETURN_FALSE; + } + new_buff = emalloc(len); + if (new_buff == NULL) { + fprintf(stderr, "getSoundData: Can't emalloc new_buff\n"); + free(data); + RETURN_FALSE; + } + memcpy(new_buff, data, len); + free(data); + RETURN_STRINGL(new_buff, (int) len, 0); +} + +PHP_METHOD(swfed, replaceMLDData) { + char *data = NULL; + int data_len = 0; + int sound_id; + swf_object_t *swf; + int result = 0; + switch (ZEND_NUM_ARGS()) { + default: + WRONG_PARAM_COUNT; + RETURN_FALSE; /* XXX */ + case 2: + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &sound_id, &data, &data_len) == FAILURE) { + RETURN_FALSE; + } + break; + } + swf = get_swf_object(getThis()); + result = swf_object_replace_melodata(swf, sound_id, + (unsigned char *)data, + (unsigned long) data_len); + if (result) { + RETURN_FALSE; + } + RETURN_TRUE; +} + +PHP_METHOD(swfed, getEditString) { + char *var_name; + int var_name_len; + swf_object_t *swf; + char *data, *new_buff; + int str_len; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", + &var_name, &var_name_len) == FAILURE) { + RETURN_FALSE; + } + swf = get_swf_object(getThis()); + data = swf_object_get_editstring(swf, var_name, var_name_len); + if (data == NULL) { + RETURN_FALSE; + } + str_len = strlen(data); + new_buff = emalloc(str_len + 1); + if (new_buff == NULL) { + fprintf(stderr, "getEditString: Can't emalloc new_buff\n"); + free(data); + RETURN_FALSE; + } + memcpy(new_buff, data, str_len + 1); + free(data); + RETURN_STRINGL(new_buff, str_len, 0); +} + +PHP_METHOD(swfed, replaceEditString) { + char *var_name, *ini_text; + int var_name_len, ini_text_len; + swf_object_t *swf; + int result; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", + &var_name, &var_name_len, + &ini_text, &ini_text_len) == FAILURE) { + RETURN_FALSE; + } + swf = get_swf_object(getThis()); + + result = swf_object_replace_editstring(swf, var_name, var_name_len, + ini_text, ini_text_len); + if (result) { + RETURN_FALSE; + } + RETURN_TRUE; +} + +PHP_METHOD(swfed, getActionData) { + long tag_seqno; + swf_object_t *swf; + char *data_ref, *new_buff; + unsigned long data_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &tag_seqno) == FAILURE) { + RETURN_FALSE; + } + swf = get_swf_object(getThis()); + + data_ref = swf_object_get_actiondata(swf, &data_len, tag_seqno); + if (data_ref == NULL) { + fprintf(stderr, "getActionData: Can't get_actiondata\n"); + RETURN_FALSE; + } + new_buff = emalloc(data_len); + if (new_buff == NULL) { + fprintf(stderr, "getActionData: Can't emalloc new_buff\n"); + RETURN_FALSE; + } + memcpy(new_buff, data_ref, data_len); + RETURN_STRINGL(new_buff, data_len, 0); +} + +PHP_METHOD(swfed, disasmActionData) { + char *data; + int data_len; + bitstream_t *bs; + swf_action_list_t *action_list; + swf_action_t *action; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, + "s", &data, &data_len) == FAILURE) { + RETURN_FALSE; + } + array_init(return_value); + bs = bitstream_open(); + bitstream_input(bs, data, data_len); + action_list = swf_action_list_create(bs); + bitstream_close(bs); + if (action_list) { + swf_action_t *action = action_list->head; + while(action) { + printf("\t"); +// swf_action_disasm(action); + action = action->next; + } + } + swf_action_list_destroy(action_list); +} + + +PHP_METHOD(swfed, swfInfo) { + swf_object_t *swf = get_swf_object(getThis()); + swf_object_print(swf); + RETURN_TRUE; +} + +static swf_object_t *get_swf_object(zval *obj TSRMLS_DC) { +// zval *data, **tmp; + zval **tmp; + swf_object_t *swf; + int id, type; +/* XXX: zend_read_property + data = zend_read_property(Z_OBJCE_P(obj), obj, "swf_object", + strlen("swf_object"), 1 TSRMLS_CC); +*/ + if (zend_hash_find(Z_OBJPROP_P(obj), "swfed", strlen("swfed") + 1, + (void **)&tmp) == FAILURE) { + return NULL; + } + id = Z_LVAL_PP(tmp); + swf = zend_list_find(id, &type); + return swf; +} + +static void free_swfed_resource(zend_rsrc_list_entry *resource TSRMLS_DC) +{ +// printf("SWFEditor->destory\n"); + swf_object_close(resource->ptr); +} -- 2.11.0