OSDN Git Service

今あるファイルを全て trunk に移動
authoryoya <yoya@7c90b180-03d5-4157-b861-58a559ae9d1e>
Fri, 10 Oct 2008 10:04:34 +0000 (10:04 +0000)
committeryoya <yoya@7c90b180-03d5-4157-b861-58a559ae9d1e>
Fri, 10 Oct 2008 10:04:34 +0000 (10:04 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/swfed/trunk@64 7c90b180-03d5-4157-b861-58a559ae9d1e

55 files changed:
doc/install.txt [new file with mode: 0644]
doc/readme.txt [new file with mode: 0644]
sample/swfcompress.phps [new file with mode: 0644]
sample/swfdump.phps [new file with mode: 0644]
sample/swfgeteditstring.phps [new file with mode: 0644]
sample/swfgetjpegalphadata.phps [new file with mode: 0644]
sample/swfgetjpegdata.phps [new file with mode: 0644]
sample/swfgetpngdata.phps [new file with mode: 0644]
sample/swfgetsounddata.phps [new file with mode: 0644]
sample/swfreplaceeditstring.phps [new file with mode: 0644]
sample/swfreplacejpegdata.phps [new file with mode: 0644]
sample/swfreplacemlddata.phps [new file with mode: 0644]
sample/swfreplacepngdata.phps [new file with mode: 0644]
src/bitstream.c [new file with mode: 0644]
src/bitstream.h [new file with mode: 0644]
src/config.m4 [new file with mode: 0644]
src/jpeg_segment.c [new file with mode: 0644]
src/jpeg_segment.h [new file with mode: 0644]
src/php_swfed.h [new file with mode: 0644]
src/swf_action.c [new file with mode: 0644]
src/swf_action.h [new file with mode: 0644]
src/swf_argb.c [new file with mode: 0644]
src/swf_argb.h [new file with mode: 0644]
src/swf_debug.c [new file with mode: 0644]
src/swf_define.h [new file with mode: 0644]
src/swf_header.c [new file with mode: 0644]
src/swf_header.h [new file with mode: 0644]
src/swf_jpeg.c [new file with mode: 0644]
src/swf_jpeg.h [new file with mode: 0644]
src/swf_object.c [new file with mode: 0644]
src/swf_object.h [new file with mode: 0644]
src/swf_png.c [new file with mode: 0644]
src/swf_png.h [new file with mode: 0644]
src/swf_rect.c [new file with mode: 0644]
src/swf_rect.h [new file with mode: 0644]
src/swf_rgb.c [new file with mode: 0644]
src/swf_rgb.h [new file with mode: 0644]
src/swf_rgba.c [new file with mode: 0644]
src/swf_rgba.h [new file with mode: 0644]
src/swf_tag.c [new file with mode: 0644]
src/swf_tag.h [new file with mode: 0644]
src/swf_tag_action.c [new file with mode: 0644]
src/swf_tag_action.h [new file with mode: 0644]
src/swf_tag_edit.c [new file with mode: 0644]
src/swf_tag_edit.h [new file with mode: 0644]
src/swf_tag_jpeg.c [new file with mode: 0644]
src/swf_tag_jpeg.h [new file with mode: 0644]
src/swf_tag_lossless.c [new file with mode: 0644]
src/swf_tag_lossless.h [new file with mode: 0644]
src/swf_tag_sound.c [new file with mode: 0644]
src/swf_tag_sound.h [new file with mode: 0644]
src/swf_test.c [new file with mode: 0644]
src/swf_xrgb.c [new file with mode: 0644]
src/swf_xrgb.h [new file with mode: 0644]
src/swfed.c [new file with mode: 0644]

diff --git a/doc/install.txt b/doc/install.txt
new file mode 100644 (file)
index 0000000..31b3305
--- /dev/null
@@ -0,0 +1,8 @@
+% tar xvfz swfed-?.??.tar.gz
+% cd src
+% phpize
+% ./configure
+% make
+% su
+Password:
+# cp modules/swfed.so <php extension dir>/.
diff --git a/doc/readme.txt b/doc/readme.txt
new file mode 100644 (file)
index 0000000..f41cde5
--- /dev/null
@@ -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 (file)
index 0000000..6630826
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+
+$compress = true;
+
+switch($argc) {
+    case 2:
+       $swf_filename = $argv[1];
+        break;
+    case 3:
+       if ($argv[1] == '-u') {
+           $compress = false;
+           $swf_filename = $argv[2];
+           break;
+       }
+    default:
+       fprintf(STDERR, "Usage: php swfcompress.phps [-u] <swf_file>\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 (file)
index 0000000..536b576
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+
+if ($argc < 2) {
+    fprintf(STDERR, "Usage: swfdump <swf_file>\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 (file)
index 0000000..5d824bd
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+
+if ($argc != 3) {
+    fprintf(STDERR, "Usage: swfgeteditstrint <swf_file> <var_name>\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 (file)
index 0000000..9fd8540
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+
+if ($argc != 3) {
+    fprintf(STDERR, "Usage: swfgetjpegalphadata <swf_file> <image_id>\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 (file)
index 0000000..cc8ad19
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+
+if ($argc != 3) {
+    fprintf(STDERR, "Usage: swfgetjpegdata <swf_file> <image_id>\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 (file)
index 0000000..47d9569
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+
+if ($argc != 3) {
+    fprintf(STDERR, "Usage: swfgetpngdata <swf_file> <image_id>\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 (file)
index 0000000..1c3060e
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+
+if ($argc != 3) {
+    fprintf(STDERR, "Usage: swfgetsounddata <swf_file> <sound_id>\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 (file)
index 0000000..c12361f
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+
+if ($argc < 4) {
+       fprintf(STDERR, "Usage: swfreplaceeditstring <swf_file> <variable_name> <initial_text>\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 (file)
index 0000000..f4008af
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+
+if ($argc < 4) {
+    fprintf(STDERR, "Usage: swfreplacejpegdata <swf_file> <image_id> <jpeg_file> [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 (file)
index 0000000..b969114
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+if (($argc < 4) || ($argc%2 != 0)) {
+    fprintf(STDERR, "Usage: swfreplacemlddata <swf_file> <sound_id> <mld_file> [<sound_id2> <mld_file2> [...]]\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 (file)
index 0000000..9a93131
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+
+if (($argc < 4) || ($argc%2 != 0)) {
+       fprintf(STDERR, "Usage: swfreplacepngdata <swf_file> <image_id> <png_file> [<image_id2> <png_file2> [...]]\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 (file)
index 0000000..eab51fc
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * bit stream routine
+ *                     (C) 2008/03/09- yoya@awm.jp
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..26a0d72
--- /dev/null
@@ -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 (file)
index 0000000..69d20f6
--- /dev/null
@@ -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 (file)
index 0000000..16d7e8a
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#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 <sys/stat.h>
+
+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 <jpeg_infile> [<jpeg_outfile>]\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 (file)
index 0000000..f412ab8
--- /dev/null
@@ -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 (file)
index 0000000..f1948b7
--- /dev/null
@@ -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 (file)
index 0000000..6242844
--- /dev/null
@@ -0,0 +1,330 @@
+#include <stdio.h>
+#include <string.h>
+#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; i<n; i++) {
+                printf("\t\t[%d]'", i);
+                d += printf("%s", d) + 1;
+                printf("'\n");
+            }
+            break;
+        case 0x96: // Push Data
+            swf_action_data_print(act->action_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 (file)
index 0000000..2c262da
--- /dev/null
@@ -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 (file)
index 0000000..13e7efa
--- /dev/null
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#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 (file)
index 0000000..5d3c9dd
--- /dev/null
@@ -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 (file)
index 0000000..78a2356
--- /dev/null
@@ -0,0 +1,141 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+// #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<MALLOC_DEBUG_TABLE_NUM; i++) {
+        malloc_debug_table[i].ptr = NULL;
+    }
+}
+
+void malloc_debug_end(void) {
+    int i;
+    for(i=0; i<MALLOC_DEBUG_TABLE_NUM; i++) {
+        if (malloc_debug_table[i].ptr) {
+            fprintf(stderr, "XXX (%d) ptr=%p (%s, %d)\n",
+                    i, malloc_debug_table[i].ptr,
+                    malloc_debug_table[i].filename,
+                    malloc_debug_table[i].linenum);
+        }
+    }
+}
+
+void *
+calloc_debug(size_t nmemb, size_t size, char *filename, int linenum) {
+    int i;
+    void *ptr;
+    ptr = calloc(nmemb, size);
+//    fprintf(stderr, "calloc_debug: ptr=%p (%s,%d)\n", ptr, filename, linenum);
+    for(i=0; i<MALLOC_DEBUG_TABLE_NUM; i++) {
+        if (malloc_debug_table[i].ptr == NULL) {
+            malloc_debug_table[i].ptr = ptr;
+            malloc_debug_table[i].filename = filename;
+            malloc_debug_table[i].linenum = linenum;
+            break;
+        }
+    }
+    return ptr;
+}
+void *
+malloc_debug(size_t size, char *filename, int linenum) {
+    int i;
+    void *ptr;
+    ptr = malloc(size);
+//    fprintf(stderr, "malloc_debug: ptr=%p (%s,%d)\n", ptr, filename, linenum);
+    for(i=0; i<MALLOC_DEBUG_TABLE_NUM; i++) {
+        if (malloc_debug_table[i].ptr == NULL) {
+            malloc_debug_table[i].ptr = ptr;
+            malloc_debug_table[i].filename = filename;
+            malloc_debug_table[i].linenum = linenum;
+//            fprintf(stderr, "(%d)\n", i);
+            return ptr;
+        }
+    }
+    fprintf(stderr, "malloc: table full... ;_;\n");
+    return ptr;
+}
+
+void
+free_debug(void *ptr, char *filename, int linenum) {
+    int i;
+//    fprintf(stderr, "free_debug: ptr=%p (%s,%d)\n", ptr, filename, linenum);
+    for(i = 0; i < MALLOC_DEBUG_TABLE_NUM; i++) {
+        if (malloc_debug_table[i].ptr == ptr) {
+            malloc_debug_table[i].ptr = NULL;
+            break;
+        }
+    }
+    if (i == MALLOC_DEBUG_TABLE_NUM) {
+        fprintf(stderr, "i == MALLOC_DEBUG_TABLE_NUM: ptr=%p (%s,%d)\n", ptr,
+                filename, linenum);
+        malloc_debug_end();
+        char *ptr = 0;
+        *ptr = 0;
+    }
+    free(ptr);
+}
+
+void *
+realloc_debug(void *ptr, size_t size, char *filename, int linenum) {
+    int i;
+    void *new_ptr;
+    new_ptr = realloc(ptr, size);
+//    fprintf(stderr, "realloc_debug: ptr=%p => new_ptr=%p (%s,%d)\n",
+//            ptr, new_ptr, filename, linenum);
+    for(i=0; i<MALLOC_DEBUG_TABLE_NUM; i++) {
+        if (malloc_debug_table[i].ptr == ptr) {
+            malloc_debug_table[i].ptr = new_ptr;
+            malloc_debug_table[i].filename = filename;
+            malloc_debug_table[i].linenum = linenum;
+            break;
+        }
+    }
+    return new_ptr;
+}
+
+#define HEXBIN_DISP_UNIT 0x10
+
+void
+print_hexbin(unsigned char *data, int data_len) {
+    int i;
+    printf("\n");
+    for(i=0; i<data_len; i++) {
+        if ((i%HEXBIN_DISP_UNIT) == 0) {
+            printf("0x%08x: ", i);
+        }
+#if 1
+        printf("%02x ", data[i] & 0xff);
+        if ((i%HEXBIN_DISP_UNIT) == HEXBIN_DISP_UNIT-1) {
+            printf("\n");
+        }
+#else
+        do {
+            unsigned char c = data[i];
+            signed int j;
+            if ((i%HEXBIN_DISP_UNIT) == 0) {
+                printf("\n");
+            }
+            for(j=7; j>=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 (file)
index 0000000..9aa67b1
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef __SWF_DEFINE__H__
+#define __SWF_DEFINE__H__
+
+#include <stdlib.h>
+
+#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 (file)
index 0000000..4e37c1d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#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 (file)
index 0000000..a75c885
--- /dev/null
@@ -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 (file)
index 0000000..831d993
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#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 (file)
index 0000000..69af038
--- /dev/null
@@ -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 (file)
index 0000000..e995ad2
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> // memcmp
+#include <zlib.h>
+#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 (file)
index 0000000..34c497f
--- /dev/null
@@ -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 (file)
index 0000000..04cdce8
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <png.h>
+#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<index_data_count; i++) {
+                png_palette[i].red   = rgb_list[i].red;
+                png_palette[i].green = rgb_list[i].green;
+                png_palette[i].blue  = rgb_list[i].blue;
+            }
+        } else {
+            swf_rgba_t *rgba_list  = index_data;
+            for (i=0; i<index_data_count; i++) {
+                png_palette[i].red   = rgba_list[i].red;
+                png_palette[i].green = rgba_list[i].green;
+                png_palette[i].blue  = rgba_list[i].blue;
+//                png_palette[i].alpha = rgba_list[i].alpha;
+            }
+        }
+        png_set_PLTE( png_ptr, png_info_ptr, png_palette, index_data_count);
+        free(png_palette);
+    }
+    png_set_gAMA(png_ptr, png_info_ptr, 1.0);
+    png_image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep));
+    if (color_type == PNG_COLOR_TYPE_PALETTE) {
+        for (y=0; y < png_height; y++) {
+            png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr));
+            for (x=0; x < png_width; x++) {
+                unsigned char *data = image_data;
+                png_image_data[y][x] = data[x + y*((png_width +3) & -4)];
+            }
+        }
+        
+    } else if (color_type == PNG_COLOR_TYPE_RGB) {
+        swf_xrgb_t *xrgb_list = image_data;
+        for (y=0; y < png_height; y++) {
+            png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr)) \
+                ;
+            for (x=0; x < png_width; x++) {
+                png_image_data[y][3*x]   =  xrgb_list[x+y*png_width].red;
+                png_image_data[y][3*x+1] =  xrgb_list[x+y*png_width].green;
+                png_image_data[y][3*x+2] =  xrgb_list[x+y*png_width].blue;
+            }
+        }
+    } else {
+        swf_argb_t *argb_list = image_data;
+        for (y=0; y < png_height; y++) {
+            png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr));
+            for (x=0; x < png_width; x++) {
+                png_image_data[y][4*x]   = argb_list[x+y*png_width].red;
+                png_image_data[y][4*x+1] = argb_list[x+y*png_width].green;
+                png_image_data[y][4*x+2] = argb_list[x+y*png_width].blue;
+                png_image_data[y][4*x+3] = argb_list[x+y*png_width].alpha;
+            }
+        }
+        
+    }
+    png_buff.data = NULL;
+    png_buff.data_len = 0;
+    png_buff.data_offset = 0;
+    png_data_write((png_structp) png_ptr, (my_png_buffer*) &png_buff);
+
+    png_write_info(png_ptr, png_info_ptr);
+    png_write_image(png_ptr, png_image_data);
+    png_write_end(png_ptr, png_info_ptr);
+    //
+    for (y=0; y < png_height; y++) {
+        free(png_image_data[y]);
+    }
+    free(png_image_data);
+    png_destroy_write_struct((png_structpp) &png_ptr,
+                             (png_infopp) &png_info_ptr);
+    *length = png_buff.data_offset;
+    return png_buff.data;
+}
diff --git a/src/swf_png.h b/src/swf_png.h
new file mode 100644 (file)
index 0000000..cfa1387
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+extern void *
+pngconv_png2lossless(unsigned char *png_data, unsigned long png_data_len,
+                     int *tag, int *format,
+                     unsigned short *width, unsigned short *height,
+                     void **colormap, int *colormap_count);
+
+extern unsigned char *
+pngconv_lossless2png(void *image_data,
+                     unsigned short width, unsigned short height,
+                     void *index_data,
+                     unsigned short index_data_count,
+                     int tag, int format,
+                     unsigned long *length);
diff --git a/src/swf_rect.c b/src/swf_rect.c
new file mode 100644 (file)
index 0000000..34bd673
--- /dev/null
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#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 (file)
index 0000000..debb522
--- /dev/null
@@ -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 (file)
index 0000000..314fc93
--- /dev/null
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#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 (file)
index 0000000..201c656
--- /dev/null
@@ -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 (file)
index 0000000..a7632a9
--- /dev/null
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#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 (file)
index 0000000..72c7018
--- /dev/null
@@ -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 (file)
index 0000000..3b00094
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#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 (file)
index 0000000..e14dd3a
--- /dev/null
@@ -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 (file)
index 0000000..7e0b9e5
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#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 (file)
index 0000000..f785baf
--- /dev/null
@@ -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 (file)
index 0000000..15c9917
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#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 (file)
index 0000000..977acf7
--- /dev/null
@@ -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 (file)
index 0000000..b6c1c66
--- /dev/null
@@ -0,0 +1,315 @@
+/* 
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strndup */
+#include <zlib.h>
+#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 (file)
index 0000000..f208fb0
--- /dev/null
@@ -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 (file)
index 0000000..ef6d360
--- /dev/null
@@ -0,0 +1,428 @@
+/* 
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strndup */
+#include <zlib.h>
+#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; i<swf_tag_lossless->colormap_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; i<bitmap_count; i++) {
+                swf_xrgb_t *xrgb = swf_tag_lossless->bitmap + i;
+                swf_xrgb_parse(bs2, xrgb);
+            }
+        } else { // tag == 36 (Lossless2)
+            swf_tag_lossless->bitmap2 = malloc(bitmap_count * sizeof(swf_argb_t));
+            for (i=0; i<bitmap_count; i++) {
+                swf_argb_t *argb = swf_tag_lossless->bitmap2 + 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; i<swf_tag_lossless->colormap_count; i++) {
+                swf_rgb_t *rgb = swf_tag_lossless->colormap + i;
+                swf_rgb_build(bs2, rgb);
+            }
+        } else { // tag == 36 (Lossless2)
+            for (i=0; i<swf_tag_lossless->colormap_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; i<bitmap_size; i++) {
+                swf_xrgb_t *xrgb = swf_tag_lossless->bitmap + i;
+                swf_xrgb_build(bs2, xrgb);
+            }
+        } else { // tag == 36 (Lossless2)
+            bitmap_size = swf_tag_lossless->width * swf_tag_lossless->height;
+            for (i=0; i<bitmap_size; i++) {
+                swf_argb_t *argb = swf_tag_lossless->bitmap2 + 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 (file)
index 0000000..11a4156
--- /dev/null
@@ -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 (file)
index 0000000..db2a58a
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#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 (file)
index 0000000..c9d7d3c
--- /dev/null
@@ -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 (file)
index 0000000..01d4b9b
--- /dev/null
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <sys/stat.h>
+#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 (file)
index 0000000..138f07b
--- /dev/null
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#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 (file)
index 0000000..72eab97
--- /dev/null
@@ -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 (file)
index 0000000..345108d
--- /dev/null
@@ -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);
+}