2 // Copyright (C) 2010, 2011 Free Software Foundation, Inc
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program 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
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "gnashconfig.h"
31 #include "npruntime.h"
35 #include <boost/algorithm/string/erase.hpp>
40 // Create an Invoke message for the standalone Gnash
42 ExternalInterface::makeInvoke (const std::string
&method
,
43 std::vector
<std::string
> args
)
46 std::vector
<std::string
>::iterator it
;
48 ss
<< "<invoke name=\"" << method
<< "\" returntype=\"xml\">";
50 for (it
=args
.begin(); it
!= args
.end(); ++it
) {
57 // Add a CR on the end so the output is more readable on the other
58 // end. XL should be ignoring the CR anyway.
65 ExternalInterface::makeNull ()
75 ExternalInterface::makeTrue ()
85 ExternalInterface::makeFalse ()
95 ExternalInterface::makeString (const std::string
&str
)
99 ss
<< "<string>" << str
<< "</string>";
106 ExternalInterface::makeProperty (const std::string
&id
, double num
)
108 std::stringstream ss
;
110 return makeProperty(id
, ss
.str());
114 ExternalInterface::makeProperty (const std::string
&id
, int num
)
116 std::stringstream ss
;
118 return makeProperty(id
, ss
.str());
122 ExternalInterface::makeProperty (const std::string
&id
, const std::string
&data
)
124 std::stringstream ss
;
126 ss
<< "<property id=\"" << id
<< "\">" << data
<< "</property>";
132 ExternalInterface::makeNumber (double num
)
134 std::stringstream ss
;
136 ss
<< "<number>" << num
<< "</number>";
142 ExternalInterface::makeNumber (int num
)
144 std::stringstream ss
;
146 ss
<< "<number>" << num
<< "</number>";
152 ExternalInterface::makeNumber (unsigned int num
)
154 std::stringstream ss
;
156 ss
<< "<number>" << num
<< "</number>";
162 ExternalInterface::makeArray (std::vector
<std::string
> &args
)
164 std::stringstream ss
;
165 std::vector
<std::string
>::iterator it
;
169 for (it
=args
.begin(); it
!= args
.end(); ++it
) {
170 ss
<< "<property id=\"" << index
<< "\">" << *it
<< "</property>";
180 ExternalInterface::makeObject (std::map
<std::string
, std::string
> &args
)
182 std::stringstream ss
;
183 std::map
<std::string
, std::string
>::iterator it
;
186 for (it
= args
.begin(); it
!= args
.end(); ++it
) {
187 ss
<< "<property id=\"" << it
->first
<< "\">" << it
->second
<< "</property>";
194 // An invoke looks like this:
195 // <invoke name=\"foobar\" returntype=\"xml\">
197 // <string>barfoo</string>
198 // <number>135.78</number>
201 ExternalInterface::invoke_t
*
202 ExternalInterface::parseInvoke(const std::string
&xml
)
208 ExternalInterface::invoke_t
*invoke
= new invoke_t
;
210 std::string::size_type start
= 0;
211 std::string::size_type end
;
214 // Look for the ending > in the first part of the data for the tag
216 if (end
!= std::string::npos
) {
217 end
++; // go past the > character
218 tag
= xml
.substr(start
, end
);
219 // Look for the easy ones first
220 if (tag
.substr(0, 7) == "<invoke") {
221 // extract the name of the method to invoke
222 start
= tag
.find("name=") + 5;
223 end
= tag
.find(" ", start
);
224 invoke
->name
= tag
.substr(start
, end
-start
);
225 // Ignore any quote characters around the string
226 boost::erase_first(invoke
->name
, "\"");
227 boost::erase_last(invoke
->name
, "\"");
229 // extract the return type of the method
230 start
= tag
.find("returntype=") + 11;
231 end
= tag
.find(">", start
);
232 invoke
->type
= tag
.substr(start
, end
-start
);
233 // Ignore any quote characters around the string
234 boost::erase_first(invoke
->type
, "\"");
235 boost::erase_last(invoke
->type
, "\"");
237 // extract the arguments to the method
238 start
= xml
.find("<arguments>");
239 end
= xml
.find("</invoke");
240 tag
= xml
.substr(start
, end
-start
);
241 invoke
->args
= parseArguments(tag
);
249 ExternalInterface::parseXML(const std::string
&xml
)
252 NULL_TO_NPVARIANT(value
);
257 std::string::size_type start
= 0;
258 std::string::size_type end
;
261 // Look for the ending > in the first part of the data for the tag
263 if (end
!= std::string::npos
) {
264 end
++; // go past the > character
265 tag
= xml
.substr(start
, end
);
266 // Look for the easy ones first
267 if (tag
== "<null/>") {
268 NULL_TO_NPVARIANT(value
);
269 } else if (tag
== "<void/>") {
270 VOID_TO_NPVARIANT(value
);
271 } else if (tag
== "<true/>") {
272 BOOLEAN_TO_NPVARIANT(true, value
);
273 } else if (tag
== "<false/>") {
274 BOOLEAN_TO_NPVARIANT(false, value
);
275 } else if (tag
== "<number>") {
277 end
= xml
.find("</number>");
278 std::string str
= xml
.substr(start
, end
-start
);
279 if (str
.find(".") != std::string::npos
) {
280 double num
= strtod(str
.c_str(), NULL
);
281 DOUBLE_TO_NPVARIANT(num
, value
);
283 int num
= strtol(str
.c_str(), NULL
, 0);
284 INT32_TO_NPVARIANT(num
, value
);
286 } else if (tag
== "<string>") {
288 end
= xml
.find("</string>");
289 std::string str
= xml
.substr(start
, end
-start
);
290 int length
= str
.size();;
291 char *data
= (char *)NPN_MemAlloc(length
+1);
292 std::copy(str
.begin(), str
.end(), data
);
293 data
[length
] = 0; // terminate the new string or bad things happen
294 // When an NPVariant becomes a string object, it *does not* make a copy.
295 // Instead it stores the pointer (and length) we just allocated.
296 STRINGN_TO_NPVARIANT(data
, length
, value
);
297 } else if (tag
== "<array>") {
298 NPObject
*obj
= (NPObject
*)NPN_MemAlloc(sizeof(NPObject
));
300 end
= xml
.find("</array");
301 std::string str
= xml
.substr(start
, end
-start
);
302 std::map
<std::string
, GnashNPVariant
> props
= parseProperties(str
);
303 std::map
<std::string
, GnashNPVariant
>::iterator it
;
304 for (it
=props
.begin(); it
!= props
.end(); ++it
) {
305 NPIdentifier id
= NPN_GetStringIdentifier(it
->first
.c_str());
306 GnashNPVariant
& value
= it
->second
;
307 NPN_SetProperty(NULL
, obj
, id
, &value
.get());
309 OBJECT_TO_NPVARIANT(obj
, value
);
310 NPN_RetainObject(obj
);
311 } else if (tag
== "<object>") {
312 NPObject
*obj
= (NPObject
*)NPN_MemAlloc(sizeof(NPObject
));
314 end
= xml
.find("</object");
315 std::string str
= xml
.substr(start
, end
-start
);
316 std::map
<std::string
, GnashNPVariant
> props
= parseProperties(str
);
317 std::map
<std::string
, GnashNPVariant
>::iterator it
;
318 for (it
=props
.begin(); it
!= props
.end(); ++it
) {
319 NPIdentifier id
= NPN_GetStringIdentifier(it
->first
.c_str());
320 GnashNPVariant
& value
= it
->second
;
321 NPN_SetProperty(NULL
, obj
, id
, &value
.get());
323 OBJECT_TO_NPVARIANT(obj
, value
);
324 NPN_RetainObject(obj
);
328 GnashNPVariant
rv(value
);
329 NPN_ReleaseVariantValue(&value
);
334 ExternalInterface::convertNPVariant (const NPVariant
*value
)
336 std::stringstream ss
;
338 if (NPVARIANT_IS_DOUBLE(*value
)) {
339 double num
= NPVARIANT_TO_DOUBLE(*value
);
340 ss
<< "<number>" << num
<< "</number>";
341 } else if (NPVARIANT_IS_STRING(*value
)) {
342 std::string str
= NPStringToString(NPVARIANT_TO_STRING(*value
));
343 ss
<< "<string>" << str
<< "</string>";
344 } else if (NPVARIANT_IS_BOOLEAN(*value
)) {
345 bool flag
= NPVARIANT_TO_BOOLEAN(*value
);
351 } else if (NPVARIANT_IS_INT32(*value
)) {
352 int num
= NPVARIANT_TO_INT32(*value
);
353 ss
<< "<number>" << num
<< "</number>";
354 } else if (NPVARIANT_IS_NULL(*value
)) {
356 } else if (NPVARIANT_IS_VOID(*value
)) {
358 } else if (NPVARIANT_IS_OBJECT(*value
)) {
359 ss
<< "<object></object>";
365 std::map
<std::string
, GnashNPVariant
>
366 ExternalInterface::parseProperties(const std::string
&xml
)
368 std::map
<std::string
, GnashNPVariant
> props
;
370 std::string::size_type start
= 0;
371 std::string::size_type end
;
374 start
= xml
.find(" id=");
375 while (start
!= std::string::npos
) {
376 // Extract the id from the property tag
378 end
= xml
.find(">", start
) - 1;
379 id
= xml
.substr(start
, end
-start
);
384 end
= xml
.find("</property>", start
) ;
385 std::string data
= xml
.substr(start
, end
-start
);
386 props
[id
] = parseXML(data
);
387 start
= xml
.find(" id=", end
);
393 std::vector
<GnashNPVariant
>
394 ExternalInterface::parseArguments(const std::string
&xml
)
396 std::vector
<GnashNPVariant
> args
;
398 std::string::size_type start
= 0;
399 std::string::size_type end
;
402 std::string data
= xml
;
403 std::string tag
= "<arguments>";
404 start
= data
.find(tag
);
405 if (start
!= std::string::npos
) {
406 data
.erase(0, tag
.size());
408 while (!data
.empty()) {
410 start
= data
.find("<", 1); // start past the opening <
411 end
= data
.find(">", start
) + 1;
412 std::string sub
= data
.substr(0, end
);
413 if (data
== "</arguments>") {
416 args
.push_back(parseXML(sub
));
423 } // namespace plugin
428 // indent-tabs-mode: nil