make swfdec_as_object_mark() only mark if not marked yet
[swfdec.git] / swfdec / swfdec_load_object_as.c
blobd69db1177a018c8f6423d24e48010417438b6d53
1 /* Swfdec
2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
3 * 2007 Pekka Lampila <pekka.lampila@iki.fi>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include <string.h>
26 #include "swfdec_load_object.h"
27 #include "swfdec_as_internal.h"
28 #include "swfdec_as_strings.h"
29 #include "swfdec_debug.h"
30 #include "swfdec_loader_internal.h"
31 #include "swfdec_player_internal.h"
33 static void
34 swfdec_load_object_on_finish (SwfdecPlayer *player, const SwfdecAsValue *target, const char *text)
36 SwfdecAsObject *object;
37 SwfdecAsValue val;
39 object = SWFDEC_AS_VALUE_GET_COMPOSITE (target);
40 if (object == NULL)
41 return;
43 if (text != NULL) {
44 SWFDEC_AS_VALUE_SET_STRING (&val, text);
45 } else {
46 SWFDEC_AS_VALUE_SET_UNDEFINED (&val);
49 swfdec_as_object_call (object, SWFDEC_AS_STR_onData, 1, &val, NULL);
52 static void
53 swfdec_load_object_on_progress (SwfdecPlayer *player, const SwfdecAsValue *target,
54 glong size, glong loaded)
56 SwfdecAsContext *cx = SWFDEC_AS_CONTEXT (player);
57 SwfdecAsObject *object;
58 SwfdecAsValue val;
60 object = SWFDEC_AS_VALUE_GET_COMPOSITE (target);
61 if (object == NULL)
62 return;
63 swfdec_as_value_set_number (cx, &val, loaded);
64 swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR__bytesLoaded,
65 &val, SWFDEC_AS_VARIABLE_HIDDEN);
67 if (size >= 0) {
68 swfdec_as_value_set_number (cx, &val, size);
69 } else {
70 swfdec_as_value_set_number (cx, &val, loaded);
72 swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR__bytesTotal,
73 &val, SWFDEC_AS_VARIABLE_HIDDEN);
76 SWFDEC_AS_NATIVE (301, 0, swfdec_load_object_as_load)
77 void
78 swfdec_load_object_as_load (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
79 SwfdecAsValue *argv, SwfdecAsValue *rval)
81 SwfdecAsValue val;
82 const char *url;
84 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, FALSE);
85 SWFDEC_AS_CHECK (0, NULL, "s", &url);
86 if (object == NULL)
87 return;
89 SWFDEC_AS_VALUE_SET_COMPOSITE (&val, object);
90 swfdec_load_object_create (SWFDEC_PLAYER (cx), &val, url, NULL, 0, NULL, NULL,
91 swfdec_load_object_on_progress, swfdec_load_object_on_finish);
93 swfdec_as_value_set_integer (cx, &val, 0);
94 swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR__bytesLoaded,
95 &val, SWFDEC_AS_VARIABLE_HIDDEN);
96 SWFDEC_AS_VALUE_SET_UNDEFINED (&val);
97 swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR__bytesTotal,
98 &val, SWFDEC_AS_VARIABLE_HIDDEN);
100 SWFDEC_AS_VALUE_SET_BOOLEAN (&val, FALSE);
101 swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_loaded, &val,
102 SWFDEC_AS_VARIABLE_HIDDEN);
104 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, TRUE);
107 #define ALLOWED_CHARACTERS " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
108 static void
109 swfdec_load_object_as_get_headers (SwfdecAsObject *object, guint *header_count,
110 char ***header_names, char ***header_values)
112 // Should these be filtered at some other point instead?
113 static const char *disallowed_names[] = { "Accept-Ranges", "Age", "Allow",
114 "Allowed", "Connection", "Content-Length", "Content-Location",
115 "Content-Range", "ETag", "Host", "Last-Modified", "Location",
116 "Max-Forwards", "Proxy-Authenticate", "Proxy-Authorization", "Public",
117 "Range", "Referer", "Retry-After", "Server", "TE", "Trailer",
118 "Transfer-Encoding", "Upgrade", "URI", "Vary", "Via", "Warning",
119 "WWW-Authenticate", "x-flash-version" };
120 GPtrArray *array_names, *array_values;
121 SwfdecAsValue val;
122 SwfdecAsObject *list;
123 int i, length;
124 guint j;
125 const char *name;
126 SwfdecAsContext *cx;
128 cx = object->context;
130 array_names = g_ptr_array_new ();
131 array_values = g_ptr_array_new ();
133 if (swfdec_as_object_get_variable (object, SWFDEC_AS_STR_contentType, &val))
135 g_ptr_array_add (array_names, g_strdup (SWFDEC_AS_STR_Content_Type));
136 g_ptr_array_add (array_values,
137 g_strdup (swfdec_as_value_to_string (cx, val)));
140 if (!swfdec_as_object_get_variable (object, SWFDEC_AS_STR__customHeaders,
141 &val))
142 goto end;
143 if (!SWFDEC_AS_VALUE_IS_COMPOSITE (&val)) {
144 SWFDEC_WARNING ("_customHeaders is not an object");
145 goto end;
147 list = SWFDEC_AS_VALUE_GET_COMPOSITE (&val);
149 swfdec_as_object_get_variable (list, SWFDEC_AS_STR_length, &val);
150 length = swfdec_as_value_to_integer (cx, &val);
152 /* FIXME: solve this with foreach, so it gets faster for weird cases */
153 name = NULL;
154 for (i = 0; i < length; i++) {
155 swfdec_as_object_get_variable (list, swfdec_as_integer_to_string (cx, i),
156 &val);
157 if (name == NULL) {
158 name = swfdec_as_value_to_string (cx, val);
159 } else {
160 const char *value = swfdec_as_value_to_string (cx, val);
161 for (j = 0; j < G_N_ELEMENTS (disallowed_names); j++) {
162 if (g_ascii_strcasecmp (name, disallowed_names[j]) == 0)
163 break;
165 if (j < G_N_ELEMENTS (disallowed_names)) {
166 SWFDEC_WARNING ("Custom header with name %s is not allowed", name);
167 } else if (strspn (name, ALLOWED_CHARACTERS) != strlen (name) || strchr (name, ':') != NULL || strchr (name, ' ') != NULL) {
168 SWFDEC_WARNING ("Custom header's name (%s) contains characters that are not allowed", name);
169 } else if (strspn (value, ALLOWED_CHARACTERS) != strlen (value)) {
170 SWFDEC_WARNING ("Custom header's value (%s) contains characters that are not allowed", value);
171 } else {
172 g_ptr_array_add (array_names, g_strdup (name));
173 g_ptr_array_add (array_values, g_strdup (value));
175 name = NULL;
178 // if there is uneven amount of elements, just ignore the last one
179 if (name != NULL)
180 SWFDEC_WARNING ("_customHeaders with uneven amount of elements");
182 end:
183 g_assert (array_names->len == array_values->len);
184 *header_count = array_names->len;
185 g_ptr_array_add (array_names, NULL);
186 g_ptr_array_add (array_values, NULL);
187 *header_names = (char **)g_ptr_array_free (array_names, FALSE);
188 *header_values = (char **)g_ptr_array_free (array_values, FALSE);
190 #undef ALLOWED_CHARACTERS
192 SWFDEC_AS_NATIVE (301, 1, swfdec_load_object_as_send)
193 void
194 swfdec_load_object_as_send (SwfdecAsContext *cx, SwfdecAsObject *object,
195 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
197 const char *url, *target = SWFDEC_AS_STR_EMPTY, *method = NULL, *data;
198 guint header_count;
199 char **header_names, **header_values;
200 SwfdecAsValue val;
201 SwfdecBuffer *buffer;
203 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, FALSE);
204 SWFDEC_AS_CHECK (0, NULL, "s|ss", &url, &target, &method);
205 if (object == NULL)
206 return;
208 SWFDEC_AS_VALUE_SET_COMPOSITE (&val, object);
209 data = swfdec_as_value_to_string (cx, val);
211 if (method == NULL || g_ascii_strcasecmp (method, "GET") == 0) {
212 url = swfdec_as_context_give_string (cx,
213 g_strjoin (NULL, url, "?", data, NULL));
214 buffer = NULL;
215 } else {
216 // don't send the nul-byte
217 buffer = swfdec_buffer_new_for_data (g_memdup (data, strlen (data)),
218 strlen (data));
221 swfdec_load_object_as_get_headers (object, &header_count, &header_names,
222 &header_values);
223 swfdec_player_launch_with_headers (SWFDEC_PLAYER (cx), url, target, buffer,
224 header_count, header_names, header_values);
226 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, TRUE);
229 SWFDEC_AS_NATIVE (301, 2, swfdec_load_object_as_sendAndLoad)
230 void
231 swfdec_load_object_as_sendAndLoad (SwfdecAsContext *cx, SwfdecAsObject *object,
232 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
234 const char *url, *data, *method = NULL;
235 guint header_count;
236 char **header_names, **header_values;
237 SwfdecAsObject *target;
238 SwfdecAsValue val;
239 SwfdecBuffer *buffer;
241 SWFDEC_AS_CHECK (0, NULL, "so|s", &url, &target,
242 &method);
243 if (object == NULL)
244 return;
246 SWFDEC_AS_VALUE_SET_COMPOSITE (&val, object);
247 data = swfdec_as_value_to_string (cx, val);
249 if (method != NULL && g_ascii_strcasecmp (method, "GET") == 0) {
250 url = swfdec_as_context_give_string (cx,
251 g_strjoin (NULL, url, "?", data, NULL));
252 buffer = NULL;
253 } else {
254 gsize len = strlen (data);
255 // don't send the nul-byte
256 buffer = swfdec_buffer_new_for_data (g_memdup (data, len), len);
259 swfdec_load_object_as_get_headers (object, &header_count, &header_names,
260 &header_values);
261 SWFDEC_AS_VALUE_SET_COMPOSITE (&val, target);
262 swfdec_load_object_create (SWFDEC_PLAYER (cx), &val, url, buffer, header_count, header_names,
263 header_values, swfdec_load_object_on_progress,
264 swfdec_load_object_on_finish);
266 swfdec_as_value_set_integer (cx, &val, 0);
267 swfdec_as_object_set_variable_and_flags (target, SWFDEC_AS_STR__bytesLoaded,
268 &val, SWFDEC_AS_VARIABLE_HIDDEN);
269 SWFDEC_AS_VALUE_SET_UNDEFINED (&val);
270 swfdec_as_object_set_variable_and_flags (target, SWFDEC_AS_STR__bytesTotal,
271 &val, SWFDEC_AS_VARIABLE_HIDDEN);
273 SWFDEC_AS_VALUE_SET_BOOLEAN (&val, FALSE);
274 swfdec_as_object_set_variable_and_flags (target, SWFDEC_AS_STR_loaded, &val,
275 SWFDEC_AS_VARIABLE_HIDDEN);
277 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, TRUE);