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_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
];
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
);
40 swfdec_amf_parse_number (SwfdecAsContext
*context
, SwfdecBits
*bits
, SwfdecAsValue
*val
)
42 SWFDEC_AS_VALUE_SET_NUMBER (val
, swfdec_bits_get_bdouble (bits
));
47 swfdec_amf_parse_string (SwfdecAsContext
*context
, SwfdecBits
*bits
, SwfdecAsValue
*val
)
49 guint len
= swfdec_bits_get_bu16 (bits
);
52 /* FIXME: the supplied version is likely incorrect */
53 s
= swfdec_bits_get_string_length (bits
, len
, context
->version
);
56 SWFDEC_AS_VALUE_SET_STRING (val
, swfdec_as_context_give_string (context
, s
));
61 swfdec_amf_parse_properties (SwfdecAsContext
*context
, SwfdecBits
*bits
, SwfdecAsObject
*object
)
64 SwfdecAmfParseFunc func
;
66 while (swfdec_bits_left (bits
)) {
70 if (!swfdec_amf_parse_string (context
, bits
, &val
))
72 name
= SWFDEC_AS_VALUE_GET_STRING (&val
);
73 type
= swfdec_bits_get_u8 (bits
);
74 if (type
== SWFDEC_AMF_END_OBJECT
)
76 if (type
>= SWFDEC_AMF_N_TYPES
||
77 (func
= parse_funcs
[type
]) == NULL
) {
78 SWFDEC_ERROR ("no parse func for AMF type %u", type
);
81 swfdec_as_object_set_variable (object
, name
, &val
); /* GC... */
82 if (!func (context
, bits
, &val
)) {
85 swfdec_as_object_set_variable (object
, name
, &val
);
87 /* no more bytes seems to end automatically */
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
))
102 SWFDEC_AS_VALUE_SET_OBJECT (val
, object
);
107 swfdec_amf_parse_mixed_array (SwfdecAsContext
*context
, SwfdecBits
*bits
, SwfdecAsValue
*val
)
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
))
116 SWFDEC_AS_VALUE_SET_OBJECT (val
, array
);
121 swfdec_amf_parse_array (SwfdecAsContext
*context
, SwfdecBits
*bits
, SwfdecAsValue
*val
)
124 SwfdecAsObject
*array
;
126 SwfdecAmfParseFunc func
;
128 len
= swfdec_bits_get_bu32 (bits
);
129 array
= swfdec_as_array_new (context
);
130 for (i
= 0; i
< len
; i
++) {
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
);
138 if (!func (context
, bits
, &tmp
))
140 swfdec_as_array_push (SWFDEC_AS_ARRAY (array
), &tmp
);
143 SWFDEC_AS_VALUE_SET_OBJECT (val
, array
);
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
));
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
,
174 SWFDEC_AMF_MOVIECLIP
= 4,
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,
182 SWFDEC_AMF_CLASS
= 16,
183 SWFDEC_AMF_FLASH9
= 17,
188 swfdec_amf_parse_one (SwfdecAsContext
*context
, SwfdecBits
*bits
,
189 SwfdecAmfType expected_type
, SwfdecAsValue
*rval
)
191 SwfdecAmfParseFunc func
;
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
);
206 if (type
>= SWFDEC_AMF_N_TYPES
||
207 (func
= parse_funcs
[type
]) == NULL
) {
208 SWFDEC_ERROR ("no parse func for AMF type %u", type
);
211 return func (context
, bits
, rval
);
215 swfdec_amf_parse (SwfdecAsContext
*context
, SwfdecBits
*bits
, guint n_items
, ...)
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
))