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.
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
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"
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_RELAY
)
50 swfdec_sandbox_dispose (GObject
*object
)
52 SwfdecSandbox
*sandbox
= SWFDEC_SANDBOX (object
);
54 swfdec_url_free (sandbox
->url
);
56 G_OBJECT_CLASS (swfdec_sandbox_parent_class
)->dispose (object
);
60 swfdec_sandbox_class_init (SwfdecSandboxClass
*klass
)
62 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
64 object_class
->dispose
= swfdec_sandbox_dispose
;
68 swfdec_sandbox_init (SwfdecSandbox
*sandbox
)
70 sandbox
->type
= SWFDEC_SANDBOX_NONE
;
74 swfdec_sandbox_initialize (SwfdecSandbox
*sandbox
, guint version
)
76 SwfdecAsContext
*context
= swfdec_gc_object_get_context (sandbox
);
77 SwfdecPlayer
*player
= SWFDEC_PLAYER (context
);
79 swfdec_sandbox_use (sandbox
);
80 if (context
->state
== SWFDEC_AS_CONTEXT_RUNNING
)
81 context
->state
= SWFDEC_AS_CONTEXT_NEW
;
82 swfdec_as_context_startup (context
);
83 /* reset state for initialization */
84 /* FIXME: have a better way to do this */
85 context
->state
= SWFDEC_AS_CONTEXT_NEW
;
86 swfdec_net_stream_init_context (player
);
88 swfdec_as_context_run_init_script (context
, swfdec_initialize
,
89 sizeof (swfdec_initialize
), version
);
91 if (context
->state
== SWFDEC_AS_CONTEXT_NEW
)
92 context
->state
= SWFDEC_AS_CONTEXT_RUNNING
;
93 swfdec_sandbox_unuse (sandbox
);
97 * swfdec_sandbox_set_allow_network:
98 * @sandbox: a #SwfdecSandbox
99 * @network: %TRUE if network access is possible
101 * Checks if the given sandbox may be loaded and if so initializes its type.
102 * This function should be called on every new sandbox.
104 * Returns: %TRUE if the sandbox initialization could be finished as requested,
105 * %FALSE if not and it shouldn't be used.
108 swfdec_sandbox_set_allow_network (SwfdecSandbox
*sandbox
, gboolean network
)
110 g_return_val_if_fail (SWFDEC_IS_SANDBOX (sandbox
), FALSE
);
112 switch (sandbox
->type
) {
113 case SWFDEC_SANDBOX_REMOTE
:
115 case SWFDEC_SANDBOX_LOCAL_FILE
:
117 case SWFDEC_SANDBOX_LOCAL_NETWORK
:
119 case SWFDEC_SANDBOX_LOCAL_TRUSTED
:
121 case SWFDEC_SANDBOX_NONE
:
124 g_assert_not_reached ();
128 if (swfdec_url_is_local (sandbox
->url
)) {
129 sandbox
->type
= network
? SWFDEC_SANDBOX_LOCAL_NETWORK
: SWFDEC_SANDBOX_LOCAL_FILE
;
131 sandbox
->type
= SWFDEC_SANDBOX_REMOTE
;
138 * swfdec_sandbox_get_for_url:
139 * @player: a #SwfdecPlayer
140 * @url: the URL this player refers to
141 * @flash_version: The Flash version for looking up the sandbox
142 * @allow_network: %TRUE to allow network access, %FALSE to only allow local
143 * file access. See the documentation of the use_network flag
144 * of the SWF FileAttributes tag for what that means.
146 * Checks if a sandbox is already in use for a given URL and if so, returns it.
147 * Otherwise a new sandbox is created, initialized and returned.
148 * Note that the given url must be a HTTP, HTTPS or a FILE url.
150 * Returns: the sandbox corresponding to the given URL or %NULL if no such
151 * sandbox is allowed.
154 swfdec_sandbox_get_for_url (SwfdecPlayer
*player
, const SwfdecURL
*url
,
155 guint flash_version
, gboolean allow_network
)
157 SwfdecPlayerPrivate
*priv
;
158 SwfdecSandbox
*sandbox
;
163 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
164 g_return_val_if_fail (url
!= NULL
, NULL
);
167 real
= swfdec_url_new_components (swfdec_url_get_protocol (url
),
168 swfdec_url_get_host (url
), swfdec_url_get_port (url
), NULL
, NULL
);
169 as_version
= flash_version
< 7 ? 1 : 2;
171 for (walk
= priv
->sandboxes
; walk
; walk
= walk
->next
) {
172 sandbox
= walk
->data
;
173 if (sandbox
->as_version
== as_version
&&
174 swfdec_url_equal (sandbox
->url
, real
))
179 swfdec_url_free (real
);
181 if (!swfdec_sandbox_set_allow_network (sandbox
, allow_network
))
184 SwfdecAsContext
*context
= SWFDEC_AS_CONTEXT (player
);
185 SwfdecAsObject
*object
;
187 sandbox
= g_object_new (SWFDEC_TYPE_SANDBOX
, "context", context
, NULL
);
189 sandbox
->as_version
= as_version
;
190 priv
->sandboxes
= g_slist_append (priv
->sandboxes
, sandbox
);
192 if (!swfdec_sandbox_set_allow_network (sandbox
, allow_network
))
195 object
= swfdec_as_object_new_empty (context
);
196 swfdec_as_object_set_relay (object
, SWFDEC_AS_RELAY (sandbox
));
198 swfdec_sandbox_initialize (sandbox
, flash_version
);
205 * swfdec_sandbox_get:
206 * @player: a SwfdecPlayer
208 * Gets the currently in-use sandbox.
210 * Returns: A #SwfdecSandbox
213 swfdec_sandbox_get (SwfdecPlayer
*player
)
215 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
216 g_return_val_if_fail (SWFDEC_AS_CONTEXT (player
)->global
!= NULL
, NULL
);
217 g_return_val_if_fail (SWFDEC_IS_SANDBOX (SWFDEC_AS_CONTEXT (player
)->global
->relay
), NULL
);
219 return SWFDEC_SANDBOX (SWFDEC_AS_CONTEXT (player
)->global
->relay
);
223 * swfdec_sandbox_use:
224 * @sandbox: the sandbox to use when executing scripts
226 * Sets @sandbox to be used for scripts that are going to be executed next. No
227 * sandbox may be set yet. You must unset the sandbox with
228 * swfdec_sandbox_unuse() after calling your script.
231 swfdec_sandbox_use (SwfdecSandbox
*sandbox
)
233 SwfdecAsContext
*context
;
234 SwfdecPlayerPrivate
*priv
;
236 g_return_if_fail (SWFDEC_IS_SANDBOX (sandbox
));
237 g_return_if_fail (sandbox
->type
!= SWFDEC_SANDBOX_NONE
);
238 g_return_if_fail (swfdec_gc_object_get_context (sandbox
)->global
== NULL
);
240 context
= swfdec_gc_object_get_context (sandbox
);
241 priv
= SWFDEC_PLAYER (context
)->priv
;
242 context
->global
= swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (sandbox
));
246 * swfdec_sandbox_try_use:
247 * @sandbox: the sandbox to use
249 * Makes sure a sandbox is in use. If no sandbox is in use currently, use the
250 * given @sandbox. This function is intended for cases where code can be called
251 * from both inside scripts with a sandbox already set or outside with no
254 * Returns: %TRUE if the new sandbox will be used. You need to call
255 * swfdec_sandbox_unuse() afterwards. %FALSE if a sandbox is already in
259 swfdec_sandbox_try_use (SwfdecSandbox
*sandbox
)
261 g_return_val_if_fail (SWFDEC_IS_SANDBOX (sandbox
), FALSE
);
262 g_return_val_if_fail (sandbox
->type
!= SWFDEC_SANDBOX_NONE
, FALSE
);
264 if (swfdec_gc_object_get_context (sandbox
)->global
)
267 swfdec_sandbox_use (sandbox
);
272 * swfdec_sandbox_unuse:
273 * @sandbox: a #SwfdecSandbox
275 * Unsets the sandbox as the current sandbox for executing scripts.
278 swfdec_sandbox_unuse (SwfdecSandbox
*sandbox
)
280 SwfdecAsContext
*context
;
282 g_return_if_fail (SWFDEC_IS_SANDBOX (sandbox
));
283 g_return_if_fail (swfdec_gc_object_get_context (sandbox
)->global
!= NULL
);
284 g_return_if_fail (swfdec_gc_object_get_context (sandbox
)->global
->relay
== SWFDEC_AS_RELAY (sandbox
));
286 context
= swfdec_gc_object_get_context (sandbox
);
287 context
->global
= NULL
;
291 swfdec_sandbox_allow (SwfdecSandbox
*sandbox
, SwfdecSandbox
*other
)
293 g_return_val_if_fail (SWFDEC_IS_SANDBOX (sandbox
), FALSE
);
294 g_return_val_if_fail (SWFDEC_IS_SANDBOX (other
), FALSE
);
296 SWFDEC_FIXME ("implement script sandbox interaction");