Benjamin Otte
2007-Feb-14 06:58 UTC
[Swfdec] 7 commits - libswfdec/swfdec_image.c libswfdec/swfdec_script.c libswfdec/swfdec_script.h test/Makefile.am test/swfdec_out.c test/swfdec_out.h test/swfedit.c test/swfedit_list.c test/swfedit_tag.c test/swfedit_token.c test/swfedit_token.h test/swfscript.c
libswfdec/swfdec_image.c | 2 libswfdec/swfdec_script.c | 25 +++ libswfdec/swfdec_script.h | 3 test/Makefile.am | 6 test/swfdec_out.c | 10 + test/swfdec_out.h | 3 test/swfedit.c | 2 test/swfedit_list.c | 18 ++ test/swfedit_tag.c | 15 ++ test/swfedit_token.c | 37 +++++ test/swfedit_token.h | 3 test/swfscript.c | 301 ++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 418 insertions(+), 7 deletions(-) New commits: diff-tree 98049e91f2ff8cd1cc2ad5b9ae5952653d065ad7 (from 0a2ba5fca5d5cd32a0161d2c6815166e4a35721c) Author: Benjamin Otte <otte@gnome.org> Date: Wed Feb 14 15:58:21 2007 +0100 fix rowstride computation in jpeg3 case diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c index 4d59b99..dc96fb6 100644 --- a/libswfdec/swfdec_image.c +++ b/libswfdec/swfdec_image.c @@ -249,7 +249,7 @@ swfdec_image_jpeg3_load (SwfdecImage *im } swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height); image->data = jpeg_decoder_get_argb_image (dec); - image->rowstride = image->width; + image->rowstride = image->width * 4; jpeg_decoder_free (dec); buffer = swfdec_bits_decompress (&bits, -1, image->width * image->height); diff-tree 0a2ba5fca5d5cd32a0161d2c6815166e4a35721c (from parents) Merge: dfd539e9810bd1e307838deb89a429ffe41da37a 46831ced770ebb02396352f786f861624f4b424a Author: Benjamin Otte <otte@gnome.org> Date: Wed Feb 14 15:36:06 2007 +0100 Merge branch 'master' of ssh://company@git.freedesktop.org/git/swfdec diff-tree dfd539e9810bd1e307838deb89a429ffe41da37a (from 147c712c0ac2f90a6ecbb83ad067b2fd3efd454f) Author: Benjamin Otte <otte@gnome.org> Date: Wed Feb 14 15:35:43 2007 +0100 add swfscript - a tool to batch-modify scripts of existing SWF files diff --git a/test/Makefile.am b/test/Makefile.am index b55bf0f..e31046b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -3,7 +3,7 @@ SUBDIRS = image sound trace various noinst_LTLIBRARIES = libswfedit.la if WITH_GTK -noinst_PROGRAMS = swfdec-extract dump parse swfedit +noinst_PROGRAMS = swfdec-extract dump parse swfedit swfscript else noinst_PROGRAMS = swfdec-extract dump parse endif @@ -24,6 +24,10 @@ swfedit_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_ swfedit_LDFLAGS = $(SWF_LIBS) $(GTK_LIBS) swfedit_LDADD = libswfedit.la +swfscript_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js +swfscript_LDFLAGS = $(SWF_LIBS) $(GTK_LIBS) +swfscript_LDADD = libswfedit.la + libswfedit_la_SOURCES = \ swfdec_out.c \ swfedit_file.c \ diff --git a/test/swfscript.c b/test/swfscript.c new file mode 100644 index 0000000..40d0e27 --- /dev/null +++ b/test/swfscript.c @@ -0,0 +1,301 @@ +/* Swfedit + * Copyright (C) 2007 Benjamin Otte <otte@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 <gtk/gtk.h> +#include "libswfdec/swfdec_script.h" +#include "swfdec_out.h" +#include "swfedit_file.h" + +/* the stuff we look for */ +guint *add_trace = NULL; + +typedef gboolean ( *SwfeditTokenForeachFunc) (SwfeditToken *token, guint idx, + const char *name, SwfeditTokenType type, gconstpointer value, gpointer data); + +static gboolean +swfedit_token_foreach (SwfeditToken *token, SwfeditTokenForeachFunc func, + gpointer data) +{ + SwfeditTokenEntry *entry; + guint i; + + g_return_val_if_fail (SWFEDIT_IS_TOKEN (token), FALSE); + g_return_val_if_fail (func != NULL, FALSE); + + for (i = 0; i < token->tokens->len; i++) { + entry = &g_array_index (token->tokens, SwfeditTokenEntry, i); + if (!func (token, i, entry->name, entry->type, entry->value, data)) + return FALSE; + if (entry->type == SWFEDIT_TOKEN_OBJECT) { + if (!swfedit_token_foreach (entry->value, func, data)) + return FALSE; + } + } + return TRUE; +} + +typedef struct { + guint offset; /* offset in bytes from start of script */ + guint new_offset; /* new offset in bytes from start of script */ + guint new_actions; /* number of actions in new script */ +} Action; + +typedef struct { + SwfdecScript * script; /* the original script */ + SwfdecOut * out; /* output for new script or NULL when buffer is set */ + SwfdecBuffer * buffer; /* buffer containing new script or NULL while constructing */ + GArray * actions; /* all actions in the script */ +} State; + +static gboolean +action_in_array (guint *array, guint action) +{ + if (array == NULL) + return FALSE; + while (*array != 0) { + if (*array == action) + return TRUE; + array++; + } + return FALSE; +} + +static guint +lookup_offset (GArray *array, guint offset) +{ + guint i; + for (i = 0; i < array->len; i++) { + Action *action = &g_array_index (array, Action, i); + if (action->offset == offset) + return action->new_offset; + } + g_assert_not_reached (); + return 0; +} + +static gboolean +fixup_jumps_foreach (gconstpointer bytecode, guint action, + const guint8 *data, guint len, gpointer user_data) +{ + State *state = user_data; + + if (action == 0x99 || action == 0x9d) { + guint offset = (guint8 *) bytecode - state->script->buffer->data; + guint jump_offset = offset + 5 + GINT16_FROM_LE (*((gint16 *) data)); + offset = lookup_offset (state->actions, offset); + jump_offset = lookup_offset (state->actions, jump_offset); + *((gint16 *) &state->buffer->data[offset + 3]) = + GINT16_TO_LE (jump_offset - offset - 5); + } + if (action == 0x8a || action == 0x8d) { + Action *cur; + guint id = action == 0x8a ? 2 : 0; + guint i, count; + guint offset = (guint8 *) bytecode - state->script->buffer->data; + for (i = 0; i < state->actions->len; i++) { + cur = &g_array_index (state->actions, Action, i); + if (cur->offset == offset) { + offset = cur->new_offset; + break; + } + } + g_assert (i < state->actions->len); + i = data[id]; + count = cur->new_actions - 1; /* FIXME: only works as long as we append actions */ + while (i > 0) { + cur++; + count += cur->new_actions; + i--; + } + g_assert (count < 256); + state->buffer->data[offset + 3 + id] = count; + } + return TRUE; +} + +static gboolean +modify_script_foreach (gconstpointer bytecode, guint action, + const guint8 *data, guint len, gpointer user_data) +{ + Action next; + State *state = user_data; + + next.offset = (guint8 *) bytecode - state->script->buffer->data; + next.new_offset = swfdec_out_get_bits (state->out) / 8; + next.new_actions = 1; + swfdec_out_put_u8 (state->out, action); + if (action & 0x80) { + swfdec_out_put_u16 (state->out, len); + swfdec_out_put_data (state->out, data, len); + } + if (action_in_array (add_trace, action)) { + swfdec_out_put_u8 (state->out, 0x4c); /* PushDuplicate */ + swfdec_out_put_u8 (state->out, 0x26); /* Trace */ + next.new_actions += 2; + } + g_array_append_val (state->actions, next); + return TRUE; +} + +static gboolean +modify_file (SwfeditToken *token, guint idx, const char *name, + SwfeditTokenType type, gconstpointer value, gpointer data) +{ + Action end; + SwfdecBits bits; + SwfdecScript *script; + State state; + + if (type != SWFEDIT_TOKEN_SCRIPT) + return TRUE; + + state.script = (SwfdecScript *) value; + state.out = swfdec_out_open (); + state.buffer = NULL; + state.actions = g_array_new (FALSE, FALSE, sizeof (Action)); + swfdec_script_foreach (state.script, modify_script_foreach, &state); + /* compute end offset */ + end.offset = g_array_index (state.actions, Action, state.actions->len - 1).offset; + if (state.script->buffer->data[end.offset] & 0x80) { + end.offset += GUINT16_FROM_LE (*((guint16* ) &state.script->buffer->data[end.offset + 1])) + 3; + } else { + end.offset++; + } + end.new_offset = swfdec_out_get_bits (state.out) / 8; + end.new_actions = 0; + g_array_append_val (state.actions, end); +#if 0 + { + guint i; + for (i = 0; i < state.actions->len; i++) { + Action *action = &g_array_index (state.actions, Action, i); + g_print ("%u %u => %u (%u actions)\n", i, action->offset, + action->new_offset, action->new_actions); + } + } +#endif + /* maybe append 0 byte */ + if (end.offset + 1 == state.script->buffer->length) { + swfdec_out_put_u8 (state.out, 0); + } else { + g_assert (end.offset == state.script->buffer->length); + } + state.buffer = swfdec_out_close (state.out); + state.out = NULL; + swfdec_script_foreach (state.script, fixup_jumps_foreach, &state); + g_array_free (state.actions, TRUE); +#if 0 + g_print ("got a new script in %u bytes - old script was %u bytes\n", + state.buffer->length, state.script->buffer->length); +#endif + swfdec_bits_init (&bits, state.buffer); + script = swfdec_script_new (&bits, state.script->name, state.script->version); + swfdec_buffer_unref (state.buffer); + g_assert (script); + swfedit_token_set (token, idx, script); + + return TRUE; +} + +static guint * +string_to_action_list (const char *list) +{ + char **actions = g_strsplit (list, ",", -1); + guint *ret; + guint i, len; + + len = g_strv_length (actions); + ret = g_new (guint, len + 1); + ret[len] = 0; + for (i = 0; i < len; i++) { + ret[i] = swfdec_action_get_from_name (actions[i]); + if (ret[i] == 0) { + g_printerr ("No such action \"%s\"\n", actions[i]); + g_free (actions); + g_free (ret); + return NULL; + } + } + g_free (actions); + return ret; +} + +int +main (int argc, char **argv) +{ + SwfeditFile *file; + GError *error = NULL; + char *add_trace_s = NULL; + GOptionEntry options[] = { + { "add-trace", 't', 0, G_OPTION_ARG_STRING, &add_trace_s, "list of actions to trace", "ACTION, ACTION" }, + { NULL } + }; + GOptionContext *ctx; + + ctx = g_option_context_new (""); + g_option_context_add_main_entries (ctx, options, "options"); + g_option_context_add_group (ctx, gtk_get_option_group (TRUE)); + g_option_context_parse (ctx, &argc, &argv, &error); + g_option_context_free (ctx); + if (error) { + g_printerr ("error parsing arguments: %s\n", error->message); + g_error_free (error); + return 1; + } + + if (argc < 2) { + g_printerr ("Usage: %s FILENAME [OUTPUT-FILENAME]\n", argv[0]); + return 1; + } + if (add_trace_s) { + add_trace = string_to_action_list (add_trace_s); + g_free (add_trace_s); + if (add_trace == NULL) + return 1; + } + file = swfedit_file_new (argv[1], &error); + if (file == NULL) { + g_printerr ("error opening file %s: %s\n", argv[1], error->message); + g_error_free (error); + return 1; + } + if (!swfedit_token_foreach (SWFEDIT_TOKEN (file), modify_file, NULL)) { + g_printerr ("modifying file %s failed.\n", argv[1]); + g_object_unref (file); + return 1; + } + g_free (file->filename); + if (argc > 2) { + file->filename = g_strdup (argv[2]); + } else { + file->filename = g_strdup_printf ("%s.out.swf", argv[1]); + } + if (!swfedit_file_save (file, &error)) { + g_printerr ("Error saving file: %s\n", error->message); + g_error_free (error); + } + g_print ("saved modified file to %s\n", file->filename); + g_object_unref (file); + return 0; +} + diff-tree 147c712c0ac2f90a6ecbb83ad067b2fd3efd454f (from e08ecaf9a240b52e46ba4b6da01016420e4943ac) Author: Benjamin Otte <otte@gnome.org> Date: Wed Feb 14 15:31:52 2007 +0100 automatically update size fields diff --git a/test/swfedit_list.c b/test/swfedit_list.c index 289d7de..36e0295 100644 --- a/test/swfedit_list.c +++ b/test/swfedit_list.c @@ -46,9 +46,25 @@ swfedit_list_changed (SwfeditToken *toke swfedit_token_set_visible (token, j, entry->value != NULL); } } + /* update length */ + j = list->def[i % list->n_defs].n_items; + if (j != 0) { + SwfeditTokenEntry *entry = &g_array_index (token->tokens, + SwfeditTokenEntry, j - 1); + if (entry->type == SWFEDIT_TOKEN_UINT32) { + SwfdecOut *out = swfdec_out_open (); + SwfdecBuffer *buffer; + swfedit_tag_write_token (token, out, i); + buffer = swfdec_out_close (out); + if (entry->value != GUINT_TO_POINTER (buffer->length)) { + swfedit_token_set (token, i / list->n_defs * list->n_defs + j - 1, + GUINT_TO_POINTER (buffer->length)); + } + swfdec_buffer_unref (buffer); + } + } /* maybe add items */ if (i == token->tokens->len - 1) { - g_print ("add fett neue items, man!\n"); for (j = 0; j < list->n_defs; j++) { const SwfeditTagDefinition *def = &list->def[(j + 1) % list->n_defs]; swfedit_tag_add_token (SWFEDIT_TOKEN (list), def->name, def->type, def->hint); diff --git a/test/swfedit_tag.c b/test/swfedit_tag.c index 75137a5..b69a5d5 100644 --- a/test/swfedit_tag.c +++ b/test/swfedit_tag.c @@ -396,6 +396,21 @@ swfedit_tag_changed (SwfeditToken *token swfedit_token_set_visible (token, j, entry->value != NULL); } } + if (def[i].n_items != 0) { + SwfeditTokenEntry *entry = &g_array_index (token->tokens, + SwfeditTokenEntry, def[i].n_items - 1); + if (entry->type == SWFEDIT_TOKEN_UINT32) { + SwfdecOut *out = swfdec_out_open (); + SwfdecBuffer *buffer; + swfedit_tag_write_token (token, out, def[i].n_items - 1); + buffer = swfdec_out_close (out); + if (entry->value != GUINT_TO_POINTER (buffer->length)) { + swfedit_token_set (token, def[i].n_items - 1, + GUINT_TO_POINTER (buffer->length)); + } + swfdec_buffer_unref (buffer); + } + } } static void diff-tree e08ecaf9a240b52e46ba4b6da01016420e4943ac (from e067398923300c8505c62abd3f0e7c020e9cbe9b) Author: Benjamin Otte <otte@gnome.org> Date: Wed Feb 14 15:31:17 2007 +0100 Add swfedit_token_set to set by index rename swfedit_token_set to swfedit_token_set_iter diff --git a/test/swfedit.c b/test/swfedit.c index 7e13bd6..24f2980 100644 --- a/test/swfedit.c +++ b/test/swfedit.c @@ -60,7 +60,7 @@ cell_renderer_edited (GtkCellRenderer *r &iter, path)) { g_assert_not_reached (); } - swfedit_token_set (SWFEDIT_TOKEN (file), &iter, new_text); + swfedit_token_set_iter (SWFEDIT_TOKEN (file), &iter, new_text); } static gboolean diff --git a/test/swfedit_token.c b/test/swfedit_token.c index 005e6c1..06c1aa4 100644 --- a/test/swfedit_token.c +++ b/test/swfedit_token.c @@ -314,12 +314,13 @@ swfedit_script_new (void) static gboolean swfedit_script_from_string (const char *s, gpointer* result) { - SwfdecBuffer *buffer; + gpointer buffer; SwfdecBits bits; SwfdecScript *script; - if (swfedit_binary_from_string (s, (gpointer *) &buffer)) + if (!swfedit_binary_from_string (s, &buffer)) { return FALSE; + } swfdec_bits_init (&bits, buffer); script = swfdec_script_new (&bits, "unknown", 6 /* FIXME */); @@ -703,7 +704,37 @@ swfedit_token_add (SwfeditToken *token, } void -swfedit_token_set (SwfeditToken *token, GtkTreeIter *iter, const char *value) +swfedit_token_set (SwfeditToken *token, guint i, gpointer value) +{ + SwfeditTokenClass *klass; + SwfeditTokenEntry *entry; + GtkTreePath *path; + SwfeditToken *model; + GtkTreeIter iter; + + g_return_if_fail (SWFEDIT_IS_TOKEN (token)); + g_return_if_fail (i < token->tokens->len); + + entry = &g_array_index (token->tokens, SwfeditTokenEntry, i); + if (converters[entry->type].free != NULL) + converters[entry->type].free (entry->value); + entry->value = value; + klass = SWFEDIT_TOKEN_GET_CLASS (token); + if (klass->changed) + klass->changed (token, i); + + model = token; + while (model->parent) + model = model->parent; + iter.user_data = token; + iter.user_data2 = GUINT_TO_POINTER (i); + path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); + gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter); + gtk_tree_path_free (path); +} + +void +swfedit_token_set_iter (SwfeditToken *token, GtkTreeIter *iter, const char *value) { SwfeditTokenClass *klass; GtkTreeModel *model; diff --git a/test/swfedit_token.h b/test/swfedit_token.h index c9e522f..448f4cb 100644 --- a/test/swfedit_token.h +++ b/test/swfedit_token.h @@ -94,6 +94,9 @@ void swfedit_token_add (SwfeditToken * SwfeditTokenType type, gpointer value); void swfedit_token_set (SwfeditToken * token, + guint i, + gpointer value); +void swfedit_token_set_iter (SwfeditToken * token, GtkTreeIter * iter, const char * value); void swfedit_token_set_visible (SwfeditToken * token, diff-tree e067398923300c8505c62abd3f0e7c020e9cbe9b (from cd8d70bf421ec13b317a7f7e682c4fb5d13f2663) Author: Benjamin Otte <otte@gnome.org> Date: Wed Feb 14 15:25:06 2007 +0100 Add swfdec_out_put_data diff --git a/test/swfdec_out.c b/test/swfdec_out.c index b17cedb..ecf5a83 100644 --- a/test/swfdec_out.c +++ b/test/swfdec_out.c @@ -112,6 +112,16 @@ swfdec_out_prepare_bytes (SwfdecOut *out } void +swfdec_out_put_data (SwfdecOut *out, const guint8 *data, guint length) +{ + g_return_if_fail (out != NULL); + + swfdec_out_prepare_bytes (out, length); + memcpy (out->ptr, data, length); + out->ptr += length; +} + +void swfdec_out_put_buffer (SwfdecOut *out, SwfdecBuffer *buffer) { g_return_if_fail (out != NULL); diff --git a/test/swfdec_out.h b/test/swfdec_out.h index 3a22f36..e343f9d 100644 --- a/test/swfdec_out.h +++ b/test/swfdec_out.h @@ -57,6 +57,9 @@ void swfdec_out_put_bits (SwfdecOut * void swfdec_out_put_sbits (SwfdecOut * out, int bits, guint n_bits); +void swfdec_out_put_data (SwfdecOut * out, + const guint8 * data, + guint length); void swfdec_out_put_buffer (SwfdecOut * out, SwfdecBuffer * buffer); void swfdec_out_put_u8 (SwfdecOut * out, diff-tree cd8d70bf421ec13b317a7f7e682c4fb5d13f2663 (from 634736d7d5ba5b7e3ef43893278b95fac05a3cb2) Author: Benjamin Otte <otte@gnome.org> Date: Wed Feb 14 15:24:37 2007 +0100 add swfdec_action_get_name and swfdec_action_get_from_name Two functions to be used by utilities that do a action code <=> string mapping diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index bf0fb07..14feaa1 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -2415,3 +2415,28 @@ swfdec_script_execute (SwfdecScript *scr return ok ? frame.rval : JSVAL_VOID; } +/*** UTILITY FUNCTIONS ***/ + +const char * +swfdec_action_get_name (guint action) +{ + g_return_val_if_fail (action < 256, NULL); + + return actions[action].name; +} + +guint +swfdec_action_get_from_name (const char *name) +{ + guint i; + + g_return_val_if_fail (name != NULL, 0); + + for (i = 0; i < 256; i++) { + if (actions[i].name && g_str_equal (name, actions[i].name)) + return i; + } + return 0; +} + + diff --git a/libswfdec/swfdec_script.h b/libswfdec/swfdec_script.h index e202aa0..93f59b9 100644 --- a/libswfdec/swfdec_script.h +++ b/libswfdec/swfdec_script.h @@ -43,6 +43,9 @@ struct _SwfdecScript { SwfdecBuffer * constant_pool; /* constant pool action */ }; +const char * swfdec_action_get_name (guint action); +guint swfdec_action_get_from_name (const char * name); + SwfdecScript * swfdec_script_new (SwfdecBits * bits, const char * name, unsigned int version);
Maybe Matching Threads
- 12 commits - configure.ac doc/swfdec.types Makefile.am test/crashfinder.c test/dump.c test/Makefile.am test/swfdec-extract.c test/swfdec_out.c test/swfdec_out.h test/swfedit.c test/swfedit_file.c test/swfedit_file.h test/swfedit_list.c test/swfedit_list.h
- 9 commits - libswfdec/js libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_codec_screen.c libswfdec/swfdec_image.c libswfdec/swfdec_script.c test/Makefile.am test/swfdec_out.c test/swfdec_out.h test/swfedit.c test/swfedit_file.c
- Branch 'interpreter' - 8 commits - libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_js.c libswfdec/swfdec_js.h libswfdec/swfdec_script.c test/swfdec_out.c test/swfdec_out.h test/swfedit_tag.c test/swfedit_token.c test/swfedit_token.h
- Branch 'interpreter' - 28 commits - configure.ac libswfdec/js libswfdec/swfdec_buffer.c libswfdec/swfdec_edittext_movie.c libswfdec/swfdec_js.c libswfdec/swfdec_js_global.c libswfdec/swfdec_js.h libswfdec/swfdec_js_movie.c libswfdec/swfdec_player.c
- 109 commits - configure.ac libswfdec/js libswfdec/Makefile.am libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_buffer.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_codec_screen.c libswfdec/swfdec_color.c libswfdec/swfdec_color.h