Benjamin Otte
2007-Jan-25 14:31 UTC
[Swfdec] 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 libswfdec/swfdec_player_internal.h libswfdec/swfdec_script.c libswfdec/swfdec_swf_decoder.c test/.gitignore test/Makefile.am test/swfdec_out.c test/swfdec_out.h test/swfedit.c test/swfedit_file.c test/swfedit_file.h test/swfedit_tag.c test/swfedit_tag.h test/swfedit_token.c test/swfedit_token.h
configure.ac | 2 libswfdec/js/jsatom.c | 6 libswfdec/js/jsatom.h | 1 libswfdec/swfdec_buffer.c | 7 libswfdec/swfdec_edittext_movie.c | 4 libswfdec/swfdec_js.c | 39 +- libswfdec/swfdec_js.h | 3 libswfdec/swfdec_js_global.c | 5 libswfdec/swfdec_js_movie.c | 1 libswfdec/swfdec_player.c | 10 libswfdec/swfdec_player_internal.h | 2 libswfdec/swfdec_script.c | 538 +++++++++++++++++++++++++++++++++++-- libswfdec/swfdec_swf_decoder.c | 2 test/.gitignore | 1 test/Makefile.am | 2 test/swfdec_out.c | 236 ++++++++++++++++ test/swfdec_out.h | 73 +++++ test/swfedit.c | 58 +++ test/swfedit_file.c | 114 ++++++- test/swfedit_file.h | 6 test/swfedit_tag.c | 132 +++++++++ test/swfedit_tag.h | 16 - test/swfedit_token.c | 151 ++++++---- test/swfedit_token.h | 11 24 files changed, 1275 insertions(+), 145 deletions(-) New commits: diff-tree 4d09855e83ee699d590e8916e4af318ab79cc99b (from 82e3f5645e07b82da355444ae96ccbb6eba637dd) Author: Benjamin Otte <otte@gnome.org> Date: Wed Jan 24 15:14:12 2007 +0100 implement saving diff --git a/test/Makefile.am b/test/Makefile.am index d168cfd..33a647c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -19,12 +19,14 @@ swfedit_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_ swfedit_LDFLAGS = $(SWF_LIBS) $(GTK_LIBS) swfedit_SOURCES = \ + swfdec_out.c \ swfedit.c \ swfedit_file.c \ swfedit_tag.c \ swfedit_token.c noinst_HEADERS = \ + swfdec_out.h \ swfedit_file.h \ swfedit_tag.h \ swfedit_token.h diff --git a/test/swfdec_out.c b/test/swfdec_out.c new file mode 100644 index 0000000..70dcc7c --- /dev/null +++ b/test/swfdec_out.c @@ -0,0 +1,236 @@ +/* Swfdec + * 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 <string.h> + +#include "swfdec_out.h" + +SwfdecOut * +swfdec_out_open (void) +{ + SwfdecOut *out = g_new0 (SwfdecOut, 1); + + out->data = g_malloc (SWFDEC_OUT_INITIAL); + out->ptr = out->data; + out->end = out->data + SWFDEC_OUT_INITIAL; + + return out; +} + +static void +swfdec_out_syncbits (SwfdecOut *out) +{ + g_return_if_fail (out != NULL); + + if (out->idx > 0) { + out->ptr++; + out->idx = 0; + } +} + +SwfdecBuffer * +swfdec_out_close (SwfdecOut *out) +{ + SwfdecBuffer *buffer; + + g_return_val_if_fail (out != NULL, NULL); + + swfdec_out_syncbits (out); + + buffer = swfdec_buffer_new (); + buffer->data = out->data; + buffer->length = out->ptr - out->data; + + g_free (out); + + return buffer; +} + +unsigned int +swfdec_out_left (SwfdecOut *out) +{ + g_return_val_if_fail (out != NULL, 0); + + return (out->end - out->ptr) * 8 - out->idx; +} + +void +swfdec_out_ensure_bits (SwfdecOut *out, unsigned int bits) +{ + unsigned int current, taken, needed; + + g_return_if_fail (out != NULL); + + current = swfdec_out_left (out); + if (current >= bits) + return; + taken = out->ptr - out->data; + needed = (bits - current + 7) / 8; + needed += SWFDEC_OUT_STEP; + needed -= needed % SWFDEC_OUT_STEP; + needed += out->end - out->data; + out->data = g_realloc (out->data, needed); + out->ptr = out->data + taken; + out->end = out->data + needed; +} + +void +swfdec_out_prepare_bytes (SwfdecOut *out, unsigned int bytes) +{ + g_return_if_fail (out != NULL); + + swfdec_out_syncbits (out); + swfdec_out_ensure_bits (out, bytes * 8); +} + +void +swfdec_out_put_buffer (SwfdecOut *out, SwfdecBuffer *buffer) +{ + g_return_if_fail (out != NULL); + + swfdec_out_prepare_bytes (out, buffer->length); + memcpy (out->ptr, buffer->data, buffer->length); + out->ptr += buffer->length; +} + +void +swfdec_out_put_u8 (SwfdecOut *out, guint i) +{ + g_return_if_fail (i <= G_MAXUINT8); + + swfdec_out_prepare_bytes (out, 1); + *out->ptr = i; + out->ptr++; +} + +void +swfdec_out_put_u16 (SwfdecOut *out, guint i) +{ + g_return_if_fail (i <= G_MAXUINT16); + + swfdec_out_prepare_bytes (out, 2); + *(guint16 *)out->ptr = GUINT16_TO_LE (i); + out->ptr += 2; +} + +void +swfdec_out_put_u32 (SwfdecOut *out, guint i) +{ + g_return_if_fail (i <= G_MAXUINT32); + + swfdec_out_prepare_bytes (out, 4); + *(guint32 *)out->ptr = GUINT32_TO_LE (i); + out->ptr += 4; +} + +void +swfdec_out_put_bit (SwfdecOut *out, gboolean bit) +{ + g_return_if_fail (out != NULL); + + swfdec_out_put_bits (out, bit ? 1 : 0, 1); +} + +void +swfdec_out_put_bits (SwfdecOut *out, guint bits, guint n_bits) +{ + g_return_if_fail (out != NULL); + + swfdec_out_ensure_bits (out, n_bits); + + /* FIXME: implement this less braindead */ + while (n_bits) { + guint bits_now = MIN (n_bits, 8 - out->idx); + guint value = bits >> (n_bits - bits_now); + + /* clear data if necessary */ + if (out->idx == 0) + *out->ptr = 0; + value &= (1 << bits_now) - 1; + value <<= 8 - out->idx - bits_now; + g_print ("putting %02X in the next %u bits\n", value, bits_now); + *out->ptr |= value; + out->idx += bits_now; + g_assert (out->idx <= 8); + if (out->idx == 8) { + out->ptr ++; + out->idx = 0; + } + n_bits -= bits_now; + } +} + +void +swfdec_out_put_sbits (SwfdecOut *out, int bits, guint n_bits) +{ + g_return_if_fail (out != NULL); + swfdec_out_put_bits (out, bits, n_bits); +} + +static guint +swfdec_out_bits_required (guint x) +{ + guint ret = 0; + + while (x > 0) { + x >>= 1; + ret++; + } + return ret; +} + +static guint +swfdec_out_sbits_required (int x) +{ + if (x < 0) + x = -x; + return swfdec_out_bits_required (x) + 1; +} + +void +swfdec_out_put_rect (SwfdecOut *out, SwfdecRect *rect) +{ + int x0, x1, y0, y1; + guint req, tmp; + + g_return_if_fail (out != NULL); + + x0 = rect->x0; + y0 = rect->y0; + x1 = rect->x1; + y1 = rect->y1; + req = swfdec_out_sbits_required (x0); + tmp = swfdec_out_sbits_required (y0); + req = MAX (req, tmp); + tmp = swfdec_out_sbits_required (x1); + req = MAX (req, tmp); + tmp = swfdec_out_sbits_required (y1); + req = MAX (req, tmp); + swfdec_out_syncbits (out); + swfdec_out_put_bits (out, req, 5); + swfdec_out_put_sbits (out, x0, req); + swfdec_out_put_sbits (out, x1, req); + swfdec_out_put_sbits (out, y0, req); + swfdec_out_put_sbits (out, y1, req); + swfdec_out_syncbits (out); +} diff --git a/test/swfdec_out.h b/test/swfdec_out.h new file mode 100644 index 0000000..b6d155f --- /dev/null +++ b/test/swfdec_out.h @@ -0,0 +1,73 @@ +/* Swfdec + * 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 + */ + +#ifndef __SWFDEC_OUT_H__ +#define __SWFDEC_OUT_H__ + +#include <libswfdec/swfdec_buffer.h> +#include <libswfdec/swfdec_rect.h> + +G_BEGIN_DECLS + + +typedef struct _SwfdecOut SwfdecOut; + +struct _SwfdecOut { + unsigned char * data; + unsigned char * ptr; + unsigned int idx; + unsigned char * end; +}; + +#define SWFDEC_OUT_INITIAL (32) +#define SWFDEC_OUT_STEP (32) + +SwfdecOut * swfdec_out_open (void); +SwfdecBuffer * swfdec_out_close (SwfdecOut * out); + +unsigned int swfdec_out_left (SwfdecOut * out); +void swfdec_out_ensure_bits (SwfdecOut * out, + unsigned int bits); +void swfdec_out_prepare_bytes (SwfdecOut * out, + unsigned int bytes); + +void swfdec_out_put_bit (SwfdecOut * out, + gboolean bit); +void swfdec_out_put_bits (SwfdecOut * out, + guint bits, + guint n_bits); +void swfdec_out_put_sbits (SwfdecOut * out, + int bits, + guint n_bits); +void swfdec_out_put_buffer (SwfdecOut * out, + SwfdecBuffer * buffer); +void swfdec_out_put_u8 (SwfdecOut * out, + guint i); +void swfdec_out_put_u16 (SwfdecOut * out, + guint i); +void swfdec_out_put_u32 (SwfdecOut * out, + guint i); + +void swfdec_out_put_rect (SwfdecOut * out, + SwfdecRect * rect); + + +G_END_DECLS + +#endif diff --git a/test/swfedit.c b/test/swfedit.c index e16d645..258f25e 100644 --- a/test/swfedit.c +++ b/test/swfedit.c @@ -27,12 +27,26 @@ static void save (GtkButton *button, SwfeditFile *file) { + GtkWidget *dialog; GError *error = NULL; - if (!swfedit_file_save (file, &error)) { - g_printerr ("Error saving fils: %s\n", error->message); - g_error_free (error); + dialog = gtk_file_chooser_dialog_new ("Save file...", + GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_OK, + NULL); + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); + gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), file->filename); + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { + g_free (file->filename); + file->filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + if (!swfedit_file_save (file, &error)) { + g_printerr ("Error saving file: %s\n", error->message); + g_error_free (error); + } } + gtk_widget_destroy (dialog); } static void diff --git a/test/swfedit_file.c b/test/swfedit_file.c index d660655..dd5e035 100644 --- a/test/swfedit_file.c +++ b/test/swfedit_file.c @@ -27,6 +27,7 @@ #include "libswfdec/swfdec_buffer.h" #include "libswfdec/swfdec_debug.h" #include "libswfdec/swfdec_swf_decoder.h" +#include "swfdec_out.h" #include "swfedit_file.h" #include "swfedit_tag.h" @@ -103,7 +104,7 @@ swf_parse_header1 (SwfeditFile *file, Sw swfedit_token_add (SWFEDIT_TOKEN (file), "version", SWFEDIT_TOKEN_UINT8, GUINT_TO_POINTER (swfdec_bits_get_u8 (bits))); - bytes_total = swfdec_bits_get_u32 (bits); + bytes_total = swfdec_bits_get_u32 (bits) - 8; if (sig1 == 'C') { /* compressed */ @@ -113,7 +114,7 @@ swf_parse_header1 (SwfeditFile *file, Sw "Unable to uncompress file"); return ret; } else { - SwfdecBuffer *ret = swfdec_bits_get_buffer (bits, -1); + SwfdecBuffer *ret = swfdec_bits_get_buffer (bits, bytes_total); if (ret == NULL) g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "File too small"); @@ -124,14 +125,9 @@ swf_parse_header1 (SwfeditFile *file, Sw static void swf_parse_header2 (SwfeditFile *file, SwfdecBits *bits) { - SwfdecRect rect; - - swfdec_bits_get_rect (bits, &rect); - swfdec_bits_syncbits (bits); - swfedit_token_add (SWFEDIT_TOKEN (file), "rate", SWFEDIT_TOKEN_UINT16, - GUINT_TO_POINTER (swfdec_bits_get_u16 (bits))); - swfedit_token_add (SWFEDIT_TOKEN (file), "frames", SWFEDIT_TOKEN_UINT16, - GUINT_TO_POINTER (swfdec_bits_get_u16 (bits))); + swfedit_tag_read_token (SWFEDIT_TOKEN (file), bits, "rect", SWFEDIT_TOKEN_RECT); + swfedit_tag_read_token (SWFEDIT_TOKEN (file), bits, "rate", SWFEDIT_TOKEN_UINT16); + swfedit_tag_read_token (SWFEDIT_TOKEN (file), bits, "frames", SWFEDIT_TOKEN_UINT16); } static gboolean @@ -193,13 +189,21 @@ swfedit_file_new (const char *filename, SwfeditFile *file; SwfdecBuffer *buffer; SwfdecBits bits; + char *absolute; + if (g_path_is_absolute (filename)) { + absolute = g_strdup (filename); + } else { + char *dir = g_get_current_dir (); + absolute = g_build_filename (dir, filename, NULL); + g_free (dir); + } buffer = swfdec_buffer_new_from_file (filename, error); if (buffer == NULL) return NULL; swfdec_bits_init (&bits, buffer); file = g_object_new (SWFEDIT_TYPE_FILE, NULL); - file->filename = g_strdup (filename); + file->filename = absolute; if (!swfedit_file_parse (file, &bits, error)) { swfdec_buffer_unref (buffer); g_object_unref (file); @@ -212,7 +216,53 @@ swfedit_file_new (const char *filename, static SwfdecBuffer * swfedit_file_write (SwfeditFile *file) { - return NULL; + guint i; + SwfeditToken *token = SWFEDIT_TOKEN (file); + SwfdecBufferQueue *queue; + SwfdecBuffer *buffer; + SwfdecOut *out; + + queue = swfdec_buffer_queue_new (); + /* write second part of header */ + out = swfdec_out_open (); + swfedit_tag_write_token (token, out, 1); + swfedit_tag_write_token (token, out, 2); + swfedit_tag_write_token (token, out, 3); + swfdec_buffer_queue_push (queue, swfdec_out_close (out)); + + for (i = 4; i < token->tokens->len; i++) { + SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, i); + g_assert (entry->type == SWFEDIT_TOKEN_OBJECT); + + buffer = swfedit_tag_write (entry->value); + out = swfdec_out_open (); + swfdec_out_put_u16 (out, SWFEDIT_TAG (entry->value)->tag << 6 | + MIN (buffer->length, 0x3f)); + if (buffer->length >= 0x3f) { + swfdec_out_put_u32 (out, buffer->length); + } + swfdec_buffer_queue_push (queue, swfdec_out_close (out)); + swfdec_buffer_queue_push (queue, buffer); + } + /* write closing tag */ + buffer = swfdec_buffer_new_and_alloc0 (2); + swfdec_buffer_queue_push (queue, buffer); + + /* FIXME: implement compression */ + out = swfdec_out_open (); + swfdec_out_put_u8 (out, 'F'); + swfdec_out_put_u8 (out, 'W'); + swfdec_out_put_u8 (out, 'S'); + swfedit_tag_write_token (token, out, 0); + g_print ("length: %u", swfdec_buffer_queue_get_depth (queue)); + swfdec_out_put_u32 (out, swfdec_buffer_queue_get_depth (queue) + 8); + swfdec_out_prepare_bytes (out, swfdec_buffer_queue_get_depth (queue)); + while ((buffer = swfdec_buffer_queue_pull_buffer (queue))) { + swfdec_out_put_buffer (out, buffer); + swfdec_buffer_unref (buffer); + } + swfdec_buffer_queue_free (queue); + return swfdec_out_close (out); } gboolean diff --git a/test/swfedit_tag.c b/test/swfedit_tag.c index 94ac4f9..0a9fb9b 100644 --- a/test/swfedit_tag.c +++ b/test/swfedit_tag.c @@ -23,7 +23,134 @@ #include <stdlib.h> #include <gtk/gtk.h> + +#include <libswfdec/swfdec_bits.h> #include "swfedit_tag.h" +#include "swfdec_out.h" + +/*** LOAD/SAVE ***/ + +static void +swfedit_binary_write (gpointer data, SwfdecOut *out) +{ + swfdec_out_put_buffer (out, data); +} + +static gpointer +swfedit_binary_read (SwfdecBits *bits) +{ + SwfdecBuffer *buffer = swfdec_bits_get_buffer (bits, -1); + if (buffer == NULL) + buffer = swfdec_buffer_new (); + return buffer; +} + +static void +swfedit_u8_write (gpointer data, SwfdecOut *out) +{ + swfdec_out_put_u8 (out, GPOINTER_TO_UINT (data)); +} + +static gpointer +swfedit_u8_read (SwfdecBits *bits) +{ + return GUINT_TO_POINTER (swfdec_bits_get_u8 (bits)); +} + +static void +swfedit_u16_write (gpointer data, SwfdecOut *out) +{ + swfdec_out_put_u16 (out, GPOINTER_TO_UINT (data)); +} + +static gpointer +swfedit_u16_read (SwfdecBits *bits) +{ + return GUINT_TO_POINTER (swfdec_bits_get_u16 (bits)); +} + +static void +swfedit_u32_write (gpointer data, SwfdecOut *out) +{ + swfdec_out_put_u32 (out, GPOINTER_TO_UINT (data)); +} + +static gpointer +swfedit_u32_read (SwfdecBits *bits) +{ + return GUINT_TO_POINTER (swfdec_bits_get_u32 (bits)); +} + +static void +swfedit_rect_write (gpointer data, SwfdecOut *out) +{ + swfdec_out_put_rect (out, data); +} + +static gpointer +swfedit_rect_read (SwfdecBits *bits) +{ + SwfdecRect *rect = g_new (SwfdecRect, 1); + swfdec_bits_get_rect (bits, rect); + return rect; +} + +struct { + void (* write) (gpointer data, SwfdecOut *out); + gpointer (* read) (SwfdecBits *bits); +} operations[SWFEDIT_N_TOKENS] = { + { NULL, NULL }, + { swfedit_binary_write, swfedit_binary_read }, + { swfedit_u8_write, swfedit_u8_read }, + { swfedit_u16_write, swfedit_u16_read }, + { swfedit_u32_write, swfedit_u32_read }, + { swfedit_rect_write, swfedit_rect_read }, +}; + +void +swfedit_tag_write_token (SwfeditToken *token, SwfdecOut *out, guint i) +{ + SwfeditTokenEntry *entry; + + g_return_if_fail (SWFEDIT_IS_TOKEN (token)); + g_return_if_fail (i < token->tokens->len); + + entry = &g_array_index (token->tokens, + SwfeditTokenEntry, i); + g_assert (operations[entry->type].write != NULL); + operations[entry->type].write (entry->value, out); +} + +SwfdecBuffer * +swfedit_tag_write (SwfeditTag *tag) +{ + guint i; + SwfdecOut *out; + + g_return_val_if_fail (SWFEDIT_IS_TAG (tag), NULL); + + out = swfdec_out_open (); + for (i = 0; i < SWFEDIT_TOKEN (tag)->tokens->len; i++) { + swfedit_tag_write_token (SWFEDIT_TOKEN (tag), out, i); + } + return swfdec_out_close (out); +} + +void +swfedit_tag_read_token (SwfeditToken *token, SwfdecBits *bits, + const char *name, SwfeditTokenType type) +{ + gpointer data; + + g_return_if_fail (SWFEDIT_IS_TOKEN (token)); + g_return_if_fail (name != NULL); + + g_assert (operations[type].read != NULL); + data = operations[type].read (bits); + swfedit_token_add (token, name, type, data); +} + +/*** SWFEDIT_TAG ***/ G_DEFINE_TYPE (SwfeditTag, swfedit_tag, SWFEDIT_TYPE_TOKEN) diff --git a/test/swfedit_tag.h b/test/swfedit_tag.h index 07c11f2..46fdb5f 100644 --- a/test/swfedit_tag.h +++ b/test/swfedit_tag.h @@ -21,6 +21,7 @@ #define __SWFEDIT_TAG_H__ #include <libswfdec/swfdec_buffer.h> +#include "swfdec_out.h" #include "swfedit_token.h" G_BEGIN_DECLS @@ -47,10 +48,18 @@ struct _SwfeditTagClass { GType swfedit_tag_get_type (void); -SwfeditTag * swfedit_tag_new (SwfeditToken * parent, - guint tag, - SwfdecBuffer * buffer); - +SwfeditTag * swfedit_tag_new (SwfeditToken * parent, + guint tag, + SwfdecBuffer * buffer); + +SwfdecBuffer * swfedit_tag_write (SwfeditTag * tag); +void swfedit_tag_write_token (SwfeditToken * token, + SwfdecOut * out, + guint i); +void swfedit_tag_read_token (SwfeditToken * token, + SwfdecBits * bits, + const char * name, + SwfeditTokenType type); G_END_DECLS diff --git a/test/swfedit_token.c b/test/swfedit_token.c index f3623fc..b2210fd 100644 --- a/test/swfedit_token.c +++ b/test/swfedit_token.c @@ -125,6 +125,21 @@ swfedit_to_string_unsigned (gconstpointe return g_strdup_printf ("%u", GPOINTER_TO_UINT (value)); } +static gboolean +swfedit_rect_from_string (const char *s, gpointer* result) +{ + return FALSE; +} + +static char * +swfedit_rect_to_string (gconstpointer value) +{ + const SwfdecRect *rect = value; + + return g_strdup_printf ("%d, %d, %d, %d", (int) rect->x0, (int) rect->y0, + (int) rect->x1, (int) rect->y1); +} + struct { gboolean (* from_string) (const char *s, gpointer *); char * (* to_string) (gconstpointer value); @@ -135,6 +150,7 @@ struct { { swfedit_uint8_from_string, swfedit_to_string_unsigned, NULL }, { swfedit_uint16_from_string, swfedit_to_string_unsigned, NULL }, { swfedit_uint32_from_string, swfedit_to_string_unsigned, NULL }, + { swfedit_rect_from_string, swfedit_rect_to_string, g_free }, }; /*** GTK_TREE_MODEL ***/ diff --git a/test/swfedit_token.h b/test/swfedit_token.h index 5235d03..8dec753 100644 --- a/test/swfedit_token.h +++ b/test/swfedit_token.h @@ -31,6 +31,7 @@ typedef enum { SWFEDIT_TOKEN_UINT8, SWFEDIT_TOKEN_UINT16, SWFEDIT_TOKEN_UINT32, + SWFEDIT_TOKEN_RECT, SWFEDIT_N_TOKENS } SwfeditTokenType; diff-tree 82e3f5645e07b82da355444ae96ccbb6eba637dd (from 89df12bea205242dd0554a48a0e7721de67d531b) Author: Benjamin Otte <otte@gnome.org> Date: Wed Jan 24 15:13:58 2007 +0100 add swfedit diff --git a/test/.gitignore b/test/.gitignore index ef52ce4..9280a20 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -11,3 +11,4 @@ Makefile.in dump parse swfdec-extract +swfedit diff-tree 89df12bea205242dd0554a48a0e7721de67d531b (from 91403c6d7fbda752ba3403e676d679afdb2bf1b0) Author: Benjamin Otte <otte@gnome.org> Date: Wed Jan 24 15:11:05 2007 +0100 We need at least gtk-2.8 diff --git a/configure.ac b/configure.ac index eb69535..fbf58c3 100644 --- a/configure.ac +++ b/configure.ac @@ -78,7 +78,7 @@ fi AC_SUBST(PANGO_LIBS) AC_SUBST(PANGO_CFLAGS) -PKG_CHECK_MODULES(GTK, gtk+-2.0, HAVE_GTK=yes, HAVE_GTK=no) +PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.8.0, HAVE_GTK=yes, HAVE_GTK=no) AC_SUBST(GTK_LIBS) AC_SUBST(GTK_CFLAGS) if test "$HAVE_GTK" = "no"; then diff-tree 91403c6d7fbda752ba3403e676d679afdb2bf1b0 (from 800b8b573d0d3553336f8541163a4731888bfbbb) Author: Benjamin Otte <otte@gnome.org> Date: Wed Jan 24 15:10:35 2007 +0100 we don't have the header in the uncompressed buffer diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c index 6539921..0bc1099 100644 --- a/libswfdec/swfdec_swf_decoder.c +++ b/libswfdec/swfdec_swf_decoder.c @@ -143,7 +143,7 @@ swf_inflate_init (SwfdecSwfDecoder * s) ret = inflateInit (z); SWFDEC_DEBUG ("inflateInit returned %d", ret); - s->uncompressed_buffer = swfdec_buffer_new_and_alloc (dec->bytes_total); + s->uncompressed_buffer = swfdec_buffer_new_and_alloc (dec->bytes_total - 8); z->next_out = s->uncompressed_buffer->data; z->avail_out = s->uncompressed_buffer->length; z->opaque = NULL; diff-tree 800b8b573d0d3553336f8541163a4731888bfbbb (from b32e8c5b76f4dfde34c72057feb9d9970bea2e7a) Author: Benjamin Otte <otte@gnome.org> Date: Wed Jan 24 15:10:04 2007 +0100 ignore 0-length buffers in bufferqueue diff --git a/libswfdec/swfdec_buffer.c b/libswfdec/swfdec_buffer.c index 3e9af24..c4ac67e 100644 --- a/libswfdec/swfdec_buffer.c +++ b/libswfdec/swfdec_buffer.c @@ -177,6 +177,13 @@ swfdec_buffer_queue_free (SwfdecBufferQu void swfdec_buffer_queue_push (SwfdecBufferQueue * queue, SwfdecBuffer * buffer) { + g_return_if_fail (queue != NULL); + g_return_if_fail (buffer != NULL); + + if (buffer->length == 0) { + swfdec_buffer_unref (buffer); + return; + } queue->buffers = g_list_append (queue->buffers, buffer); queue->depth += buffer->length; } diff-tree b32e8c5b76f4dfde34c72057feb9d9970bea2e7a (from 3d7f4a9fd93c17adc999370d40eff49d1983f126) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 23 15:16:17 2007 +0100 export the entry format and rename it to SwfeditTokenEntry diff --git a/test/swfedit_token.c b/test/swfedit_token.c index bb1e76b..f3623fc 100644 --- a/test/swfedit_token.c +++ b/test/swfedit_token.c @@ -137,14 +137,6 @@ struct { { swfedit_uint32_from_string, swfedit_to_string_unsigned, NULL }, }; -/*** STRUCTS ***/ - -typedef struct { - char * name; - SwfeditTokenType type; - gpointer value; -} Entry; - /*** GTK_TREE_MODEL ***/ #if 0 @@ -191,12 +183,12 @@ swfedit_token_get_iter (GtkTreeModel *tr { SwfeditToken *token = SWFEDIT_TOKEN (tree_model); guint i = gtk_tree_path_get_indices (path)[0]; - Entry *entry; + SwfeditTokenEntry *entry; REPORT; if (i > token->tokens->len) return FALSE; - entry = &g_array_index (token->tokens, Entry, i); + entry = &g_array_index (token->tokens, SwfeditTokenEntry, i); if (gtk_tree_path_get_depth (path) > 1) { GtkTreePath *new; int j; @@ -232,7 +224,7 @@ swfedit_token_get_path (GtkTreeModel *tr guint i; SwfeditToken *parent = token->parent; for (i = 0; i < parent->tokens->len; i++) { - Entry *entry = &g_array_index (parent->tokens, Entry, i); + SwfeditTokenEntry *entry = &g_array_index (parent->tokens, SwfeditTokenEntry, i); if (entry->type != SWFEDIT_TOKEN_OBJECT) continue; if (entry->value == token) @@ -249,7 +241,7 @@ swfedit_token_get_value (GtkTreeModel *t gint column, GValue *value) { SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data); - Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2)); + SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2)); REPORT; switch (column) { @@ -289,12 +281,12 @@ static gboolean swfedit_token_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) { SwfeditToken *token; - Entry *entry; + SwfeditTokenEntry *entry; REPORT; if (parent) { token = SWFEDIT_TOKEN (parent->user_data); - entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2)); + entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (parent->user_data2)); if (entry->type != SWFEDIT_TOKEN_OBJECT) return FALSE; token = entry->value; @@ -311,7 +303,7 @@ static gboolean swfedit_token_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter) { SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data); - Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2)); + SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2)); REPORT; return entry->type == SWFEDIT_TOKEN_OBJECT; @@ -321,7 +313,7 @@ static gint swfedit_token_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter) { SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data); - Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2)); + SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2)); REPORT; if (entry->type != SWFEDIT_TOKEN_OBJECT) @@ -336,12 +328,12 @@ swfedit_token_iter_nth_child (GtkTreeMod GtkTreeIter *parent, gint n) { SwfeditToken *token; - Entry *entry; + SwfeditTokenEntry *entry; REPORT; if (parent) { token = SWFEDIT_TOKEN (parent->user_data); - entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2)); + entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (parent->user_data2)); if (entry->type != SWFEDIT_TOKEN_OBJECT) return FALSE; @@ -370,7 +362,7 @@ swfedit_token_iter_parent (GtkTreeModel return FALSE; for (i = 0; i < parent->tokens->len; i++) { - Entry *entry = &g_array_index (parent->tokens, Entry, i); + SwfeditTokenEntry *entry = &g_array_index (parent->tokens, SwfeditTokenEntry, i); if (entry->type != SWFEDIT_TOKEN_OBJECT) continue; if (entry->value == token) @@ -411,7 +403,7 @@ swfedit_token_dispose (GObject *object) guint i; for (i = 0; i < token->tokens->len; i++) { - Entry *entry = &g_array_index (token->tokens, Entry, i); + SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, i); g_free (entry->name); if (converters[entry->type].free) converters[entry->type].free (entry->value); @@ -432,7 +424,7 @@ swfedit_token_class_init (SwfeditTokenCl static void swfedit_token_init (SwfeditToken *token) { - token->tokens = g_array_new (FALSE, FALSE, sizeof (Entry)); + token->tokens = g_array_new (FALSE, FALSE, sizeof (SwfeditTokenEntry)); } SwfeditToken * @@ -447,7 +439,7 @@ swfedit_token_new (void) void swfedit_token_add (SwfeditToken *token, const char *name, SwfeditTokenType type, gpointer value) { - Entry entry = { NULL, type, value }; + SwfeditTokenEntry entry = { NULL, type, value }; g_return_if_fail (SWFEDIT_IS_TOKEN (token)); g_return_if_fail (name != NULL); @@ -461,7 +453,7 @@ void swfedit_token_set (SwfeditToken *token, GtkTreeIter *iter, const char *value) { GtkTreeModel *model; - Entry *entry; + SwfeditTokenEntry *entry; guint i; gpointer new; GtkTreePath *path; @@ -473,7 +465,7 @@ swfedit_token_set (SwfeditToken *token, model = GTK_TREE_MODEL (token); token = iter->user_data; i = GPOINTER_TO_UINT (iter->user_data2); - entry = &g_array_index (token->tokens, Entry, i); + entry = &g_array_index (token->tokens, SwfeditTokenEntry, i); if (converters[entry->type].from_string == NULL) return; if (!converters[entry->type].from_string (value, &new)) diff --git a/test/swfedit_token.h b/test/swfedit_token.h index 1640027..5235d03 100644 --- a/test/swfedit_token.h +++ b/test/swfedit_token.h @@ -40,6 +40,8 @@ typedef enum { SWFEDIT_COLUMN_VALUE } SwfeditColumn; +typedef struct _SwfeditTokenEntry SwfeditTokenEntry; + typedef struct _SwfeditToken SwfeditToken; typedef struct _SwfeditTokenClass SwfeditTokenClass; @@ -50,12 +52,18 @@ typedef struct _SwfeditTokenClass Swfedi #define SWFEDIT_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFEDIT_TYPE_TOKEN, SwfeditTokenClass)) #define SWFEDIT_TOKEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFEDIT_TYPE_TOKEN, SwfeditTokenClass)) +struct _SwfeditTokenEntry { + char * name; + SwfeditTokenType type; + gpointer value; +}; + struct _SwfeditToken { GObject object; SwfeditToken * parent; /* parent of this token or NULL */ gchar * name; /* name of token */ - GArray * tokens; /* list of tokens */ + GArray * tokens; /* of SwfeditTokenEntry */ }; struct _SwfeditTokenClass { diff-tree 3d7f4a9fd93c17adc999370d40eff49d1983f126 (from 705e9e78e30cdb063445873c670cdbdfb918d07e) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 23 14:41:40 2007 +0100 add stubs for saving diff --git a/test/swfedit.c b/test/swfedit.c index 5dd2535..e16d645 100644 --- a/test/swfedit.c +++ b/test/swfedit.c @@ -25,6 +25,17 @@ #include "swfedit_file.h" static void +save (GtkButton *button, SwfeditFile *file) +{ + GError *error = NULL; + + if (!swfedit_file_save (file, &error)) { + g_printerr ("Error saving fils: %s\n", error->message); + g_error_free (error); + } +} + +static void cell_renderer_edited (GtkCellRenderer *renderer, char *path, char *new_text, SwfeditFile *file) { @@ -41,26 +52,29 @@ static gboolean open_window (char *filename) { SwfeditFile *file; - GtkWidget *window, *scroll, *treeview; + GtkWidget *window, *scroll, *box, *button, *treeview; GError *error = NULL; GtkTreeViewColumn *column; GtkCellRenderer *renderer; file = swfedit_file_new (filename, &error); if (file == NULL) { - g_printerr ("Error openeing file %s: %s\n", filename, error->message); + g_printerr ("Error opening file %s: %s\n", filename, error->message); g_error_free (error); return FALSE; } window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), filename); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + box = gtk_vbox_new (FALSE, 3); + gtk_container_add (GTK_CONTAINER (window), box); + scroll = gtk_scrolled_window_new (NULL, NULL); - gtk_container_add (GTK_CONTAINER (window), scroll); + gtk_box_pack_start (GTK_BOX (box), scroll, TRUE, TRUE, 0); treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (file)); gtk_container_add (GTK_CONTAINER (scroll), treeview); - gtk_widget_show_all (window); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Name", renderer, @@ -76,6 +90,11 @@ open_window (char *filename) gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); + button = gtk_button_new_from_stock (GTK_STOCK_SAVE); + g_signal_connect (button, "clicked", G_CALLBACK (save), file); + gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0); + + gtk_widget_show_all (window); return TRUE; } diff --git a/test/swfedit_file.c b/test/swfedit_file.c index 7f2f240..d660655 100644 --- a/test/swfedit_file.c +++ b/test/swfedit_file.c @@ -37,8 +37,6 @@ swfedit_file_dispose (GObject *object) { SwfeditFile *file = SWFEDIT_FILE (object); - g_list_foreach (file->tags, (GFunc) g_object_unref, NULL); - g_list_free (file->tags); g_free (file->filename); G_OBJECT_CLASS (swfedit_file_parent_class)->dispose (object); @@ -210,3 +208,30 @@ swfedit_file_new (const char *filename, swfdec_buffer_unref (buffer); return file; } + +static SwfdecBuffer * +swfedit_file_write (SwfeditFile *file) +{ + return NULL; +} + +gboolean +swfedit_file_save (SwfeditFile *file, GError **error) +{ + SwfdecBuffer *buffer; + gboolean ret; + + g_return_val_if_fail (SWFEDIT_IS_FILE (file), FALSE); + + buffer = swfedit_file_write (file); + if (buffer == NULL) { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, + "Failed to render file"); + return FALSE; + } + ret = g_file_set_contents (file->filename, (char *) buffer->data, + buffer->length, error); + swfdec_buffer_unref (buffer); + return ret; +} + diff --git a/test/swfedit_file.h b/test/swfedit_file.h index 39a89c5..e904950 100644 --- a/test/swfedit_file.h +++ b/test/swfedit_file.h @@ -39,9 +39,6 @@ struct _SwfeditFile { SwfeditToken token; char * filename; /* name this file is saved to */ - - /* defined objects */ - GList * tags; /* ordered list of all tags in the file */ }; struct _SwfeditFileClass { @@ -53,6 +50,9 @@ GType swfedit_file_get_type (void); SwfeditFile * swfedit_file_new (const char * filename, GError ** error); +gboolean swfedit_file_save (SwfeditFile * file, + GError ** error); + G_END_DECLS diff-tree 705e9e78e30cdb063445873c670cdbdfb918d07e (from ce02af774584cc4bb00655d77b6e7e350b77402c) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 23 14:41:24 2007 +0100 change read/write to from_string/to_string diff --git a/test/swfedit_token.c b/test/swfedit_token.c index 2819b52..bb1e76b 100644 --- a/test/swfedit_token.c +++ b/test/swfedit_token.c @@ -12,7 +12,7 @@ * 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 + * License along with this library; if not, to_string to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -29,7 +29,7 @@ /*** CONVERTERS ***/ static gboolean -swfedit_binary_read (const char *s, gpointer* result) +swfedit_binary_from_string (const char *s, gpointer* result) { GByteArray *array = g_byte_array_new (); guint8 byte; @@ -71,7 +71,7 @@ swfedit_binary_read (const char *s, gpoi } static char * -swfedit_binary_write (gconstpointer value) +swfedit_binary_to_string (gconstpointer value) { guint i; const SwfdecBuffer *buffer = value; @@ -86,7 +86,7 @@ swfedit_binary_write (gconstpointer valu } static gboolean -swfedit_read_unsigned (const char *s, gulong max, gpointer* result) +swfedit_from_string_unsigned (const char *s, gulong max, gpointer* result) { char *end; gulong u; @@ -102,39 +102,39 @@ swfedit_read_unsigned (const char *s, gu } static gboolean -swfedit_uint8_read (const char *s, gpointer* result) +swfedit_uint8_from_string (const char *s, gpointer* result) { - return swfedit_read_unsigned (s, G_MAXUINT8, result); + return swfedit_from_string_unsigned (s, G_MAXUINT8, result); } static gboolean -swfedit_uint16_read (const char *s, gpointer* result) +swfedit_uint16_from_string (const char *s, gpointer* result) { - return swfedit_read_unsigned (s, G_MAXUINT16, result); + return swfedit_from_string_unsigned (s, G_MAXUINT16, result); } static gboolean -swfedit_uint32_read (const char *s, gpointer* result) +swfedit_uint32_from_string (const char *s, gpointer* result) { - return swfedit_read_unsigned (s, G_MAXUINT32, result); + return swfedit_from_string_unsigned (s, G_MAXUINT32, result); } static char * -swfedit_write_unsigned (gconstpointer value) +swfedit_to_string_unsigned (gconstpointer value) { return g_strdup_printf ("%u", GPOINTER_TO_UINT (value)); } struct { - gboolean (* read) (const char *s, gpointer *); - char * (* write) (gconstpointer value); + gboolean (* from_string) (const char *s, gpointer *); + char * (* to_string) (gconstpointer value); void (* free) (gpointer value); } converters[SWFEDIT_N_TOKENS] = { { NULL, NULL, g_object_unref }, - { swfedit_binary_read, swfedit_binary_write, (GDestroyNotify) swfdec_buffer_unref }, - { swfedit_uint8_read, swfedit_write_unsigned, NULL }, - { swfedit_uint16_read, swfedit_write_unsigned, NULL }, - { swfedit_uint32_read, swfedit_write_unsigned, NULL }, + { swfedit_binary_from_string, swfedit_binary_to_string, (GDestroyNotify) swfdec_buffer_unref }, + { swfedit_uint8_from_string, swfedit_to_string_unsigned, NULL }, + { swfedit_uint16_from_string, swfedit_to_string_unsigned, NULL }, + { swfedit_uint32_from_string, swfedit_to_string_unsigned, NULL }, }; /*** STRUCTS ***/ @@ -259,12 +259,12 @@ swfedit_token_get_value (GtkTreeModel *t return; case SWFEDIT_COLUMN_VALUE_VISIBLE: g_value_init (value, G_TYPE_BOOLEAN); - g_value_set_boolean (value, converters[entry->type].write != NULL); + g_value_set_boolean (value, converters[entry->type].to_string != NULL); return; case SWFEDIT_COLUMN_VALUE: g_value_init (value, G_TYPE_STRING); - if (converters[entry->type].write) - g_value_take_string (value, converters[entry->type].write (entry->value)); + if (converters[entry->type].to_string) + g_value_take_string (value, converters[entry->type].to_string (entry->value)); return; default: break; @@ -474,9 +474,9 @@ swfedit_token_set (SwfeditToken *token, token = iter->user_data; i = GPOINTER_TO_UINT (iter->user_data2); entry = &g_array_index (token->tokens, Entry, i); - if (converters[entry->type].read == NULL) + if (converters[entry->type].from_string == NULL) return; - if (!converters[entry->type].read (value, &new)) + if (!converters[entry->type].from_string (value, &new)) return; if (converters[entry->type].free != NULL) converters[entry->type].free (entry->value); diff-tree ce02af774584cc4bb00655d77b6e7e350b77402c (from b5b36b679993d6c5576dc83f4deacd80fe2e5ce3) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 23 10:05:46 2007 +0100 enable editing of properties diff --git a/test/swfedit.c b/test/swfedit.c index 71a86aa..5dd2535 100644 --- a/test/swfedit.c +++ b/test/swfedit.c @@ -24,6 +24,19 @@ #include <gtk/gtk.h> #include "swfedit_file.h" +static void +cell_renderer_edited (GtkCellRenderer *renderer, char *path, + char *new_text, SwfeditFile *file) +{ + GtkTreeIter iter; + + if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (file), + &iter, path)) { + g_assert_not_reached (); + } + swfedit_token_set (SWFEDIT_TOKEN (file), &iter, new_text); +} + static gboolean open_window (char *filename) { @@ -57,6 +70,7 @@ open_window (char *filename) renderer = gtk_cell_renderer_text_new (); g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL); + g_signal_connect (renderer, "edited", G_CALLBACK (cell_renderer_edited), file); column = gtk_tree_view_column_new_with_attributes ("Value", renderer, "text", SWFEDIT_COLUMN_VALUE, "visible", SWFEDIT_COLUMN_VALUE_VISIBLE, NULL); gtk_tree_view_column_set_resizable (column, TRUE); diff-tree b5b36b679993d6c5576dc83f4deacd80fe2e5ce3 (from d6679238c4929bf1d9cbb997b1ba9987c018e01e) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 23 10:05:35 2007 +0100 make parsing binary data work diff --git a/test/swfedit_token.c b/test/swfedit_token.c index 4e027eb..2819b52 100644 --- a/test/swfedit_token.c +++ b/test/swfedit_token.c @@ -45,13 +45,13 @@ swfedit_binary_read (const char *s, gpoi else break; s++; - byte *= 255; + byte *= 16; if (s[0] >= '0' && s[0] <= '9') - byte = s[0] - '0'; + byte += s[0] - '0'; else if (s[0] >= 'a' && s[0] <= 'f') - byte = s[0] + 10 - 'a'; + byte += s[0] + 10 - 'a'; else if (s[0] >= 'A' && s[0] <= 'F') - byte = s[0] + 10 - 'A'; + byte += s[0] + 10 - 'A'; else break; s++; diff-tree d6679238c4929bf1d9cbb997b1ba9987c018e01e (from 1af4da9dd02f8d5cd65b06bf25c6ac013bc26450) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 23 10:04:05 2007 +0100 ensure _get_nth_child works with token == NULL I hate it that you need -O2 to catch uninitialized variables diff --git a/test/swfedit_token.c b/test/swfedit_token.c index 704b98b..4e027eb 100644 --- a/test/swfedit_token.c +++ b/test/swfedit_token.c @@ -347,9 +347,11 @@ swfedit_token_iter_nth_child (GtkTreeMod return FALSE; token = entry->value; - if ((guint) n >= token->tokens->len) - return FALSE; + } else { + token = SWFEDIT_TOKEN (tree_model); } + if ((guint) n >= token->tokens->len) + return FALSE; iter->stamp = 0; /* FIXME */ iter->user_data = token; iter->user_data2 = GINT_TO_POINTER (n); diff-tree 1af4da9dd02f8d5cd65b06bf25c6ac013bc26450 (from 97ce107c67c3bcbd363eaf12e3669ca8226e4143) Author: Benjamin Otte <otte@gnome.org> Date: Mon Jan 22 22:05:34 2007 +0100 print the actual tag name diff --git a/test/swfedit_file.c b/test/swfedit_file.c index 2ae8fa2..7f2f240 100644 --- a/test/swfedit_file.c +++ b/test/swfedit_file.c @@ -26,6 +26,7 @@ #include "libswfdec/swfdec_bits.h" #include "libswfdec/swfdec_buffer.h" #include "libswfdec/swfdec_debug.h" +#include "libswfdec/swfdec_swf_decoder.h" #include "swfedit_file.h" #include "swfedit_tag.h" @@ -152,7 +153,7 @@ swfedit_file_parse (SwfeditFile *file, S guint tag_len = x & 0x3f; SwfdecBuffer *buffer; SwfeditTag *item; - char *name; + if (tag_len == 0x3f) tag_len = swfdec_bits_get_u32 (bits); if (tag == 0) @@ -167,9 +168,9 @@ swfedit_file_parse (SwfeditFile *file, S return FALSE; } item = swfedit_tag_new (SWFEDIT_TOKEN (file), tag, buffer); - name = g_strdup_printf ("Tag %u", tag); - swfedit_token_add (SWFEDIT_TOKEN (file), name, SWFEDIT_TOKEN_OBJECT, item); - g_free (name); + swfedit_token_add (SWFEDIT_TOKEN (file), + swfdec_swf_decoder_get_tag_name (tag), + SWFEDIT_TOKEN_OBJECT, item); } swfdec_buffer_unref (next); return TRUE; diff-tree 97ce107c67c3bcbd363eaf12e3669ca8226e4143 (from bd5adea0669a5dbbbe75e887a400d6e538de0555) Author: Benjamin Otte <otte@gnome.org> Date: Mon Jan 22 22:03:11 2007 +0100 make it not crash includes adding optional debugging help for the treeview diff --git a/test/swfedit.c b/test/swfedit.c index 76fa744..71a86aa 100644 --- a/test/swfedit.c +++ b/test/swfedit.c @@ -28,7 +28,7 @@ static gboolean open_window (char *filename) { SwfeditFile *file; - GtkWidget *window, *treeview; + GtkWidget *window, *scroll, *treeview; GError *error = NULL; GtkTreeViewColumn *column; GtkCellRenderer *renderer; @@ -42,8 +42,11 @@ open_window (char *filename) window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_container_add (GTK_CONTAINER (window), scroll); + treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (file)); - gtk_container_add (GTK_CONTAINER (window), treeview); + gtk_container_add (GTK_CONTAINER (scroll), treeview); gtk_widget_show_all (window); renderer = gtk_cell_renderer_text_new (); diff --git a/test/swfedit_file.c b/test/swfedit_file.c index e995c1b..2ae8fa2 100644 --- a/test/swfedit_file.c +++ b/test/swfedit_file.c @@ -155,6 +155,8 @@ swfedit_file_parse (SwfeditFile *file, S char *name; if (tag_len == 0x3f) tag_len = swfdec_bits_get_u32 (bits); + if (tag == 0) + break; if (tag_len > 0) buffer = swfdec_bits_get_buffer (bits, tag_len); else @@ -164,7 +166,7 @@ swfedit_file_parse (SwfeditFile *file, S "Invalid contents in file"); return FALSE; } - item = swfedit_tag_new (tag, buffer); + item = swfedit_tag_new (SWFEDIT_TOKEN (file), tag, buffer); name = g_strdup_printf ("Tag %u", tag); swfedit_token_add (SWFEDIT_TOKEN (file), name, SWFEDIT_TOKEN_OBJECT, item); g_free (name); diff --git a/test/swfedit_tag.c b/test/swfedit_tag.c index 9bbebeb..94ac4f9 100644 --- a/test/swfedit_tag.c +++ b/test/swfedit_tag.c @@ -49,12 +49,15 @@ swfedit_tag_init (SwfeditTag *tag) } SwfeditTag * -swfedit_tag_new (guint tag, SwfdecBuffer *buffer) +swfedit_tag_new (SwfeditToken *parent, guint tag, SwfdecBuffer *buffer) { SwfeditTag *item; + g_return_val_if_fail (SWFEDIT_IS_TOKEN (parent), NULL); + item = g_object_new (SWFEDIT_TYPE_TAG, NULL); item->tag = tag; + SWFEDIT_TOKEN (item)->parent = parent; swfedit_token_add (SWFEDIT_TOKEN (item), "contents", SWFEDIT_TOKEN_BINARY, buffer); return item; } diff --git a/test/swfedit_tag.h b/test/swfedit_tag.h index aad879e..07c11f2 100644 --- a/test/swfedit_tag.h +++ b/test/swfedit_tag.h @@ -47,7 +47,8 @@ struct _SwfeditTagClass { GType swfedit_tag_get_type (void); -SwfeditTag * swfedit_tag_new (guint tag, +SwfeditTag * swfedit_tag_new (SwfeditToken * parent, + guint tag, SwfdecBuffer * buffer); diff --git a/test/swfedit_token.c b/test/swfedit_token.c index 78951f2..704b98b 100644 --- a/test/swfedit_token.c +++ b/test/swfedit_token.c @@ -80,7 +80,7 @@ swfedit_binary_write (gconstpointer valu for (i = 0; i < buffer->length; i++) { if (i && i % 4 == 0) g_string_append_c (string, ' '); - g_string_append_printf (string, "%2X", buffer->data[i]); + g_string_append_printf (string, "%02X", buffer->data[i]); } return g_string_free (string, FALSE); } @@ -147,9 +147,15 @@ typedef struct { /*** GTK_TREE_MODEL ***/ +#if 0 +# define REPORT g_print ("%s\n", G_STRFUNC) +#else +# define REPORT +#endif static GtkTreeModelFlags swfedit_token_get_flags (GtkTreeModel *tree_model) { + REPORT; return 0; } @@ -158,12 +164,14 @@ swfedit_token_get_n_columns (GtkTreeMode { SwfeditToken *token = SWFEDIT_TOKEN (tree_model); + REPORT; return token->tokens->len; } static GType swfedit_token_get_column_type (GtkTreeModel *tree_model, gint index_) { + REPORT; switch (index_) { case SWFEDIT_COLUMN_NAME: return G_TYPE_STRING; @@ -185,6 +193,7 @@ swfedit_token_get_iter (GtkTreeModel *tr guint i = gtk_tree_path_get_indices (path)[0]; Entry *entry; + REPORT; if (i > token->tokens->len) return FALSE; entry = &g_array_index (token->tokens, Entry, i); @@ -199,7 +208,7 @@ swfedit_token_get_iter (GtkTreeModel *tr new = gtk_tree_path_new (); indices = gtk_tree_path_get_indices (path); for (j = 1; j < gtk_tree_path_get_depth (path); j++) { - gtk_tree_path_append_index (path, indices[j]); + gtk_tree_path_append_index (new, indices[j]); } ret = swfedit_token_get_iter (GTK_TREE_MODEL (entry->value), iter, new); gtk_tree_path_free (new); @@ -218,6 +227,7 @@ swfedit_token_get_path (GtkTreeModel *tr SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data); GtkTreePath *path = gtk_tree_path_new_from_indices (GPOINTER_TO_INT (iter->user_data2), -1); + REPORT; while (token->parent) { guint i; SwfeditToken *parent = token->parent; @@ -241,6 +251,7 @@ swfedit_token_get_value (GtkTreeModel *t SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data); Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2)); + REPORT; switch (column) { case SWFEDIT_COLUMN_NAME: g_value_init (value, G_TYPE_STRING); @@ -266,6 +277,7 @@ swfedit_token_iter_next (GtkTreeModel *t { SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data); + REPORT; if ((guint) GPOINTER_TO_INT (iter->user_data2) + 1 >= token->tokens->len) return FALSE; @@ -276,14 +288,21 @@ swfedit_token_iter_next (GtkTreeModel *t static gboolean swfedit_token_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) { - SwfeditToken *token = SWFEDIT_TOKEN (parent->user_data); - Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2)); - - if (entry->type != SWFEDIT_TOKEN_OBJECT) - return FALSE; + SwfeditToken *token; + Entry *entry; + REPORT; + if (parent) { + token = SWFEDIT_TOKEN (parent->user_data); + entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2)); + if (entry->type != SWFEDIT_TOKEN_OBJECT) + return FALSE; + token = entry->value; + } else { + token = SWFEDIT_TOKEN (tree_model); + } iter->stamp = 0; /* FIXME */ - iter->user_data = entry->value; + iter->user_data = token; iter->user_data2 = GINT_TO_POINTER (0); return TRUE; } @@ -294,6 +313,7 @@ swfedit_token_iter_has_child (GtkTreeMod SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data); Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2)); + REPORT; return entry->type == SWFEDIT_TOKEN_OBJECT; } @@ -303,6 +323,7 @@ swfedit_token_iter_n_children (GtkTreeMo SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data); Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2)); + REPORT; if (entry->type != SWFEDIT_TOKEN_OBJECT) return FALSE; @@ -317,6 +338,7 @@ swfedit_token_iter_nth_child (GtkTreeMod SwfeditToken *token; Entry *entry; + REPORT; if (parent) { token = SWFEDIT_TOKEN (parent->user_data); entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2)); @@ -341,6 +363,7 @@ swfedit_token_iter_parent (GtkTreeModel SwfeditToken *token = SWFEDIT_TOKEN (child->user_data); SwfeditToken *parent = token->parent; + REPORT; if (parent == NULL) return FALSE; @@ -352,7 +375,7 @@ swfedit_token_iter_parent (GtkTreeModel break; } iter->stamp = 0; /* FIXME */ - iter->user_data = token; + iter->user_data = parent; iter->user_data2 = GINT_TO_POINTER (i); return TRUE; } diff-tree bd5adea0669a5dbbbe75e887a400d6e538de0555 (from parents) Merge: 8c426c32f7343fff4ff23015f5f7eee647b5aee7 72caf9482e2e7eb4bdc6cc0fa7578beb31645bac Author: Benjamin Otte <otte@gnome.org> Date: Mon Jan 22 18:40:04 2007 +0100 Merge branch 'interpreter' of ssh://company@git.freedesktop.org/git/swfdec into interpreter diff-tree 8c426c32f7343fff4ff23015f5f7eee647b5aee7 (from f2e4bc2ff2bfa289f325e525619b79dcf4815f9c) Author: Benjamin Otte <otte@gnome.org> Date: Mon Jan 22 10:54:05 2007 +0100 implement Increment and Decrement diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 909cba4..171877f 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -753,6 +753,26 @@ swfdec_action_if (JSContext *cx, guint a return JS_TRUE; } +static JSBool +swfdec_action_decrement (JSContext *cx, guint action, const guint8 *data, guint len) +{ + double d; + + d = swfdec_action_to_number (cx, cx->fp->sp[-1]); + d--; + return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]); +} + +static JSBool +swfdec_action_increment (JSContext *cx, guint action, const guint8 *data, guint len) +{ + double d; + + d = swfdec_action_to_number (cx, cx->fp->sp[-1]); + d++; + return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]); +} + /*** PRINT FUNCTIONS ***/ static char * @@ -967,8 +987,8 @@ static const SwfdecActionSpec actions[25 [0x4d] = { "Swap", NULL }, [0x4e] = { "GetMember", NULL, 2, 1, { NULL, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member } }, [0x4f] = { "SetMember", NULL, 3, 0, { NULL, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member } }, - [0x50] = { "Increment", NULL }, - [0x51] = { "Decrement", NULL }, + [0x50] = { "Increment", NULL, 1, 1, { NULL, NULL, swfdec_action_increment, swfdec_action_increment, swfdec_action_increment } }, + [0x51] = { "Decrement", NULL, 1, 1, { NULL, NULL, swfdec_action_decrement, swfdec_action_decrement, swfdec_action_decrement } }, [0x52] = { "CallMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_call_method, swfdec_action_call_method, swfdec_action_call_method } }, [0x53] = { "NewMethod", NULL }, /* version 6 */ diff-tree f2e4bc2ff2bfa289f325e525619b79dcf4815f9c (from 568f6fdf0b44ea7cfcc87b33ed4ac09e88bbd47e) Author: Benjamin Otte <otte@gnome.org> Date: Mon Jan 22 10:23:59 2007 +0100 Implement Jump, If and Not Also includes a fix to voncert booleans to numbers correctly 11/44 failures diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 104af78..909cba4 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -527,6 +527,8 @@ swfdec_action_to_number (JSContext *cx, return JSVAL_TO_INT (val); } else if (JSVAL_IS_DOUBLE (val)) { return *JSVAL_TO_DOUBLE (val); + } else if (JSVAL_IS_BOOLEAN (val)) { + return JSVAL_TO_BOOLEAN (val); } else { return 0; } @@ -704,9 +706,76 @@ swfdec_action_new_comparison_7 (JSContex return JS_TRUE; } +static JSBool +swfdec_action_not_4 (JSContext *cx, guint action, const guint8 *data, guint len) +{ + double d; + + d = swfdec_action_to_number (cx, cx->fp->sp[-1]); + cx->fp->sp[-1] = INT_TO_JSVAL (d == 0 ? 1 : 0); + return JS_TRUE; +} + +static JSBool +swfdec_action_not_5 (JSContext *cx, guint action, const guint8 *data, guint len) +{ + double d; + + d = swfdec_action_to_number (cx, cx->fp->sp[-1]); + cx->fp->sp[-1] = d == 0 ? JSVAL_TRUE : JSVAL_FALSE; + return JS_TRUE; +} + +static JSBool +swfdec_action_jump (JSContext *cx, guint action, const guint8 *data, guint len) +{ + if (len != 2) { + SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len); + return JS_FALSE; + } + cx->fp->pc += 4 + GINT16_FROM_LE (*((gint16*) data)); + return JS_TRUE; +} + +static JSBool +swfdec_action_if (JSContext *cx, guint action, const guint8 *data, guint len) +{ + double d; + + if (len != 2) { + SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len); + return JS_FALSE; + } + d = swfdec_action_to_number (cx, cx->fp->sp[-1]); + cx->fp->sp--; + if (d != 0) + cx->fp->pc += 4 + GINT16_FROM_LE (*((gint16*) data)); + return JS_TRUE; +} + /*** PRINT FUNCTIONS ***/ static char * +swfdec_action_print_if (guint action, const guint8 *data, guint len) +{ + if (len != 2) { + SWFDEC_ERROR ("If action length invalid (is %u, should be 2", len); + return NULL; + } + return g_strdup_printf ("If %d", GINT16_FROM_LE (*((gint16*) data))); +} + +static char * +swfdec_action_print_jump (guint action, const guint8 *data, guint len) +{ + if (len != 2) { + SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len); + return NULL; + } + return g_strdup_printf ("Jump %d", GINT16_FROM_LE (*((gint16*) data))); +} + +static char * swfdec_action_print_push (guint action, const guint8 *data, guint len) { gboolean first = TRUE; @@ -844,7 +913,7 @@ static const SwfdecActionSpec actions[25 [0x0f] = { "Less", NULL }, [0x10] = { "And", NULL }, [0x11] = { "Or", NULL }, - [0x12] = { "Not", NULL }, + [0x12] = { "Not", NULL, 1, 1, { NULL, swfdec_action_not_4, swfdec_action_not_5, swfdec_action_not_5, swfdec_action_not_5 } }, [0x13] = { "StringEquals", NULL }, [0x14] = { "StringLength", NULL }, [0x15] = { "StringExtract", NULL }, @@ -938,12 +1007,12 @@ static const SwfdecActionSpec actions[25 [0x94] = { "With", NULL }, /* version 4 */ [0x96] = { "Push", swfdec_action_print_push, 0, -1, { NULL, swfdec_action_push, swfdec_action_push, swfdec_action_push, swfdec_action_push } }, - [0x99] = { "Jump", NULL }, + [0x99] = { "Jump", swfdec_action_print_jump, 0, 0, { NULL, swfdec_action_jump, swfdec_action_jump, swfdec_action_jump, swfdec_action_jump } }, [0x9a] = { "GetURL2", NULL }, /* version 5 */ [0x9b] = { "DefineFunction", NULL }, /* version 4 */ - [0x9d] = { "If", NULL }, + [0x9d] = { "If", swfdec_action_print_if, 1, 0, { NULL, swfdec_action_if, swfdec_action_if, swfdec_action_if, swfdec_action_if } }, [0x9e] = { "Call", NULL }, [0x9f] = { "GotoFrame2", NULL } }; diff-tree 568f6fdf0b44ea7cfcc87b33ed4ac09e88bbd47e (from e06e79a0c20256854b9073ee7c73a047e81dd820) Author: Benjamin Otte <otte@gnome.org> Date: Sun Jan 21 20:48:06 2007 +0100 fix binary ops for undefined2-7.swf 13/44 failures diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 3bbd168..104af78 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -540,8 +540,15 @@ swfdec_action_binary (JSContext *cx, gui rval = cx->fp->sp[-1]; lval = cx->fp->sp[-2]; - l = swfdec_action_to_number (cx, lval); - r = swfdec_action_to_number (cx, rval); + if (((SwfdecScript *) cx->fp->swf)->version < 7) { + l = swfdec_action_to_number (cx, lval); + r = swfdec_action_to_number (cx, rval); + } else { + if (!JS_ValueToNumber(cx, lval, &l) || + !JS_ValueToNumber(cx, rval, &r)) + return JS_FALSE; + } + cx->fp->sp--; switch (action) { case 0x0a: l = l + r; @@ -557,17 +564,22 @@ swfdec_action_binary (JSContext *cx, gui JSString *str = JS_InternString (cx, "#ERROR#"); if (str == NULL) return JS_FALSE; - cx->fp->sp--; cx->fp->sp[-1] = STRING_TO_JSVAL (str); return JS_TRUE; } + if (((SwfdecScript *) cx->fp->swf)->version >= 7 && + JSVAL_IS_VOID (rval)) { + cx->fp->sp[-1] = DOUBLE_TO_JSVAL (r < 0 ? + cx->runtime->jsNegativeInfinity : + cx->runtime->jsPositiveInfinity); + return JS_TRUE; + } l = l / r; break; default: g_assert_not_reached (); return r; } - cx->fp->sp--; return JS_NewNumberValue (cx, l, &cx->fp->sp[-1]); } diff-tree e06e79a0c20256854b9073ee7c73a047e81dd820 (from 659db3d36cca2f586498ba8dd554f17dd50906f4) Author: Benjamin Otte <otte@gnome.org> Date: Sun Jan 21 19:24:27 2007 +0100 implement Less2 and Greater actions and fix a big bug The code used to always execute the v7 script. 14/44 failues diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 5b9f960..3bbd168 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -651,6 +651,47 @@ swfdec_action_set_member (JSContext *cx, return JS_TRUE; } +static JSBool +swfdec_action_new_comparison_6 (JSContext *cx, guint action, const guint8 *data, guint len) +{ + jsval lval, rval; + double d, d2; + + rval = cx->fp->sp[-1]; + lval = cx->fp->sp[-2]; + cx->fp->sp--; + d = swfdec_action_to_number (cx, lval); + d2 = swfdec_action_to_number (cx, rval); + if (action == 0x48) + cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (d < d2); + else + cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (d > d2); + return JS_TRUE; +} + +static JSBool +swfdec_action_new_comparison_7 (JSContext *cx, guint action, const guint8 *data, guint len) +{ + jsval lval, rval; + + rval = cx->fp->sp[-1]; + lval = cx->fp->sp[-2]; + cx->fp->sp--; + if (JSVAL_IS_VOID (rval) || JSVAL_IS_VOID (lval)) { + cx->fp->sp[-1] = JSVAL_VOID; + } else if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) { + int comp = JS_CompareStrings (JSVAL_TO_STRING (lval), JSVAL_TO_STRING (rval)); + cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (action == 0x48 ? comp < 0 : comp > 0); + } else { + double d, d2; + if (!JS_ValueToNumber(cx, lval, &d) || + !JS_ValueToNumber(cx, rval, &d2)) + return JS_FALSE; + cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (action == 0x48 ? d < d2 : d > d2); + } + return JS_TRUE; +} + /*** PRINT FUNCTIONS ***/ static char * @@ -762,7 +803,7 @@ swfdec_action_print_wait_for_frame (guin /* defines minimum and maximum versions for which we have seperate scripts */ #define MINSCRIPTVERSION 3 #define MAXSCRIPTVERSION 7 -#define EXTRACT_VERSION(v) MAX ((v) - MINSCRIPTVERSION, MAXSCRIPTVERSION - MINSCRIPTVERSION) +#define EXTRACT_VERSION(v) MIN ((v) - MINSCRIPTVERSION, MAXSCRIPTVERSION - MINSCRIPTVERSION) typedef JSBool (* SwfdecActionExec) (JSContext *cx, guint action, const guint8 *data, guint len); typedef struct { @@ -837,7 +878,7 @@ static const SwfdecActionSpec actions[25 [0x45] = { "TargetPath", NULL }, [0x46] = { "Enumerate", NULL }, [0x47] = { "Add2", NULL, 2, 1, { NULL, NULL, NULL, NULL, swfdec_action_add2_7 } }, - [0x48] = { "Less2", NULL }, + [0x48] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } }, [0x49] = { "Equals2", NULL }, [0x4a] = { "ToNumber", NULL }, [0x4b] = { "ToString", NULL }, @@ -861,7 +902,7 @@ static const SwfdecActionSpec actions[25 [0x65] = { "BitURShift", NULL }, /* version 6 */ [0x66] = { "StrictEquals", NULL }, - [0x67] = { "Greater", NULL }, + [0x67] = { "Greater", NULL, 2, 1, { NULL, NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } }, [0x68] = { "StringGreater", NULL }, /* version 7 */ [0x69] = { "Extends", NULL }, diff-tree 659db3d36cca2f586498ba8dd554f17dd50906f4 (from 39276bcb05d190d1fc6a0c35490774ee309f4ffb) Author: Benjamin Otte <otte@gnome.org> Date: Sat Jan 20 17:01:06 2007 +0100 Fix case handling (don't make it global anymore) and implement SetVariable with this there's 17/44 failures diff --git a/libswfdec/js/jsatom.c b/libswfdec/js/jsatom.c index f0816b2..c4c85b7 100644 --- a/libswfdec/js/jsatom.c +++ b/libswfdec/js/jsatom.c @@ -673,10 +673,10 @@ out: JSAtom * js_AtomizeString(JSContext *cx, JSString *str, uintN flags) { - if (cx->caseSensitive) - return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys); - else + if (flags & ATOM_NOCASE) return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys_no_case); + else + return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys); } JS_FRIEND_API(JSAtom *) diff --git a/libswfdec/js/jsatom.h b/libswfdec/js/jsatom.h index 6f486c3..d9d2025 100644 --- a/libswfdec/js/jsatom.h +++ b/libswfdec/js/jsatom.h @@ -58,6 +58,7 @@ JS_BEGIN_EXTERN_C #define ATOM_PINNED 0x01 /* atom is pinned against GC */ #define ATOM_INTERNED 0x02 /* pinned variant for JS_Intern* API */ #define ATOM_MARK 0x04 /* atom is reachable via GC */ +#define ATOM_NOCASE 0x20 /* treat atom case-insensitive */ #define ATOM_NOCOPY 0x40 /* don't copy atom string bytes */ #define ATOM_TMPSTR 0x80 /* internal, to avoid extra string */ diff --git a/libswfdec/swfdec_edittext_movie.c b/libswfdec/swfdec_edittext_movie.c index 421f6bc..e3d2119 100644 --- a/libswfdec/swfdec_edittext_movie.c +++ b/libswfdec/swfdec_edittext_movie.c @@ -80,7 +80,7 @@ swfdec_edit_text_movie_iterate (SwfdecMo jsobj = swfdec_scriptable_get_object (parent); if (jsobj == NULL) return; - val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable); + val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable, FALSE); if (JSVAL_IS_VOID (val)) return; @@ -110,7 +110,7 @@ swfdec_edit_text_movie_init_movie (Swfde if (jsobj == NULL) return; if (text->text->variable_prefix) { - val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix); + val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix, FALSE); if (!JSVAL_IS_OBJECT (val)) return; jsobj = JSVAL_TO_OBJECT (val); diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index cf14f65..bbd6a43 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -300,29 +300,26 @@ fail: static JSBool swfdec_js_eval_get_property (JSContext *cx, JSObject *obj, - const char *name, gboolean initial, jsval *ret) + const char *name, gboolean initial, gboolean ignore_case, jsval *ret) { JSAtom *atom; JSObject *pobj; JSProperty *prop; - if (!JS_GetProperty (cx, obj, name, ret)) - return JS_FALSE; - if (!JSVAL_IS_VOID (*ret)) - return JS_TRUE; - if (!initial) - return JS_FALSE; - - atom = js_Atomize(cx, name, strlen(name), 0); + atom = js_Atomize (cx, name, strlen(name), ignore_case ? ATOM_NOCASE : 0); if (!atom) return JS_FALSE; - if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop)) - return JS_FALSE; - if (!prop) - return JS_FALSE; - if (pobj) - obj = pobj; - return OBJ_GET_PROPERTY (cx, obj, (jsid) prop->id, ret); + if (initial) { + return OBJ_GET_PROPERTY (cx, obj, (jsid) atom, ret); + } else { + if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop)) + return JS_FALSE; + if (!prop) + return JS_FALSE; + if (pobj) + obj = pobj; + return OBJ_GET_PROPERTY (cx, obj, (jsid) prop->id, ret); + } } /** @@ -330,6 +327,7 @@ swfdec_js_eval_get_property (JSContext * * @cx: a #JSContext * @obj: #JSObject to use as a source for evaluating * @str: The string to evaluate + * @ignore_case: TRUE for case insensitive evaluation * * This function works like the Actionscript eval function used on @obj. * It handles both slash-style and dot-style notation. @@ -337,7 +335,8 @@ swfdec_js_eval_get_property (JSContext * * Returns: the value or JSVAL_VOID if no value was found. **/ jsval -swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str) +swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str, + gboolean ignore_case) { jsval cur; char *work = NULL; @@ -365,12 +364,12 @@ swfdec_js_eval (JSContext *cx, JSObject obj = JSVAL_TO_OBJECT (cur); if (dot) { char *name = g_strndup (str, dot - str); - if (!swfdec_js_eval_get_property (cx, obj, name, initial, &cur)) + if (!swfdec_js_eval_get_property (cx, obj, name, initial, ignore_case, &cur)) goto out; g_free (name); str = dot + 1; } else { - if (!swfdec_js_eval_get_property (cx, obj, str, initial, &cur)) + if (!swfdec_js_eval_get_property (cx, obj, str, initial, ignore_case, &cur)) goto out; str = NULL; } @@ -384,3 +383,5 @@ out: g_free (work); return JSVAL_VOID; } + + diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h index ced8046..47e97ff 100644 --- a/libswfdec/swfdec_js.h +++ b/libswfdec/swfdec_js.h @@ -49,7 +49,8 @@ void swfdec_js_movie_remove_property (S char * swfdec_js_slash_to_dot (const char * slash_str); jsval swfdec_js_eval (JSContext * cx, JSObject * obj, - const char * str); + const char * str, + gboolean ignore_case); /* support functions */ const char * swfdec_js_to_string (JSContext * cx, diff --git a/libswfdec/swfdec_js_global.c b/libswfdec/swfdec_js_global.c index 328d74d..27522c1 100644 --- a/libswfdec/swfdec_js_global.c +++ b/libswfdec/swfdec_js_global.c @@ -33,7 +33,7 @@ swfdec_js_global_eval (JSContext *cx, JS const char *bytes = swfdec_js_to_string (cx, argv[0]); if (bytes == NULL) return JS_FALSE; - *rval = swfdec_js_eval (cx, obj, bytes); + *rval = swfdec_js_eval (cx, obj, bytes, FALSE); } else { *rval = argv[0]; } diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 23ca8ef..5b9f960 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -315,7 +315,26 @@ swfdec_action_get_variable (JSContext *c s = swfdec_js_to_string (cx, cx->fp->sp[-1]); if (s == NULL) return JS_FALSE; - cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s); + cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s, + ((SwfdecScript *) cx->fp->swf)->version < 7); + return JS_TRUE; +} + +static JSBool +swfdec_action_set_variable (JSContext *cx, guint action, const guint8 *data, guint len) +{ + const char *s; + + s = swfdec_js_to_string (cx, cx->fp->sp[-2]); + if (s == NULL) + return JS_FALSE; + + if (strpbrk (s, "./:")) { + SWFDEC_WARNING ("FIXME: implement paths"); + } + if (!JS_SetProperty (cx, cx->fp->scopeChain, s, &cx->fp->sp[-1])) + return JS_FALSE; + cx->fp->sp -= 2; return JS_TRUE; } @@ -425,7 +444,8 @@ swfdec_eval_jsval (JSContext *cx, JSObje const char *bytes = swfdec_js_to_string (cx, *val); if (bytes == NULL) return JS_FALSE; - *val = swfdec_js_eval (cx, obj, bytes); + *val = swfdec_js_eval (cx, obj, bytes, + ((SwfdecScript *) cx->fp->swf)->version < 7); } else { *val = OBJECT_TO_JSVAL (obj); } @@ -500,6 +520,57 @@ out: return JS_TRUE; } +static double +swfdec_action_to_number (JSContext *cx, jsval val) +{ + if (JSVAL_IS_INT (val)) { + return JSVAL_TO_INT (val); + } else if (JSVAL_IS_DOUBLE (val)) { + return *JSVAL_TO_DOUBLE (val); + } else { + return 0; + } +} + +static JSBool +swfdec_action_binary (JSContext *cx, guint action, const guint8 *data, guint len) +{ + jsval lval, rval; + double l, r; + + rval = cx->fp->sp[-1]; + lval = cx->fp->sp[-2]; + l = swfdec_action_to_number (cx, lval); + r = swfdec_action_to_number (cx, rval); + switch (action) { + case 0x0a: + l = l + r; + break; + case 0x0b: + l = l - r; + break; + case 0x0c: + l = l * r; + break; + case 0x0d: + if (r == 0 && ((SwfdecScript *) cx->fp->swf)->version < 5) { + JSString *str = JS_InternString (cx, "#ERROR#"); + if (str == NULL) + return JS_FALSE; + cx->fp->sp--; + cx->fp->sp[-1] = STRING_TO_JSVAL (str); + return JS_TRUE; + } + l = l / r; + break; + default: + g_assert_not_reached (); + return r; + } + cx->fp->sp--; + return JS_NewNumberValue (cx, l, &cx->fp->sp[-1]); +} + static JSBool swfdec_action_add2_7 (JSContext *cx, guint action, const guint8 *data, guint len) { @@ -539,7 +610,7 @@ swfdec_action_add2_7 (JSContext *cx, gui return JS_FALSE; d += d2; cx->fp->sp--; - return JS_NewDoubleValue(cx, d, &cx->fp->sp[-1]); + return JS_NewNumberValue(cx, d, &cx->fp->sp[-1]); } return JS_TRUE; } @@ -712,10 +783,10 @@ static const SwfdecActionSpec actions[25 [0x08] = { "ToggleQuality", NULL }, [0x09] = { "StopSounds", NULL }, /* version 4 */ - [0x0a] = { "Add", NULL }, - [0x0b] = { "Subtract", NULL }, - [0x0c] = { "Multiply", NULL }, - [0x0d] = { "Divide", NULL }, + [0x0a] = { "Add", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } }, + [0x0b] = { "Subtract", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } }, + [0x0c] = { "Multiply", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } }, + [0x0d] = { "Divide", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } }, [0x0e] = { "Equals", NULL }, [0x0f] = { "Less", NULL }, [0x10] = { "And", NULL }, @@ -727,7 +798,7 @@ static const SwfdecActionSpec actions[25 [0x17] = { "Pop", NULL, 1, 0, { NULL, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop } }, [0x18] = { "ToInteger", NULL }, [0x1c] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } }, - [0x1d] = { "SetVariable", NULL }, + [0x1d] = { "SetVariable", NULL, 2, 0, { NULL, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable } }, [0x20] = { "SetTarget2", NULL }, [0x21] = { "StringAdd", NULL }, [0x22] = { "GetProperty", NULL, 2, 1, { NULL, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property } }, diff-tree 39276bcb05d190d1fc6a0c35490774ee309f4ffb (from 41d6a77090dff7583e4a61937120db79d1c4c547) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 19 22:14:26 2007 +0100 fix SetMember 20/44 failures diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 0256d8c..23ca8ef 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -427,7 +427,7 @@ swfdec_eval_jsval (JSContext *cx, JSObje return JS_FALSE; *val = swfdec_js_eval (cx, obj, bytes); } else { - SWFDEC_ERROR ("huh?"); + *val = OBJECT_TO_JSVAL (obj); } return JS_TRUE; } @@ -475,7 +475,7 @@ swfdec_action_set_property (JSContext *c JSObject *jsobj; guint32 id; - val = cx->fp->sp[-2]; + val = cx->fp->sp[-3]; if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val)) return JS_FALSE; movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE); @@ -483,7 +483,7 @@ swfdec_action_set_property (JSContext *c SWFDEC_WARNING ("specified target does not reference a movie clip"); goto out; } - if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-1], &id)) + if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-2], &id)) return JS_FALSE; if (id > (((SwfdecScript *) cx->fp->swf)->version > 4 ? 21 : 18)) @@ -492,7 +492,7 @@ swfdec_action_set_property (JSContext *c if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)))) return JS_FALSE; - if (!JS_SetProperty (cx, jsobj, properties[id], &cx->fp->sp[-3])) + if (!JS_SetProperty (cx, jsobj, properties[id], &cx->fp->sp[-1])) return JS_FALSE; out: diff-tree 41d6a77090dff7583e4a61937120db79d1c4c547 (from f07034751126d85a58b48ff77bbf57c5dc8021ca) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 19 21:17:45 2007 +0100 push a double, not a float diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 583c2f1..0256d8c 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -251,7 +251,7 @@ swfdec_action_push (JSContext *cx, guint break; case 6: /* double */ { - double d = swfdec_bits_get_float (&bits); + double d = swfdec_bits_get_double (&bits); if (!JS_NewDoubleValue (cx, d, cx->fp->sp)) return JS_FALSE; cx->fp->sp++; diff-tree f07034751126d85a58b48ff77bbf57c5dc8021ca (from 34c98c5cf9deb0b5fc10f0cbee7bf368f3653000) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 19 21:16:28 2007 +0100 fix string Add2 diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index e4bf0d4..583c2f1 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -520,11 +520,11 @@ swfdec_action_add2_7 (JSContext *cx, gui JSString *str, *str2; if (cond) { str = JSVAL_TO_STRING (lval); - if ((str2 = js_ValueToString (cx, rval)) != NULL) + if ((str2 = js_ValueToString (cx, rval)) == NULL) return JS_FALSE; } else { str2 = JSVAL_TO_STRING (rval); - if ((str = js_ValueToString (cx, lval)) != NULL) + if ((str = js_ValueToString (cx, lval)) == NULL) return JS_FALSE; } str = js_ConcatStrings (cx, str, str2); diff-tree 34c98c5cf9deb0b5fc10f0cbee7bf368f3653000 (from 756c3c6c257d890fd5b35221ab7451017bb56d03) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 19 21:16:11 2007 +0100 implement SetMember diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 8f073b7..e4bf0d4 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -563,6 +563,23 @@ swfdec_action_get_member (JSContext *cx, return JS_TRUE; } +static JSBool +swfdec_action_set_member (JSContext *cx, guint action, const guint8 *data, guint len) +{ + const char *s; + + s = swfdec_js_to_string (cx, cx->fp->sp[-2]); + if (s == NULL) + return JS_FALSE; + + if (JSVAL_IS_OBJECT (cx->fp->sp[-3])) { + if (!JS_SetProperty (cx, JSVAL_TO_OBJECT (cx->fp->sp[-3]), s, &cx->fp->sp[-1])) + return JS_FALSE; + } + cx->fp->sp -= 3; + return JS_TRUE; +} + /*** PRINT FUNCTIONS ***/ static char * @@ -756,7 +773,7 @@ static const SwfdecActionSpec actions[25 [0x4c] = { "PushDuplicate", NULL }, [0x4d] = { "Swap", NULL }, [0x4e] = { "GetMember", NULL, 2, 1, { NULL, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member } }, - [0x4f] = { "SetMember", NULL }, /* apparently the result is ignored */ + [0x4f] = { "SetMember", NULL, 3, 0, { NULL, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member } }, [0x50] = { "Increment", NULL }, [0x51] = { "Decrement", NULL }, [0x52] = { "CallMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_call_method, swfdec_action_call_method, swfdec_action_call_method } }, diff-tree 756c3c6c257d890fd5b35221ab7451017bb56d03 (from 469151c6400bd4dde8b9e0356274bbec5f105c4b) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 19 19:34:22 2007 +0100 implement GetMember and Add2 for Flash7 30/44 failures diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index b8d3dc6..8f073b7 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -500,6 +500,69 @@ out: return JS_TRUE; } +static JSBool +swfdec_action_add2_7 (JSContext *cx, guint action, const guint8 *data, guint len) +{ + jsval rval, lval; + gboolean cond; + + rval = cx->fp->sp[-1]; + lval = cx->fp->sp[-2]; + if (!JSVAL_IS_PRIMITIVE (rval)) { + if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT (rval), 0 , &rval)) + return JS_FALSE; + } + if (!JSVAL_IS_PRIMITIVE (lval)) { + if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT (lval), 0 , &lval)) + return JS_FALSE; + } + if ((cond = JSVAL_IS_STRING (lval)) || JSVAL_IS_STRING (rval)) { + JSString *str, *str2; + if (cond) { + str = JSVAL_TO_STRING (lval); + if ((str2 = js_ValueToString (cx, rval)) != NULL) + return JS_FALSE; + } else { + str2 = JSVAL_TO_STRING (rval); + if ((str = js_ValueToString (cx, lval)) != NULL) + return JS_FALSE; + } + str = js_ConcatStrings (cx, str, str2); + if (!str) + return JS_FALSE; + cx->fp->sp--; + cx->fp->sp[-1] = STRING_TO_JSVAL (str); + } else { + double d, d2; + if (!JS_ValueToNumber(cx, lval, &d) || + !JS_ValueToNumber(cx, rval, &d2)) + return JS_FALSE; + d += d2; + cx->fp->sp--; + return JS_NewDoubleValue(cx, d, &cx->fp->sp[-1]); + } + return JS_TRUE; +} + +static JSBool +swfdec_action_get_member (JSContext *cx, guint action, const guint8 *data, guint len) +{ + const char *s; + + s = swfdec_js_to_string (cx, cx->fp->sp[-1]); + if (s == NULL) + return JS_FALSE; + + if (JSVAL_IS_OBJECT (cx->fp->sp[-2])) { + if (!JS_GetProperty (cx, JSVAL_TO_OBJECT (cx->fp->sp[-2]), s, &cx->fp->sp[-2])) + return JS_FALSE; + } else { + cx->fp->sp[-2] = JSVAL_VOID; + } + cx->fp->sp--; + return JS_TRUE; +} + /*** PRINT FUNCTIONS ***/ static char * @@ -685,14 +748,14 @@ static const SwfdecActionSpec actions[25 [0x44] = { "Typeof", NULL }, [0x45] = { "TargetPath", NULL }, [0x46] = { "Enumerate", NULL }, - [0x47] = { "Add2", NULL }, + [0x47] = { "Add2", NULL, 2, 1, { NULL, NULL, NULL, NULL, swfdec_action_add2_7 } }, [0x48] = { "Less2", NULL }, [0x49] = { "Equals2", NULL }, [0x4a] = { "ToNumber", NULL }, [0x4b] = { "ToString", NULL }, [0x4c] = { "PushDuplicate", NULL }, [0x4d] = { "Swap", NULL }, - [0x4e] = { "GetMember", NULL }, + [0x4e] = { "GetMember", NULL, 2, 1, { NULL, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member } }, [0x4f] = { "SetMember", NULL }, /* apparently the result is ignored */ [0x50] = { "Increment", NULL }, [0x51] = { "Decrement", NULL }, diff-tree 469151c6400bd4dde8b9e0356274bbec5f105c4b (from 1df9fa9d227af58658f4c2b9bf1e9a6719c4d9dc) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 19 13:27:27 2007 +0100 add GetProperty and SetProperty actions 32/44 failures now diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index e688089..b8d3dc6 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -410,6 +410,96 @@ swfdec_action_pop (JSContext *cx, guint return JS_TRUE; } +static const char *properties[22] = { + "_x", "_y", "_xscale", "_yscale", "_currentframe", + "_totalframes", "_alpha", "_visible", "_width", "_height", + "_rotation", "_target", "_framesloaded", "_name", "_droptarget", + "_url", "_highquality", "_focusrect", "_soundbuftime", "_quality", + "_xmouse", "_ymouse" +}; + +static JSBool +swfdec_eval_jsval (JSContext *cx, JSObject *obj, jsval *val) +{ + if (JSVAL_IS_STRING (*val)) { + const char *bytes = swfdec_js_to_string (cx, *val); + if (bytes == NULL) + return JS_FALSE; + *val = swfdec_js_eval (cx, obj, bytes); + } else { + SWFDEC_ERROR ("huh?"); + } + return JS_TRUE; +} + +static JSBool +swfdec_action_get_property (JSContext *cx, guint action, const guint8 *data, guint len) +{ + jsval val; + SwfdecMovie *movie; + JSObject *jsobj; + guint32 id; + + val = cx->fp->sp[-2]; + if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val)) + return JS_FALSE; + movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE); + val = JSVAL_VOID; + if (movie == NULL) { + SWFDEC_WARNING ("specified target does not reference a movie clip"); + goto out; + } + if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-1], &id)) + return JS_FALSE; + + if (id > (((SwfdecScript *) cx->fp->swf)->version > 4 ? 21 : 18)) + goto out; + + if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)))) + return JS_FALSE; + + if (!JS_GetProperty (cx, jsobj, properties[id], &val)) + return JS_FALSE; + +out: + cx->fp->sp -= 1; + cx->fp->sp[-1] = val; + return JS_TRUE; +} + +static JSBool +swfdec_action_set_property (JSContext *cx, guint action, const guint8 *data, guint len) +{ + jsval val; + SwfdecMovie *movie; + JSObject *jsobj; + guint32 id; + + val = cx->fp->sp[-2]; + if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val)) + return JS_FALSE; + movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE); + if (movie == NULL) { + SWFDEC_WARNING ("specified target does not reference a movie clip"); + goto out; + } + if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-1], &id)) + return JS_FALSE; + + if (id > (((SwfdecScript *) cx->fp->swf)->version > 4 ? 21 : 18)) + goto out; + + if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)))) + return JS_FALSE; + + if (!JS_SetProperty (cx, jsobj, properties[id], &cx->fp->sp[-3])) + return JS_FALSE; + +out: + cx->fp->sp -= 3; + return JS_TRUE; +} + /*** PRINT FUNCTIONS ***/ static char * @@ -560,8 +650,8 @@ static const SwfdecActionSpec actions[25 [0x1d] = { "SetVariable", NULL }, [0x20] = { "SetTarget2", NULL }, [0x21] = { "StringAdd", NULL }, - [0x22] = { "GetProperty", NULL }, - [0x23] = { "SetProperty", NULL }, + [0x22] = { "GetProperty", NULL, 2, 1, { NULL, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property } }, + [0x23] = { "SetProperty", NULL, 3, 0, { NULL, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property } }, [0x24] = { "CloneSprite", NULL }, [0x25] = { "RemoveSprite", NULL }, [0x26] = { "Trace", NULL, 1, 0, { NULL, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace } }, diff-tree 1df9fa9d227af58658f4c2b9bf1e9a6719c4d9dc (from 1fbe061229c9be6b6374f95fc0e70a786e8a33d5) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 19 13:27:05 2007 +0100 add stub for _quality property diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c index f5bf871..70ddece 100644 --- a/libswfdec/swfdec_js_movie.c +++ b/libswfdec/swfdec_js_movie.c @@ -1056,6 +1056,7 @@ static JSPropertySpec movieclip_props[] {"_highquality", -1, MC_PROP_ATTRS, not_reached, not_reached }, {"_focusrect", -1, MC_PROP_ATTRS, not_reached, not_reached }, {"_soundbuftime", -1, MC_PROP_ATTRS, not_reached, not_reached }, + {"_quality", -1, MC_PROP_ATTRS, not_reached, not_reached }, {"_xmouse", -1, MC_PROP_ATTRS, not_reached, not_reached }, {"_ymouse", -1, MC_PROP_ATTRS, not_reached, not_reached }, {"_parent", -1, MC_PROP_ATTRS | JSPROP_READONLY, mc_parent, NULL}, diff-tree 1fbe061229c9be6b6374f95fc0e70a786e8a33d5 (from 5f777f6697273122587f8bcf645e3a81a7f77228) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 19 12:53:56 2007 +0100 implement CallMethod and Pop + lots of bugfixing after this commit, test/trace has 33/44 failures diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index ed5ac44..e688089 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -304,7 +304,7 @@ swfdec_action_push (JSContext *cx, guint return JS_FALSE; } } - return swfdec_bits_left (&bits) ? JS_TRUE : JS_FALSE; + return swfdec_bits_left (&bits) ? JS_FALSE : JS_TRUE; } static JSBool @@ -326,6 +326,7 @@ swfdec_action_trace (JSContext *cx, guin const char *bytes; bytes = swfdec_js_to_string (cx, cx->fp->sp[-1]); + cx->fp->sp--; if (bytes == NULL) return JS_TRUE; @@ -333,6 +334,82 @@ swfdec_action_trace (JSContext *cx, guin return JS_TRUE; } +/** + * swfdec_action_invoke: + * @cx: the #JSContext + * @n_args: number of arguments + * + * This function is similar to js_Invoke, however it uses a reversed stack + * order. sp[-1] has to be the function to call, sp[-2] will be the object the + * function is called on, sp[-3] is the first argument, followed by the rest of + * the arguments. The function reorders the stack on success and pushes the + * return value on top. + * + * Returns: JS_TRUE on success, JS_FALSE on failure. + **/ +static JSBool +swfdec_action_call (JSContext *cx, guint n_args, guint flags) +{ + int i, j; + jsval tmp; + + j = -1; + i = - (n_args + 2); + while (i < j) { + tmp = cx->fp->sp[j]; + cx->fp->sp[j] = cx->fp->sp[i]; + cx->fp->sp[i] = tmp; + j--; + i++; + } + return js_Invoke (cx, n_args, flags); +} + +static JSBool +swfdec_action_call_method (JSContext *cx, guint action, const guint8 *data, guint len) +{ + JSStackFrame *fp = cx->fp; + const char *s; + guint32 n_args; + JSObject *obj; + jsval fun; + + s = swfdec_js_to_string (cx, fp->sp[-1]); + if (s == NULL) + return JS_FALSE; + if (!JS_ValueToECMAUint32 (cx, fp->sp[-3], &n_args)) + return JS_FALSE; + if (n_args + 3 > (guint) (fp->sp - fp->spbase)) + return JS_FALSE; + + if (!JSVAL_IS_OBJECT (fp->sp[-2])) + goto fail; + obj = JSVAL_TO_OBJECT (fp->sp[-2]); + if (s[0] == '\0') { + fun = OBJECT_TO_JSVAL (obj); + } else { + if (!JS_GetProperty (cx, obj, s, &fun)) + return JS_FALSE; + } + fp->sp--; + fp->sp[-1] = fun; + fp->sp[-2] = OBJECT_TO_JSVAL (obj); + swfdec_action_call (cx, n_args, 0); + return JS_TRUE; + +fail: + fp->sp -= 2 + n_args; + fp->sp[-1] = JSVAL_VOID; + return JS_TRUE; +} + +static JSBool +swfdec_action_pop (JSContext *cx, guint action, const guint8 *data, guint len) +{ + cx->fp->sp--; + return JS_TRUE; +} + /*** PRINT FUNCTIONS ***/ static char * @@ -477,7 +554,7 @@ static const SwfdecActionSpec actions[25 [0x13] = { "StringEquals", NULL }, [0x14] = { "StringLength", NULL }, [0x15] = { "StringExtract", NULL }, - [0x17] = { "Pop", NULL }, + [0x17] = { "Pop", NULL, 1, 0, { NULL, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop } }, [0x18] = { "ToInteger", NULL }, [0x1c] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } }, [0x1d] = { "SetVariable", NULL }, @@ -529,7 +606,7 @@ static const SwfdecActionSpec actions[25 [0x4f] = { "SetMember", NULL }, /* apparently the result is ignored */ [0x50] = { "Increment", NULL }, [0x51] = { "Decrement", NULL }, - [0x52] = { "CallMethod", NULL }, + [0x52] = { "CallMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_call_method, swfdec_action_call_method, swfdec_action_call_method } }, [0x53] = { "NewMethod", NULL }, /* version 6 */ [0x54] = { "InstanceOf", NULL }, @@ -726,7 +803,7 @@ swfdec_script_interpret (SwfdecScript *s guint8 *startpc, *pc, *endpc, *nextpc; JSBool ok = JS_TRUE; void *mark; - jsval *startsp, *endsp; + jsval *startsp, *endsp, *checksp; int stack_check; guint action, len; guint8 *data; @@ -800,6 +877,8 @@ swfdec_script_interpret (SwfdecScript *s goto internal_error; } if (spec->add < 0) { + /* HACK FIXME: if added args are -1, we pass the number of free space on the stack + * instead of the action */ action = endsp - fp->sp; } else { if (fp->sp + spec->add - MAX (spec->remove, 0) > endsp) { @@ -807,9 +886,18 @@ swfdec_script_interpret (SwfdecScript *s goto internal_error; } } + checksp = (spec->add >= 0 && spec->remove >= 0) ? fp->sp + spec->add - spec->remove : NULL; ok = spec->exec[version] (cx, action, data, len); - if (!ok) + if (!ok) { + SWFDEC_WARNING ("action %s failed", spec->name); goto out; + } + if (checksp != NULL && checksp != fp->sp) { + /* check stack was handled like expected */ + g_error ("action %s was supposed to change the stack by %d (+%d -%d), but it changed by %d", + spec->name, spec->add - spec->remove, spec->add, spec->remove, + fp->sp - checksp + spec->add - spec->remove); + } if (fp->pc == pc) { fp->pc = pc = nextpc; } else { diff-tree 5f777f6697273122587f8bcf645e3a81a7f77228 (from 878ec656b0711cd19c11554d0617109a058af799) Author: Benjamin Otte <otte@gnome.org> Date: Thu Jan 18 18:15:51 2007 +0100 implement Trace action includes changing the API to have a swfdec_player_trace function diff --git a/libswfdec/swfdec_js_global.c b/libswfdec/swfdec_js_global.c index daa8f75..328d74d 100644 --- a/libswfdec/swfdec_js_global.c +++ b/libswfdec/swfdec_js_global.c @@ -50,8 +50,7 @@ swfdec_js_trace (JSContext *cx, JSObject if (bytes == NULL) return JS_TRUE; - /* FIXME: accumulate and emit after JS handling? */ - g_signal_emit_by_name (player, "trace", bytes); + swfdec_player_trace (player, bytes); return JS_TRUE; } diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c index 811e7c6..4b29d28 100644 --- a/libswfdec/swfdec_player.c +++ b/libswfdec/swfdec_player.c @@ -837,6 +837,16 @@ swfdec_player_stop_all_sounds (SwfdecPla } void +swfdec_player_trace (SwfdecPlayer *player, const char *text) +{ + g_return_if_fail (SWFDEC_IS_PLAYER (player)); + g_return_if_fail (text != NULL); + + /* FIXME: accumulate and emit after JS handling? */ + g_signal_emit (player, signals[TRACE], 0, text); +} + +void swfdec_player_invalidate (SwfdecPlayer *player, const SwfdecRect *rect) { if (swfdec_rect_is_empty (rect)) { diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h index dd10949..2da8ecc 100644 --- a/libswfdec/swfdec_player_internal.h +++ b/libswfdec/swfdec_player_internal.h @@ -122,6 +122,8 @@ void swfdec_player_set_drag_movie (Swfd SwfdecMovie * drag, gboolean center, SwfdecRect * rect); +void swfdec_player_trace (SwfdecPlayer * player, + const char * text); void swfdec_player_stop_all_sounds (SwfdecPlayer * player); SwfdecRootMovie * swfdec_player_add_level_from_loader (SwfdecPlayer * player, diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 49ad92f..ed5ac44 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -31,6 +31,7 @@ #include "swfdec_decoder.h" #include "swfdec_js.h" #include "swfdec_movie.h" +#include "swfdec_player_internal.h" #include "swfdec_root_movie.h" /*** CONSTANT POOLS ***/ @@ -318,6 +319,20 @@ swfdec_action_get_variable (JSContext *c return JS_TRUE; } +static JSBool +swfdec_action_trace (JSContext *cx, guint action, const guint8 *data, guint len) +{ + SwfdecPlayer *player = JS_GetContextPrivate (cx); + const char *bytes; + + bytes = swfdec_js_to_string (cx, cx->fp->sp[-1]); + if (bytes == NULL) + return JS_TRUE; + + swfdec_player_trace (player, bytes); + return JS_TRUE; +} + /*** PRINT FUNCTIONS ***/ static char * @@ -472,7 +487,7 @@ static const SwfdecActionSpec actions[25 [0x23] = { "SetProperty", NULL }, [0x24] = { "CloneSprite", NULL }, [0x25] = { "RemoveSprite", NULL }, - [0x26] = { "Trace", NULL }, + [0x26] = { "Trace", NULL, 1, 0, { NULL, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace } }, [0x27] = { "StartDrag", NULL }, [0x28] = { "EndDrag", NULL }, [0x29] = { "StringLess", NULL },
Seemingly Similar Threads
- 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
- 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
- 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
- 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