[Swfdec-commits] 8 commits - swfdec/swfdec_script.c swfdec/swfdec_swf_decoder.c swfdec/swfdec_tag.c vivified/code

Benjamin Otte company at kemper.freedesktop.org
Tue Apr 22 03:30:11 PDT 2008


 swfdec/swfdec_script.c                  |    2 
 swfdec/swfdec_swf_decoder.c             |    2 
 swfdec/swfdec_tag.c                     |    2 
 vivified/code/Makefile.am               |    9 +
 vivified/code/rewrite.c                 |  246 ++++++++++++++++++++++++++++++++
 vivified/code/vivi_code_asm_code.c      |   29 +--
 vivified/code/vivi_code_asm_function.c  |   30 +++
 vivified/code/vivi_code_asm_function2.c |   28 +++
 vivified/code/vivi_code_asm_if.c        |   22 ++
 vivified/code/vivi_code_asm_jump.c      |   23 ++
 vivified/code/vivi_code_assembler.c     |   28 +++
 vivified/code/vivi_code_assembler.h     |    4 
 vivified/code/vivi_code_comment.c       |    7 
 vivified/code/vivi_code_emitter.c       |   28 +++
 vivified/code/vivi_code_emitter.h       |    7 
 vivified/code/vivi_code_error.h         |    4 
 vivified/code/vivi_code_label.c         |   12 +
 17 files changed, 446 insertions(+), 37 deletions(-)

New commits:
commit 26cfb037f80e8eda7c3c2b09374e078212dfbd0d
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 22 12:26:32 2008 +0200

    implement code emission
    
    vivi-rewrite now does the full process:
    - decompress Flash file
    - parse Flash file and find scripts
    - disassemble script into ViviCodeAssembler
    - ???
    - assemble ViviCodeAssembler to script
    - put new scripts into file instead of old scripts
    - save file
    
    now I just need to implement ??? and improve error reporting

diff --git a/vivified/code/rewrite.c b/vivified/code/rewrite.c
index 6b626fc..89375cb 100644
--- a/vivified/code/rewrite.c
+++ b/vivified/code/rewrite.c
@@ -46,6 +46,8 @@ do_script (SwfdecBuffer *buffer, guint version)
   script = vivi_code_assembler_assemble_script (assembler, version, &error);
   g_object_unref (assembler);
   if (script == NULL) {
+    g_print ("error: %s\n", error->message);
+    g_error_free (error);
     return NULL;
   }
 
@@ -103,14 +105,25 @@ process_buffer (SwfdecBuffer *original)
 	  SwfdecBots *bots2 = swfdec_bots_open ();
 	  swfdec_bots_put_u16 (bots2, buffer->data[0] | buffer->data[1] << 8);
 	  sub = do_script (sub, version);
+	  if (sub == NULL) {
+	    swfdec_bots_free (bots2);
+	    swfdec_bots_free (bots);
+	    swfdec_buffer_unref (original);
+	    return NULL;
+	  }
 	  swfdec_bots_put_buffer (bots2, sub);
 	  swfdec_buffer_unref (sub);
 	  swfdec_buffer_unref (buffer);
-	  buffer = swfdec_bots_close (bots);
+	  buffer = swfdec_bots_close (bots2);
 	}
 	break;
       case SWFDEC_TAG_DOACTION:
 	buffer = do_script (buffer, version);
+	if (buffer == NULL) {
+	  swfdec_bots_free (bots);
+	  swfdec_buffer_unref (original);
+	  return NULL;
+	}
 	break;
       default:
 	break;
@@ -211,13 +224,13 @@ main (int argc, char *argv[])
   }
   buffer = buffer_decode (buffer);
   if (buffer == NULL) {
-    g_printerr ("\"%s\" is not a Flash file", argv[1]);
+    g_printerr ("\"%s\" is not a Flash file\n", argv[1]);
     return 1;
   }
 
   buffer = process_buffer (buffer);
   if (buffer == NULL) {
-    g_printerr ("\"%s\": Broken Flash file", argv[1]);
+    g_printerr ("\"%s\": Broken Flash file\n", argv[1]);
     return 1;
   }
 
diff --git a/vivified/code/vivi_code_asm_function.c b/vivified/code/vivi_code_asm_function.c
index 5a70473..d436973 100644
--- a/vivified/code/vivi_code_asm_function.c
+++ b/vivified/code/vivi_code_asm_function.c
@@ -32,10 +32,32 @@
 
 static gboolean
 vivi_code_asm_function_resolve (ViviCodeEmitter *emitter, SwfdecBuffer *buffer,
-    gpointer data, GError **error)
+    gsize offset, gpointer data, GError **error)
 {
-  /* FIXME: write */
-  g_return_val_if_reached (FALSE);
+  ViviCodeAsmFunction *fun = VIVI_CODE_ASM_FUNCTION (data);
+  gssize label_offset;
+  gsize diff;
+
+  label_offset = vivi_code_emitter_get_label_offset (emitter, fun->label);
+  if (label_offset < 0) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_MISSING_LABEL,
+	"no label \"%s\"", vivi_code_label_get_name (fun->label));
+    return FALSE;
+  }
+  if ((gsize) label_offset < offset) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_INVALID_LABEL,
+	"cannot jump backwards");
+    return FALSE;
+  }
+  diff = label_offset - offset;
+  if (diff > G_MAXUINT16) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"function body too big");
+    return FALSE;
+  }
+  buffer->data[offset - 1] = diff >> 8;
+  buffer->data[offset - 2] = diff;
+  return TRUE;
 }
 
 static gboolean
@@ -48,7 +70,7 @@ vivi_code_asm_function_emit (ViviCodeAsm *code, ViviCodeEmitter *emitter, GError
 
   bots = swfdec_bots_open ();
   swfdec_bots_put_string (bots, fun->name ? fun->name : "");
-  len = g_strv_length (fun->args);
+  len = fun->args ? g_strv_length (fun->args) : 0;
   g_assert (len <= G_MAXUINT16);
   swfdec_bots_put_u16 (bots, len);
   for (i = 0; i < len; i++) {
diff --git a/vivified/code/vivi_code_asm_function2.c b/vivified/code/vivi_code_asm_function2.c
index 142f512..db26a4d 100644
--- a/vivified/code/vivi_code_asm_function2.c
+++ b/vivified/code/vivi_code_asm_function2.c
@@ -33,10 +33,32 @@
 
 static gboolean
 vivi_code_asm_function2_resolve (ViviCodeEmitter *emitter, SwfdecBuffer *buffer,
-    gpointer data, GError **error)
+    gsize offset, gpointer data, GError **error)
 {
-  /* FIXME: write */
-  g_return_val_if_reached (FALSE);
+  ViviCodeAsmFunction2 *fun = VIVI_CODE_ASM_FUNCTION2 (data);
+  gssize label_offset;
+  gsize diff;
+
+  label_offset = vivi_code_emitter_get_label_offset (emitter, fun->label);
+  if (label_offset < 0) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_MISSING_LABEL,
+	"no label \"%s\"", vivi_code_label_get_name (fun->label));
+    return FALSE;
+  }
+  if ((gsize) label_offset < offset) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_INVALID_LABEL,
+	"cannot jump backwards");
+    return FALSE;
+  }
+  diff = label_offset - offset;
+  if (diff > G_MAXUINT16) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"function body too big");
+    return FALSE;
+  }
+  buffer->data[offset - 1] = diff >> 8;
+  buffer->data[offset - 2] = diff;
+  return TRUE;
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_asm_if.c b/vivified/code/vivi_code_asm_if.c
index 91ea302..2557da0 100644
--- a/vivified/code/vivi_code_asm_if.c
+++ b/vivified/code/vivi_code_asm_if.c
@@ -32,10 +32,26 @@
 
 static gboolean
 vivi_code_asm_if_resolve (ViviCodeEmitter *emitter, SwfdecBuffer *buffer,
-    gpointer data, GError **error)
+    gsize offset, gpointer data, GError **error)
 {
-  /* FIXME: write */
-  g_return_val_if_reached (FALSE);
+  ViviCodeAsmIf *iff = VIVI_CODE_ASM_IF (data);
+  gssize label_offset, diff;
+
+  label_offset = vivi_code_emitter_get_label_offset (emitter, iff->label);
+  if (label_offset < 0) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_MISSING_LABEL,
+	"no label \"%s\"", vivi_code_label_get_name (iff->label));
+    return FALSE;
+  }
+  diff = label_offset - offset;
+  if (diff > G_MAXINT16 || diff < G_MININT16) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"branch target too far away");
+    return FALSE;
+  }
+  buffer->data[offset - 1] = diff >> 8;
+  buffer->data[offset - 2] = diff;
+  return TRUE;
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_asm_jump.c b/vivified/code/vivi_code_asm_jump.c
index 2db716f..b491656 100644
--- a/vivified/code/vivi_code_asm_jump.c
+++ b/vivified/code/vivi_code_asm_jump.c
@@ -32,12 +32,29 @@
 
 static gboolean
 vivi_code_asm_jump_resolve (ViviCodeEmitter *emitter, SwfdecBuffer *buffer,
-    gpointer data, GError **error)
+    gsize offset, gpointer data, GError **error)
 {
-  /* FIXME: write */
-  g_return_val_if_reached (FALSE);
+  ViviCodeAsmJump *jump = VIVI_CODE_ASM_JUMP (data);
+  gssize label_offset, diff;
+
+  label_offset = vivi_code_emitter_get_label_offset (emitter, jump->label);
+  if (label_offset < 0) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_MISSING_LABEL,
+	"no label \"%s\"", vivi_code_label_get_name (jump->label));
+    return FALSE;
+  }
+  diff = label_offset - offset;
+  if (diff > G_MAXINT16 || diff < G_MININT16) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"branch target too far away");
+    return FALSE;
+  }
+  buffer->data[offset - 1] = diff >> 8;
+  buffer->data[offset - 2] = diff;
+  return TRUE;
 }
 
+
 static gboolean
 vivi_code_asm_jump_emit (ViviCodeAsm *code, ViviCodeEmitter *emitter, GError **error)
 {
diff --git a/vivified/code/vivi_code_emitter.c b/vivified/code/vivi_code_emitter.c
index ea2d1af..e9c8b98 100644
--- a/vivified/code/vivi_code_emitter.c
+++ b/vivified/code/vivi_code_emitter.c
@@ -38,7 +38,7 @@ vivi_code_emitter_dispose (GObject *object)
   g_slist_foreach (emit->later, (GFunc) g_free, NULL);
   g_slist_free (emit->later);
   emit->later = NULL;
-  g_hash_table_remove_all (emit->labels);
+  g_hash_table_destroy (emit->labels);
   emit->labels = NULL;
 
   G_OBJECT_CLASS (vivi_code_emitter_parent_class)->dispose (object);
@@ -57,7 +57,7 @@ vivi_code_emitter_init (ViviCodeEmitter *emit)
 {
   emit->bots = swfdec_bots_open ();
   emit->labels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
-      g_object_unref, g_free);
+      g_object_unref, NULL);
 }
 
 gboolean
@@ -97,6 +97,7 @@ vivi_code_emitter_get_label_offset (ViviCodeEmitter *emitter, ViviCodeLabel *lab
 
 typedef struct {
   ViviCodeEmitLater	func;
+  gsize			offset;
   gpointer		data;
 } Later;
 
@@ -110,6 +111,7 @@ vivi_code_emitter_add_later (ViviCodeEmitter *emitter, ViviCodeEmitLater func, g
 
   later = g_new (Later, 1);
   later->func = func;
+  later->offset = swfdec_bots_get_bytes (emitter->bots);
   later->data = data;
   emitter->later = g_slist_prepend (emitter->later, later);
 }
@@ -126,7 +128,7 @@ vivi_code_emitter_finish (ViviCodeEmitter *emitter, GError **error)
   emitter->bots = NULL;
   for (walk = emitter->later; walk; walk = walk->next) {
     Later *later = walk->data;
-    if (!later->func (emitter, buffer, later->data, error)) {
+    if (!later->func (emitter, buffer, later->offset, later->data, error)) {
       swfdec_buffer_unref (buffer);
       buffer = NULL;
       break;
diff --git a/vivified/code/vivi_code_emitter.h b/vivified/code/vivi_code_emitter.h
index bd77d94..56d0708 100644
--- a/vivified/code/vivi_code_emitter.h
+++ b/vivified/code/vivi_code_emitter.h
@@ -29,7 +29,8 @@ G_BEGIN_DECLS
 
 
 typedef struct _ViviCodeEmitterClass ViviCodeEmitterClass;
-typedef gboolean (* ViviCodeEmitLater) (ViviCodeEmitter *emitter, SwfdecBuffer *buffer, gpointer data, GError **error);
+typedef gboolean (* ViviCodeEmitLater) (ViviCodeEmitter *emitter, SwfdecBuffer *buffer,
+    gsize offset, gpointer data, GError **error);
 
 #define VIVI_TYPE_CODE_EMITTER                    (vivi_code_emitter_get_type())
 #define VIVI_IS_CODE_EMITTER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_EMITTER))
diff --git a/vivified/code/vivi_code_error.h b/vivified/code/vivi_code_error.h
index 854bad8..da66b5e 100644
--- a/vivified/code/vivi_code_error.h
+++ b/vivified/code/vivi_code_error.h
@@ -27,7 +27,9 @@ G_BEGIN_DECLS
 #define VIVI_CODE_ERROR (vivi_code_error_quark())
 
 typedef enum {
-  VIVI_CODE_ERROR_SIZE
+  VIVI_CODE_ERROR_SIZE,
+  VIVI_CODE_ERROR_MISSING_LABEL,
+  VIVI_CODE_ERROR_INVALID_LABEL
 } ViviCodeError;
 
 GQuark		vivi_code_error_quark	(void);
commit 8873b7bce7602beb62394bb6daeb5bc78e9c408a
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 22 10:00:14 2008 +0200

    fix refcounting issues

diff --git a/vivified/code/vivi_code_assembler.c b/vivified/code/vivi_code_assembler.c
index 91940fa..582886b 100644
--- a/vivified/code/vivi_code_assembler.c
+++ b/vivified/code/vivi_code_assembler.c
@@ -180,7 +180,6 @@ vivi_code_assembler_assemble_script (ViviCodeAssembler *assembler,
   if (buffer == NULL)
     return NULL;
   script = swfdec_script_new (buffer, "compiled", version);
-  swfdec_buffer_unref (buffer);
   return script;
 }
 
diff --git a/vivified/code/vivi_code_emitter.c b/vivified/code/vivi_code_emitter.c
index 158f8fc..ea2d1af 100644
--- a/vivified/code/vivi_code_emitter.c
+++ b/vivified/code/vivi_code_emitter.c
@@ -129,6 +129,7 @@ vivi_code_emitter_finish (ViviCodeEmitter *emitter, GError **error)
     if (!later->func (emitter, buffer, later->data, error)) {
       swfdec_buffer_unref (buffer);
       buffer = NULL;
+      break;
     }
   }
   g_slist_foreach (emitter->later, (GFunc) g_free, NULL);
commit a4ca150babab930438255a64b5115556ddfd3719
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 22 09:56:36 2008 +0200

    implement emit for labels and comments

diff --git a/vivified/code/vivi_code_comment.c b/vivified/code/vivi_code_comment.c
index 631862d..2d2ee91 100644
--- a/vivified/code/vivi_code_comment.c
+++ b/vivified/code/vivi_code_comment.c
@@ -26,9 +26,16 @@
 #include "vivi_code_compiler.h"
 #include "vivi_code_printer.h"
 
+static gboolean
+vivi_code_comment_emit (ViviCodeAsm *code, ViviCodeEmitter *emitter, GError **error)
+{
+  return TRUE;
+}
+
 static void
 vivi_code_comment_asm_init (ViviCodeAsmInterface *iface)
 {
+  iface->emit = vivi_code_comment_emit;
 }
 
 G_DEFINE_TYPE_WITH_CODE (ViviCodeComment, vivi_code_comment, VIVI_TYPE_CODE_STATEMENT,
diff --git a/vivified/code/vivi_code_label.c b/vivified/code/vivi_code_label.c
index e3f95fc..caf8174 100644
--- a/vivified/code/vivi_code_label.c
+++ b/vivified/code/vivi_code_label.c
@@ -24,11 +24,23 @@
 #include "vivi_code_label.h"
 #include "vivi_code_asm.h"
 #include "vivi_code_compiler.h"
+#include "vivi_code_emitter.h"
 #include "vivi_code_printer.h"
 
+static gboolean
+vivi_code_label_emit (ViviCodeAsm *code, ViviCodeEmitter *emitter, GError **error)
+{
+  ViviCodeLabel *label = VIVI_CODE_LABEL (code);
+
+  vivi_code_emitter_add_label (emitter, label);
+
+  return TRUE;
+}
+
 static void
 vivi_code_label_asm_init (ViviCodeAsmInterface *iface)
 {
+  iface->emit = vivi_code_label_emit;
 }
 
 G_DEFINE_TYPE_WITH_CODE (ViviCodeLabel, vivi_code_label, VIVI_TYPE_CODE_STATEMENT,
commit 59e54803c60f68f51d801d63fe468c729ca43a38
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 22 09:53:44 2008 +0200

    implement ViviCodeAsm.emit

diff --git a/vivified/code/vivi_code_asm_code.c b/vivified/code/vivi_code_asm_code.c
index dc9fdf2..8f47ee5 100644
--- a/vivified/code/vivi_code_asm_code.c
+++ b/vivified/code/vivi_code_asm_code.c
@@ -25,33 +25,34 @@
 
 #include "vivi_code_asm_code.h"
 #include "vivi_code_asm.h"
-#include "vivi_code_compiler.h"
+#include "vivi_code_emitter.h"
 #include "vivi_code_printer.h"
 
+static gboolean
+vivi_code_asm_code_emit (ViviCodeAsm *asm_code, ViviCodeEmitter *emitter, GError **error)
+{
+  ViviCodeAsmCode *code = VIVI_CODE_ASM_CODE (asm_code);
+  ViviCodeAsmCodeClass *klass = VIVI_CODE_ASM_CODE_GET_CLASS (code);
+  SwfdecBots *bots = vivi_code_emitter_get_bots (emitter);
+
+  swfdec_bots_put_u8 (bots, klass->bytecode);
+  if (klass->bytecode & 0x80)
+    swfdec_bots_put_u16 (bots, 0);
+  return TRUE;
+}
+
 static void
 vivi_code_asm_code_asm_init (ViviCodeAsmInterface *iface)
 {
+  iface->emit = vivi_code_asm_code_emit;
 }
 
 G_DEFINE_TYPE_WITH_CODE (ViviCodeAsmCode, vivi_code_asm_code, VIVI_TYPE_CODE_TOKEN,
     G_IMPLEMENT_INTERFACE (VIVI_TYPE_CODE_ASM, vivi_code_asm_code_asm_init))
 
 static void
-vivi_code_asm_code_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
-{
-  ViviCodeAsmCode *code = VIVI_CODE_ASM_CODE (token);
-  SwfdecAsAction action = vivi_code_asm_code_get_action (code);
-
-  g_assert (action < 0x80);
-  vivi_code_compiler_write_empty_action (compiler, action); 
-}
-
-static void
 vivi_code_asm_code_class_init (ViviCodeAsmCodeClass *klass)
 {
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
-
-  token_class->compile = vivi_code_asm_code_compile;
 }
 
 static void
commit b85fd1f302ce71c4b36844a9729e31cbc4301082
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 22 09:48:56 2008 +0200

    add API to emit asm code into a buffer.
    
    And use it. :)

diff --git a/vivified/code/rewrite.c b/vivified/code/rewrite.c
index 5a27346..6b626fc 100644
--- a/vivified/code/rewrite.c
+++ b/vivified/code/rewrite.c
@@ -23,6 +23,39 @@
 #include <swfdec/swfdec.h>
 #include <swfdec/swfdec_bits.h>
 #include <swfdec/swfdec_bots.h>
+#include <swfdec/swfdec_script_internal.h>
+#include <swfdec/swfdec_tag.h>
+
+#include <vivified/code/vivi_code_assembler.h>
+#include <vivified/code/vivi_decompiler.h>
+
+static SwfdecBuffer *
+do_script (SwfdecBuffer *buffer, guint version)
+{
+  ViviCodeAssembler *assembler;
+  SwfdecScript *script;
+  GError *error = NULL;
+
+  script = swfdec_script_new (buffer, "script", version);
+
+  assembler = VIVI_CODE_ASSEMBLER (vivi_disassemble_script (script));
+  swfdec_script_unref (script);
+
+  /* FIXME: modify script here! */
+
+  script = vivi_code_assembler_assemble_script (assembler, version, &error);
+  g_object_unref (assembler);
+  if (script == NULL) {
+    return NULL;
+  }
+
+  /* FIXME: We want swfdec_script_get_buffer() */
+  g_assert (script->main == script->buffer->data);
+  buffer = swfdec_buffer_ref (script->buffer);
+  swfdec_script_unref (script);
+
+  return buffer;
+}
 
 static SwfdecBuffer *
 process_buffer (SwfdecBuffer *original)
@@ -64,6 +97,21 @@ process_buffer (SwfdecBuffer *original)
     }
 
     switch (tag) {
+      case SWFDEC_TAG_DOINITACTION:
+	{
+	  SwfdecBuffer *sub = swfdec_buffer_new_subbuffer (buffer, 2, buffer->length - 2);
+	  SwfdecBots *bots2 = swfdec_bots_open ();
+	  swfdec_bots_put_u16 (bots2, buffer->data[0] | buffer->data[1] << 8);
+	  sub = do_script (sub, version);
+	  swfdec_bots_put_buffer (bots2, sub);
+	  swfdec_buffer_unref (sub);
+	  swfdec_buffer_unref (buffer);
+	  buffer = swfdec_bots_close (bots);
+	}
+	break;
+      case SWFDEC_TAG_DOACTION:
+	buffer = do_script (buffer, version);
+	break;
       default:
 	break;
     }
diff --git a/vivified/code/vivi_code_assembler.c b/vivified/code/vivi_code_assembler.c
index 49d52cb..91940fa 100644
--- a/vivified/code/vivi_code_assembler.c
+++ b/vivified/code/vivi_code_assembler.c
@@ -26,6 +26,7 @@
 
 #include "vivi_code_assembler.h"
 #include "vivi_code_comment.h"
+#include "vivi_code_emitter.h"
 #include "vivi_code_label.h"
 #include "vivi_code_printer.h"
 #include "vivi_code_compiler.h"
@@ -155,3 +156,31 @@ vivi_code_assembler_remove_code (ViviCodeAssembler *assembler, ViviCodeAsm *code
     g_return_if_reached ();
 }
 
+SwfdecScript *
+vivi_code_assembler_assemble_script (ViviCodeAssembler *assembler,
+    guint version, GError **error)
+{
+  ViviCodeEmitter *emit;
+  SwfdecBuffer *buffer;
+  SwfdecScript *script;
+  guint i;
+
+  g_return_val_if_fail (VIVI_IS_CODE_ASSEMBLER (assembler), NULL);
+
+  emit = vivi_code_emitter_new (version);
+  for (i = 0; i < assembler->codes->len; i++) {
+    if (!vivi_code_emitter_emit_asm (emit, 
+	  g_ptr_array_index (assembler->codes, i), error)) {
+      g_object_unref (emit);
+      return NULL;
+    }
+  }
+  buffer = vivi_code_emitter_finish (emit, error);
+  g_object_unref (emit);
+  if (buffer == NULL)
+    return NULL;
+  script = swfdec_script_new (buffer, "compiled", version);
+  swfdec_buffer_unref (buffer);
+  return script;
+}
+
diff --git a/vivified/code/vivi_code_assembler.h b/vivified/code/vivi_code_assembler.h
index 2fcd1f3..e692cf1 100644
--- a/vivified/code/vivi_code_assembler.h
+++ b/vivified/code/vivi_code_assembler.h
@@ -62,6 +62,10 @@ void			vivi_code_assembler_insert_code  	(ViviCodeAssembler *	assembler,
 void			vivi_code_assembler_remove_code		(ViviCodeAssembler *	assembler,
 								 ViviCodeAsm *		code);
 
+SwfdecScript *		vivi_code_assembler_assemble_script	(ViviCodeAssembler *	assembler,
+								 guint			version,
+								 GError **		error);
+
 
 G_END_DECLS
 #endif
diff --git a/vivified/code/vivi_code_emitter.c b/vivified/code/vivi_code_emitter.c
index 21750a5..158f8fc 100644
--- a/vivified/code/vivi_code_emitter.c
+++ b/vivified/code/vivi_code_emitter.c
@@ -140,6 +140,17 @@ vivi_code_emitter_finish (ViviCodeEmitter *emitter, GError **error)
   return buffer;
 }
 
+ViviCodeEmitter *
+vivi_code_emitter_new (guint version)
+{
+  ViviCodeEmitter *emit;
+
+  emit = g_object_new (VIVI_TYPE_CODE_EMITTER, NULL);
+  emit->version = version;
+
+  return emit;
+}
+
 SwfdecBots *
 vivi_code_emitter_get_bots (ViviCodeEmitter *emitter)
 {
@@ -148,3 +159,11 @@ vivi_code_emitter_get_bots (ViviCodeEmitter *emitter)
   return emitter->bots;
 }
 
+guint
+vivi_code_emitter_get_version (ViviCodeEmitter *emitter)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_EMITTER (emitter), 0);
+
+  return emitter->version;
+}
+
diff --git a/vivified/code/vivi_code_emitter.h b/vivified/code/vivi_code_emitter.h
index baf0765..bd77d94 100644
--- a/vivified/code/vivi_code_emitter.h
+++ b/vivified/code/vivi_code_emitter.h
@@ -42,6 +42,7 @@ struct _ViviCodeEmitter
 {
   GObject		object;
 
+  guint			version;	/* version we emit code for */
   SwfdecBots *		bots;		/* output stream */
   GHashTable *		labels;		/* ViviCodeLabel => offset + 1 */
   GSList *		later;		/* ViviCodeEmitLater/data tuples */
@@ -54,13 +55,14 @@ struct _ViviCodeEmitterClass
 
 GType			vivi_code_emitter_get_type   	(void);
 
-ViviCodeEmitter *	vivi_code_emitter_new		(void);
+ViviCodeEmitter *	vivi_code_emitter_new		(guint			version);
 
 gboolean		vivi_code_emitter_emit_asm	(ViviCodeEmitter *	emitter,
 							 ViviCodeAsm *		code,
 							 GError **		error);
 
 SwfdecBots *		vivi_code_emitter_get_bots	(ViviCodeEmitter *	emitter);
+guint			vivi_code_emitter_get_version	(ViviCodeEmitter *	emitter);
 void			vivi_code_emitter_add_label	(ViviCodeEmitter *	emitter,
 							 ViviCodeLabel *	label);
 gssize			vivi_code_emitter_get_label_offset 
commit 34d8ff4df84fc84217e9f926cd9a4597fd817cb3
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 21 22:35:25 2008 +0200

    typo

diff --git a/swfdec/swfdec_script.c b/swfdec/swfdec_script.c
index 07d4c79..d7e9e38 100644
--- a/swfdec/swfdec_script.c
+++ b/swfdec/swfdec_script.c
@@ -122,7 +122,7 @@ swfdec_script_foreach (SwfdecScript *script, SwfdecScriptForeachFunc func, gpoin
  *
  * Creates a new script for the actionscript provided in @buffer.
  *
- * Returns: a new #SwfdecScript for executing the script i @buffer.
+ * Returns: a new #SwfdecScript for executing the script in @buffer.
  **/
 SwfdecScript *
 swfdec_script_new (SwfdecBuffer *buffer, const char *name, guint version)
commit 3d4edc8f42d0104e057eaea2bf1ff4756ad1f2cb
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 21 22:26:26 2008 +0200

    remove useless and-ing
    
    It's a shifted U16, so there's not more bytes left anyway.

diff --git a/swfdec/swfdec_swf_decoder.c b/swfdec/swfdec_swf_decoder.c
index da750e1..2dabaac 100644
--- a/swfdec/swfdec_swf_decoder.c
+++ b/swfdec/swfdec_swf_decoder.c
@@ -307,7 +307,7 @@ swfdec_swf_decoder_parse_one (SwfdecSwfDecoder *s)
 	return SWFDEC_STATUS_NEEDBITS;
 
       x = swfdec_bits_get_u16 (&bits);
-      tag = (x >> 6) & 0x3ff;
+      tag = x >> 6;
       SWFDEC_DEBUG ("tag %d %s", tag, swfdec_swf_decoder_get_tag_name (tag));
       tag_len = x & 0x3f;
       if (tag_len == 0x3f) {
diff --git a/swfdec/swfdec_tag.c b/swfdec/swfdec_tag.c
index 65fa514..2f91b7d 100644
--- a/swfdec/swfdec_tag.c
+++ b/swfdec/swfdec_tag.c
@@ -201,7 +201,7 @@ tag_func_define_sprite (SwfdecSwfDecoder * s, guint define_sprite_tag)
     SwfdecTagFunc func;
 
     x = swfdec_bits_get_u16 (&parse);
-    tag = (x >> 6) & 0x3ff;
+    tag = x >> 6;
     tag_len = x & 0x3f;
     if (tag_len == 0x3f) {
       tag_len = swfdec_bits_get_u32 (&parse);
commit 1d1dcdfc8460e81b08ff59372a50745304ef9f5a
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 21 22:08:47 2008 +0200

    add a simple tool for changing Flash files
    
    The goal is to have a list of possible actions that can be performed on the
    file, like "add a trace to the beginning of every function" name or "remove all
    traces of the character 56". This should be done without modifying other
    aspects of the Flash file to preserve bugs.

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index a54e680..acd4dbf 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -159,7 +159,7 @@ noinst_HEADERS = \
 	vivi_parser_scanner_lex.h \
 	vivified-compiler.h
 
-noinst_PROGRAMS = vivi-decompile vivi-compile
+noinst_PROGRAMS = vivi-decompile vivi-compile vivi-rewrite
 
 vivi_decompile_SOURCES = \
 	decompiler.c
@@ -174,3 +174,10 @@ vivi_compile_SOURCES = \
 vivi_compile_CFLAGS =  $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
 vivi_compile_LDFLAGS = $(SWFDEC_LIBS)
 vivi_compile_LDADD = libvivified-compiler.la
+
+vivi_rewrite_SOURCES = \
+	rewrite.c
+
+vivi_rewrite_CFLAGS =  $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
+vivi_rewrite_LDFLAGS = $(SWFDEC_LIBS) -lz
+vivi_rewrite_LDADD = libvivified-compiler.la
diff --git a/vivified/code/rewrite.c b/vivified/code/rewrite.c
new file mode 100644
index 0000000..5a27346
--- /dev/null
+++ b/vivified/code/rewrite.c
@@ -0,0 +1,185 @@
+/* Swfdec
+ * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <swfdec/swfdec.h>
+#include <swfdec/swfdec_bits.h>
+#include <swfdec/swfdec_bots.h>
+
+static SwfdecBuffer *
+process_buffer (SwfdecBuffer *original)
+{
+  SwfdecRect rect;
+  SwfdecBits bits;
+  SwfdecBots *bots, *full;
+  SwfdecBuffer *buffer;
+  guint version, tag, len;
+  gboolean long_header;
+
+  bots = swfdec_bots_open ();
+  swfdec_bits_init (&bits, original);
+
+  /* copy header */
+  swfdec_bits_get_u8 (&bits);
+  swfdec_bits_get_u8 (&bits);
+  swfdec_bits_get_u8 (&bits);
+  version = swfdec_bits_get_u8 (&bits);
+  swfdec_bits_get_u32 (&bits);
+  swfdec_bits_get_rect (&bits, &rect);
+  swfdec_bots_put_rect (bots, &rect);
+  swfdec_bots_put_u16 (bots, swfdec_bits_get_u16 (&bits));
+  swfdec_bots_put_u16 (bots, swfdec_bits_get_u16 (&bits));
+
+  while (swfdec_bits_left (&bits)) {
+    len = swfdec_bits_get_u16 (&bits);
+    tag = (len >> 6);
+    len = len & 0x3f;
+    long_header = (len == 0x3f);
+    if (long_header)
+      len = swfdec_bits_get_u32 (&bits);
+
+    buffer = swfdec_bits_get_buffer (&bits, len);
+    if (buffer == NULL) {
+      swfdec_bots_free (bots);
+      swfdec_buffer_unref (original);
+      return NULL;
+    }
+
+    switch (tag) {
+      default:
+	break;
+    }
+    long_header |= buffer->length >= 0x3f;
+    swfdec_bots_put_u16 (bots, tag << 6 | (long_header ? 0x3f : buffer->length));
+    if (long_header)
+      swfdec_bots_put_u32 (bots, buffer->length);
+    swfdec_bots_put_buffer (bots, buffer);
+    swfdec_buffer_unref (buffer);
+  }
+
+  swfdec_buffer_unref (original);
+  full = swfdec_bots_open ();
+  swfdec_bots_put_u8 (full, 'F');
+  swfdec_bots_put_u8 (full, 'W');
+  swfdec_bots_put_u8 (full, 'S');
+  swfdec_bots_put_u8 (full, version);
+  swfdec_bots_put_u32 (full, swfdec_bots_get_bytes (bots));
+  swfdec_bots_put_bots (full, bots);
+  swfdec_bots_free (bots);
+  return swfdec_bots_close (full);
+}
+
+static SwfdecBuffer *
+buffer_decode (SwfdecBuffer *buffer)
+{
+  SwfdecBits bits;
+  SwfdecBots *bots;
+  SwfdecBuffer *decoded;
+  guint u;
+
+  swfdec_bits_init (&bits, buffer);
+  u = swfdec_bits_get_u8 (&bits);
+  if ((u != 'C' && u != 'F') ||
+      swfdec_bits_get_u8 (&bits) != 'W' ||
+      swfdec_bits_get_u8 (&bits) != 'S') {
+    swfdec_buffer_unref (buffer);
+    return NULL;
+  }
+  
+  if (u == 'F')
+    return buffer;
+
+  bots = swfdec_bots_open ();
+  swfdec_bots_put_u8 (bots, 'F');
+  swfdec_bots_put_u8 (bots, 'W');
+  swfdec_bots_put_u8 (bots, 'S');
+  swfdec_bots_put_u8 (bots, swfdec_bits_get_u8 (&bits));
+  u = swfdec_bits_get_u32 (&bits);
+  g_assert (u <= G_MAXINT32);
+  decoded = swfdec_bits_decompress (&bits, -1, u);
+  swfdec_buffer_unref (buffer);
+  if (decoded == NULL)
+    return NULL;
+  swfdec_bots_put_u32 (bots, u);
+  swfdec_bots_put_buffer (bots, decoded);
+  swfdec_buffer_unref (decoded);
+  buffer = swfdec_bots_close (bots);
+  return buffer;
+}
+
+int 
+main (int argc, char *argv[])
+{
+  GError *error = NULL;
+  SwfdecBuffer *buffer;
+
+  GOptionEntry options[] = {
+    //{ "asm", 'a', 0, G_OPTION_ARG_NONE, &use_asm, "output assembler instead of decompiled script", NULL },
+    { NULL }
+  };
+  GOptionContext *ctx;
+
+  ctx = g_option_context_new ("");
+  g_option_context_add_main_entries (ctx, options, "options");
+  g_option_context_parse (ctx, &argc, &argv, &error);
+  g_option_context_free (ctx);
+
+  if (error) {
+    g_printerr ("Error parsing command line arguments: %s\n", error->message);
+    g_error_free (error);
+    return 1;
+  }
+
+  if (argc < 3) {
+    g_printerr ("%s [OPTIONS] INFILE OUTFILE\n", argv[0]);
+    return 1;
+  }
+
+  swfdec_init ();
+
+  buffer = swfdec_buffer_new_from_file (argv[1], &error);
+  if (buffer == NULL) {
+    g_printerr ("Error loading: %s\n", error->message);
+    g_error_free (error);
+    return 1;
+  }
+  buffer = buffer_decode (buffer);
+  if (buffer == NULL) {
+    g_printerr ("\"%s\" is not a Flash file", argv[1]);
+    return 1;
+  }
+
+  buffer = process_buffer (buffer);
+  if (buffer == NULL) {
+    g_printerr ("\"%s\": Broken Flash file", argv[1]);
+    return 1;
+  }
+
+  if (!g_file_set_contents (argv[2], (char *) buffer->data, buffer->length, &error)) {
+    swfdec_buffer_unref (buffer);
+    g_printerr ("Error saving: %s\n", error->message);
+    return 1;
+  }
+  
+  swfdec_buffer_unref (buffer);
+  return 0;
+}
+


More information about the Swfdec-commits mailing list