update copyright date
[gnash.git] / plugin / npapi / external.cpp
blob5e18e3c2ef91ccef010f95b368a6d6f20c4a5679
1 //
2 // Copyright (C) 2010, 2011 Free Software Foundation, Inc
3 //
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.
8 //
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
19 #ifdef HAVE_CONFIG_H
20 #include "gnashconfig.h"
21 #endif
23 #include <string>
24 #include <sstream>
25 #include <vector>
26 #include <map>
27 #include <cstring>
28 #include <cstdlib>
30 #include "npapi.h"
31 #include "npruntime.h"
32 #include "external.h"
33 #include "plugin.h"
35 #include <boost/algorithm/string/erase.hpp>
37 namespace gnash {
38 namespace plugin {
40 // Create an Invoke message for the standalone Gnash
41 std::string
42 ExternalInterface::makeInvoke (const std::string &method,
43 std::vector<std::string> args)
45 std::stringstream ss;
46 std::vector<std::string>::iterator it;
48 ss << "<invoke name=\"" << method << "\" returntype=\"xml\">";
49 ss << "<arguments>";
50 for (it=args.begin(); it != args.end(); ++it) {
51 ss << *it;
54 ss << "</arguments>";
55 ss << "</invoke>";
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.
59 ss << std::endl;
61 return ss.str();
64 std::string
65 ExternalInterface::makeNull ()
67 std::stringstream ss;
69 ss << "<null/>";
71 return ss.str();
74 std::string
75 ExternalInterface::makeTrue ()
77 std::stringstream ss;
79 ss << "<true/>";
81 return ss.str();
84 std::string
85 ExternalInterface::makeFalse ()
87 std::stringstream ss;
89 ss << "<false/>";
91 return ss.str();
94 std::string
95 ExternalInterface::makeString (const std::string &str)
97 std::stringstream ss;
99 ss << "<string>" << str << "</string>";
101 return ss.str();
105 std::string
106 ExternalInterface::makeProperty (const std::string &id, double num)
108 std::stringstream ss;
109 ss << num;
110 return makeProperty(id, ss.str());
113 std::string
114 ExternalInterface::makeProperty (const std::string &id, int num)
116 std::stringstream ss;
117 ss << num;
118 return makeProperty(id, ss.str());
121 std::string
122 ExternalInterface::makeProperty (const std::string &id, const std::string &data)
124 std::stringstream ss;
126 ss << "<property id=\"" << id << "\">" << data << "</property>";
128 return ss.str();
131 std::string
132 ExternalInterface::makeNumber (double num)
134 std::stringstream ss;
136 ss << "<number>" << num << "</number>";
138 return ss.str();
141 std::string
142 ExternalInterface::makeNumber (int num)
144 std::stringstream ss;
146 ss << "<number>" << num << "</number>";
148 return ss.str();
151 std::string
152 ExternalInterface::makeNumber (unsigned int num)
154 std::stringstream ss;
156 ss << "<number>" << num << "</number>";
158 return ss.str();
161 std::string
162 ExternalInterface::makeArray (std::vector<std::string> &args)
164 std::stringstream ss;
165 std::vector<std::string>::iterator it;
166 int index = 0;
168 ss << "<array>";
169 for (it=args.begin(); it != args.end(); ++it) {
170 ss << "<property id=\"" << index << "\">" << *it << "</property>";
171 index++;
174 ss << "</array>";
176 return ss.str();
179 std::string
180 ExternalInterface::makeObject (std::map<std::string, std::string> &args)
182 std::stringstream ss;
183 std::map<std::string, std::string>::iterator it;
185 ss << "<object>";
186 for (it = args.begin(); it != args.end(); ++it) {
187 ss << "<property id=\"" << it->first << "\">" << it->second << "</property>";
189 ss << "</object>";
191 return ss.str();
194 // An invoke looks like this:
195 // <invoke name=\"foobar\" returntype=\"xml\">
196 // <arguments>
197 // <string>barfoo</string>
198 // <number>135.78</number>
199 // </arguments>
200 // </invoke>
201 ExternalInterface::invoke_t *
202 ExternalInterface::parseInvoke(const std::string &xml)
204 if (xml.empty()) {
205 return 0;
208 ExternalInterface::invoke_t *invoke = new invoke_t;
210 std::string::size_type start = 0;
211 std::string::size_type end;
212 std::string tag;
214 // Look for the ending > in the first part of the data for the tag
215 end = xml.find(">");
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);
245 return invoke;
248 GnashNPVariant
249 ExternalInterface::parseXML(const std::string &xml)
251 NPVariant value;
252 NULL_TO_NPVARIANT(value);
254 if (xml.empty()) {
255 return value;
257 std::string::size_type start = 0;
258 std::string::size_type end;
259 std::string tag;
261 // Look for the ending > in the first part of the data for the tag
262 end = xml.find(">");
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>") {
276 start = end;
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);
282 } else {
283 int num = strtol(str.c_str(), NULL, 0);
284 INT32_TO_NPVARIANT(num, value);
286 } else if (tag == "<string>") {
287 start = end;
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));
299 start = end;
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));
313 start = end;
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);
330 return rv;
333 std::string
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);
346 if (flag) {
347 ss << "<true/>";
348 } else {
349 ss << "<false/>";
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)) {
355 ss << "<null/>";
356 } else if (NPVARIANT_IS_VOID(*value)) {
357 ss << "<void/>";
358 } else if (NPVARIANT_IS_OBJECT(*value)) {
359 ss << "<object></object>";
362 return ss.str();
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;
373 std::string id;
374 start = xml.find(" id=");
375 while (start != std::string::npos) {
376 // Extract the id from the property tag
377 start++;
378 end = xml.find(">", start) - 1;
379 id = xml.substr(start, end-start);
380 id.erase(0, 4);
382 // Extract the data
383 start = end + 2;
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);
390 return props;
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;
401 std::string name;
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()) {
409 // Extract the data
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>") {
414 break;
416 args.push_back(parseXML(sub));
417 data.erase(0, end);
420 return args;
423 } // namespace plugin
424 } // namespace gnash
426 // local Variables:
427 // mode: C++
428 // indent-tabs-mode: nil
429 // End: