back to development
[swfdec.git] / swfdec / swfdec_amf.c
blob251a764103ee0cbc38f47deee41cc5fb5f7fc99c
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 #ifndef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_amf.h"
25 #include "swfdec_as_array.h"
26 #include "swfdec_as_date.h"
27 #include "swfdec_debug.h"
29 typedef gboolean (* SwfdecAmfParseFunc) (SwfdecAsContext *cx, SwfdecBits *bits, SwfdecAsValue *val);
30 extern const SwfdecAmfParseFunc parse_funcs[SWFDEC_AMF_N_TYPES];
32 static gboolean
33 swfdec_amf_parse_boolean (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
35 SWFDEC_AS_VALUE_SET_BOOLEAN (val, swfdec_bits_get_u8 (bits) ? TRUE : FALSE);
36 return TRUE;
39 static gboolean
40 swfdec_amf_parse_number (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
42 SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_bits_get_bdouble (bits));
43 return TRUE;
46 static gboolean
47 swfdec_amf_parse_string (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
49 guint len = swfdec_bits_get_bu16 (bits);
50 char *s;
52 /* FIXME: the supplied version is likely incorrect */
53 s = swfdec_bits_get_string_length (bits, len, context->version);
54 if (s == NULL)
55 return FALSE;
56 SWFDEC_AS_VALUE_SET_STRING (val, swfdec_as_context_give_string (context, s));
57 return TRUE;
60 static gboolean
61 swfdec_amf_parse_properties (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsObject *object)
63 guint type;
64 SwfdecAmfParseFunc func;
66 while (swfdec_bits_left (bits)) {
67 SwfdecAsValue val;
68 const char *name;
70 if (!swfdec_amf_parse_string (context, bits, &val))
71 return FALSE;
72 name = SWFDEC_AS_VALUE_GET_STRING (&val);
73 type = swfdec_bits_get_u8 (bits);
74 if (type == SWFDEC_AMF_END_OBJECT)
75 break;
76 if (type >= SWFDEC_AMF_N_TYPES ||
77 (func = parse_funcs[type]) == NULL) {
78 SWFDEC_ERROR ("no parse func for AMF type %u", type);
79 goto error;
81 swfdec_as_object_set_variable (object, name, &val); /* GC... */
82 if (!func (context, bits, &val)) {
83 goto error;
85 swfdec_as_object_set_variable (object, name, &val);
87 /* no more bytes seems to end automatically */
88 return TRUE;
90 error:
91 return FALSE;
94 static gboolean
95 swfdec_amf_parse_object (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
97 SwfdecAsObject *object;
99 object = swfdec_as_object_new (context);
100 if (!swfdec_amf_parse_properties (context, bits, object))
101 return FALSE;
102 SWFDEC_AS_VALUE_SET_OBJECT (val, object);
103 return TRUE;
106 static gboolean
107 swfdec_amf_parse_mixed_array (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
109 guint len;
110 SwfdecAsObject *array;
112 len = swfdec_bits_get_bu32 (bits);
113 array = swfdec_as_array_new (context);
114 if (!swfdec_amf_parse_properties (context, bits, array))
115 return FALSE;
116 SWFDEC_AS_VALUE_SET_OBJECT (val, array);
117 return TRUE;
120 static gboolean
121 swfdec_amf_parse_array (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
123 guint i, len;
124 SwfdecAsObject *array;
125 guint type;
126 SwfdecAmfParseFunc func;
128 len = swfdec_bits_get_bu32 (bits);
129 array = swfdec_as_array_new (context);
130 for (i = 0; i < len; i++) {
131 SwfdecAsValue tmp;
132 type = swfdec_bits_get_u8 (bits);
133 if (type >= SWFDEC_AMF_N_TYPES ||
134 (func = parse_funcs[type]) == NULL) {
135 SWFDEC_ERROR ("no parse func for AMF type %u", type);
136 goto fail;
138 if (!func (context, bits, &tmp))
139 goto fail;
140 swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &tmp);
143 SWFDEC_AS_VALUE_SET_OBJECT (val, array);
144 return TRUE;
146 fail:
147 return FALSE;
150 // FIXME: untested
151 static gboolean
152 swfdec_amf_parse_date (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
154 double milliseconds = swfdec_bits_get_bdouble (bits);
155 int utc_offset = swfdec_bits_get_bu16 (bits);
157 if (utc_offset > 12 * 60)
158 utc_offset -= 12 * 60;
160 SWFDEC_AS_VALUE_SET_OBJECT (val,
161 swfdec_as_date_new (context, milliseconds, utc_offset));
162 return TRUE;
165 const SwfdecAmfParseFunc parse_funcs[SWFDEC_AMF_N_TYPES] = {
166 [SWFDEC_AMF_NUMBER] = swfdec_amf_parse_number,
167 [SWFDEC_AMF_BOOLEAN] = swfdec_amf_parse_boolean,
168 [SWFDEC_AMF_STRING] = swfdec_amf_parse_string,
169 [SWFDEC_AMF_OBJECT] = swfdec_amf_parse_object,
170 [SWFDEC_AMF_MIXED_ARRAY] = swfdec_amf_parse_mixed_array,
171 [SWFDEC_AMF_ARRAY] = swfdec_amf_parse_array,
172 [SWFDEC_AMF_DATE] = swfdec_amf_parse_date,
173 #if 0
174 SWFDEC_AMF_MOVIECLIP = 4,
175 SWFDEC_AMF_NULL = 5,
176 SWFDEC_AMF_UNDEFINED = 6,
177 SWFDEC_AMF_REFERENCE = 7,
178 SWFDEC_AMF_END_OBJECT = 9,
179 SWFDEC_AMF_BIG_STRING = 12,
180 SWFDEC_AMF_RECORDSET = 14,
181 SWFDEC_AMF_XML = 15,
182 SWFDEC_AMF_CLASS = 16,
183 SWFDEC_AMF_FLASH9 = 17,
184 #endif
187 gboolean
188 swfdec_amf_parse_one (SwfdecAsContext *context, SwfdecBits *bits,
189 SwfdecAmfType expected_type, SwfdecAsValue *rval)
191 SwfdecAmfParseFunc func;
192 guint type;
194 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0);
195 g_return_val_if_fail (context->global != NULL, 0);
196 g_return_val_if_fail (bits != NULL, FALSE);
197 g_return_val_if_fail (rval != NULL, FALSE);
198 g_return_val_if_fail (expected_type < SWFDEC_AMF_N_TYPES, FALSE);
200 type = swfdec_bits_get_u8 (bits);
201 if (type != expected_type) {
202 SWFDEC_ERROR ("parse object should be type %u, but is %u",
203 expected_type, type);
204 return FALSE;
206 if (type >= SWFDEC_AMF_N_TYPES ||
207 (func = parse_funcs[type]) == NULL) {
208 SWFDEC_ERROR ("no parse func for AMF type %u", type);
209 return FALSE;
211 return func (context, bits, rval);
214 guint
215 swfdec_amf_parse (SwfdecAsContext *context, SwfdecBits *bits, guint n_items, ...)
217 va_list args;
218 guint i;
220 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0);
221 g_return_val_if_fail (context->global != NULL, 0);
222 g_return_val_if_fail (bits != NULL, 0);
224 va_start (args, n_items);
225 for (i = 0; i < n_items; i++) {
226 SwfdecAmfType type = va_arg (args, SwfdecAmfType);
227 SwfdecAsValue *val = va_arg (args, SwfdecAsValue *);
228 if (!swfdec_amf_parse_one (context, bits, type, val))
229 break;
231 va_end (args);
232 return i;