back to development
[swfdec.git] / swfdec / swfdec_sandbox.c
blobf468a075e880707ed0be72d0e0aabdb0d6a8964d
1 /* Swfdec
2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_sandbox.h"
25 #include "swfdec_as_internal.h"
26 #include "swfdec_debug.h"
27 #include "swfdec_initialize.h"
28 #include "swfdec_internal.h"
29 #include "swfdec_player_internal.h"
31 /*** GTK-DOC ***/
33 /**
34 * SECTION:SwfdecSandbox
35 * @title: SwfdecSandbox
36 * @short_description: global object used for security
38 * The SwfdecSandbox object is a garbage-collected script object that does two
39 * things. The simple thing is its use as the global object while code is
40 * executed in a #SwfdecPlayer. So you can always assume that the global object
41 * is a #SwfdecSandbox. The second task it fulfills is acting as the security
42 * mechanism used by native functions to determine if a given action should be
43 * allowed or not. This is easy, because script functions can always refer to
44 * it as the global object.
47 G_DEFINE_TYPE (SwfdecSandbox, swfdec_sandbox, SWFDEC_TYPE_AS_OBJECT)
49 static void
50 swfdec_sandbox_mark (SwfdecGcObject *object)
52 SwfdecSandbox *sandbox = SWFDEC_SANDBOX (object);
54 swfdec_gc_object_mark (sandbox->Function);
55 swfdec_gc_object_mark (sandbox->Function_prototype);
56 swfdec_gc_object_mark (sandbox->Object);
57 swfdec_gc_object_mark (sandbox->Object_prototype);
58 swfdec_gc_object_mark (sandbox->MovieClip);
59 swfdec_gc_object_mark (sandbox->Video);
61 SWFDEC_GC_OBJECT_CLASS (swfdec_sandbox_parent_class)->mark (object);
64 static void
65 swfdec_sandbox_dispose (GObject *object)
67 SwfdecSandbox *sandbox = SWFDEC_SANDBOX (object);
69 swfdec_url_free (sandbox->url);
71 G_OBJECT_CLASS (swfdec_sandbox_parent_class)->dispose (object);
74 static void
75 swfdec_sandbox_class_init (SwfdecSandboxClass *klass)
77 GObjectClass *object_class = G_OBJECT_CLASS (klass);
78 SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
80 object_class->dispose = swfdec_sandbox_dispose;
82 gc_class->mark = swfdec_sandbox_mark;
85 static void
86 swfdec_sandbox_init (SwfdecSandbox *sandbox)
88 sandbox->type = SWFDEC_SANDBOX_NONE;
91 static void
92 swfdec_sandbox_initialize (SwfdecSandbox *sandbox, guint version)
94 SwfdecAsContext *context = swfdec_gc_object_get_context (sandbox);
95 SwfdecPlayer *player = SWFDEC_PLAYER (context);
97 swfdec_sandbox_use (sandbox);
98 if (context->state == SWFDEC_AS_CONTEXT_RUNNING)
99 context->state = SWFDEC_AS_CONTEXT_NEW;
100 swfdec_as_context_startup (context);
101 /* reset state for initialization */
102 /* FIXME: have a better way to do this */
103 context->state = SWFDEC_AS_CONTEXT_NEW;
104 swfdec_sprite_movie_init_context (player);
105 swfdec_video_movie_init_context (player);
106 swfdec_net_stream_init_context (player);
108 swfdec_as_context_run_init_script (context, swfdec_initialize,
109 sizeof (swfdec_initialize), version);
111 sandbox->Function = context->Function;
112 sandbox->Function_prototype = context->Function_prototype;
113 sandbox->Object = context->Object;
114 sandbox->Object_prototype = context->Object_prototype;
116 if (context->state == SWFDEC_AS_CONTEXT_NEW)
117 context->state = SWFDEC_AS_CONTEXT_RUNNING;
118 swfdec_sandbox_unuse (sandbox);
122 * swfdec_sandbox_set_allow_network:
123 * @sandbox: a #SwfdecSandbox
124 * @network: %TRUE if network access is possible
126 * Checks if the given sandbox may be loaded and if so initializes its type.
127 * This function should be called on every new sandbox.
129 * Returns: %TRUE if the sandbox initialization could be finished as requested,
130 * %FALSE if not and it shouldn't be used.
132 static gboolean
133 swfdec_sandbox_set_allow_network (SwfdecSandbox *sandbox, gboolean network)
135 g_return_val_if_fail (SWFDEC_IS_SANDBOX (sandbox), FALSE);
137 switch (sandbox->type) {
138 case SWFDEC_SANDBOX_REMOTE:
139 return TRUE;
140 case SWFDEC_SANDBOX_LOCAL_FILE:
141 return !network;
142 case SWFDEC_SANDBOX_LOCAL_NETWORK:
143 return network;
144 case SWFDEC_SANDBOX_LOCAL_TRUSTED:
145 return TRUE;
146 case SWFDEC_SANDBOX_NONE:
147 break;
148 default:
149 g_assert_not_reached ();
150 break;
153 if (swfdec_url_is_local (sandbox->url)) {
154 sandbox->type = network ? SWFDEC_SANDBOX_LOCAL_NETWORK : SWFDEC_SANDBOX_LOCAL_FILE;
155 } else {
156 sandbox->type = SWFDEC_SANDBOX_REMOTE;
159 return TRUE;
163 * swfdec_sandbox_get_for_url:
164 * @player: a #SwfdecPlayer
165 * @url: the URL this player refers to
166 * @flash_version: The Flash version for looking up the sandbox
167 * @allow_network: %TRUE to allow network access, %FALSE to only allow local
168 * file access. See the documentation of the use_network flag
169 * of the SWF FileAttributes tag for what that means.
171 * Checks if a sandbox is already in use for a given URL and if so, returns it.
172 * Otherwise a new sandbox is created, initialized and returned.
173 * Note that the given url must be a HTTP, HTTPS or a FILE url.
175 * Returns: the sandbox corresponding to the given URL or %NULL if no such
176 * sandbox is allowed.
178 SwfdecSandbox *
179 swfdec_sandbox_get_for_url (SwfdecPlayer *player, const SwfdecURL *url,
180 guint flash_version, gboolean allow_network)
182 SwfdecPlayerPrivate *priv;
183 SwfdecSandbox *sandbox;
184 SwfdecURL *real;
185 guint as_version;
186 GSList *walk;
188 g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
189 g_return_val_if_fail (url != NULL, NULL);
191 priv = player->priv;
192 real = swfdec_url_new_components (swfdec_url_get_protocol (url),
193 swfdec_url_get_host (url), swfdec_url_get_port (url), NULL, NULL);
194 as_version = flash_version < 7 ? 1 : 2;
196 for (walk = priv->sandboxes; walk; walk = walk->next) {
197 sandbox = walk->data;
198 if (sandbox->as_version == as_version &&
199 swfdec_url_equal (sandbox->url, real))
200 break;
203 if (walk) {
204 swfdec_url_free (real);
206 if (!swfdec_sandbox_set_allow_network (sandbox, allow_network))
207 return NULL;
208 } else {
209 SwfdecAsContext *context = SWFDEC_AS_CONTEXT (player);
211 sandbox = g_object_new (SWFDEC_TYPE_SANDBOX, "context", context, NULL);
212 sandbox->url = real;
213 sandbox->as_version = as_version;
214 priv->sandboxes = g_slist_append (priv->sandboxes, sandbox);
216 if (!swfdec_sandbox_set_allow_network (sandbox, allow_network))
217 return NULL;
219 swfdec_sandbox_initialize (sandbox, flash_version);
223 return sandbox;
227 * swfdec_sandbox_use:
228 * @sandbox: the sandbox to use when executing scripts
230 * Sets @sandbox to be used for scripts that are going to be executed next. No
231 * sandbox may be set yet. You must unset the sandbox with
232 * swfdec_sandbox_unuse() after calling your script.
234 void
235 swfdec_sandbox_use (SwfdecSandbox *sandbox)
237 SwfdecAsContext *context;
238 SwfdecPlayerPrivate *priv;
240 g_return_if_fail (SWFDEC_IS_SANDBOX (sandbox));
241 g_return_if_fail (sandbox->type != SWFDEC_SANDBOX_NONE);
242 g_return_if_fail (swfdec_gc_object_get_context (sandbox)->global == NULL);
244 context = swfdec_gc_object_get_context (sandbox);
245 priv = SWFDEC_PLAYER (context)->priv;
246 context->global = SWFDEC_AS_OBJECT (sandbox);
248 context->Function = sandbox->Function;
249 context->Function_prototype = sandbox->Function_prototype;
250 context->Object = sandbox->Object;
251 context->Object_prototype = sandbox->Object_prototype;
255 * swfdec_sandbox_try_use:
256 * @sandbox: the sandbox to use
258 * Makes sure a sandbox is in use. If no sandbox is in use currently, use the
259 * given @sandbox. This function is intended for cases where code can be called
260 * from both inside scripts with a sandbox already set or outside with no
261 * sandbox in use.
263 * Returns: %TRUE if the new sandbox will be used. You need to call
264 * swfdec_sandbox_unuse() afterwards. %FALSE if a sandbox is already in
265 * use.
267 gboolean
268 swfdec_sandbox_try_use (SwfdecSandbox *sandbox)
270 g_return_val_if_fail (SWFDEC_IS_SANDBOX (sandbox), FALSE);
271 g_return_val_if_fail (sandbox->type != SWFDEC_SANDBOX_NONE, FALSE);
273 if (swfdec_gc_object_get_context (sandbox)->global)
274 return FALSE;
276 swfdec_sandbox_use (sandbox);
277 return TRUE;
281 * swfdec_sandbox_unuse:
282 * @sandbox: a #SwfdecSandbox
284 * Unsets the sandbox as the current sandbox for executing scripts.
286 void
287 swfdec_sandbox_unuse (SwfdecSandbox *sandbox)
289 SwfdecAsContext *context;
291 g_return_if_fail (SWFDEC_IS_SANDBOX (sandbox));
292 g_return_if_fail (swfdec_gc_object_get_context (sandbox)->global == SWFDEC_AS_OBJECT (sandbox));
294 context = swfdec_gc_object_get_context (sandbox);
295 context->global = NULL;
296 context->Function = NULL;
297 context->Function_prototype = NULL;
298 context->Object = NULL;
299 context->Object_prototype = NULL;