⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swfscript.c

📁 Swfdec is a decoder/renderer for Macromedia Flash animations. The decoding and rendering engine is
💻 C
字号:
/* 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_internal.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 gbooleanswfedit_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 gbooleanaction_in_array (guint *array, guint action){  if (array == NULL)    return FALSE;  while (*array != 0) {    if (*array == action)      return TRUE;    array++;  }  return FALSE;}static guintlookup_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 gbooleanfixup_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 = NULL; /* silence gcc */    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 gbooleanmodify_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 gbooleanmodify_file (SwfeditToken *token, guint idx, const char *name,     SwfeditTokenType type, gconstpointer value, gpointer data){  Action end;  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  script = swfdec_script_new (state.buffer, state.script->name, state.script->version);  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;}intmain (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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -