[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog server/Makefile.am server/asobj...
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] gnash ChangeLog server/Makefile.am server/asobj... |
Date: |
Fri, 24 Nov 2006 09:19:51 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Sandro Santilli <strk> 06/11/24 09:19:50
Modified files:
. : ChangeLog
server : Makefile.am
server/asobj : Makefile.am
Added files:
server/asobj : xml.cpp xml.h xmlattrs.cpp xmlattrs.h
xmlnode.cpp xmlnode.h xmlsocket.cpp xmlsocket.h
Removed files:
server : xml.cpp xml.h xmlattrs.cpp xmlattrs.h
xmlnode.cpp xmlnode.h xmlsocket.cpp xmlsocket.h
Log message:
* server: {xmlattres,xmlnode,xmlsocket}.{h,cpp} => asobj
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.1736&r2=1.1737
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.89&r2=1.90
http://cvs.savannah.gnu.org/viewcvs/gnash/server/xml.cpp?cvsroot=gnash&r1=1.34&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/xml.h?cvsroot=gnash&r1=1.21&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/xmlattrs.cpp?cvsroot=gnash&r1=1.7&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/xmlattrs.h?cvsroot=gnash&r1=1.10&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/xmlnode.cpp?cvsroot=gnash&r1=1.22&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/xmlnode.h?cvsroot=gnash&r1=1.11&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/xmlsocket.cpp?cvsroot=gnash&r1=1.28&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/xmlsocket.h?cvsroot=gnash&r1=1.13&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Makefile.am?cvsroot=gnash&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xml.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xml.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xmlattrs.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xmlattrs.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xmlnode.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xmlnode.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xmlsocket.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xmlsocket.h?cvsroot=gnash&rev=1.1
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.1736
retrieving revision 1.1737
diff -u -b -r1.1736 -r1.1737
--- ChangeLog 24 Nov 2006 09:17:49 -0000 1.1736
+++ ChangeLog 24 Nov 2006 09:19:50 -0000 1.1737
@@ -1,7 +1,7 @@
2006-11-24 Sandro Santilli <address@hidden>
* server/gnash.h: ok, include as_value, but document what's needed
- from it (as_c_function_ptr typedef, in this case)
+ * server: {xmlattres,xmlnode,xmlsocket}.{h,cpp} => asobj
2006-11-24 Sandro Santilli <address@hidden>
Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.89
retrieving revision 1.90
diff -u -b -r1.89 -r1.90
--- server/Makefile.am 24 Nov 2006 09:04:24 -0000 1.89
+++ server/Makefile.am 24 Nov 2006 09:19:50 -0000 1.90
@@ -18,7 +18,7 @@
#
#
-# $Id: Makefile.am,v 1.89 2006/11/24 09:04:24 strk Exp $
+# $Id: Makefile.am,v 1.90 2006/11/24 09:19:50 strk Exp $
AUTOMAKE_OPTIONS =
@@ -46,104 +46,96 @@
$(NULL)
libgnashserver_la_SOURCES = \
- as_object.cpp \
- as_value.cpp \
+ GetterSetter.cpp \
+ PropertyList.cpp \
+ URLAccessManager.cpp \
as_environment.cpp \
as_function.cpp \
- swf_function.cpp \
+ as_object.cpp \
+ as_value.cpp \
character.cpp \
+ edit_text_character.cpp \
generic_character.cpp \
- textformat.cpp \
- timers.cpp \
- xml.cpp \
- xmlattrs.cpp \
- xmlnode.cpp \
+ matrix.cpp \
+ movie_instance.cpp \
movie_root.cpp \
- xmlsocket.cpp \
+ rect.cpp \
+ shm.cpp \
+ sprite_instance.cpp \
+ swf/TagLoadersTable.cpp \
+ swf/tag_loaders.cpp \
+ swf_function.cpp \
+ video_stream_instance.cpp \
+ video_yuv.cpp \
+ StreamProvider.cpp \
+ array.cpp \
button_character_instance.cpp \
dlist.cpp \
- edit_text_character.cpp \
font.cpp \
fontlib.cpp \
- GetterSetter.cpp \
impl.cpp \
- rect.cpp \
render.cpp \
shape.cpp \
- shm.cpp \
sound.cpp \
- sprite_instance.cpp \
- matrix.cpp \
- movie_instance.cpp \
- PropertyList.cpp \
stream.cpp \
- StreamProvider.cpp \
- URLAccessManager.cpp \
styles.cpp \
tesselate.cpp \
text.cpp \
- array.cpp \
- swf/TagLoadersTable.cpp \
- swf/tag_loaders.cpp \
+ textformat.cpp \
+ timers.cpp \
types.cpp \
- video_yuv.cpp \
- video_stream_instance.cpp \
$(NULL)
noinst_HEADERS = \
+ GetterSetter.h \
+ Global.h \
+ Property.h \
+ PropertyList.h \
+ Sprite.h \
+ StreamProvider.h \
+ StringPredicates.h \
+ URLAccessManager.h \
array.h \
- as_value.h \
as_environment.h \
as_function.h \
- builtin_function.h \
- swf_function.h \
- as_prop_flags.h \
as_object.h \
+ as_prop_flags.h \
+ as_value.h \
+ builtin_function.h \
button_character_instance.h \
- matrix.h \
- mouse_button_state.h \
- dlist.h \
character.h \
- generic_character.h \
+ dlist.h \
edit_text_character.h \
event_id.h \
execute_tag.h \
font.h \
fontlib.h \
- GetterSetter.h \
- Global.h \
+ generic_character.h \
gnash.h \
impl.h \
+ matrix.h \
+ mouse_button_state.h \
+ movie_instance.h \
movie_root.h \
- Property.h \
- PropertyList.h \
rect.h \
- resource.h \
render.h \
+ resource.h \
shape.h \
shm.h \
sound.h \
- Sprite.h \
sprite_instance.h \
- StringPredicates.h \
- movie_instance.h \
stream.h \
- StreamProvider.h \
- URLAccessManager.h \
styles.h \
swf.h \
+ swf/TagLoadersTable.h \
+ swf/tag_loaders.h \
swf_event.h \
+ swf_function.h \
tesselate.h \
- textformat.h \
text.h \
+ textformat.h \
timers.h \
types.h \
- xmlattrs.h \
- xml.h \
- xmlnode.h \
- swf/TagLoadersTable.h \
- swf/tag_loaders.h \
- xmlsocket.h \
$(NULL)
libgnashserver_la_LIBADD = \
Index: server/asobj/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Makefile.am,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- server/asobj/Makefile.am 24 Nov 2006 09:04:24 -0000 1.19
+++ server/asobj/Makefile.am 24 Nov 2006 09:19:50 -0000 1.20
@@ -18,7 +18,7 @@
#
#
-# $Id: Makefile.am,v 1.19 2006/11/24 09:04:24 strk Exp $
+# $Id: Makefile.am,v 1.20 2006/11/24 09:19:50 strk Exp $
AUTOMAKE_OPTIONS =
@@ -43,6 +43,7 @@
$(NULL)
libgnashasobjs_la_SOURCES = \
+ ASSound.cpp \
Boolean.cpp \
Camera.cpp \
Color.cpp \
@@ -50,27 +51,31 @@
CustomActions.cpp\
Date.cpp \
Error.cpp \
- Math.cpp \
Global.cpp \
Key.cpp \
LoadVars.cpp \
LocalConnection.cpp\
+ Math.cpp \
Microphone.cpp \
Mouse.cpp \
MovieClip.cpp \
- MovieClipLoader.cpp\
NetConnection.cpp\
NetStream.cpp \
Number.cpp \
Object.cpp \
Selection.cpp \
SharedObject.cpp\
- ASSound.cpp \
- string.cpp \
Stage.cpp \
System.cpp \
TextSnapshot.cpp\
- Video.cpp
+ Video.cpp \
+ MovieClipLoader.cpp\
+ string.cpp \
+ xml.cpp \
+ xmlattrs.cpp \
+ xmlnode.cpp \
+ xmlsocket.cpp \
+ $(NULL)
noinst_HEADERS = \
ASSound.h \
@@ -81,12 +86,11 @@
CustomActions.h \
Date.h \
Error.h \
+ GMath.h \
Key.h \
LoadVars.h \
LocalConnection.h\
Microphone.h \
- GMath.h \
- gstring.h \
Mouse.h \
MovieClip.h \
MovieClipLoader.h \
@@ -99,7 +103,13 @@
Stage.h \
System.h \
TextSnapshot.h \
- Video.h
+ Video.h \
+ gstring.h \
+ xml.h \
+ xmlsocket.h \
+ xmlattrs.h \
+ xmlnode.h \
+ $(NULL)
libgnashasobjs_la_LIBADD = \
$(top_builddir)/libamf/libgnashamf.la \
Index: server/asobj/xml.cpp
===================================================================
RCS file: server/asobj/xml.cpp
diff -N server/asobj/xml.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/xml.cpp 24 Nov 2006 09:19:50 -0000 1.1
@@ -0,0 +1,1328 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+//
+//
+//
+
+/* $Id: xml.cpp,v 1.1 2006/11/24 09:19:50 strk Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string>
+#include <vector>
+
+#include "log.h"
+#include "tu_config.h"
+#include "as_function.h" // for as_function
+#include "fn_call.h"
+
+#ifdef HAVE_LIBXML
+
+#include <unistd.h>
+#include "xmlattrs.h"
+#include "xmlnode.h"
+#include "xml.h"
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlreader.h>
+
+using namespace std;
+
+namespace gnash {
+
+//#define DEBUG_MEMORY_ALLOCATION 1
+
+XML::XML()
+ :_loaded(false), _nodename(0), _nodes(0), _bytes_loaded(0),
_bytes_total(0)
+{
+ GNASH_REPORT_FUNCTION;
+#ifdef DEBUG_MEMORY_ALLOCATION
+ log_msg("Creating XML data at %p \n", this);
+#endif
+ //log_msg("%s: %p \n", __FUNCTION__, this);
+}
+
+
+// Parse the ASCII XML string into memory
+XML::XML(tu_string xml_in)
+{
+ GNASH_REPORT_FUNCTION;
+#ifdef DEBUG_MEMORY_ALLOCATION
+ log_msg("Creating XML data at %p \n", this);
+#endif
+ //log_msg("%s: %p \n", __FUNCTION__, this);
+ //memset(&_nodes, 0, sizeof(XMLNode));
+ parseXML(xml_in);
+}
+
+XML::XML(struct node */* childNode */)
+{
+ GNASH_REPORT_FUNCTION;
+#ifdef DEBUG_MEMORY_ALLOCATION
+ log_msg("\tCreating XML data at %p \n", this);
+#endif
+ //log_msg("%s: %p \n", __FUNCTION__, this);
+}
+
+
+XML::~XML()
+{
+ GNASH_REPORT_FUNCTION;
+
+#ifdef DEBUG_MEMORY_ALLOCATION
+ if (this->_nodes) {
+ log_msg("\tDeleting XML top level node %s at %p \n",
this->_nodes->_name, this);
+ } else {
+ log_msg("\tDeleting XML top level node at %p \n", this);
+ }
+#endif
+
+ //log_msg("%s: %p \n", __FUNCTION__, this);
+ delete _nodes;
+}
+
+const char *
+XML::nodeName()
+{
+ printf("%s: XML %p _nodes at %p\n", __PRETTY_FUNCTION__, (void*)this,
(void*)_nodes);
+ if (_nodes) {
+ return _nodes->nodeName();
+ }
+ return "undefined";
+}
+
+const char *
+XML::nodeValue()
+{
+ printf("%s: XML _nodes at %p\n", __PRETTY_FUNCTION__, (void*)_nodes);
+ if (_nodes) {
+ return _nodes->nodeValue();
+ }
+ return "undefined";
+}
+
+void
+XML::nodeNameSet(char */*name */)
+{
+ if (!_nodes) {
+ _nodes = new XMLNode;
+ printf("%s: New XML %p _nodes at %p\n", __PRETTY_FUNCTION__, (void*)this,
(void*)_nodes);
+ }
+ // _nodes->nodeNameSet(name);
+ printf("%s: XML %p _name at %p, %s\n", __PRETTY_FUNCTION__, (void*)this,
+ _nodes->nodeName(), _nodes->nodeName() );
+}
+
+void
+XML::nodeValueSet(char */* value */)
+{
+ if (!_nodes) {
+ _nodes = new XMLNode;
+ printf("%s: New XML _nodes at %p\n", __PRETTY_FUNCTION__, (void*)_nodes);
+ }
+
+ // _nodes->nodeValueSet(value);
+ printf("%s: XML _nodes at %p\n", __PRETTY_FUNCTION__, (void*)_nodes);
+}
+
+// Dispatch event handler(s), if any.
+bool
+XML::on_event(const event_id& /* id */)
+{
+ GNASH_REPORT_FUNCTION;
+
+ // Keep m_as_environment alive during any method calls!
+ // boost::intrusive_ptr<as_object_interface> this_ptr(this);
+
+#if 0
+ // First, check for built-in event handler.
+ as_value method;
+ if (get_event_handler(event_id(id), &method)) {
+ call_method0(method, &m_as_environment, this);
+ return true;
+ }
+
+ // Check for member function.
+ // In ActionScript 2.0, event method names are CASE SENSITIVE.
+ // In ActionScript 1.0, event method names are CASE INSENSITIVE.
+ const tu_string& method_name = id.get_function_name();
+ if (method_name.length() > 0) {
+ as_value method;
+ if (get_member(method_name, &method)) {
+ call_method0(method, &m_as_environment, this);
+ return true;
+ }
+ }
+#endif
+ return false;
+}
+
+void
+XML::on_event_load()
+{
+ // Do the events that (appear to) happen as the movie
+ // loads. frame1 tags and actions are executed (even
+ // before advance() is called). Then the onLoad event
+ // is triggered.
+ on_event(event_id::LOAD);
+}
+
+XMLNode*
+XML::extractNode(xmlNodePtr node, bool mem)
+{
+ xmlAttrPtr attr;
+ xmlNodePtr childnode;
+ xmlChar *ptr = NULL;
+ XMLNode *element, *child;
+ int len;
+
+ element = new XMLNode;
+
+ //log_msg("Created new element for %s at %p\n", node->name, element);
+ memset(element, 0, sizeof (XMLNode));
+
+ log_msg("%s: extracting node %s\n", __FUNCTION__, node->name);
+
+ // See if we have any Attributes (properties)
+ attr = node->properties;
+ while (attr != NULL) {
+ //log_msg("extractNode %s has property %s, value is %s\n",
+ // node->name, attr->name, attr->children->content);
+ XMLAttr *attrib = new XMLAttr;
+ len = memadjust(strlen(reinterpret_cast<const char *>(attr->name))+1);
+ attrib->_name = (char *)new char[len];
+ memset(attrib->_name, 0, len);
+ strcpy(attrib->_name, reinterpret_cast<const char *>(attr->name));
+ len = memadjust(strlen(reinterpret_cast<const char
*>(attr->children->content))+1);
+ attrib->_value = (char *)new char[len];
+ memset(attrib->_value, 0, len);
+ strcpy(attrib->_value, reinterpret_cast<const char
*>(attr->children->content));
+ //log_msg("\tPushing attribute %s for element %s has value %s\n",
+ // attr->name, node->name, attr->children->content);
+ element->_attributes.push_back(attrib);
+ attr = attr->next;
+ }
+
+ len = memadjust(strlen(reinterpret_cast<const char *>(node->name))+1);
+ element->_name = (char *)new char[len];
+ memset(element->_name, 0, len);
+ strcpy(element->_name, reinterpret_cast<const char *>(node->name));
+ //element->_name = reinterpret_cast<const char *>(node->name);
+ if (node->children) {
+ //ptr = node->children->content;
+ ptr = xmlNodeGetContent(node->children);
+ if (ptr != NULL) {
+ if ((strchr((const char *)ptr, '\n') == 0) && (ptr[0] != 0)) {
+ if (node->children->content == NULL) {
+ //log_msg("Node %s has no contents\n", node->name);
+ } else {
+ //log_msg("extractChildNode from text for %s has contents
%s\n", node->name, ptr);
+ len = memadjust(strlen(reinterpret_cast<const char
*>(ptr))+1);
+ element->_value = (char *)new char[len];
+ memset(element->_value, 0, len);
+ strcpy(element->_value, reinterpret_cast<const char
*>(ptr));
+ //element->_value = reinterpret_cast<const char *>(ptr);
+ }
+ }
+ xmlFree(ptr);
+ }
+ }
+
+ // See if we have any data (content)
+ childnode = node->children;
+
+ while (childnode != NULL) {
+ if (childnode->type == XML_ELEMENT_NODE) {
+ //log_msg("\t\t extracting node %s\n", childnode->name);
+ child = extractNode(childnode, mem);
+ //if (child->_value.get_type() != as_value::UNDEFINED) {
+ if (child->_value != 0) {
+ //log_msg("\tPushing childNode %s, value %s on element %p\n",
child->_name.c_str(), child->_value.to_string(), element);
+ } else {
+ //log_msg("\tPushing childNode %s on element %p\n",
child->_name.c_str(), element);
+ }
+ element->_children.push_back(child);
+ }
+ childnode = childnode->next;
+ }
+
+ return element;
+}
+
+// Read in an XML document from the specified source
+bool
+XML::parseDoc(xmlDocPtr document, bool mem)
+{
+ GNASH_REPORT_FUNCTION;
+
+ XMLNode *top;
+ xmlNodePtr cur;
+
+ if (document == 0) {
+ log_error("Can't load XML file!\n");
+ return false;
+ }
+
+ cur = xmlDocGetRootElement(document);
+
+ if (cur != NULL) {
+ top = extractNode(cur, mem);
+ //_nodes->_name = reinterpret_cast<const char *>(cur->name);
+ _nodes = top;
+ //_node_data.push_back(top);
+ //cur = cur->next;
+ }
+
+ _loaded = true;
+ return true;
+}
+
+// This reads in an XML file from disk and parses into into a memory resident
+// tree which can be walked through later.
+bool
+XML::parseXML(tu_string xml_in)
+{
+ GNASH_REPORT_FUNCTION;
+
+ log_msg("Parse XML from memory: %s\n", xml_in.c_str());
+
+ if (xml_in.size() == 0) {
+ log_error("XML data is empty!\n");
+ return false;
+ }
+
+#ifndef USE_DMALLOC
+ //dump_memory_stats(__FUNCTION__, __LINE__, "before xmlParseMemory");
+#endif
+
+ _bytes_total = _bytes_loaded = xml_in.size();
+
+#ifdef USE_XMLREADER
+ XMLNode *node = 0;
+ xmlTextReaderPtr reader;
+
+ reader = xmlReaderForMemory(xml_in.c_str(), xml_in.size(), NULL, NULL, 0);
+ if (reader != NULL) {
+ bool ret = true;
+ while (ret) {
+ ret = xmlTextReaderRead(reader);
+ node = processNode(reader, node);
+ }
+ xmlFreeTextReader(reader);
+ if (ret != false) {
+ log_error("%s : couldn't parse\n", xml_in.c_str());
+ return false;
+ }
+ } else {
+ log_error("Unable to open %s\n", xml_in.c_str());
+ return false;
+ }
+ xmlCleanupParser();
+ return true;
+#else
+
+bool ret = true;
+
+#ifdef USE_DOM
+ xmlInitParser();
+
+ _doc = xmlParseMemory(xml_in.c_str(), xml_in.size());
+ if (_doc == 0) {
+ log_error("Can't parse XML data!\n");
+ return false;
+ }
+ ret = parseDoc(_doc, true);
+ xmlCleanupParser();
+ xmlFreeDoc(_doc);
+ xmlMemoryDump();
+#endif
+#ifndef USE_DMALLOC
+ //dump_memory_stats(__FUNCTION__, __LINE__, "after xmlParseMemory");
+#endif
+ return ret;
+#endif
+
+}
+
+// XML_READER_TYPE_NONE = 0
+// XML_READER_TYPE_ELEMENT = 1,
+// XML_READER_TYPE_ATTRIBUTE = 2,
+// XML_READER_TYPE_TEXT = 3,
+// XML_READER_TYPE_COMMENT = 8,
+// XML_READER_TYPE_SIGNIFICANT_WHITESPACE = 14,
+// XML_READER_TYPE_END_ELEMENT = 15,
+//
+// processNode:
+// 2 1 IP 0// processNode:
+// 3 3 #text 0 192.168.2.50
+// processNode:
+// 2 15 IP 0
+// processNode:
+// 2 14 #text 0
+const char *tabs[] = {
+ "",
+ "\t",
+ "\t\t",
+ "\t\t\t",
+ "\t\t\t",
+ "\t\t\t\t",
+};
+
+#ifdef USE_XMLREADER
+// This is an xmlReader (SAX) based parser. For some reason it core dumps
+// when compiled with GCC 3.x, but works just fine with GCC 4.x.
+XMLNode*
+XML::processNode(xmlTextReaderPtr reader, XMLNode *node)
+{
+ log_msg("%s: node is %p\n", __PRETTY_FUNCTION__, node);
+ static XMLNode *parent[10];
+ xmlChar *name, *value;
+ int depth;
+ XMLNode *element;
+ //static int previous_depth = 0;
+ xmlReaderTypes type;
+
+ if (node == 0) {
+ memset(parent, 0, sizeof(XMLNode *));
+ }
+ type = (xmlReaderTypes)xmlTextReaderNodeType(reader);
+ depth = xmlTextReaderDepth(reader);
+ value = xmlTextReaderValue(reader);
+ name = xmlTextReaderName(reader);
+
+ if (name == NULL)
+ name = xmlStrdup(BAD_CAST "--");
+
+#if 0
+ printf("%d %d %s %d\n",
+ depth,
+ (int)type,
+ name,
+ xmlTextReaderIsEmptyElement(reader));
+#endif
+
+
+ //child = node->_children[0];
+ switch(xmlTextReaderNodeType(reader)) {
+ case XML_READER_TYPE_NONE:
+ break;
+ case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: // This is an empty text
node
+ //log_msg("\tWhitespace at depth %d\n", depth);
+ break;
+ case XML_READER_TYPE_END_ELEMENT:
+ if (depth == 0) { // This is the last node in the file
+ element = node;
+ break;
+ }
+ parent[depth]->_children.push_back(element);
+// log_msg("Pushing element %s on node %s\n", node->_name,
parent[depth]->_name);
+// log_msg("End element at depth %d is %s for parent %s %p\n", depth,
name,
+// parent[depth]->_name, parent[depth]);
+ element = parent[depth];
+ break;
+ case XML_READER_TYPE_ELEMENT:
+ element = new XMLNode;
+// log_msg("%sElement at depth %d is %s for node at %p\n", tabs[depth],
depth, name, element);
+ element->_name = (char *)new char[strlen(reinterpret_cast<const char
*>(name))+1];
+ memset(element->_name, 0, strlen(reinterpret_cast<const char
*>(name))+1);
+ strcpy(element->_name, reinterpret_cast<const char *>(name));
+ if (node == 0) {
+ _nodes = element;
+ parent[0] = element;
+ } else {
+ parent[depth] = node;
+ parent[depth+1] = node;
+ }
+ // xmlTextReaderAttributeCount(reader);
+ if (xmlTextReaderHasAttributes(reader)) {
+ // log_msg("Has Attributes!\n");
+ xmlTextReaderMoveToFirstAttribute(reader);
+ processNode(reader, element);
+ while(xmlTextReaderMoveToNextAttribute(reader)) {
+ processNode(reader, element);
+ }
+ }
+ break;
+ case XML_READER_TYPE_TEXT:
+ element = node;
+// log_msg("%sValue at depth %d is \"%s\" for node at %p\n", tabs[depth],
depth, value, element);
+ element->_value = (char *)new char[strlen(reinterpret_cast<const
char *>(value))+1];
+ memset(element->_value, 0, strlen(reinterpret_cast<const char
*>(value))+1);
+ strcpy(element->_value, reinterpret_cast<const char *>(value));
+ break;
+ case XML_READER_TYPE_ATTRIBUTE:
+ element = node;
+ XMLAttr *attrib = new XMLAttr;
+ attrib->_name = (char *)new char[strlen(reinterpret_cast<const char
*>(name))+1];
+ memset(attrib->_name, 0, strlen(reinterpret_cast<const char
*>(name))+1);
+ strcpy(attrib->_name, reinterpret_cast<const char *>(name));
+ attrib->_value = (char *)new char[strlen(reinterpret_cast<const char
*>(value))+1];
+ memset(attrib->_value, 0, strlen(reinterpret_cast<const char
*>(value))+1);
+ strcpy(attrib->_value, reinterpret_cast<const char *>(value));
+// log_msg("%sPushing attribute %s, value \"%s\" for node %s\n",
tabs[depth], name, value, element->_name);
+ element->_attributes.push_back(attrib);
+ break;
+ default: // FIXME: why does this break GCC 3.3.3 but not 3.4.3 ?
+ log_error("Unsupported XML type %d\n!", type);
+ break;
+ };
+
+ xmlFree(name);
+ if (value != NULL) {
+ xmlFree(value);
+ }
+ //previous_depth = depth;
+ return element;
+}
+#endif
+
+// This reads in an XML file from disk and parses into into a memory resident
+// tree which can be walked through later.
+bool
+XML::load(const char *filespec)
+{
+ GNASH_REPORT_FUNCTION;
+ struct stat stats;
+ log_msg("Load disk XML file: %s\n", filespec);
+
+ //log_msg("%s: mem is %d\n", __FUNCTION__, mem);
+
+ // See if the file exists
+ if (stat(filespec, &stats) == 0) {
+ _bytes_total = stats.st_size;
+ _bytes_loaded = stats.st_size; // FIXME: this should probably
+ // be set later on after the
+ // file is loaded
+ }
+#ifdef USE_XMLREADER
+ XMLNode *node = 0;
+ xmlTextReaderPtr reader;
+
+ reader = xmlNewTextReaderFilename(filespec);
+ if (reader != NULL) {
+ bool ret = true;
+ while (ret) {
+ ret = xmlTextReaderRead(reader);
+ node = processNode(reader, node);
+ }
+ xmlFreeTextReader(reader);
+ if (ret != false) {
+ log_error("%s : couldn't parse\n", filespec);
+ return false;
+ }
+ } else {
+ log_error("Unable to open %s\n", filespec);
+ return false;
+ }
+ xmlCleanupParser();
+ return true;
+#else
+#ifdef USE_DOM
+ xmlInitParser();
+ _doc = xmlParseFile(filespec);
+ if (_doc == 0) {
+ log_error("Can't load XML file: %s!\n", filespec);
+ return false;
+ }
+ parseDoc(_doc, false);
+ xmlCleanupParser();
+ xmlFreeDoc(_doc);
+ xmlMemoryDump();
+ return true;
+#else
+#error "You have to enable either a DOM or an xmlReader XML parser"
+#endif
+#endif
+}
+
+
+vector<XMLNode *>
+XML::childNodes()
+{
+ if (_nodes) {
+ return _nodes->_children;
+ } else {
+ return static_cast< vector<XMLNode*> >(0);
+ }
+}
+
+bool
+XML::onLoad()
+{
+ log_msg("%s: FIXME: onLoad Default event handler\n", __FUNCTION__);
+
+ return(_loaded);
+}
+
+XMLNode *
+XML::operator [] (int x) {
+ log_msg("%s:\n", __FUNCTION__);
+
+ return _nodes->_children[x];
+}
+
+void
+XML::cleanupStackFrames(XMLNode */* xml */)
+{
+ GNASH_REPORT_FUNCTION;
+}
+
+as_object *
+XML::setupFrame(as_object *obj, XMLNode *xml, bool mem)
+{
+// GNASH_REPORT_FUNCTION;
+
+ int child;
+ unsigned int i;
+ const char *nodename;
+ //const char *nodevalue;
+ //AS_value nodevalue;
+ int length;
+ as_value inum;
+ XMLNode *childnode;
+ xmlnode_as_object *xmlchildnode_obj;
+ xmlattr_as_object* attr_obj;
+
+ //log_msg("\t%s: processing node %s for object %p, mem is %d\n",
__FUNCTION__, xml->_name, obj, mem);
+
+ // Get the data for this node
+ nodename = xml->_name;
+ //nodename = xml->_name.c_str();
+ //nodevalue = xml->_value;
+ length = xml->length();
+
+ // Set these members in the top level object passed in. This are used
+ // primarily by the disk based XML parser, where at least in all my current
+ // test cases this is referenced with firstChild first, then nodeName and
+ // childNodes.
+ obj->set_member("nodeName", nodename);
+ obj->set_member("length", length);
+ if (xml->_value != 0) {
+ obj->set_member("nodeValue", xml->_value);
+ log_msg("\tnodevalue for %s is: %s\n", nodename, xml->_value);
+ } else {
+ obj->set_member("nodeValue", as_value::UNDEFINED);
+ }
+
+// if (nodevalue.get_type() != as_value::UNDEFINED) {
+// obj->set_member("nodeValue", nodevalue.to_string());
+// log_msg("\tnodevalue for %s is: %s\n", nodename, nodevalue.to_string());
+// } else {
+// // If there is no value, we want to define it as an empty
+// // string.
+// obj->set_member("nodeValue", "");
+// }
+
+
+ // Process the attributes, if any
+ if (xml->_attributes.size() == 0) {
+ //log_msg("\t\tNo attributes for node %s, created empty object at
%p\n", nodename, attr_obj);
+// log_msg("\t\tNo attributes for node %s\n", nodename);
+ } else {
+ attr_obj = new xmlattr_as_object;
+ for (i=0; i<xml->_attributes.size(); i++) {
+ attr_obj->set_member(xml->_attributes[i]->_name,
xml->_attributes[i]->_value);
+ log_msg("\t\tAdding attribute as member %s, value is %s to node %s
(%p)\n",
+ xml->_attributes[i]->_name,
+ xml->_attributes[i]->_value, nodename,
static_cast<void*>(obj) );
+ }
+ obj->set_member("attributes", attr_obj);
+ }
+
+ //xml->_attributes.resize(0);
+ //obj->set_member("attributes", attr_obj);
+
+ // Process the children, if there are any
+ if (length) {
+ //log_msg("\tProcessing %d children nodes for %s\n", length, nodename);
+ inum = 0;
+ for (child=0; child<length; child++) {
+ // Create a new AS object for this node's children
+ xmlchildnode_obj = new xmlnode_as_object;
+ // When parsing XML from memory, the test movies I have expect the
firstChild
+ // to be the first element of the array instead.
+ if (mem) {
+ childnode = xml;
+ //obj->set_member(inum.to_string(), obj);
+ //inum += 1;
+ //childnode = xml->_children[child];
+ } else {
+ childnode = xml->_children[child];
+ }
+ setupFrame(xmlchildnode_obj, childnode, false); // setup child node
+ obj->set_member(inum.to_string(), xmlchildnode_obj);
+ inum += 1;
+ }
+ } else {
+ //log_msg("\tNode %s has no children\n", nodename);
+ }
+
+ return obj;
+}
+
+
+/// \brief add or change the HTTP Request header
+///
+/// Method; adds or changes HTTP request headers (such as Content-Type
+/// or SOAPAction) sent with POST actions. In the first usage, you pass
+/// two strings to the method: headerName and headerValue. In the
+/// second usage, you pass an array of strings, alternating header
+/// names and header values.
+///
+/// If multiple calls are made to set the same header name, each
+/// successive value replaces the value set in the previous call.
+void
+XML::addRequestHeader(const char */* name */, const char */* value */)
+{
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+
+/// \brief append a node the the XML object
+///
+/// Method; appends the specified node to the XML object's child
+/// list. This method operates directly on the node referenced by the
+/// childNode parameter; it does not append a copy of the node. If the
+/// node to be appended already exists in another tree structure,
+/// appending the node to the new location will remove it from its
+/// current location. If the childNode parameter refers to a node that
+/// already exists in another XML tree structure, the appended child
+/// node is placed in the new tree structure after it is removed from
+/// its existing parent node.
+void
+XML::appendChild(XMLNode *node)
+{
+ if (!_nodes) {
+ _nodes = new XMLNode;
+ }
+ _nodes->_children.push_back(node);
+ // log_msg("%s: %p at _nodes at %p\n", __PRETTY_FUNCTION__, this,
_nodes);
+}
+
+/// \brief copy a node
+///
+/// Method; constructs and returns a new XML node of the same type,
+/// name, value, and attributes as the specified XML object. If deep
+/// is set to true, all child nodes are recursively cloned, resulting
+/// in an exact copy of the original object's document tree.
+XMLNode &
+XML::cloneNode(XMLNode &newnode, bool deep)
+{
+ log_msg("%s: deep is %d\n", __PRETTY_FUNCTION__, deep);
+
+ if (deep) {
+ newnode = _nodes;
+// } else {
+// newnode.nodeNameSet((char *)_nodes->nodeName());
+// newnode.nodeValueSet((char *)_nodes->nodeValue());
+ }
+
+ return newnode;
+
+ log_msg("%s:partially unimplemented \n", __PRETTY_FUNCTION__);
+}
+
+/// \brief create a new XML element
+///
+/// Method; creates a new XML element with the name specified in the
+/// parameter. The new element initially has no parent, no children,
+/// and no siblings. The method returns a reference to the newly
+/// created XML object that represents the element. This method and
+/// the XML.createTextNode() method are the constructor methods for
+/// creating nodes for an XML object.
+XMLNode *
+XML::createElement(const char */* name */)
+{
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+ return (XMLNode*)0;
+}
+
+/// \brief Create a new XML node
+///
+/// Method; creates a new XML text node with the specified text. The
+/// new node initially has no parent, and text nodes cannot have
+/// children or siblings. This method returns a reference to the XML
+/// object that represents the new text node. This method and the
+/// XML.createElement() method are the constructor methods for
+/// creating nodes for an XML object.
+XMLNode *
+XML::createTextNode(const char */* name */)
+{
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+ return (XMLNode*)0;
+}
+
+/// \brief insert a node before a node
+///
+/// Method; inserts a new child node into the XML object's child
+/// list, before the beforeNode node. If the beforeNode parameter is
+/// undefined or null, the node is added using the appendChild()
+/// method. If beforeNode is not a child of my_xml, the insertion
+/// fails.
+void
+XML::insertBefore(XMLNode */* newnode */, XMLNode */* node */)
+{
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+
+void
+XML::load()
+{
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+
+void
+XML::parseXML()
+{
+ log_msg("%s: unimplemented \n", __FUNCTION__);
+}
+
+/// \brief removes the specified XML object from its parent. Also
+/// deletes all descendants of the node.
+void
+XML::removeNode()
+{
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+
+void
+XML::send()
+{
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+
+void
+XML::sendAndLoad()
+{
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+
+const char *
+XML::toString()
+{
+ if (_nodes) {
+ return stringify(_nodes);
+ }
+ return NULL;
+}
+
+//
+const char *
+XML::stringify(XMLNode *xml)
+{
+ int child;
+ unsigned int i;
+ const char *nodename = xml->nodeName();
+ int length;
+ string str;
+
+ log_msg("%s: processing for object %p\n", __PRETTY_FUNCTION__,
(void*)this);
+
+ // Process the attributes, if any
+ if (_nodes->_attributes.size() == 0) {
+ log_msg("\t\tNo attributes for node\n");
+ } else {
+ for (i=0; i<xml->_attributes.size(); i++) {
+ log_msg("\t\tAdding attribute as member %s, value is %s to node
%s\n",
+ xml->_attributes[i]->_name,
+ xml->_attributes[i]->_value, nodename);
+ }
+ }
+
+ vector<XMLNode *>::iterator it;
+ for (it = _nodes->_children.begin(); it != _nodes->_children.end(); ++it) {
+ log_msg("Found One!!!! %p\n", (void*)*it);
+ }
+
+ // Process the children, if there are any
+ length = xml->_children.size();
+
+ if (length) {
+ log_msg("\tProcessing %d children nodes\n", length);
+ for (child=0; child<length; child++) {
+ log_msg("Name %p\n", (void*)(xml->_children[child]));
+ if (xml->_children[child]->_name) {
+// log_msg("Name %p", xml->_children[child]);
+ }
+ if (xml->_children[child]->_value) {
+// log_msg("Value %s", xml->_children[child]->_value);
+ }
+
+// str += stringify(xml->_children[child]);
+ }
+ } else {
+ log_msg("\tNode %s has no children\n", nodename);
+ }
+ return str.c_str();
+}
+
+//
+// Callbacks. These are the wrappers for the C++ functions so they'll work as
+// callbacks from within gnash.
+//
+void
+xml_load(const fn_call& fn)
+{
+ as_value method;
+ as_value val;
+ bool ret;
+ struct stat stats;
+
+ //GNASH_REPORT_FUNCTION;
+
+ xml_as_object *xml_obj = (xml_as_object*)fn.this_ptr;
+
+ const std::string filespec =
fn.env->bottom(fn.first_arg_bottom_index).to_string();
+
+ // If the file doesn't exist, don't try to do anything.
+ if (stat(filespec.c_str(), &stats) < 0) {
+ fprintf(stderr, "ERROR: doesn't exist.%s\n", filespec.c_str());
+ fn.result->set_bool(false);
+ return;
+ }
+
+ // Set the argument to the function event handler based on whether the load
+ // was successful or failed.
+ ret = xml_obj->obj.load(filespec.c_str());
+ fn.result->set_bool(ret);
+
+ if (ret == false) {
+ return;
+ }
+
+ //env->bottom(first_arg) = ret;
+ // struct node *first_node = ptr->obj.firstChildGet();
+
+ //const char *name = ptr->obj.nodeNameGet();
+
+ if (xml_obj->obj.hasChildNodes() == false) {
+ log_error("%s: No child nodes!\n", __FUNCTION__);
+ }
+ xml_obj->obj.setupFrame(xml_obj, xml_obj->obj.firstChild(), false);
+
+#if 1
+ if (fn.this_ptr->get_member("onLoad", &method)) {
+ // log_msg("FIXME: Found onLoad!\n");
+ fn.env->set_variable("success", true);
+ fn.env->bottom(fn.first_arg_bottom_index) = true;
+ as_c_function_ptr func = method.to_c_function();
+ if (func) {
+ // It's a C function. Call it.
+ log_msg("Calling C function for onLoad\n");
+ (*func)(fn_call(&val, xml_obj, fn.env, fn.nargs,
fn.first_arg_bottom_index)); // was this_ptr instead of node
+ } else if (as_function* as_func = method.to_as_function()) {
+ // It's an ActionScript function. Call it.
+ log_msg("Calling ActionScript function for onLoad\n");
+ (*as_func)(fn_call(&val, xml_obj, fn.env, fn.nargs,
fn.first_arg_bottom_index)); // was this_ptr instead of node
+ } else {
+ log_error("error in call_method(): method is not a function\n");
+ }
+ } else {
+ log_msg("Couldn't find onLoad event handler, setting up callback\n");
+ // ptr->set_event_handler(event_id::XML_LOAD,
(as_c_function_ptr)&xml_onload);
+ }
+#else
+ xml_obj->set_event_handler(event_id::XML_LOAD, &xml_onload);
+
+#endif
+
+ fn.result->set_bool(true);
+}
+
+// This executes the event handler for XML::XML_LOAD if it's been defined,
+// and the XML file has loaded sucessfully.
+void
+xml_onload(const fn_call& fn)
+{
+ //log_msg("%s:\n", __FUNCTION__);
+
+ as_value method;
+ as_value val;
+ static bool first = true; // This event handler should only be
executed once.
+ xml_as_object* ptr = (xml_as_object*) (as_object*) fn.this_ptr;
+ assert(ptr);
+
+ if ((ptr->obj.loaded()) && (first)) {
+ // env->set_variable("success", true, 0);
+ //as_value bo(true);
+ //env->push_val(bo);
+
+ first = false;
+ log_msg("The XML file has been loaded successfully!\n");
+ // ptr->on_event(event_id::XML_LOAD);
+ //env->set_variable("success", true, 0);
+ //env->bottom(0) = true;
+
+ if (fn.this_ptr->get_member("onLoad", &method)) {
+ // log_msg("FIXME: Found onLoad!\n");
+ as_c_function_ptr func = method.to_c_function();
+ if (func)
+ {
+ // It's a C function. Call it.
+ log_msg("Calling C function for onLoad\n");
+ (*func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
+ }
+ else if (as_function* as_func = method.to_as_function())
+ {
+ // It's an ActionScript function. Call it.
+ log_msg("Calling ActionScript function for onLoad\n");
+ (*as_func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
+ }
+ else
+ {
+ log_error("error in call_method(): method is not a
function\n");
+ }
+ } else {
+ log_msg("FIXME: Couldn't find onLoad!\n");
+ }
+ }
+
+ fn.result->set_bool(val.to_bool());
+}
+
+// This is the default event handler, and is usually redefined in the SWF
script
+void
+xml_ondata(const fn_call& fn)
+{
+ log_msg("%s:\n", __FUNCTION__);
+
+ as_value method;
+ as_value val;
+ static bool first = true; // FIXME: ugly hack!
+
+ xml_as_object* ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+
+ if ((ptr->obj.loaded()) && (first)) {
+ if (fn.this_ptr->get_member("onData", &method)) {
+ log_msg("FIXME: Found onData!\n");
+ as_c_function_ptr func = method.to_c_function();
+ fn.env->set_variable("success", true);
+ if (func)
+ {
+ // It's a C function. Call it.
+ log_msg("Calling C function for onData\n");
+ (*func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
+ }
+ else if (as_function* as_func = method.to_as_function())
+ {
+ // It's an ActionScript function. Call it.
+ log_msg("Calling ActionScript function for onData\n");
+ (*as_func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
+ }
+ else
+ {
+ log_error("error in call_method(): method is not a
function\n");
+ }
+ } else {
+ log_msg("FIXME: Couldn't find onData!\n");
+ }
+ }
+
+ //fn.result->set(&val);
+ fn.result->set_bool(val.to_bool());
+}
+
+void
+xml_new(const fn_call& fn)
+{
+ as_value inum;
+ xml_as_object *xml_obj;
+ //const char *data;
+
+ // log_msg("%s: nargs=%d\n", __FUNCTION__, fn.nargs);
+
+ if (fn.nargs > 0) {
+ if (fn.env->top(0).get_type() == as_value::STRING) {
+ xml_obj = new xml_as_object;
+ //log_msg("\tCreated New XML object at %p\n", xml_obj);
+ tu_string datain = fn.env->top(0).to_tu_string();
+ xml_obj->obj.parseXML(datain);
+ //log_msg("*** Start setting up the stack frames ***\n");
+ xml_obj->obj.setupFrame(xml_obj, xml_obj->obj.firstChild(), true);
+ //xml_obj->obj.clear();
+ //delete xml_obj->obj.firstChild();
+ } else {
+ xml_as_object* xml_obj =
(xml_as_object*)fn.env->top(0).to_object();
+ //log_msg("\tCloned the XML object at %p\n", xml_obj);
+ //result->set(xml_obj);
+ fn.result->set_as_object(xml_obj);
+ return;
+ }
+ } else {
+ xml_obj = new xml_as_object;
+ //log_msg("\tCreated New XML object at %p\n", xml_obj);
+ // FIXME: this doesn't appear to exist in the MM player, should it ?
+ xml_obj->set_member("loaded", &xml_loaded);
+
+ xml_obj->set_member("addRequestHeader", &xml_addrequestheader);
+ xml_obj->set_member("appendChild", &xml_appendchild);
+ xml_obj->set_member("cloneNode", &xml_clonenode);
+ xml_obj->set_member("createElement", &xml_createelement);
+ xml_obj->set_member("createTextNode", &xml_createtextnode);
+ xml_obj->set_member("getBytesLoaded", &xml_getbytesloaded);
+ xml_obj->set_member("getBytesTotal", &xml_getbytestotal);
+ xml_obj->set_member("hasChildNodes", &xml_haschildnodes);
+ xml_obj->set_member("insertBefore", &xml_insertbefore);
+ xml_obj->set_member("load", &xml_load);
+ xml_obj->set_member("parseXML", &xml_parsexml);
+ xml_obj->set_member("removeNode", &xml_removenode);
+ xml_obj->set_member("send", &xml_send);
+ xml_obj->set_member("sendAndLoad", &xml_sendandload);
+ xml_obj->set_member("toString", &xml_tostring);
+ // Properties
+ xml_obj->set_member("nodeName", as_value(""));
+ xml_obj->set_member("nodevalue", as_value(""));
+
+ }
+
+ fn.result->set_as_object(xml_obj);
+}
+
+//
+// SWF Property of this class. These are "accessors" into the private data
+// of the class.
+//
+
+// determines whether the document-loading process initiated by the XML.load()
+// call has completed. If the process completes successfully, the method
+// returns true; otherwise, it returns false.
+void
+xml_loaded(const fn_call& fn)
+{
+ as_value method;
+ as_value val;
+
+ log_msg("%s:\n", __FUNCTION__);
+
+ xml_as_object* ptr = (xml_as_object*) (as_object*) fn.this_ptr;
+ assert(ptr);
+ std::string filespec =
fn.env->bottom(fn.first_arg_bottom_index).to_string();
+ //fn.result->set(ptr->obj.loaded());
+ fn.result->set_bool(ptr->obj.loaded());
+}
+
+
+void xml_addrequestheader(const fn_call& fn)
+{
+ log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+
+// fn.result->set_int(ptr->obj.getAllocated());
+// ptr->obj.addRequestHeader();
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+void xml_appendchild(const fn_call& fn)
+{
+ // log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+ xmlnode_as_object *xml_obj =
(xmlnode_as_object*)fn.env->top(0).to_object();
+
+ ptr->obj.appendChild(&(xml_obj->obj));
+}
+
+void xml_clonenode(const fn_call& fn)
+{
+ log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ xmlnode_as_object *xml_obj;
+ assert(ptr);
+
+ if (fn.nargs > 0) {
+ bool deep = fn.env->bottom(fn.first_arg_bottom_index).to_bool();
+ xml_obj = new xmlnode_as_object;
+ xml_obj->set_member("nodeName", as_value(""));
+ xml_obj->set_member("nodeValue", as_value(""));
+ xml_obj->set_member("appendChild", &xmlnode_appendchild);
+ ptr->obj.cloneNode(xml_obj->obj, deep);
+ fn.result->set_as_object(xml_obj);
+ } else {
+ log_msg("ERROR: no Depth paramater!\n");
+ }
+
+}
+void xml_createelement(const fn_call& fn)
+{
+ // log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+ xmlnode_as_object *xml_obj;
+ const char *text;
+
+ if (fn.nargs > 0) {
+ text = fn.env->bottom(fn.first_arg_bottom_index).to_string();
+ xml_obj = new xmlnode_as_object;
+ xml_obj->set_member("nodeName", as_value(text));
+ xml_obj->set_member("nodeValue", as_value(""));
+ xml_obj->set_member("appendChild", &xmlnode_appendchild);
+// xml_obj->obj.nodeNameSet((char *)text);
+ xml_obj->obj._type = XML_ELEMENT_NODE;
+ fn.result->set_as_object(xml_obj);
+ } else {
+ log_msg("ERROR: no text for element creation!\n");
+ }
+}
+
+
+void xml_createtextnode(const fn_call& fn)
+{
+ // log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+ xmlnode_as_object *xml_obj;
+ const char *text;
+
+ if (fn.nargs > 0) {
+ text = fn.env->bottom(fn.first_arg_bottom_index).to_string();
+ xml_obj = new xmlnode_as_object;
+ xml_obj->set_member("nodeName", as_value(""));
+ xml_obj->set_member("nodeValue", as_value(text));
+ xml_obj->set_member("appendChild", &xmlnode_appendchild);
+// xml_obj->obj.nodeValueSet((char *)text);
+ xml_obj->obj._type = XML_TEXT_NODE;
+ fn.result->set_as_object(xml_obj);
+// log_msg("%s: xml obj is %p\n", __PRETTY_FUNCTION__, xml_obj);
+ } else {
+ log_msg("ERROR: no text for text node creation!\n");
+ }
+}
+
+void xml_getbytesloaded(const fn_call& fn)
+{
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+ fn.result->set_int(ptr->obj.getBytesLoaded());
+}
+
+void xml_getbytestotal(const fn_call& fn)
+{
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+ fn.result->set_int(ptr->obj.getBytesTotal());
+}
+
+void xml_haschildnodes(const fn_call& fn)
+{
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+ fn.result->set_bool(ptr->obj.hasChildNodes());
+}
+void xml_insertbefore(const fn_call& fn)
+{
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+
+// fn.result->set_int(ptr->obj.getAllocated());
+// ptr->obj.insertBefore();
+ log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+void xml_parsexml(const fn_call& fn)
+{
+ const char *text;
+ as_value method;
+ as_value val;
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+
+ if (fn.nargs > 0) {
+ text = fn.env->bottom(fn.first_arg_bottom_index).to_string();
+ ptr->obj.parseXML(text);
+ ptr->obj.setupFrame(ptr, ptr->obj.firstChild(), false);
+ }
+
+#if 1
+ if (fn.this_ptr->get_member("onLoad", &method)) {
+ // log_msg("FIXME: Found onLoad!\n");
+ fn.env->set_variable("success", true);
+ fn.env->bottom(fn.first_arg_bottom_index) = true;
+ as_c_function_ptr func = method.to_c_function();
+ if (func) {
+ // It's a C function. Call it.
+ log_msg("Calling C function for onLoad\n");
+ (*func)(fn_call(&val, ptr, fn.env, fn.nargs,
fn.first_arg_bottom_index)); // was this_ptr instead of node
+ } else if (as_function* as_func = method.to_as_function()) {
+ // It's an ActionScript function. Call it.
+ log_msg("Calling ActionScript function for onLoad\n");
+ (*as_func)(fn_call(&val, ptr, fn.env, fn.nargs,
fn.first_arg_bottom_index)); // was this_ptr instead of node
+ } else {
+ log_error("error in call_method(): method is not a function\n");
+ }
+ } else {
+ log_msg("Couldn't find onLoad event handler, setting up callback\n");
+ // ptr->set_event_handler(event_id::XML_LOAD,
(as_c_function_ptr)&xml_onload);
+ }
+#else
+
+#endif
+// fn.result->set_int(ptr->obj.getAllocated());
+}
+
+void xml_removenode(const fn_call& fn)
+{
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+
+// fn.result->set_int(ptr->obj.getAllocated());
+ ptr->obj.removeNode();
+}
+void xml_send(const fn_call& fn)
+{
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+
+// fn.result->set_int(ptr->obj.getAllocated());
+ ptr->obj.send();
+}
+void xml_sendandload(const fn_call& fn)
+{
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+
+// fn.result->set_int(ptr->obj.getAllocated());
+ ptr->obj.sendAndLoad();
+}
+void xml_tostring(const fn_call& fn)
+{
+ xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
+ assert(ptr);
+
+ fn.result->set_string(ptr->obj.toString());
+}
+
+int
+memadjust(int x)
+{
+ return (x + (4 - x % 4));
+}
+
+
+} // end of gnash namespace
+
+// HAVE_LIBXML
+#endif
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/asobj/xml.h
===================================================================
RCS file: server/asobj/xml.h
diff -N server/asobj/xml.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/xml.h 24 Nov 2006 09:19:50 -0000 1.1
@@ -0,0 +1,266 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+//
+//
+//
+
+#ifndef __XML_H__
+#define __XML_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tu_config.h"
+
+#include "event_id.h"
+#include "action.h"
+
+//#define DEBUG_MEMORY_ALLOCATION 1
+#include <vector>
+
+#ifdef HAVE_LIBXML
+
+#include "xmlattrs.h"
+#include "xmlnode.h"
+
+#ifdef DEBUG_MEMORY_ALLOCATION
+ #include "log.h"
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xmlreader.h>
+
+// Forward declarations
+namespace gnash {
+ class fn_call;
+}
+
+namespace gnash {
+
+/// XML class
+class DSOLOCAL XML {
+public:
+ XML();
+ XML(tu_string xml_in);
+ XML(struct node * childNode);
+ virtual ~XML();
+
+ // Methods
+ // This is the base method used by both parseXML() and load().
+ bool parseDoc(xmlDocPtr document, bool mem);
+ // Parses an XML document into the specified XML object tree.
+ bool parseXML(tu_string xml_in);
+ // Loads a document (specified by
+ bool load(const char *filespec);
+ // the XML object) from a URL.
+
+ // An event handler that returns a
+ bool onLoad();
+ // Boolean value indicating whether
+ // the XML object was successfully
+ // loaded with XML.load() or
+ // XML.sendAndLoad().
+
+ // Appends a node to the end of the specified object's child list.
+ void appendChild(XMLNode *node);
+
+ virtual bool on_event(const gnash::event_id& id);
+ virtual void on_event_load();
+ bool loaded() { return _loaded; }
+
+ XMLNode *firstChild() {
+ return _nodes;
+ //return _node_data[0];
+ }
+
+ void clear() {
+ delete _nodes;
+ }
+
+ std::vector<XMLNode *> childNodes();
+
+ const char *stringify(XMLNode *xml);
+ // Returns true if the specified node has child nodes; otherwise, returns
false.
+ bool hasChildNodes() {
+ if (_nodes) {
+ if (_nodes->_children.size()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ XMLNode *extractNode(xmlNodePtr node, bool mem);
+ XMLNode *processNode(xmlTextReaderPtr reader, XMLNode *node);
+
+ void change_stack_frame(int frame, gnash::as_object *xml,
gnash::as_environment *env);
+// void setupStackFrames(gnash::as_object *xml, gnash::as_environment
*env);
+ void cleanupStackFrames( XMLNode *data);
+ as_object *setupFrame(gnash::as_object *xml, XMLNode *data, bool src);
+
+ const char *nodeNameGet() { return _nodename; }
+ const char *nodeName();
+ const char *nodeValue();
+ void nodeNameSet(char *name);
+ void nodeValueSet(char *value);
+ int length() { return _nodes->length(); }
+
+ // These 6 have to
+ void addRequestHeader(const char *name, const char *value);
+ XMLNode &cloneNode(XMLNode &newnode, bool deep);
+ XMLNode *createElement(const char *name);
+ XMLNode *createTextNode(const char *name);
+ void insertBefore(XMLNode *newnode, XMLNode *node);
+
+ void load();
+ void parseXML();
+ void removeNode();
+ void send();
+ void sendAndLoad();
+ const char *toString();
+
+ int getBytesLoaded() { return _bytes_loaded; };
+ int getBytesTotal() { return _bytes_total; };
+
+ virtual void on_xml_event(const gnash::event_id& id)
+ {
+ on_event(id);
+ }
+
+ // Special event handler;
+ void on_event_close()
+ {
+ on_event(gnash::event_id::SOCK_CLOSE);
+ }
+
+ XMLNode *operator [] (int x);
+#if 0
+ XMLNode *operator = (XMLNode &node) {
+ gnash::log_msg("%s: copy element %s\n", __PRETTY_FUNCTION__,
node._name);
+ // _nodes = node.;
+ }
+
+#endif
+ XML *operator = (XMLNode *node) {
+ _nodes = node;
+ return this;
+ }
+
+private:
+ xmlDocPtr _doc;
+ xmlNodePtr _firstChild;
+
+ // Properties
+ bool _loaded;
+ const char *_nodename;
+ XMLNode *_nodes;
+
+ int _bytes_loaded;
+ int _bytes_total;
+
+ bool _contentType;
+ bool _attributes;
+ bool _childNodes;
+ bool _xmlDecl;
+ bool _docTypeDecl;
+ bool _ignoreWhite;
+ bool _lastChild;
+ bool _nextSibling;
+ bool _nodeType;
+ bool _nodeValue;
+ bool _parentNode;
+ bool _status;
+ bool _previousSibling;
+
+};
+
+/// XML ActionScript object
+class DSOLOCAL xml_as_object : public gnash::as_object
+{
+public:
+ XML obj;
+#ifdef DEBUG_MEMORY_ALLOCATION
+ xml_as_object() {
+ log_msg("\tCreating xml_as_object at %p\n", this);
+ };
+ ~xml_as_object() {
+ log_msg("\tDeleting xml_as_object at %p\n", this);
+ };
+#endif
+
+ virtual bool get_member(const tu_stringi& name, as_value* val) {
+ //printf("GET XML MEMBER: %s at %p for object %p\n", name.c_str(),
val, this);
+
+ if ((name == "firstChild") || (name == "childNodes")) {
+// printf("Returning a self reference for %s for object at %p\n",
+// name.c_str(), this);
+ val->set_as_object(this);
+ return true;
+ }
+
+ return get_member_default(name, val);
+
+ }
+};
+
+
+DSOEXPORT void xml_load(const fn_call& fn);
+DSOEXPORT void xml_set_current(const fn_call& fn);
+DSOEXPORT void xml_new(const fn_call& fn);
+
+DSOEXPORT void xml_addrequestheader(const fn_call& fn);
+DSOEXPORT void xml_appendchild(const fn_call& fn);
+DSOEXPORT void xml_clonenode(const fn_call& fn);
+DSOEXPORT void xml_createelement(const fn_call& fn);
+DSOEXPORT void xml_createtextnode(const fn_call& fn);
+DSOEXPORT void xml_getbytesloaded(const fn_call& fn);
+DSOEXPORT void xml_getbytestotal(const fn_call& fn);
+DSOEXPORT void xml_haschildnodes(const fn_call& fn);
+DSOEXPORT void xml_insertbefore(const fn_call& fn);
+DSOEXPORT void xml_parsexml(const fn_call& fn);
+DSOEXPORT void xml_removenode(const fn_call& fn);
+DSOEXPORT void xml_send(const fn_call& fn);
+DSOEXPORT void xml_sendandload(const fn_call& fn);
+DSOEXPORT void xml_tostring(const fn_call& fn);
+
+// These are the event handlers called for this object
+DSOEXPORT void xml_onload(const fn_call& fn);
+DSOEXPORT void xml_ondata(const fn_call& fn);
+DSOEXPORT void xml_loaded(const fn_call& fn);
+
+// Properties
+DSOEXPORT void xml_nodename(const fn_call& fn);
+DSOEXPORT void xml_nodevalue(const fn_call& fn);
+
+
+DSOEXPORT int memadjust(int x);
+
+
+} // end namespace gnash
+
+
+#endif // HAVE_LIBXML
+
+#endif // __XML_H__
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/asobj/xmlattrs.cpp
===================================================================
RCS file: server/asobj/xmlattrs.cpp
diff -N server/asobj/xmlattrs.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/xmlattrs.cpp 24 Nov 2006 09:19:50 -0000 1.1
@@ -0,0 +1,90 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+//
+//
+//
+
+/* $Id: xmlattrs.cpp,v 1.1 2006/11/24 09:19:50 strk Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <vector>
+
+#include "action.h"
+#include "impl.h"
+#include "tu_config.h"
+#include "as_function.h"
+
+#ifdef HAVE_LIBXML
+
+#include "xmlattrs.h"
+
+#ifdef DEBUG_MEMORY_ALLOCATION
+ #include "log.h"
+#endif
+
+#include <unistd.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlreader.h>
+
+using namespace std;
+
+namespace gnash {
+
+//#define DEBUG_MEMORY_ALLOCATION 1
+
+//std::vector<as_object *> _xmlobjs; // FIXME: hack alert
+
+XMLAttr::XMLAttr()
+{
+#ifdef DEBUG_MEMORY_ALLOCATION
+ log_msg("\t\tCreating XMLAttr data at %p \n", this);
+#endif
+ _name = 0;
+ _value = 0;
+}
+
+XMLAttr::~XMLAttr()
+{
+#ifdef DEBUG_MEMORY_ALLOCATION
+ log_msg("\t\tDeleting XMLAttr data %s at %p \n", this->_name, this);
+#endif
+ //log_msg("%s: %p \n", __FUNCTION__, this);
+ if (_name) {
+ delete _name;
+ }
+ if (_value) {
+ delete _value;
+ }
+}
+
+} // end of gnash namespace
+
+// HAVE_LIBXML
+#endif
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/asobj/xmlattrs.h
===================================================================
RCS file: server/asobj/xmlattrs.h
diff -N server/asobj/xmlattrs.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/xmlattrs.h 24 Nov 2006 09:19:50 -0000 1.1
@@ -0,0 +1,102 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+//
+//
+//
+
+#ifndef __XML_ATTRS_H__
+#define __XML_ATTRS_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_LIBXML
+
+#include "tu_config.h"
+
+//#define DEBUG_MEMORY_ALLOCATION 1
+#include "as_object.h" // for inheritance
+
+#include "log.h"
+
+#include <vector>
+
+#ifdef DEBUG_MEMORY_ALLOCATION
+ #include "log.h"
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xmlreader.h>
+
+namespace gnash {
+
+/// XML Attribute class
+class DSOLOCAL XMLAttr {
+public:
+ XMLAttr();
+ ~XMLAttr();
+
+ // why don't we use std::strings here ?
+ // code would be much simpler and safer!
+ char *_name;
+ char *_value;
+ xmlAttributeType _type;
+
+ XMLAttr *operator = (XMLAttr node) {
+ log_msg("\t\tCopying XMLAttr object at %p\n", (void*)this);
+
+ _name = new char[strlen(node._name)+2];
+ memset(_name, 0, strlen(node._name)+2);
+ strcpy(_name, node._name);
+
+ _value = new char[strlen(node._value)+2];
+ memset(_value, 0, strlen(node._value)+2);
+ strcpy(_value, node._value);
+
+ return this;
+ }
+};
+
+/// XML Attribute ActionScript Object
+class DSOLOCAL xmlattr_as_object : public as_object
+{
+public:
+ //XMLAttr obj;
+ int padding;
+#ifdef DEBUG_MEMORY_ALLOCATION
+ xmlattr_as_object() {
+ log_msg("\t\tCreating xmlattr_as_object at %p\n", this);
+ };
+ ~xmlattr_as_object() {
+ log_msg("\tDeleting xmlattr_as_object at %p \n", this);
+ };
+#endif
+};
+
+} // end of gnash namespace
+
+#endif // HAVE_LIBXML
+
+#endif // __XML_ATTRS_H__
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/asobj/xmlnode.cpp
===================================================================
RCS file: server/asobj/xmlnode.cpp
diff -N server/asobj/xmlnode.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/xmlnode.cpp 24 Nov 2006 09:19:50 -0000 1.1
@@ -0,0 +1,449 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+//
+//
+//
+
+/* $Id: xmlnode.cpp,v 1.1 2006/11/24 09:19:50 strk Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <vector>
+#include "tu_config.h"
+#include "fn_call.h"
+
+#ifdef HAVE_LIBXML
+
+//#define DEBUG_MEMORY_ALLOCATION 1
+
+#include "xmlnode.h"
+
+#ifdef DEBUG_MEMORY_ALLOCATION
+ #include "log.h"
+#endif
+
+#include <unistd.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlreader.h>
+
+using namespace std;
+
+namespace gnash {
+
+//std::vector<as_object *> _xmlobjs; // FIXME: hack alert
+
+XMLNode::XMLNode() :_name(0), _value(0), _type(XML_ELEMENT_NODE)
+{
+ //log_msg("%s: %p \n", __PRETTY_FUNCTION__, this);
+#ifdef DEBUG_MEMORY_ALLOCATION
+ log_msg("\tCreating XMLNode data at %p \n", this);
+#endif
+ _name = 0;
+ _value = 0;
+}
+
+XMLNode::~XMLNode()
+{
+ unsigned int i;
+ //log_msg("%s: %p \n", __PRETTY_FUNCTION__, this);
+#ifdef DEBUG_MEMORY_ALLOCATION
+ log_msg("\tDeleting XMLNode data %s at %p\n", this->_name, this);
+#endif
+
+ for (i=0; i<_children.size(); i++) {
+ if (_children[i]->_name) {
+ delete [] _children[i]->_name;
+ }
+ if (_children[i]->_value) {
+ delete [] _children[i]->_value;
+ }
+ }
+
+ for (i=0; i<_attributes.size(); i++) {
+ if (_attributes[i]->_name) {
+ delete [] _attributes[i]->_name;
+ }
+ if (_attributes[i]->_value) {
+ delete [] _attributes[i]->_value;
+ }
+ }
+
+ _children.clear();
+ _attributes.clear();
+
+ if (_name) {
+ delete [] _name;
+ }
+ if (_value) {
+ delete [] _value;
+ }
+ // _value.set_undefined();
+}
+
+void
+XMLNode::nodeNameSet(char *name)
+{
+ int len = strlen(name) + 1;
+
+ if (!_name) {
+ _name = (char *)new char[len];
+ memset(_name, 0, len);
+ strcpy(_name, reinterpret_cast<const char *>(name));
+ }
+}
+
+void
+XMLNode::nodeValueSet(char *value)
+{
+ int len = strlen(value) + 1;
+
+ if (!_value) {
+ _value = (char *)new char[len];
+ memset(_value, 0, len);
+ strcpy(_value, reinterpret_cast<const char *>(value));
+ }
+}
+
+/// \brief Get the type of an XML Node.
+///
+
+/// Read-only property; a nodeType value, either 1 for an XML element
+/// or 3 for a text node. The nodeType is a numeric value from the
+/// NodeType enumeration in the W3C DOM Level 1 recommendation:
+/// www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html.
+/// The following table lists the values.
+int
+XMLNode::nodeType()
+{
+ switch (_type) {
+ case XML_TEXT_NODE:
+ return 3;
+ break;
+ case XML_ELEMENT_NODE:
+ return 1;
+ break;
+ default:
+ return 0;
+ }
+ // you should never get here
+ return -1;
+}
+
+const char *
+XMLNode::nodeName()
+{
+ if (_name) {
+ return _name;
+ }
+ return "unknown";
+}
+
+const char *
+XMLNode::nodeValue()
+{
+ if (_value) {
+ return _value;
+ }
+ return "unknown";
+}
+
+/// \brief append a node the the XMLNode object
+///
+/// Method; appends the specified node to the XMLNode object's child
+/// list. This method operates directly on the node referenced by the
+/// childNode parameter; it does not append a copy of the node. If the
+/// node to be appended already exists in another tree structure,
+/// appending the node to the new location will remove it from its
+/// current location. If the childNode parameter refers to a node that
+/// already exists in another XMLNode tree structure, the appended child
+/// node is placed in the new tree structure after it is removed from
+/// its existing parent node.
+void
+XMLNode::appendChild(as_object *as, XMLNode *node)
+{
+// log_msg("%s: %p, as is %d, node is %d\n",
+// __PRETTY_FUNCTION__, this, _objects.size(), _children.size());
+
+ if (node) {
+ _children.push_back(node);
+ }
+
+ if (as) {
+ _objects.push_back(as);
+ }
+
+// log_msg("%s: partially unimplemented\n", __PRETTY_FUNCTION__);
+}
+
+/// \brief copy a node
+///
+/// Method; constructs and returns a new XML node of the same type,
+/// name, value, and attributes as the specified XML object. If deep
+/// is set to true, all child nodes are recursively cloned, resulting
+/// in an exact copy of the original object's document tree.
+XMLNode &
+XMLNode::cloneNode(XMLNode &newnode, bool deep)
+{
+ log_msg("%s: deep is %d\n", __PRETTY_FUNCTION__, deep);
+
+ if (deep) {
+// newnode = _nodes;
+ } else {
+ newnode.nodeNameSet(_name);
+ newnode.nodeValueSet(_value);
+ }
+
+ return newnode;
+
+ log_msg("%s: partially unimplemented \n", __PRETTY_FUNCTION__);
+}
+
+/// \brief insert a node before a node
+///
+/// Method; inserts a new child node into the XML object's child
+/// list, before the beforeNode node. If the beforeNode parameter is
+/// undefined or null, the node is added using the appendChild()
+/// method. If beforeNode is not a child of my_xml, the insertion
+/// fails.
+void
+XMLNode::insertBefore(XMLNode */* newnode */, XMLNode */* node */)
+{
+ log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
+}
+/// \brief removes the specified XML object from its parent. Also
+/// deletes all descendants of the node.
+void
+XMLNode::removeNode()
+{
+ log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
+}
+const char *
+XMLNode::toString()
+{
+ XMLNode *node;
+
+ vector<XMLNode *>::const_iterator it;
+ for (it = _children.begin(); it != _children.end(); it++) {
+ node = *it;
+// log_msg("Got something\n");
+ if (node->_name) {
+ log_msg("Node name is %s", node->_name);
+ }
+ if (node->_value) {
+ log_msg("Node value is %s", node->_name);
+ }
+ }
+
+ log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
+ return "Hello World!";
+}
+
+as_object *
+XMLNode::previousSibling(int x)
+{
+ log_msg("%s: partially implemented. " SIZET_FMT " objects\n",
+ __PRETTY_FUNCTION__, _objects.size());
+ if (_objects.size() > 0) {
+ return _objects[x-1];
+ }
+
+ return NULL;
+}
+
+as_object *
+XMLNode::nextSibling(int x)
+{
+ log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
+ if (x < (int) _objects.size()) {
+ return _objects[x];
+ }
+ return NULL;
+}
+
+void
+xmlnode_new(const fn_call& fn)
+{
+ xmlnode_as_object *xml_obj;
+ //const char *data;
+
+// log_msg("%s\n", __PRETTY_FUNCTION__);
+
+ xml_obj = new xmlnode_as_object;
+ // Methods
+ xml_obj->set_member("appendChild", &xmlnode_appendchild);
+ xml_obj->set_member("cloneNode", &xmlnode_clonenode);
+ xml_obj->set_member("hasChildNodes", &xmlnode_haschildnodes);
+ xml_obj->set_member("insertBefore", &xmlnode_insertbefore);
+ xml_obj->set_member("removeNode", &xmlnode_removenode);
+ xml_obj->set_member("toString", &xmlnode_tostring);
+
+ // Properties
+ xml_obj->set_member("nodeName", as_value(""));
+ xml_obj->set_member("nodeValue", as_value(""));
+ xml_obj->set_member("nodeType", as_value(""));
+
+ // FIXME: these need real values
+ // These two return an array of objects
+ xml_obj->set_member("attributes", as_value(""));
+ xml_obj->set_member("childNodes", as_value(""));
+
+ //These return a reference to an object
+
+ /// \fn MLNode::firstChild
+ /// \brief XMLNode::firstChild property
+ ///
+ /// Read-only property; evaluates the specified XML object and
+ /// references the first child in the parent node\ufffds child
+ /// list. This property is null if the node does not have
+ /// children. This property is undefined if the node is a text
+ /// node. This is a read-only property and cannot be used to
+ /// manipulate child nodes; use the appendChild(), insertBefore(),
+ /// and removeNode() methods to manipulate child nodes.
+
+ xml_obj->set_member("firstChild", as_value(""));
+ /// \fn MLNode::lastChild
+ /// \brief XMLNode::lastChild property
+ ///
+ /// Read-only property; an XMLNode value that references the last
+ /// child in the node's child list. The XML.lastChild property
+ /// is null if the node does not have children. This property cannot
+ /// be used to manipulate child nodes; use the appendChild(),
+ /// insertBefore(), and removeNode() methods to manipulate child
+ /// nodes.
+ xml_obj->set_member("lastChild", as_value(""));
+ xml_obj->set_member("nextSibling", as_value(""));
+ xml_obj->set_member("parentNode", as_value(""));
+ xml_obj->set_member("previousSibling", as_value(""));
+
+ fn.result->set_as_object(xml_obj);
+}
+
+void xmlnode_appendchild(const fn_call& fn)
+{
+ xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
+ assert(ptr);
+// log_msg("%s: %p, %d args\n", __PRETTY_FUNCTION__, ptr, fn.nargs);
+
+ xmlnode_as_object *xml_obj =
(xmlnode_as_object*)fn.env->bottom(fn.first_arg_bottom_index).to_object();
+
+// log_msg("%s: %p \n", __PRETTY_FUNCTION__, xml_obj);
+ XMLNode *node = &(xml_obj->obj);
+ if (ptr->obj.hasChildNodes() == false) {
+ ptr->set_member("firstChild", xml_obj);
+ }
+ int length = ptr->obj.length();
+ if (length > 0) {
+ as_object *ass = xml_obj->obj.previousSibling(length);
+// FIXME: This shouldn't always be NULL
+// log_msg("%s: ASS is %p, length is %d\n", __PRETTY_FUNCTION__,
+// ass, length);
+ ptr->set_member("previousSibling", ass);
+// ptr->set_member("nextSibling",
xml_obj->obj.nextSibling(ptr->obj.length()));
+ }
+ ptr->obj.appendChild((as_object *)xml_obj, node);
+ // The last child in the list is always the one we just appended
+ ptr->set_member("lastChild", xml_obj);
+
+// ptr->obj.appendChild(&(xml_obj->obj));
+// ptr->obj.nodeValueSet((char *)xmlnode_obj->obj.nodeValue());
+}
+
+void xmlnode_clonenode(const fn_call& fn)
+{
+ log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
+ xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
+ xmlnode_as_object *xmlnode_obj;
+ assert(ptr);
+
+ if (fn.nargs > 0) {
+ bool deep = fn.env->bottom(fn.first_arg_bottom_index).to_bool();
+ xmlnode_obj = new xmlnode_as_object;
+ ptr->obj.cloneNode(xmlnode_obj->obj, deep);
+ fn.result->set_as_object(xmlnode_obj);
+ } else {
+ log_msg("ERROR: no Depth paramater!\n");
+ }
+
+}
+
+void xmlnode_insertbefore(const fn_call& fn)
+{
+ xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
+ assert(ptr);
+
+// fn.result->set_int(ptr->obj.getAllocated());
+// ptr->obj.insertBefore();
+ log_msg("%s:unimplemented \n", __PRETTY_FUNCTION__);
+}
+void xmlnode_removenode(const fn_call& fn)
+{
+ xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
+ assert(ptr);
+
+// fn.result->set_int(ptr->obj.getAllocated());
+ ptr->obj.removeNode();
+}
+void xmlnode_tostring(const fn_call& fn)
+{
+ xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
+ assert(ptr);
+
+ fn.result->set_string(ptr->obj.toString());
+}
+
+void xmlnode_haschildnodes(const fn_call& fn)
+{
+ xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
+ assert(ptr);
+ fn.result->set_bool(ptr->obj.hasChildNodes());
+}
+
+#ifdef ENABLE_TESTING
+void xmlnode_nodevalue(const fn_call& fn)
+{
+ log_msg("%s: \n", __PRETTY_FUNCTION__);
+ xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
+ assert(ptr);
+
+ fn.result->set_string(ptr->obj.nodeValue());
+}
+void xmlnode_nodename(const fn_call& fn)
+{
+ log_msg("%s: \n", __PRETTY_FUNCTION__);
+ xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
+ assert(ptr);
+
+ fn.result->set_string(ptr->obj.nodeName());
+}
+#endif
+
+} // end of gnash namespace
+
+// HAVE_LIBXML
+#endif
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/asobj/xmlnode.h
===================================================================
RCS file: server/asobj/xmlnode.h
diff -N server/asobj/xmlnode.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/xmlnode.h 24 Nov 2006 09:19:50 -0000 1.1
@@ -0,0 +1,167 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+//
+//
+//
+
+#ifndef __XML_NODE_H__
+#define __XML_NODE_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tu_config.h"
+
+//#define DEBUG_MEMORY_ALLOCATION 1
+#include <vector>
+#include "action.h"
+#include "impl.h"
+
+#ifdef HAVE_LIBXML
+
+#include "xmlattrs.h"
+
+#ifdef DEBUG_MEMORY_ALLOCATION
+ #include "log.h"
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xmlreader.h>
+
+namespace gnash {
+
+/// XML Node
+class DSOLOCAL XMLNode
+{
+public:
+ XMLNode();
+ ~XMLNode();
+
+ int length() { return _children.size(); }
+ const char *nodeName();
+ const char *nodeValue();
+ int nodeType();
+
+ // char *valueGet();
+
+ void nodeNameSet(char *name);
+ void nodeValueSet(char *value);
+ // nodeType XML.nodeType
+
+ bool hasChildNodes() {
+ if (_children.size()) {
+ return true;
+ }
+ return false;
+ }
+
+ XMLNode *firstChild() { return _children[0]; }
+
+ std::vector<XMLNode *>childNodes() { return _children; }
+
+ XMLNode *operator [] (int x) {
+ gnash::log_msg("%s: get element %d\n", __PRETTY_FUNCTION__, x);
+
+ return _children[x];
+ }
+
+ XMLNode *operator = (XMLNode &node) {
+ gnash::log_msg("%s: \n", __PRETTY_FUNCTION__);
+ _name = node._name;
+ _value = node._value;
+ _children = node._children;
+ _attributes = node._attributes;
+ return this;
+ }
+
+ XMLNode *operator = (XMLNode *node) {
+ gnash::log_msg("%s: \n", __PRETTY_FUNCTION__);
+ _name = node->_name;
+ _value = node->_value;
+ _children = node->_children;
+ _attributes = node->_attributes;
+ return this;
+ }
+
+ as_object *previousSibling(int x);
+ as_object *nextSibling(int x);
+ XMLNode &cloneNode(XMLNode &newnode, bool deep);
+ void appendChild(as_object *as,XMLNode *node);
+ void insertBefore(XMLNode *newnode, XMLNode *node);
+ void removeNode();
+ const char *toString();
+
+ void change_stack_frame(int frame, gnash::as_object *xml,
gnash::as_environment *env);
+
+
+ // why don't we use std::strings here ?
+ // code would be much simpler and safer!
+ char *_name;
+ char *_value;
+
+ xmlElementType _type;
+ std::vector<as_object *> _objects;
+ std::vector<XMLNode *> _children;
+ std::vector<XMLAttr *> _attributes;
+};
+
+/// XML Node ActionScript object
+class DSOLOCAL xmlnode_as_object : public gnash::as_object
+{
+public:
+ XMLNode obj;
+// int _padding;
+
+#ifdef DEBUG_MEMORY_ALLOCATION
+ xmlnode_as_object() {
+ // obj = new XMLNode;
+ log_msg("\tCreating xmlnode_as_object at %p \n", this);
+ };
+ ~xmlnode_as_object() {
+ log_msg("\tDeleting xmlnode_as_object at %p \n", this);
+ };
+#endif
+};
+
+DSOEXPORT void xmlnode_new(const fn_call& fn);
+
+DSOEXPORT void xmlnode_haschildren(const fn_call& fn);
+DSOEXPORT void xmlnode_nodename(const fn_call& fn);
+DSOEXPORT void xmlnode_nodevalue(const fn_call& fn);
+DSOEXPORT void xmlnode_nodetype(const fn_call& fn);
+
+DSOEXPORT void xmlnode_appendchild(const fn_call& fn);
+DSOEXPORT void xmlnode_clonenode(const fn_call& fn);
+DSOEXPORT void xmlnode_haschildnodes(const fn_call& fn);
+DSOEXPORT void xmlnode_insertbefore(const fn_call& fn);
+DSOEXPORT void xmlnode_removenode(const fn_call& fn);
+DSOEXPORT void xmlnode_tostring(const fn_call& fn);
+
+} // end of gnash namespace
+
+
+#endif // HAVE_LIBXML
+
+#endif // __XMLNODE_NODE_H__
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/asobj/xmlsocket.cpp
===================================================================
RCS file: server/asobj/xmlsocket.cpp
diff -N server/asobj/xmlsocket.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/xmlsocket.cpp 24 Nov 2006 09:19:50 -0000 1.1
@@ -0,0 +1,811 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+//
+//
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "utility.h"
+#include "xml.h"
+#include "xmlsocket.h"
+#include "timers.h"
+#include "as_function.h"
+#include "fn_call.h"
+#include "sprite_instance.h"
+
+#ifdef HAVE_LIBXML
+
+#include "log.h"
+
+#include <sys/types.h>
+#include <fcntl.h>
+#ifdef HAVE_WINSOCK
+# include <WinSock2.h>
+# include <windows.h>
+# include <sys/stat.h>
+# include <io.h>
+#else
+# include <sys/time.h>
+# include <unistd.h>
+# include <sys/select.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <sys/socket.h>
+# include <netdb.h>
+# include <cerrno>
+# include <sys/param.h>
+# include <sys/select.h>
+#endif
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+
+int xml_fd = 0; // FIXME: This file descriptor is used by
+ // XML::checkSocket() when called from the main
+ // processing loop.
+
+namespace gnash {
+const int SOCKET_DATA = 1;
+
+const int INBUF = 10000;
+
+XMLSocket::XMLSocket() {
+ //log_msg("%s: \n", __FUNCTION__);
+ _data = false;
+ _xmldata = false;
+ _closed = false;
+ _connect = false;
+ _processing = false;
+ _port = 0;
+ _sockfd = 0;
+ xml_fd = 0;
+}
+
+XMLSocket::~XMLSocket()
+{
+ //log_msg("%s: \n", __FUNCTION__);
+}
+
+bool
+XMLSocket::connect(const char *host, int port)
+{
+ struct sockaddr_in sock_in;
+ fd_set fdset;
+ struct timeval tval;
+ int ret;
+ int retries;
+ char thishostname[MAXHOSTNAMELEN];
+ struct protoent *proto;
+
+ if (port < 1024) {
+ log_error("Can't connect to priviledged port #%d!\n", port);
+ _connect = false;
+ return false;
+ }
+
+ log_msg("%s: to host %s at port %d\n", __FUNCTION__, host, port);
+
+ memset(&sock_in, 0, sizeof(struct sockaddr_in));
+ memset(&thishostname, 0, MAXHOSTNAMELEN);
+ if (strlen(host) == 0) {
+ if (gethostname(thishostname, MAXHOSTNAMELEN) == 0) {
+ log_msg("The hostname for this machine is %s.\n", thishostname);
+ } else {
+ log_msg("Couldn't get the hostname for this machine!\n");
+ return false;
+ }
+ }
+ const struct hostent *hent = ::gethostbyname(host);
+ if (hent > 0) {
+ ::memcpy(&sock_in.sin_addr, hent->h_addr, hent->h_length);
+ }
+ sock_in.sin_family = AF_INET;
+ sock_in.sin_port = ntohs(static_cast<short>(port));
+
+#if 0
+ char ascip[32];
+ inet_ntop(AF_INET, &sock_in.sin_addr.s_addr, ascip, INET_ADDRSTRLEN);
+ log_msg("The IP address for this client socket is %s\n", ascip);
+#endif
+
+ proto = ::getprotobyname("TCP");
+
+ _sockfd = ::socket(PF_INET, SOCK_STREAM, proto->p_proto);
+ if (_sockfd < 0)
+ {
+ log_error("unable to create socket : %s\n", strerror(errno));
+ _sockfd = -1;
+ return false;
+ }
+
+ retries = 2;
+ while (retries-- > 0) {
+ // We use select to wait for the read file descriptor to be
+ // active, which means there is a client waiting to connect.
+ FD_ZERO(&fdset);
+ FD_SET(_sockfd, &fdset);
+
+ // Reset the timeout value, since select modifies it on return. To
+ // block, set the timeout to zero.
+ tval.tv_sec = 5;
+ tval.tv_usec = 0;
+
+ ret = ::select(_sockfd+1, &fdset, NULL, NULL, &tval);
+
+ // If interupted by a system call, try again
+ if (ret == -1 && errno == EINTR)
+ {
+ log_msg("The connect() socket for fd #%d was interupted by a system
call!\n",
+ _sockfd);
+ continue;
+ }
+
+ if (ret == -1)
+ {
+ log_msg("The connect() socket for fd #%d never was available for
writing!\n",
+ _sockfd);
+#ifdef HAVE_WINSOCK
+ ::shutdown(_sockfd, SHUT_BOTH);
+#else
+ ::shutdown(_sockfd, SHUT_RDWR);
+#endif
+ _sockfd = -1;
+ return false;
+ }
+ if (ret == 0) {
+ log_error("The connect() socket for fd #%d timed out waiting to
write!\n",
+ _sockfd);
+ continue;
+ }
+
+ if (ret > 0) {
+ ret = ::connect(_sockfd, reinterpret_cast<struct sockaddr *>(&sock_in),
sizeof(sock_in));
+ if (ret == 0) {
+ log_msg("\tport %d at IP %s for fd #%d\n", port,
+ ::inet_ntoa(sock_in.sin_addr), _sockfd);
+ _connect = true;
+ xml_fd = _sockfd; // FIXME: This file descriptor is used
by
+ // XML::checkSocket() when called from
+ // the main processing loop.
+ return true;
+ }
+ if (ret == -1) {
+ log_msg("The connect() socket for fd #%d never was available for
writing!\n",
+ _sockfd);
+ _sockfd = -1;
+ return false;
+ }
+ }
+ }
+ // ::close(_sockfd);
+ // return false;
+
+ printf("\tConnected at port %d on IP %s for fd #%d\n", port,
+ ::inet_ntoa(sock_in.sin_addr), _sockfd);
+
+#ifndef HAVE_WINSOCK
+ fcntl(_sockfd, F_SETFL, O_NONBLOCK);
+#endif
+
+ _connect = true;
+ return true;
+}
+
+void
+XMLSocket::close()
+{
+ log_msg("%s: \n", __FUNCTION__);
+ // Since the return code from close() doesn't get used by Shockwave,
+ // we don't care either.
+ if (_sockfd > 0) {
+ ::close(_sockfd);
+ }
+}
+
+// Return true if there is data in the socket, otherwise return false.
+bool
+XMLSocket::anydata(char **msgs)
+{
+ //printf("%s: \n", __FUNCTION__);
+ return anydata(_sockfd, msgs);
+}
+
+bool XMLSocket::processingData()
+{
+ //printf("%s: processing flags is is %d\n", __FUNCTION__, _processing);
+ return _processing;
+}
+
+void XMLSocket::processing(bool x)
+{
+ //printf("%s: set processing flag to %d\n", __FUNCTION__, x);
+ _processing = x;
+}
+
+bool
+XMLSocket::anydata(int fd, char **msgs)
+{
+ fd_set fdset;
+ struct timeval tval;
+ int ret = 0;
+ char buf[INBUF];
+ char *packet;
+ int retries = 10;
+ char *ptr, *eom;
+ int cr, index = 0;
+ static char *leftover = 0;
+ int adjusted_size;
+
+ //log_msg("%s: \n", __FUNCTION__);
+
+ if (fd <= 0) {
+ return false;
+ }
+
+ //msgs = (char **)realloc(msgs, sizeof(char *));
+
+ while (retries-- > 0) {
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+
+ tval.tv_sec = 0;
+ tval.tv_usec = 103;
+
+ ret = ::select(fd+1, &fdset, NULL, NULL, &tval);
+
+ // If interupted by a system call, try again
+ if (ret == -1 && errno == EINTR) {
+ log_msg("The socket for fd #%d was interupted by a system call!\n",
+ fd);
+ continue;
+ }
+ if (ret == -1) {
+ log_error("The socket for fd #%d never was available!\n", fd);
+ return false;
+ }
+ if (ret == 0) {
+ //log_msg("There is no data in the socket for fd #%d!\n", fd);
+ return false;
+ }
+ if (ret > 0) {
+ //log_msg("There is data in the socket for fd #%d!\n", fd);
+ //break;
+ }
+ memset(buf, 0, INBUF);
+ ret = ::read(_sockfd, buf, INBUF-2);
+ cr = strlen(buf);
+ //log_msg("%s: read %d bytes, first msg terminates at %d\n", __FUNCTION__,
ret, cr);
+ //log_msg("%s: read (%d,%d) %s\n", __FUNCTION__, buf[0], buf[1], buf);
+ ptr = buf;
+ // If we get a single XML message, do less work
+ if (ret == cr + 1) {
+ adjusted_size = memadjust(ret + 1);
+ packet = new char[adjusted_size];
+ //printf("Packet size is %d at %p\n", ret + 1, packet);
+ memset(packet, 0, adjusted_size);
+ strcpy(packet, ptr);
+ eom = strrchr(packet, '\n'); // drop the CR off the end if there is one
+ if (eom) {
+ *eom = 0;
+ }
+ //data.push_back(packet);
+ msgs[index] = packet;
+ msgs[index+1] = 0;
+ //printf("%d: Pushing Packet of size %d at %p\n", __LINE__,
strlen(packet), packet);
+ processing(false);
+ return true;
+ }
+
+ // If we get multiple messages in a single transmission, break the buffer
+ // into separate messages.
+ while (strchr(ptr, '\n') > 0) {
+ if (leftover) {
+ processing(false);
+ //printf("%s: The remainder is: \"%s\"\n", __FUNCTION__, leftover);
+ //printf("%s: The rest of the message is: \"%s\"\n", __FUNCTION__,
ptr);
+ adjusted_size = memadjust(cr + strlen(leftover) + 1);
+ packet = new char[adjusted_size];
+ memset(packet, 0, adjusted_size);
+ strcpy(packet, leftover);
+ strcat(packet, ptr);
+ eom = strrchr(packet, '\n'); // drop the CR off the end there is one
+ if (eom) {
+ *eom = 0;
+ }
+ //printf("%s: The whole message is: \"%s\"\n", __FUNCTION__, packet);
+ ptr = strchr(ptr, '\n') + 2; // messages are delimited by a "\n\0"
+ delete leftover;
+ leftover = 0;
+ } else {
+ adjusted_size = memadjust(cr + 1);
+ packet = new char[adjusted_size];
+ memset(packet, 0, adjusted_size);
+ strcpy(packet, ptr);
+ ptr += cr + 1;
+ } // end of if remainder
+ if (*packet == '<') {
+ //printf("%d: Pushing Packet #%d of size %d at %p: %s\n", __LINE__,
+ // data.size(), strlen(packet), packet, packet);
+ eom = strrchr(packet, '\n'); // drop the CR off the end there is one
+ if (eom) {
+ *eom = 0;
+ }
+ //printf("Allocating new packet at %p\n", packet);
+ //data.push_back(packet);
+ msgs[index++] = packet;
+ } else {
+ log_error("Throwing out partial packet %s\n", packet);
+ }
+
+ //log_msg("%d messages in array now\n", data.size());
+ cr = strlen(ptr);
+ } // end of while (cr)
+
+ if (strlen(ptr) > 0) {
+ leftover = new char[strlen(ptr) + 1];
+ strcpy(leftover, ptr);
+ processing(true);
+ //printf("%s: Adding remainder: \"%s\"\n", __FUNCTION__, leftover);
+ }
+
+ processing(false);
+ printf("Returning %d messages\n", index);
+ return true;
+
+ } // end of while (retires)
+
+ return true;
+}
+
+bool
+XMLSocket::send(std::string str)
+{
+ //GNASH_REPORT_FUNCTION;
+
+ str += '\0';
+ int ret = write(_sockfd, str.c_str(), str.size());
+
+ //log_msg("%s: sent %d bytes, data was %s\n", __FUNCTION__, ret,
str.c_str());
+ if (ret == static_cast<signed int>(str.size())) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// Callbacks
+
+void
+XMLSocket::onClose(std::string /* str */)
+{
+ log_msg("%s: \n", __FUNCTION__);
+}
+
+void
+XMLSocket::onConnect(std::string /* str */)
+{
+ log_msg("%s: \n", __FUNCTION__);
+}
+
+void
+XMLSocket::onData(std::string /* str */)
+{
+ log_msg("%s: \n", __FUNCTION__);
+}
+
+void
+XMLSocket::onXML(std::string /* str */)
+{
+ log_msg("%s: \n", __FUNCTION__);
+}
+
+void
+XMLSocket::push(as_object *obj)
+{
+ _nodes.push_back(obj);
+}
+
+void
+XMLSocket::clear()
+{
+ unsigned int i;
+ for (i=0; i< _nodes.size(); i++) {
+ delete _nodes[i];
+ }
+}
+
+int
+XMLSocket::count()
+{
+ return _nodes.size();
+}
+
+int
+XMLSocket::checkSockets(void)
+{
+ return checkSockets(_sockfd);
+}
+
+int
+XMLSocket::checkSockets(int fd)
+{
+ fd_set fdset;
+ int ret = 0;
+ struct timeval tval;
+
+ //log_msg("%s:\n", __FUNCTION__);
+
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+
+ tval.tv_sec = 2;
+ tval.tv_usec = 10;
+
+ ret = ::select(fd+1, &fdset, NULL, NULL, &tval); // &tval
+
+ // If interupted by a system call, try again
+ if (ret == -1 && errno == EINTR) {
+ log_msg("The socket for fd #%d was interupted by a system call in this
thread!\n",
+ fd);
+ }
+ if (ret == -1) {
+ log_error("The socket for fd #%d never was available!\n", fd);
+ }
+ if (ret == 0) {
+ printf("There is no data in the socket for fd #%d!\n", fd);
+ }
+ if (ret > 0) {
+ //printf("There is data in the socket for fd #%d!\n", fd);
+ }
+
+ return ret;
+}
+
+void
+xmlsocket_connect(const fn_call& fn)
+{
+ as_value method;
+ as_value val;
+ static bool first = true; // This event handler should only be executed
once.
+
+ if (!first) {
+ fn.result->set_bool(true);
+ return;
+ }
+
+ log_msg("%s: nargs=%d\n", __FUNCTION__, fn.nargs);
+ xmlsocket_as_object* ptr = (xmlsocket_as_object*) (as_object*) fn.this_ptr;
+ assert(ptr);
+ const std::string host =
fn.env->bottom(fn.first_arg_bottom_index).to_string();
+ std::string port_str =
fn.env->bottom(fn.first_arg_bottom_index-1).to_string();
+ double port = atof(port_str.c_str());
+
+ ptr->obj.connect(host.c_str(), static_cast<int>(port));
+
+#if 0 // use connect return as result
+ // Push result onto stack for onConnect
+ if (ret) {
+ fn.env->push(as_value(true));
+ }
+ else {
+ fn.env->push(as_value(false));
+ }
+#endif
+ fn.env->push(as_value(true));
+ if (fn.this_ptr->get_member("onConnect", &method)) {
+ // log_msg("FIXME: Found onConnect!\n");
+ as_c_function_ptr func = method.to_c_function();
+ first = false;
+ //env->set_variable("success", true, 0);
+
+ if (func) {
+ // It's a C function. Call it.
+ log_msg("Calling C function for onConnect\n");
+ (*func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
+ }
+ else if (as_function* as_func = method.to_as_function()) {
+ // It's an ActionScript function. Call it.
+ log_msg("Calling ActionScript function for onConnect\n");
+ (*as_func)(fn_call(&val, fn.this_ptr, fn.env, 2, 2));
+ } else {
+ log_error("error in call_method(): method is not a function\n");
+ }
+ } else {
+ //ptr->set_event_handler(event_id::SOCK_CONNECT,
(as_c_function_ptr)&xmlsocket_event_connect);
+ }
+
+#if 1
+ sprite_instance* mov = fn.env->get_target()->get_root_movie();
+ Timer *timer = new Timer;
+ as_c_function_ptr ondata_handler =
+ (as_c_function_ptr)&xmlsocket_event_ondata;
+ timer->setInterval(ondata_handler, 50, ptr, fn.env);
+ timer->setObject(ptr);
+ mov->add_interval_timer(timer);
+#endif
+
+ fn.env->pop();
+
+ fn.result->set_bool(true);
+}
+
+
+void
+xmlsocket_send(const fn_call& fn)
+{
+ as_value method;
+ as_value val;
+
+ xmlsocket_as_object* ptr = (xmlsocket_as_object*) (as_object*) fn.this_ptr;
+ assert(ptr);
+ const std::string object = fn.env->bottom(
fn.first_arg_bottom_index).to_string();
+ // log_msg("%s: host=%s, port=%g\n", __FUNCTION__, host, port);
+ fn.result->set_bool(ptr->obj.send(object));
+}
+
+void
+xmlsocket_close(const fn_call& fn)
+{
+ as_value method;
+ as_value val;
+
+ xmlsocket_as_object* ptr = (xmlsocket_as_object*) (as_object*) fn.this_ptr;
+ assert(ptr);
+ // Since the return code from close() doesn't get used by Shockwave,
+ // we don't care either.
+ ptr->obj.close();
+}
+
+void
+xmlsocket_xml_new(const fn_call& fn)
+{
+ //log_msg("%s: nargs=%d\n", __FUNCTION__, nargs);
+
+ xml_new(fn);
+}
+
+void
+xmlsocket_new(const fn_call& fn)
+{
+ //log_msg("%s: nargs=%d\n", __FUNCTION__, nargs);
+
+ as_object* xmlsock_obj = new xmlsocket_as_object;
+ //log_msg("\tCreated New XMLSocket object at 0x%X\n", (unsigned
int)xmlsock_obj);
+ xmlsock_obj->set_member("connect", &xmlsocket_connect);
+ xmlsock_obj->set_member("send", &xmlsocket_send);
+ xmlsock_obj->set_member("close", &xmlsocket_close);
+ xmlsock_obj->set_member("Connected", true);
+ // swf_event* ev = new swf_event;
+ // m_event_handlers.push_back(ev);
+ // Setup event handlers
+#if 0
+ xmlsock_obj->set_event_handler(event_id::SOCK_DATA,
+ (as_c_function_ptr)&xmlsocket_event_ondata);
+ xmlsock_obj->set_event_handler(event_id::SOCK_CLOSE,
+ (as_c_function_ptr)&xmlsocket_event_close);
+ //
xmlsock_obj->set_event_handler(event_id::SOCK_CONNECT,
+ //
(as_c_function_ptr)&xmlsocket_event_connect);
+ xmlsock_obj->set_event_handler(event_id::SOCK_XML,
+ (as_c_function_ptr)&xmlsocket_event_xml);
+#endif
+ //periodic_events.set_event_handler(xmlsock_obj);
+
+
+#if 1
+ //as_c_function_ptr int_handler = (as_c_function_ptr)&timer_setinterval;
+ //env->set_member("setInterval", int_handler);
+ fn.env->set_member("setInterval", timer_setinterval);
+
+ //as_c_function_ptr clr_handler = timer_clearinterval;
+ fn.env->set_member("clearInterval", timer_clearinterval);
+ //env->set_variable("setInterval", int_handler, 0);
+ //xmlsock_obj->set_event_handler(event_id::TIMER,
+ // (as_c_function_ptr)&timer_expire);
+#if 0
+ Timer *timer = new Timer;
+ as_c_function_ptr ondata_handler =
+ (as_c_function_ptr)&xmlsocket_event_ondata;
+ timer->setInterval(ondata_handler, 10);
+ timer->setObject(xmlsock_obj);
+ current_movie->add_interval_timer(timer);
+#endif
+
+ fn.result->set_bool(xmlsock_obj);
+
+ // Tune malloc for the best performance
+ //mallopt(M_MMAP_MAX,0);
+ //mallopt(M_TRIM_THRESHOLD,-1);
+ //mallopt(M_MMAP_THRESHOLD,16);
+
+#endif
+}
+
+
+void
+xmlsocket_event_ondata(const fn_call& fn)
+{
+ //log_msg("%s: nargs is %d\n", __FUNCTION__, nargs);
+
+ as_value method;
+ as_value val;
+ as_value datain;
+ std::vector<const char *> msgs;
+ char *messages[200];
+ int i;
+ as_c_function_ptr func;
+ as_function* as_func;
+
+ xmlsocket_as_object* ptr = (xmlsocket_as_object*)fn.this_ptr;
+ assert(ptr);
+ if (ptr->obj.processingData()) {
+ log_msg("Still processing data!\n");
+ fn.result->set_bool(false);
+ return;
+ }
+
+ memset(messages, 0, sizeof(char *)*200);
+
+#ifndef USE_DMALLOC
+ //dump_memory_stats(__FUNCTION__, __LINE__, "memory checkpoint");
+#endif
+
+ if (ptr->obj.anydata(messages)) {
+ if (fn.this_ptr->get_member("onData", &method)) {
+ func = method.to_c_function();
+ as_func = method.to_as_function();
+ //log_msg("Got %d messages from XMLsocket\n", msgs.size());
+ // for (i=0; i<msgs.size(); i++) {
+ for (i=0; messages[i] != 0; i++) {
+// log_msg("Got message #%d, %d bytes long at %p: %s: \n", i,
+// strlen(messages[i]), messages[i], messages[i]);
+ datain = messages[i];
+ //fn.env->push(datain);
+#ifndef USE_DMALLOC
+ //dump_memory_stats(__FUNCTION__, __LINE__, "start");
+#endif
+ as_environment *env = new as_environment;
+ env->push(datain);
+ if (func) {
+ // It's a C function. Call it.
+ //log_msg("Calling C function for onData\n");
+ (*func)(fn_call(&val, fn.this_ptr, env, 1, 0));
+ } else if (as_func) {
+ // It's an ActionScript function. Call it.
+ //log_msg("Calling ActionScript function for onData, processing msg
%d\n", i);
+ (*as_func)(fn_call(&val, fn.this_ptr, env, 1, 0));
+ } else {
+ log_error("error in call_method(): method is not a function\n");
+ }
+ env->pop();
+ delete env;
+#ifndef USE_DMALLOC
+ //dump_memory_stats(__FUNCTION__, __LINE__, "end");
+#endif
+ //log_msg("Deleting message #%d at %p\n", i, messages[i]);
+ //delete messages[i];
+ //fn.env->pop();
+ datain.set_undefined();
+ }
+ ptr->obj.processing(false);
+ } else {
+ log_error("Couldn't find onData!\n");
+ }
+ // Delete this in a batch for now so we can track memory allocation
+ for (i=0; messages[i] != 0; i++) {
+ //log_msg("Deleting message #%d at %p\n", i, messages[i]);
+ delete messages[i];
+ }
+ }
+
+ //malloc_trim(0);
+
+ //result->set(&data);
+ fn.result->set_bool(true);
+}
+
+void
+xmlsocket_event_close(const fn_call& /* fn */)
+{
+#if 0
+ as_value* result = fn.result;
+ as_object* this_ptr = fn.this_ptr;
+ int nargs = fn.nargs;
+ int first_arg = fn.first_arg_bottom_index;
+#else
+ log_error("%s: unimplemented!\n", __FUNCTION__);
+#endif
+}
+
+void
+xmlsocket_event_connect(const fn_call& fn)
+{
+ as_value method;
+ as_value val;
+ static bool first = true; // This event handler should only be executed
once.
+
+ if (!first) {
+ fn.result->set_bool(true);
+ return;
+ }
+
+ xmlsocket_as_object* ptr = (xmlsocket_as_object*) (as_object*) fn.this_ptr;
+ assert(ptr);
+
+ log_msg("%s: connected = %d\n", __FUNCTION__, ptr->obj.connected());
+ if ((ptr->obj.connected()) && (first)) {
+ first = false;
+ //env->set_variable("success", true, 0);
+ //env->bottom(0) = true;
+
+ if (fn.this_ptr->get_member("onConnect", &method)) {
+ as_c_function_ptr func = method.to_c_function();
+ if (func)
+ {
+ // It's a C function. Call it.
+ //log_msg("Calling C function for onConnect\n");
+ (*func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
+ }
+ else if (as_function* as_func = method.to_as_function())
+ {
+ // It's an ActionScript function. Call it.
+ //log_msg("Calling ActionScript function for onConnect\n");
+ (*as_func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
+ }
+ else
+ {
+ log_error("error in call_method(): method is not a function\n");
+ }
+ } else {
+ log_msg("FIXME: Couldn't find onConnect!\n");
+ }
+ }
+
+ fn.result->set_bool(val.to_bool());
+}
+void
+xmlsocket_event_xml(const fn_call& /* fn */)
+{
+#if 0
+ as_value* result = fn.result;
+ as_object* this_ptr = fn.this_ptr;
+ int nargs = fn.nargs;
+ int first_arg = fn.first_arg_bottom_index;
+#else
+ log_error("%s: unimplemented!\n", __FUNCTION__);
+#endif
+}
+
+static XMLSocket xs;
+
+int
+check_sockets(int x)
+{
+ if (xml_fd == 0) {
+ return -1;
+ }
+
+ return xs.checkSockets(x);
+}
+
+} // end of gnaash namespace
+
+// HAVE_LIBXML
+#endif
Index: server/asobj/xmlsocket.h
===================================================================
RCS file: server/asobj/xmlsocket.h
diff -N server/asobj/xmlsocket.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/xmlsocket.h 24 Nov 2006 09:19:50 -0000 1.1
@@ -0,0 +1,119 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+//
+//
+//
+
+#ifndef __XMLSOCKET_H__
+#define __XMLSOCKET_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tu_config.h"
+#include "xml.h"
+#include "impl.h"
+
+#include <string>
+
+#ifdef HAVE_LIBXML
+
+namespace gnash {
+
+extern const int SOCKET_DATA;
+
+class DSOLOCAL XMLSocket {
+ public:
+ XMLSocket();
+ ~XMLSocket();
+
+ bool connect(const char *host, int port);
+ bool send(std::string str);
+ void close();
+
+
+ bool anydata(char **msgs);
+ bool anydata(int sockfd, char **msgs);
+ bool connected() { return _connect; };
+ bool fdclosed() { return _closed; }
+ bool xmlmsg() { return _xmldata; }
+
+ void messagesClear() { _messages.clear(); }
+ void messageRemove(int x) { _messages.erase(_messages.begin() + x); }
+ int messagesCount() { return _messages.size(); }
+ std::string operator [] (int x) { return _messages[x]; }
+
+ bool processingData();
+ void processing(bool x);
+
+ // Event Handlers
+ void onClose(std::string);
+ void onConnect(std::string);
+ void onData(std::string);
+ void onXML(std::string);
+
+ // These handle the array of XML nodes
+ void push(as_object *obj);
+ void clear();
+ int count();
+
+ int checkSockets(void);
+ int checkSockets(int x);
+
+ private:
+ std::string _host;
+ short _port;
+ int _sockfd;
+ bool _data;
+ bool _xmldata;
+ bool _closed;
+ bool _connect;
+ bool _processing;
+ std::vector<std::string> _messages;
+ std::vector<as_object *> _nodes;
+};
+
+
+class DSOLOCAL xmlsocket_as_object : public gnash::as_object
+{
+public:
+ XMLSocket obj;
+};
+
+DSOEXPORT void xmlsocket_connect(const fn_call& fn);
+DSOEXPORT void xmlsocket_send(const fn_call& fn);
+DSOEXPORT void xmlsocket_xml_new(const fn_call& fn);
+DSOEXPORT void xmlsocket_new(const fn_call& fn);
+DSOEXPORT void xmlsocket_close(const fn_call& fn);
+
+// These are the event handlers called for this object
+DSOEXPORT void xmlsocket_event_ondata(const fn_call& fn);
+DSOEXPORT void xmlsocket_event_close(const fn_call& fn);
+DSOEXPORT void xmlsocket_event_connect(const fn_call& fn);
+DSOEXPORT void xmlsocket_event_xml(const fn_call& fn);
+
+DSOEXPORT int check_sockets(int fd);
+
+} // end of gnash namespace
+
+// HAVE_LIBXML
+#endif
+
+// __XMLSOCKETSOCKET_H__
+#endif
+
Index: server/xml.cpp
===================================================================
RCS file: server/xml.cpp
diff -N server/xml.cpp
--- server/xml.cpp 20 Nov 2006 22:06:38 -0000 1.34
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,1328 +0,0 @@
-//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-//
-//
-//
-
-/* $Id: xml.cpp,v 1.34 2006/11/20 22:06:38 strk Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string>
-#include <vector>
-
-#include "log.h"
-#include "tu_config.h"
-#include "as_function.h" // for as_function
-#include "fn_call.h"
-
-#ifdef HAVE_LIBXML
-
-#include <unistd.h>
-#include "xmlattrs.h"
-#include "xmlnode.h"
-#include "xml.h"
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlreader.h>
-
-using namespace std;
-
-namespace gnash {
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-
-XML::XML()
- :_loaded(false), _nodename(0), _nodes(0), _bytes_loaded(0),
_bytes_total(0)
-{
- GNASH_REPORT_FUNCTION;
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_msg("Creating XML data at %p \n", this);
-#endif
- //log_msg("%s: %p \n", __FUNCTION__, this);
-}
-
-
-// Parse the ASCII XML string into memory
-XML::XML(tu_string xml_in)
-{
- GNASH_REPORT_FUNCTION;
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_msg("Creating XML data at %p \n", this);
-#endif
- //log_msg("%s: %p \n", __FUNCTION__, this);
- //memset(&_nodes, 0, sizeof(XMLNode));
- parseXML(xml_in);
-}
-
-XML::XML(struct node */* childNode */)
-{
- GNASH_REPORT_FUNCTION;
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_msg("\tCreating XML data at %p \n", this);
-#endif
- //log_msg("%s: %p \n", __FUNCTION__, this);
-}
-
-
-XML::~XML()
-{
- GNASH_REPORT_FUNCTION;
-
-#ifdef DEBUG_MEMORY_ALLOCATION
- if (this->_nodes) {
- log_msg("\tDeleting XML top level node %s at %p \n",
this->_nodes->_name, this);
- } else {
- log_msg("\tDeleting XML top level node at %p \n", this);
- }
-#endif
-
- //log_msg("%s: %p \n", __FUNCTION__, this);
- delete _nodes;
-}
-
-const char *
-XML::nodeName()
-{
- printf("%s: XML %p _nodes at %p\n", __PRETTY_FUNCTION__, (void*)this,
(void*)_nodes);
- if (_nodes) {
- return _nodes->nodeName();
- }
- return "undefined";
-}
-
-const char *
-XML::nodeValue()
-{
- printf("%s: XML _nodes at %p\n", __PRETTY_FUNCTION__, (void*)_nodes);
- if (_nodes) {
- return _nodes->nodeValue();
- }
- return "undefined";
-}
-
-void
-XML::nodeNameSet(char */*name */)
-{
- if (!_nodes) {
- _nodes = new XMLNode;
- printf("%s: New XML %p _nodes at %p\n", __PRETTY_FUNCTION__, (void*)this,
(void*)_nodes);
- }
- // _nodes->nodeNameSet(name);
- printf("%s: XML %p _name at %p, %s\n", __PRETTY_FUNCTION__, (void*)this,
- _nodes->nodeName(), _nodes->nodeName() );
-}
-
-void
-XML::nodeValueSet(char */* value */)
-{
- if (!_nodes) {
- _nodes = new XMLNode;
- printf("%s: New XML _nodes at %p\n", __PRETTY_FUNCTION__, (void*)_nodes);
- }
-
- // _nodes->nodeValueSet(value);
- printf("%s: XML _nodes at %p\n", __PRETTY_FUNCTION__, (void*)_nodes);
-}
-
-// Dispatch event handler(s), if any.
-bool
-XML::on_event(const event_id& /* id */)
-{
- GNASH_REPORT_FUNCTION;
-
- // Keep m_as_environment alive during any method calls!
- // boost::intrusive_ptr<as_object_interface> this_ptr(this);
-
-#if 0
- // First, check for built-in event handler.
- as_value method;
- if (get_event_handler(event_id(id), &method)) {
- call_method0(method, &m_as_environment, this);
- return true;
- }
-
- // Check for member function.
- // In ActionScript 2.0, event method names are CASE SENSITIVE.
- // In ActionScript 1.0, event method names are CASE INSENSITIVE.
- const tu_string& method_name = id.get_function_name();
- if (method_name.length() > 0) {
- as_value method;
- if (get_member(method_name, &method)) {
- call_method0(method, &m_as_environment, this);
- return true;
- }
- }
-#endif
- return false;
-}
-
-void
-XML::on_event_load()
-{
- // Do the events that (appear to) happen as the movie
- // loads. frame1 tags and actions are executed (even
- // before advance() is called). Then the onLoad event
- // is triggered.
- on_event(event_id::LOAD);
-}
-
-XMLNode*
-XML::extractNode(xmlNodePtr node, bool mem)
-{
- xmlAttrPtr attr;
- xmlNodePtr childnode;
- xmlChar *ptr = NULL;
- XMLNode *element, *child;
- int len;
-
- element = new XMLNode;
-
- //log_msg("Created new element for %s at %p\n", node->name, element);
- memset(element, 0, sizeof (XMLNode));
-
- log_msg("%s: extracting node %s\n", __FUNCTION__, node->name);
-
- // See if we have any Attributes (properties)
- attr = node->properties;
- while (attr != NULL) {
- //log_msg("extractNode %s has property %s, value is %s\n",
- // node->name, attr->name, attr->children->content);
- XMLAttr *attrib = new XMLAttr;
- len = memadjust(strlen(reinterpret_cast<const char *>(attr->name))+1);
- attrib->_name = (char *)new char[len];
- memset(attrib->_name, 0, len);
- strcpy(attrib->_name, reinterpret_cast<const char *>(attr->name));
- len = memadjust(strlen(reinterpret_cast<const char
*>(attr->children->content))+1);
- attrib->_value = (char *)new char[len];
- memset(attrib->_value, 0, len);
- strcpy(attrib->_value, reinterpret_cast<const char
*>(attr->children->content));
- //log_msg("\tPushing attribute %s for element %s has value %s\n",
- // attr->name, node->name, attr->children->content);
- element->_attributes.push_back(attrib);
- attr = attr->next;
- }
-
- len = memadjust(strlen(reinterpret_cast<const char *>(node->name))+1);
- element->_name = (char *)new char[len];
- memset(element->_name, 0, len);
- strcpy(element->_name, reinterpret_cast<const char *>(node->name));
- //element->_name = reinterpret_cast<const char *>(node->name);
- if (node->children) {
- //ptr = node->children->content;
- ptr = xmlNodeGetContent(node->children);
- if (ptr != NULL) {
- if ((strchr((const char *)ptr, '\n') == 0) && (ptr[0] != 0)) {
- if (node->children->content == NULL) {
- //log_msg("Node %s has no contents\n", node->name);
- } else {
- //log_msg("extractChildNode from text for %s has contents
%s\n", node->name, ptr);
- len = memadjust(strlen(reinterpret_cast<const char
*>(ptr))+1);
- element->_value = (char *)new char[len];
- memset(element->_value, 0, len);
- strcpy(element->_value, reinterpret_cast<const char
*>(ptr));
- //element->_value = reinterpret_cast<const char *>(ptr);
- }
- }
- xmlFree(ptr);
- }
- }
-
- // See if we have any data (content)
- childnode = node->children;
-
- while (childnode != NULL) {
- if (childnode->type == XML_ELEMENT_NODE) {
- //log_msg("\t\t extracting node %s\n", childnode->name);
- child = extractNode(childnode, mem);
- //if (child->_value.get_type() != as_value::UNDEFINED) {
- if (child->_value != 0) {
- //log_msg("\tPushing childNode %s, value %s on element %p\n",
child->_name.c_str(), child->_value.to_string(), element);
- } else {
- //log_msg("\tPushing childNode %s on element %p\n",
child->_name.c_str(), element);
- }
- element->_children.push_back(child);
- }
- childnode = childnode->next;
- }
-
- return element;
-}
-
-// Read in an XML document from the specified source
-bool
-XML::parseDoc(xmlDocPtr document, bool mem)
-{
- GNASH_REPORT_FUNCTION;
-
- XMLNode *top;
- xmlNodePtr cur;
-
- if (document == 0) {
- log_error("Can't load XML file!\n");
- return false;
- }
-
- cur = xmlDocGetRootElement(document);
-
- if (cur != NULL) {
- top = extractNode(cur, mem);
- //_nodes->_name = reinterpret_cast<const char *>(cur->name);
- _nodes = top;
- //_node_data.push_back(top);
- //cur = cur->next;
- }
-
- _loaded = true;
- return true;
-}
-
-// This reads in an XML file from disk and parses into into a memory resident
-// tree which can be walked through later.
-bool
-XML::parseXML(tu_string xml_in)
-{
- GNASH_REPORT_FUNCTION;
-
- log_msg("Parse XML from memory: %s\n", xml_in.c_str());
-
- if (xml_in.size() == 0) {
- log_error("XML data is empty!\n");
- return false;
- }
-
-#ifndef USE_DMALLOC
- //dump_memory_stats(__FUNCTION__, __LINE__, "before xmlParseMemory");
-#endif
-
- _bytes_total = _bytes_loaded = xml_in.size();
-
-#ifdef USE_XMLREADER
- XMLNode *node = 0;
- xmlTextReaderPtr reader;
-
- reader = xmlReaderForMemory(xml_in.c_str(), xml_in.size(), NULL, NULL, 0);
- if (reader != NULL) {
- bool ret = true;
- while (ret) {
- ret = xmlTextReaderRead(reader);
- node = processNode(reader, node);
- }
- xmlFreeTextReader(reader);
- if (ret != false) {
- log_error("%s : couldn't parse\n", xml_in.c_str());
- return false;
- }
- } else {
- log_error("Unable to open %s\n", xml_in.c_str());
- return false;
- }
- xmlCleanupParser();
- return true;
-#else
-
-bool ret = true;
-
-#ifdef USE_DOM
- xmlInitParser();
-
- _doc = xmlParseMemory(xml_in.c_str(), xml_in.size());
- if (_doc == 0) {
- log_error("Can't parse XML data!\n");
- return false;
- }
- ret = parseDoc(_doc, true);
- xmlCleanupParser();
- xmlFreeDoc(_doc);
- xmlMemoryDump();
-#endif
-#ifndef USE_DMALLOC
- //dump_memory_stats(__FUNCTION__, __LINE__, "after xmlParseMemory");
-#endif
- return ret;
-#endif
-
-}
-
-// XML_READER_TYPE_NONE = 0
-// XML_READER_TYPE_ELEMENT = 1,
-// XML_READER_TYPE_ATTRIBUTE = 2,
-// XML_READER_TYPE_TEXT = 3,
-// XML_READER_TYPE_COMMENT = 8,
-// XML_READER_TYPE_SIGNIFICANT_WHITESPACE = 14,
-// XML_READER_TYPE_END_ELEMENT = 15,
-//
-// processNode:
-// 2 1 IP 0// processNode:
-// 3 3 #text 0 192.168.2.50
-// processNode:
-// 2 15 IP 0
-// processNode:
-// 2 14 #text 0
-const char *tabs[] = {
- "",
- "\t",
- "\t\t",
- "\t\t\t",
- "\t\t\t",
- "\t\t\t\t",
-};
-
-#ifdef USE_XMLREADER
-// This is an xmlReader (SAX) based parser. For some reason it core dumps
-// when compiled with GCC 3.x, but works just fine with GCC 4.x.
-XMLNode*
-XML::processNode(xmlTextReaderPtr reader, XMLNode *node)
-{
- log_msg("%s: node is %p\n", __PRETTY_FUNCTION__, node);
- static XMLNode *parent[10];
- xmlChar *name, *value;
- int depth;
- XMLNode *element;
- //static int previous_depth = 0;
- xmlReaderTypes type;
-
- if (node == 0) {
- memset(parent, 0, sizeof(XMLNode *));
- }
- type = (xmlReaderTypes)xmlTextReaderNodeType(reader);
- depth = xmlTextReaderDepth(reader);
- value = xmlTextReaderValue(reader);
- name = xmlTextReaderName(reader);
-
- if (name == NULL)
- name = xmlStrdup(BAD_CAST "--");
-
-#if 0
- printf("%d %d %s %d\n",
- depth,
- (int)type,
- name,
- xmlTextReaderIsEmptyElement(reader));
-#endif
-
-
- //child = node->_children[0];
- switch(xmlTextReaderNodeType(reader)) {
- case XML_READER_TYPE_NONE:
- break;
- case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: // This is an empty text
node
- //log_msg("\tWhitespace at depth %d\n", depth);
- break;
- case XML_READER_TYPE_END_ELEMENT:
- if (depth == 0) { // This is the last node in the file
- element = node;
- break;
- }
- parent[depth]->_children.push_back(element);
-// log_msg("Pushing element %s on node %s\n", node->_name,
parent[depth]->_name);
-// log_msg("End element at depth %d is %s for parent %s %p\n", depth,
name,
-// parent[depth]->_name, parent[depth]);
- element = parent[depth];
- break;
- case XML_READER_TYPE_ELEMENT:
- element = new XMLNode;
-// log_msg("%sElement at depth %d is %s for node at %p\n", tabs[depth],
depth, name, element);
- element->_name = (char *)new char[strlen(reinterpret_cast<const char
*>(name))+1];
- memset(element->_name, 0, strlen(reinterpret_cast<const char
*>(name))+1);
- strcpy(element->_name, reinterpret_cast<const char *>(name));
- if (node == 0) {
- _nodes = element;
- parent[0] = element;
- } else {
- parent[depth] = node;
- parent[depth+1] = node;
- }
- // xmlTextReaderAttributeCount(reader);
- if (xmlTextReaderHasAttributes(reader)) {
- // log_msg("Has Attributes!\n");
- xmlTextReaderMoveToFirstAttribute(reader);
- processNode(reader, element);
- while(xmlTextReaderMoveToNextAttribute(reader)) {
- processNode(reader, element);
- }
- }
- break;
- case XML_READER_TYPE_TEXT:
- element = node;
-// log_msg("%sValue at depth %d is \"%s\" for node at %p\n", tabs[depth],
depth, value, element);
- element->_value = (char *)new char[strlen(reinterpret_cast<const
char *>(value))+1];
- memset(element->_value, 0, strlen(reinterpret_cast<const char
*>(value))+1);
- strcpy(element->_value, reinterpret_cast<const char *>(value));
- break;
- case XML_READER_TYPE_ATTRIBUTE:
- element = node;
- XMLAttr *attrib = new XMLAttr;
- attrib->_name = (char *)new char[strlen(reinterpret_cast<const char
*>(name))+1];
- memset(attrib->_name, 0, strlen(reinterpret_cast<const char
*>(name))+1);
- strcpy(attrib->_name, reinterpret_cast<const char *>(name));
- attrib->_value = (char *)new char[strlen(reinterpret_cast<const char
*>(value))+1];
- memset(attrib->_value, 0, strlen(reinterpret_cast<const char
*>(value))+1);
- strcpy(attrib->_value, reinterpret_cast<const char *>(value));
-// log_msg("%sPushing attribute %s, value \"%s\" for node %s\n",
tabs[depth], name, value, element->_name);
- element->_attributes.push_back(attrib);
- break;
- default: // FIXME: why does this break GCC 3.3.3 but not 3.4.3 ?
- log_error("Unsupported XML type %d\n!", type);
- break;
- };
-
- xmlFree(name);
- if (value != NULL) {
- xmlFree(value);
- }
- //previous_depth = depth;
- return element;
-}
-#endif
-
-// This reads in an XML file from disk and parses into into a memory resident
-// tree which can be walked through later.
-bool
-XML::load(const char *filespec)
-{
- GNASH_REPORT_FUNCTION;
- struct stat stats;
- log_msg("Load disk XML file: %s\n", filespec);
-
- //log_msg("%s: mem is %d\n", __FUNCTION__, mem);
-
- // See if the file exists
- if (stat(filespec, &stats) == 0) {
- _bytes_total = stats.st_size;
- _bytes_loaded = stats.st_size; // FIXME: this should probably
- // be set later on after the
- // file is loaded
- }
-#ifdef USE_XMLREADER
- XMLNode *node = 0;
- xmlTextReaderPtr reader;
-
- reader = xmlNewTextReaderFilename(filespec);
- if (reader != NULL) {
- bool ret = true;
- while (ret) {
- ret = xmlTextReaderRead(reader);
- node = processNode(reader, node);
- }
- xmlFreeTextReader(reader);
- if (ret != false) {
- log_error("%s : couldn't parse\n", filespec);
- return false;
- }
- } else {
- log_error("Unable to open %s\n", filespec);
- return false;
- }
- xmlCleanupParser();
- return true;
-#else
-#ifdef USE_DOM
- xmlInitParser();
- _doc = xmlParseFile(filespec);
- if (_doc == 0) {
- log_error("Can't load XML file: %s!\n", filespec);
- return false;
- }
- parseDoc(_doc, false);
- xmlCleanupParser();
- xmlFreeDoc(_doc);
- xmlMemoryDump();
- return true;
-#else
-#error "You have to enable either a DOM or an xmlReader XML parser"
-#endif
-#endif
-}
-
-
-vector<XMLNode *>
-XML::childNodes()
-{
- if (_nodes) {
- return _nodes->_children;
- } else {
- return static_cast< vector<XMLNode*> >(0);
- }
-}
-
-bool
-XML::onLoad()
-{
- log_msg("%s: FIXME: onLoad Default event handler\n", __FUNCTION__);
-
- return(_loaded);
-}
-
-XMLNode *
-XML::operator [] (int x) {
- log_msg("%s:\n", __FUNCTION__);
-
- return _nodes->_children[x];
-}
-
-void
-XML::cleanupStackFrames(XMLNode */* xml */)
-{
- GNASH_REPORT_FUNCTION;
-}
-
-as_object *
-XML::setupFrame(as_object *obj, XMLNode *xml, bool mem)
-{
-// GNASH_REPORT_FUNCTION;
-
- int child;
- unsigned int i;
- const char *nodename;
- //const char *nodevalue;
- //AS_value nodevalue;
- int length;
- as_value inum;
- XMLNode *childnode;
- xmlnode_as_object *xmlchildnode_obj;
- xmlattr_as_object* attr_obj;
-
- //log_msg("\t%s: processing node %s for object %p, mem is %d\n",
__FUNCTION__, xml->_name, obj, mem);
-
- // Get the data for this node
- nodename = xml->_name;
- //nodename = xml->_name.c_str();
- //nodevalue = xml->_value;
- length = xml->length();
-
- // Set these members in the top level object passed in. This are used
- // primarily by the disk based XML parser, where at least in all my current
- // test cases this is referenced with firstChild first, then nodeName and
- // childNodes.
- obj->set_member("nodeName", nodename);
- obj->set_member("length", length);
- if (xml->_value != 0) {
- obj->set_member("nodeValue", xml->_value);
- log_msg("\tnodevalue for %s is: %s\n", nodename, xml->_value);
- } else {
- obj->set_member("nodeValue", as_value::UNDEFINED);
- }
-
-// if (nodevalue.get_type() != as_value::UNDEFINED) {
-// obj->set_member("nodeValue", nodevalue.to_string());
-// log_msg("\tnodevalue for %s is: %s\n", nodename, nodevalue.to_string());
-// } else {
-// // If there is no value, we want to define it as an empty
-// // string.
-// obj->set_member("nodeValue", "");
-// }
-
-
- // Process the attributes, if any
- if (xml->_attributes.size() == 0) {
- //log_msg("\t\tNo attributes for node %s, created empty object at
%p\n", nodename, attr_obj);
-// log_msg("\t\tNo attributes for node %s\n", nodename);
- } else {
- attr_obj = new xmlattr_as_object;
- for (i=0; i<xml->_attributes.size(); i++) {
- attr_obj->set_member(xml->_attributes[i]->_name,
xml->_attributes[i]->_value);
- log_msg("\t\tAdding attribute as member %s, value is %s to node %s
(%p)\n",
- xml->_attributes[i]->_name,
- xml->_attributes[i]->_value, nodename,
static_cast<void*>(obj) );
- }
- obj->set_member("attributes", attr_obj);
- }
-
- //xml->_attributes.resize(0);
- //obj->set_member("attributes", attr_obj);
-
- // Process the children, if there are any
- if (length) {
- //log_msg("\tProcessing %d children nodes for %s\n", length, nodename);
- inum = 0;
- for (child=0; child<length; child++) {
- // Create a new AS object for this node's children
- xmlchildnode_obj = new xmlnode_as_object;
- // When parsing XML from memory, the test movies I have expect the
firstChild
- // to be the first element of the array instead.
- if (mem) {
- childnode = xml;
- //obj->set_member(inum.to_string(), obj);
- //inum += 1;
- //childnode = xml->_children[child];
- } else {
- childnode = xml->_children[child];
- }
- setupFrame(xmlchildnode_obj, childnode, false); // setup child node
- obj->set_member(inum.to_string(), xmlchildnode_obj);
- inum += 1;
- }
- } else {
- //log_msg("\tNode %s has no children\n", nodename);
- }
-
- return obj;
-}
-
-
-/// \brief add or change the HTTP Request header
-///
-/// Method; adds or changes HTTP request headers (such as Content-Type
-/// or SOAPAction) sent with POST actions. In the first usage, you pass
-/// two strings to the method: headerName and headerValue. In the
-/// second usage, you pass an array of strings, alternating header
-/// names and header values.
-///
-/// If multiple calls are made to set the same header name, each
-/// successive value replaces the value set in the previous call.
-void
-XML::addRequestHeader(const char */* name */, const char */* value */)
-{
- log_msg("%s:unimplemented \n", __FUNCTION__);
-}
-
-/// \brief append a node the the XML object
-///
-/// Method; appends the specified node to the XML object's child
-/// list. This method operates directly on the node referenced by the
-/// childNode parameter; it does not append a copy of the node. If the
-/// node to be appended already exists in another tree structure,
-/// appending the node to the new location will remove it from its
-/// current location. If the childNode parameter refers to a node that
-/// already exists in another XML tree structure, the appended child
-/// node is placed in the new tree structure after it is removed from
-/// its existing parent node.
-void
-XML::appendChild(XMLNode *node)
-{
- if (!_nodes) {
- _nodes = new XMLNode;
- }
- _nodes->_children.push_back(node);
- // log_msg("%s: %p at _nodes at %p\n", __PRETTY_FUNCTION__, this,
_nodes);
-}
-
-/// \brief copy a node
-///
-/// Method; constructs and returns a new XML node of the same type,
-/// name, value, and attributes as the specified XML object. If deep
-/// is set to true, all child nodes are recursively cloned, resulting
-/// in an exact copy of the original object's document tree.
-XMLNode &
-XML::cloneNode(XMLNode &newnode, bool deep)
-{
- log_msg("%s: deep is %d\n", __PRETTY_FUNCTION__, deep);
-
- if (deep) {
- newnode = _nodes;
-// } else {
-// newnode.nodeNameSet((char *)_nodes->nodeName());
-// newnode.nodeValueSet((char *)_nodes->nodeValue());
- }
-
- return newnode;
-
- log_msg("%s:partially unimplemented \n", __PRETTY_FUNCTION__);
-}
-
-/// \brief create a new XML element
-///
-/// Method; creates a new XML element with the name specified in the
-/// parameter. The new element initially has no parent, no children,
-/// and no siblings. The method returns a reference to the newly
-/// created XML object that represents the element. This method and
-/// the XML.createTextNode() method are the constructor methods for
-/// creating nodes for an XML object.
-XMLNode *
-XML::createElement(const char */* name */)
-{
- log_msg("%s:unimplemented \n", __FUNCTION__);
- return (XMLNode*)0;
-}
-
-/// \brief Create a new XML node
-///
-/// Method; creates a new XML text node with the specified text. The
-/// new node initially has no parent, and text nodes cannot have
-/// children or siblings. This method returns a reference to the XML
-/// object that represents the new text node. This method and the
-/// XML.createElement() method are the constructor methods for
-/// creating nodes for an XML object.
-XMLNode *
-XML::createTextNode(const char */* name */)
-{
- log_msg("%s:unimplemented \n", __FUNCTION__);
- return (XMLNode*)0;
-}
-
-/// \brief insert a node before a node
-///
-/// Method; inserts a new child node into the XML object's child
-/// list, before the beforeNode node. If the beforeNode parameter is
-/// undefined or null, the node is added using the appendChild()
-/// method. If beforeNode is not a child of my_xml, the insertion
-/// fails.
-void
-XML::insertBefore(XMLNode */* newnode */, XMLNode */* node */)
-{
- log_msg("%s:unimplemented \n", __FUNCTION__);
-}
-
-void
-XML::load()
-{
- log_msg("%s:unimplemented \n", __FUNCTION__);
-}
-
-void
-XML::parseXML()
-{
- log_msg("%s: unimplemented \n", __FUNCTION__);
-}
-
-/// \brief removes the specified XML object from its parent. Also
-/// deletes all descendants of the node.
-void
-XML::removeNode()
-{
- log_msg("%s:unimplemented \n", __FUNCTION__);
-}
-
-void
-XML::send()
-{
- log_msg("%s:unimplemented \n", __FUNCTION__);
-}
-
-void
-XML::sendAndLoad()
-{
- log_msg("%s:unimplemented \n", __FUNCTION__);
-}
-
-const char *
-XML::toString()
-{
- if (_nodes) {
- return stringify(_nodes);
- }
- return NULL;
-}
-
-//
-const char *
-XML::stringify(XMLNode *xml)
-{
- int child;
- unsigned int i;
- const char *nodename = xml->nodeName();
- int length;
- string str;
-
- log_msg("%s: processing for object %p\n", __PRETTY_FUNCTION__,
(void*)this);
-
- // Process the attributes, if any
- if (_nodes->_attributes.size() == 0) {
- log_msg("\t\tNo attributes for node\n");
- } else {
- for (i=0; i<xml->_attributes.size(); i++) {
- log_msg("\t\tAdding attribute as member %s, value is %s to node
%s\n",
- xml->_attributes[i]->_name,
- xml->_attributes[i]->_value, nodename);
- }
- }
-
- vector<XMLNode *>::iterator it;
- for (it = _nodes->_children.begin(); it != _nodes->_children.end(); ++it) {
- log_msg("Found One!!!! %p\n", (void*)*it);
- }
-
- // Process the children, if there are any
- length = xml->_children.size();
-
- if (length) {
- log_msg("\tProcessing %d children nodes\n", length);
- for (child=0; child<length; child++) {
- log_msg("Name %p\n", (void*)(xml->_children[child]));
- if (xml->_children[child]->_name) {
-// log_msg("Name %p", xml->_children[child]);
- }
- if (xml->_children[child]->_value) {
-// log_msg("Value %s", xml->_children[child]->_value);
- }
-
-// str += stringify(xml->_children[child]);
- }
- } else {
- log_msg("\tNode %s has no children\n", nodename);
- }
- return str.c_str();
-}
-
-//
-// Callbacks. These are the wrappers for the C++ functions so they'll work as
-// callbacks from within gnash.
-//
-void
-xml_load(const fn_call& fn)
-{
- as_value method;
- as_value val;
- bool ret;
- struct stat stats;
-
- //GNASH_REPORT_FUNCTION;
-
- xml_as_object *xml_obj = (xml_as_object*)fn.this_ptr;
-
- const std::string filespec =
fn.env->bottom(fn.first_arg_bottom_index).to_string();
-
- // If the file doesn't exist, don't try to do anything.
- if (stat(filespec.c_str(), &stats) < 0) {
- fprintf(stderr, "ERROR: doesn't exist.%s\n", filespec.c_str());
- fn.result->set_bool(false);
- return;
- }
-
- // Set the argument to the function event handler based on whether the load
- // was successful or failed.
- ret = xml_obj->obj.load(filespec.c_str());
- fn.result->set_bool(ret);
-
- if (ret == false) {
- return;
- }
-
- //env->bottom(first_arg) = ret;
- // struct node *first_node = ptr->obj.firstChildGet();
-
- //const char *name = ptr->obj.nodeNameGet();
-
- if (xml_obj->obj.hasChildNodes() == false) {
- log_error("%s: No child nodes!\n", __FUNCTION__);
- }
- xml_obj->obj.setupFrame(xml_obj, xml_obj->obj.firstChild(), false);
-
-#if 1
- if (fn.this_ptr->get_member("onLoad", &method)) {
- // log_msg("FIXME: Found onLoad!\n");
- fn.env->set_variable("success", true);
- fn.env->bottom(fn.first_arg_bottom_index) = true;
- as_c_function_ptr func = method.to_c_function();
- if (func) {
- // It's a C function. Call it.
- log_msg("Calling C function for onLoad\n");
- (*func)(fn_call(&val, xml_obj, fn.env, fn.nargs,
fn.first_arg_bottom_index)); // was this_ptr instead of node
- } else if (as_function* as_func = method.to_as_function()) {
- // It's an ActionScript function. Call it.
- log_msg("Calling ActionScript function for onLoad\n");
- (*as_func)(fn_call(&val, xml_obj, fn.env, fn.nargs,
fn.first_arg_bottom_index)); // was this_ptr instead of node
- } else {
- log_error("error in call_method(): method is not a function\n");
- }
- } else {
- log_msg("Couldn't find onLoad event handler, setting up callback\n");
- // ptr->set_event_handler(event_id::XML_LOAD,
(as_c_function_ptr)&xml_onload);
- }
-#else
- xml_obj->set_event_handler(event_id::XML_LOAD, &xml_onload);
-
-#endif
-
- fn.result->set_bool(true);
-}
-
-// This executes the event handler for XML::XML_LOAD if it's been defined,
-// and the XML file has loaded sucessfully.
-void
-xml_onload(const fn_call& fn)
-{
- //log_msg("%s:\n", __FUNCTION__);
-
- as_value method;
- as_value val;
- static bool first = true; // This event handler should only be
executed once.
- xml_as_object* ptr = (xml_as_object*) (as_object*) fn.this_ptr;
- assert(ptr);
-
- if ((ptr->obj.loaded()) && (first)) {
- // env->set_variable("success", true, 0);
- //as_value bo(true);
- //env->push_val(bo);
-
- first = false;
- log_msg("The XML file has been loaded successfully!\n");
- // ptr->on_event(event_id::XML_LOAD);
- //env->set_variable("success", true, 0);
- //env->bottom(0) = true;
-
- if (fn.this_ptr->get_member("onLoad", &method)) {
- // log_msg("FIXME: Found onLoad!\n");
- as_c_function_ptr func = method.to_c_function();
- if (func)
- {
- // It's a C function. Call it.
- log_msg("Calling C function for onLoad\n");
- (*func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
- }
- else if (as_function* as_func = method.to_as_function())
- {
- // It's an ActionScript function. Call it.
- log_msg("Calling ActionScript function for onLoad\n");
- (*as_func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
- }
- else
- {
- log_error("error in call_method(): method is not a
function\n");
- }
- } else {
- log_msg("FIXME: Couldn't find onLoad!\n");
- }
- }
-
- fn.result->set_bool(val.to_bool());
-}
-
-// This is the default event handler, and is usually redefined in the SWF
script
-void
-xml_ondata(const fn_call& fn)
-{
- log_msg("%s:\n", __FUNCTION__);
-
- as_value method;
- as_value val;
- static bool first = true; // FIXME: ugly hack!
-
- xml_as_object* ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
-
- if ((ptr->obj.loaded()) && (first)) {
- if (fn.this_ptr->get_member("onData", &method)) {
- log_msg("FIXME: Found onData!\n");
- as_c_function_ptr func = method.to_c_function();
- fn.env->set_variable("success", true);
- if (func)
- {
- // It's a C function. Call it.
- log_msg("Calling C function for onData\n");
- (*func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
- }
- else if (as_function* as_func = method.to_as_function())
- {
- // It's an ActionScript function. Call it.
- log_msg("Calling ActionScript function for onData\n");
- (*as_func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
- }
- else
- {
- log_error("error in call_method(): method is not a
function\n");
- }
- } else {
- log_msg("FIXME: Couldn't find onData!\n");
- }
- }
-
- //fn.result->set(&val);
- fn.result->set_bool(val.to_bool());
-}
-
-void
-xml_new(const fn_call& fn)
-{
- as_value inum;
- xml_as_object *xml_obj;
- //const char *data;
-
- // log_msg("%s: nargs=%d\n", __FUNCTION__, fn.nargs);
-
- if (fn.nargs > 0) {
- if (fn.env->top(0).get_type() == as_value::STRING) {
- xml_obj = new xml_as_object;
- //log_msg("\tCreated New XML object at %p\n", xml_obj);
- tu_string datain = fn.env->top(0).to_tu_string();
- xml_obj->obj.parseXML(datain);
- //log_msg("*** Start setting up the stack frames ***\n");
- xml_obj->obj.setupFrame(xml_obj, xml_obj->obj.firstChild(), true);
- //xml_obj->obj.clear();
- //delete xml_obj->obj.firstChild();
- } else {
- xml_as_object* xml_obj =
(xml_as_object*)fn.env->top(0).to_object();
- //log_msg("\tCloned the XML object at %p\n", xml_obj);
- //result->set(xml_obj);
- fn.result->set_as_object(xml_obj);
- return;
- }
- } else {
- xml_obj = new xml_as_object;
- //log_msg("\tCreated New XML object at %p\n", xml_obj);
- // FIXME: this doesn't appear to exist in the MM player, should it ?
- xml_obj->set_member("loaded", &xml_loaded);
-
- xml_obj->set_member("addRequestHeader", &xml_addrequestheader);
- xml_obj->set_member("appendChild", &xml_appendchild);
- xml_obj->set_member("cloneNode", &xml_clonenode);
- xml_obj->set_member("createElement", &xml_createelement);
- xml_obj->set_member("createTextNode", &xml_createtextnode);
- xml_obj->set_member("getBytesLoaded", &xml_getbytesloaded);
- xml_obj->set_member("getBytesTotal", &xml_getbytestotal);
- xml_obj->set_member("hasChildNodes", &xml_haschildnodes);
- xml_obj->set_member("insertBefore", &xml_insertbefore);
- xml_obj->set_member("load", &xml_load);
- xml_obj->set_member("parseXML", &xml_parsexml);
- xml_obj->set_member("removeNode", &xml_removenode);
- xml_obj->set_member("send", &xml_send);
- xml_obj->set_member("sendAndLoad", &xml_sendandload);
- xml_obj->set_member("toString", &xml_tostring);
- // Properties
- xml_obj->set_member("nodeName", as_value(""));
- xml_obj->set_member("nodevalue", as_value(""));
-
- }
-
- fn.result->set_as_object(xml_obj);
-}
-
-//
-// SWF Property of this class. These are "accessors" into the private data
-// of the class.
-//
-
-// determines whether the document-loading process initiated by the XML.load()
-// call has completed. If the process completes successfully, the method
-// returns true; otherwise, it returns false.
-void
-xml_loaded(const fn_call& fn)
-{
- as_value method;
- as_value val;
-
- log_msg("%s:\n", __FUNCTION__);
-
- xml_as_object* ptr = (xml_as_object*) (as_object*) fn.this_ptr;
- assert(ptr);
- std::string filespec =
fn.env->bottom(fn.first_arg_bottom_index).to_string();
- //fn.result->set(ptr->obj.loaded());
- fn.result->set_bool(ptr->obj.loaded());
-}
-
-
-void xml_addrequestheader(const fn_call& fn)
-{
- log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
-
-// fn.result->set_int(ptr->obj.getAllocated());
-// ptr->obj.addRequestHeader();
- log_msg("%s:unimplemented \n", __FUNCTION__);
-}
-void xml_appendchild(const fn_call& fn)
-{
- // log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
- xmlnode_as_object *xml_obj =
(xmlnode_as_object*)fn.env->top(0).to_object();
-
- ptr->obj.appendChild(&(xml_obj->obj));
-}
-
-void xml_clonenode(const fn_call& fn)
-{
- log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- xmlnode_as_object *xml_obj;
- assert(ptr);
-
- if (fn.nargs > 0) {
- bool deep = fn.env->bottom(fn.first_arg_bottom_index).to_bool();
- xml_obj = new xmlnode_as_object;
- xml_obj->set_member("nodeName", as_value(""));
- xml_obj->set_member("nodeValue", as_value(""));
- xml_obj->set_member("appendChild", &xmlnode_appendchild);
- ptr->obj.cloneNode(xml_obj->obj, deep);
- fn.result->set_as_object(xml_obj);
- } else {
- log_msg("ERROR: no Depth paramater!\n");
- }
-
-}
-void xml_createelement(const fn_call& fn)
-{
- // log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
- xmlnode_as_object *xml_obj;
- const char *text;
-
- if (fn.nargs > 0) {
- text = fn.env->bottom(fn.first_arg_bottom_index).to_string();
- xml_obj = new xmlnode_as_object;
- xml_obj->set_member("nodeName", as_value(text));
- xml_obj->set_member("nodeValue", as_value(""));
- xml_obj->set_member("appendChild", &xmlnode_appendchild);
-// xml_obj->obj.nodeNameSet((char *)text);
- xml_obj->obj._type = XML_ELEMENT_NODE;
- fn.result->set_as_object(xml_obj);
- } else {
- log_msg("ERROR: no text for element creation!\n");
- }
-}
-
-
-void xml_createtextnode(const fn_call& fn)
-{
- // log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
- xmlnode_as_object *xml_obj;
- const char *text;
-
- if (fn.nargs > 0) {
- text = fn.env->bottom(fn.first_arg_bottom_index).to_string();
- xml_obj = new xmlnode_as_object;
- xml_obj->set_member("nodeName", as_value(""));
- xml_obj->set_member("nodeValue", as_value(text));
- xml_obj->set_member("appendChild", &xmlnode_appendchild);
-// xml_obj->obj.nodeValueSet((char *)text);
- xml_obj->obj._type = XML_TEXT_NODE;
- fn.result->set_as_object(xml_obj);
-// log_msg("%s: xml obj is %p\n", __PRETTY_FUNCTION__, xml_obj);
- } else {
- log_msg("ERROR: no text for text node creation!\n");
- }
-}
-
-void xml_getbytesloaded(const fn_call& fn)
-{
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
- fn.result->set_int(ptr->obj.getBytesLoaded());
-}
-
-void xml_getbytestotal(const fn_call& fn)
-{
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
- fn.result->set_int(ptr->obj.getBytesTotal());
-}
-
-void xml_haschildnodes(const fn_call& fn)
-{
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
- fn.result->set_bool(ptr->obj.hasChildNodes());
-}
-void xml_insertbefore(const fn_call& fn)
-{
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
-
-// fn.result->set_int(ptr->obj.getAllocated());
-// ptr->obj.insertBefore();
- log_msg("%s:unimplemented \n", __FUNCTION__);
-}
-void xml_parsexml(const fn_call& fn)
-{
- const char *text;
- as_value method;
- as_value val;
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
-
- if (fn.nargs > 0) {
- text = fn.env->bottom(fn.first_arg_bottom_index).to_string();
- ptr->obj.parseXML(text);
- ptr->obj.setupFrame(ptr, ptr->obj.firstChild(), false);
- }
-
-#if 1
- if (fn.this_ptr->get_member("onLoad", &method)) {
- // log_msg("FIXME: Found onLoad!\n");
- fn.env->set_variable("success", true);
- fn.env->bottom(fn.first_arg_bottom_index) = true;
- as_c_function_ptr func = method.to_c_function();
- if (func) {
- // It's a C function. Call it.
- log_msg("Calling C function for onLoad\n");
- (*func)(fn_call(&val, ptr, fn.env, fn.nargs,
fn.first_arg_bottom_index)); // was this_ptr instead of node
- } else if (as_function* as_func = method.to_as_function()) {
- // It's an ActionScript function. Call it.
- log_msg("Calling ActionScript function for onLoad\n");
- (*as_func)(fn_call(&val, ptr, fn.env, fn.nargs,
fn.first_arg_bottom_index)); // was this_ptr instead of node
- } else {
- log_error("error in call_method(): method is not a function\n");
- }
- } else {
- log_msg("Couldn't find onLoad event handler, setting up callback\n");
- // ptr->set_event_handler(event_id::XML_LOAD,
(as_c_function_ptr)&xml_onload);
- }
-#else
-
-#endif
-// fn.result->set_int(ptr->obj.getAllocated());
-}
-
-void xml_removenode(const fn_call& fn)
-{
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
-
-// fn.result->set_int(ptr->obj.getAllocated());
- ptr->obj.removeNode();
-}
-void xml_send(const fn_call& fn)
-{
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
-
-// fn.result->set_int(ptr->obj.getAllocated());
- ptr->obj.send();
-}
-void xml_sendandload(const fn_call& fn)
-{
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
-
-// fn.result->set_int(ptr->obj.getAllocated());
- ptr->obj.sendAndLoad();
-}
-void xml_tostring(const fn_call& fn)
-{
- xml_as_object *ptr = (xml_as_object*)fn.this_ptr;
- assert(ptr);
-
- fn.result->set_string(ptr->obj.toString());
-}
-
-int
-memadjust(int x)
-{
- return (x + (4 - x % 4));
-}
-
-
-} // end of gnash namespace
-
-// HAVE_LIBXML
-#endif
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/xml.h
===================================================================
RCS file: server/xml.h
diff -N server/xml.h
--- server/xml.h 20 Nov 2006 22:06:38 -0000 1.21
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,266 +0,0 @@
-//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-//
-//
-//
-
-#ifndef __XML_H__
-#define __XML_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "tu_config.h"
-
-#include "event_id.h"
-#include "action.h"
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-#include <vector>
-
-#ifdef HAVE_LIBXML
-
-#include "xmlattrs.h"
-#include "xmlnode.h"
-
-#ifdef DEBUG_MEMORY_ALLOCATION
- #include "log.h"
-#endif
-
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/xmlreader.h>
-
-// Forward declarations
-namespace gnash {
- class fn_call;
-}
-
-namespace gnash {
-
-/// XML class
-class DSOLOCAL XML {
-public:
- XML();
- XML(tu_string xml_in);
- XML(struct node * childNode);
- virtual ~XML();
-
- // Methods
- // This is the base method used by both parseXML() and load().
- bool parseDoc(xmlDocPtr document, bool mem);
- // Parses an XML document into the specified XML object tree.
- bool parseXML(tu_string xml_in);
- // Loads a document (specified by
- bool load(const char *filespec);
- // the XML object) from a URL.
-
- // An event handler that returns a
- bool onLoad();
- // Boolean value indicating whether
- // the XML object was successfully
- // loaded with XML.load() or
- // XML.sendAndLoad().
-
- // Appends a node to the end of the specified object's child list.
- void appendChild(XMLNode *node);
-
- virtual bool on_event(const gnash::event_id& id);
- virtual void on_event_load();
- bool loaded() { return _loaded; }
-
- XMLNode *firstChild() {
- return _nodes;
- //return _node_data[0];
- }
-
- void clear() {
- delete _nodes;
- }
-
- std::vector<XMLNode *> childNodes();
-
- const char *stringify(XMLNode *xml);
- // Returns true if the specified node has child nodes; otherwise, returns
false.
- bool hasChildNodes() {
- if (_nodes) {
- if (_nodes->_children.size()) {
- return true;
- }
- }
- return false;
- }
-
- XMLNode *extractNode(xmlNodePtr node, bool mem);
- XMLNode *processNode(xmlTextReaderPtr reader, XMLNode *node);
-
- void change_stack_frame(int frame, gnash::as_object *xml,
gnash::as_environment *env);
-// void setupStackFrames(gnash::as_object *xml, gnash::as_environment
*env);
- void cleanupStackFrames( XMLNode *data);
- as_object *setupFrame(gnash::as_object *xml, XMLNode *data, bool src);
-
- const char *nodeNameGet() { return _nodename; }
- const char *nodeName();
- const char *nodeValue();
- void nodeNameSet(char *name);
- void nodeValueSet(char *value);
- int length() { return _nodes->length(); }
-
- // These 6 have to
- void addRequestHeader(const char *name, const char *value);
- XMLNode &cloneNode(XMLNode &newnode, bool deep);
- XMLNode *createElement(const char *name);
- XMLNode *createTextNode(const char *name);
- void insertBefore(XMLNode *newnode, XMLNode *node);
-
- void load();
- void parseXML();
- void removeNode();
- void send();
- void sendAndLoad();
- const char *toString();
-
- int getBytesLoaded() { return _bytes_loaded; };
- int getBytesTotal() { return _bytes_total; };
-
- virtual void on_xml_event(const gnash::event_id& id)
- {
- on_event(id);
- }
-
- // Special event handler;
- void on_event_close()
- {
- on_event(gnash::event_id::SOCK_CLOSE);
- }
-
- XMLNode *operator [] (int x);
-#if 0
- XMLNode *operator = (XMLNode &node) {
- gnash::log_msg("%s: copy element %s\n", __PRETTY_FUNCTION__,
node._name);
- // _nodes = node.;
- }
-
-#endif
- XML *operator = (XMLNode *node) {
- _nodes = node;
- return this;
- }
-
-private:
- xmlDocPtr _doc;
- xmlNodePtr _firstChild;
-
- // Properties
- bool _loaded;
- const char *_nodename;
- XMLNode *_nodes;
-
- int _bytes_loaded;
- int _bytes_total;
-
- bool _contentType;
- bool _attributes;
- bool _childNodes;
- bool _xmlDecl;
- bool _docTypeDecl;
- bool _ignoreWhite;
- bool _lastChild;
- bool _nextSibling;
- bool _nodeType;
- bool _nodeValue;
- bool _parentNode;
- bool _status;
- bool _previousSibling;
-
-};
-
-/// XML ActionScript object
-class DSOLOCAL xml_as_object : public gnash::as_object
-{
-public:
- XML obj;
-#ifdef DEBUG_MEMORY_ALLOCATION
- xml_as_object() {
- log_msg("\tCreating xml_as_object at %p\n", this);
- };
- ~xml_as_object() {
- log_msg("\tDeleting xml_as_object at %p\n", this);
- };
-#endif
-
- virtual bool get_member(const tu_stringi& name, as_value* val) {
- //printf("GET XML MEMBER: %s at %p for object %p\n", name.c_str(),
val, this);
-
- if ((name == "firstChild") || (name == "childNodes")) {
-// printf("Returning a self reference for %s for object at %p\n",
-// name.c_str(), this);
- val->set_as_object(this);
- return true;
- }
-
- return get_member_default(name, val);
-
- }
-};
-
-
-DSOEXPORT void xml_load(const fn_call& fn);
-DSOEXPORT void xml_set_current(const fn_call& fn);
-DSOEXPORT void xml_new(const fn_call& fn);
-
-DSOEXPORT void xml_addrequestheader(const fn_call& fn);
-DSOEXPORT void xml_appendchild(const fn_call& fn);
-DSOEXPORT void xml_clonenode(const fn_call& fn);
-DSOEXPORT void xml_createelement(const fn_call& fn);
-DSOEXPORT void xml_createtextnode(const fn_call& fn);
-DSOEXPORT void xml_getbytesloaded(const fn_call& fn);
-DSOEXPORT void xml_getbytestotal(const fn_call& fn);
-DSOEXPORT void xml_haschildnodes(const fn_call& fn);
-DSOEXPORT void xml_insertbefore(const fn_call& fn);
-DSOEXPORT void xml_parsexml(const fn_call& fn);
-DSOEXPORT void xml_removenode(const fn_call& fn);
-DSOEXPORT void xml_send(const fn_call& fn);
-DSOEXPORT void xml_sendandload(const fn_call& fn);
-DSOEXPORT void xml_tostring(const fn_call& fn);
-
-// These are the event handlers called for this object
-DSOEXPORT void xml_onload(const fn_call& fn);
-DSOEXPORT void xml_ondata(const fn_call& fn);
-DSOEXPORT void xml_loaded(const fn_call& fn);
-
-// Properties
-DSOEXPORT void xml_nodename(const fn_call& fn);
-DSOEXPORT void xml_nodevalue(const fn_call& fn);
-
-
-DSOEXPORT int memadjust(int x);
-
-
-} // end namespace gnash
-
-
-#endif // HAVE_LIBXML
-
-#endif // __XML_H__
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/xmlattrs.cpp
===================================================================
RCS file: server/xmlattrs.cpp
diff -N server/xmlattrs.cpp
--- server/xmlattrs.cpp 29 Oct 2006 18:34:11 -0000 1.7
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,90 +0,0 @@
-//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-//
-//
-//
-
-/* $Id: xmlattrs.cpp,v 1.7 2006/10/29 18:34:11 rsavoye Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <vector>
-
-#include "action.h"
-#include "impl.h"
-#include "tu_config.h"
-#include "as_function.h"
-
-#ifdef HAVE_LIBXML
-
-#include "xmlattrs.h"
-
-#ifdef DEBUG_MEMORY_ALLOCATION
- #include "log.h"
-#endif
-
-#include <unistd.h>
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlreader.h>
-
-using namespace std;
-
-namespace gnash {
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-
-//std::vector<as_object *> _xmlobjs; // FIXME: hack alert
-
-XMLAttr::XMLAttr()
-{
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_msg("\t\tCreating XMLAttr data at %p \n", this);
-#endif
- _name = 0;
- _value = 0;
-}
-
-XMLAttr::~XMLAttr()
-{
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_msg("\t\tDeleting XMLAttr data %s at %p \n", this->_name, this);
-#endif
- //log_msg("%s: %p \n", __FUNCTION__, this);
- if (_name) {
- delete _name;
- }
- if (_value) {
- delete _value;
- }
-}
-
-} // end of gnash namespace
-
-// HAVE_LIBXML
-#endif
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/xmlattrs.h
===================================================================
RCS file: server/xmlattrs.h
diff -N server/xmlattrs.h
--- server/xmlattrs.h 22 Nov 2006 15:19:51 -0000 1.10
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,102 +0,0 @@
-//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-//
-//
-//
-
-#ifndef __XML_ATTRS_H__
-#define __XML_ATTRS_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_LIBXML
-
-#include "tu_config.h"
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-#include "as_object.h" // for inheritance
-
-#include "log.h"
-
-#include <vector>
-
-#ifdef DEBUG_MEMORY_ALLOCATION
- #include "log.h"
-#endif
-
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/xmlreader.h>
-
-namespace gnash {
-
-/// XML Attribute class
-class DSOLOCAL XMLAttr {
-public:
- XMLAttr();
- ~XMLAttr();
-
- // why don't we use std::strings here ?
- // code would be much simpler and safer!
- char *_name;
- char *_value;
- xmlAttributeType _type;
-
- XMLAttr *operator = (XMLAttr node) {
- log_msg("\t\tCopying XMLAttr object at %p\n", (void*)this);
-
- _name = new char[strlen(node._name)+2];
- memset(_name, 0, strlen(node._name)+2);
- strcpy(_name, node._name);
-
- _value = new char[strlen(node._value)+2];
- memset(_value, 0, strlen(node._value)+2);
- strcpy(_value, node._value);
-
- return this;
- }
-};
-
-/// XML Attribute ActionScript Object
-class DSOLOCAL xmlattr_as_object : public as_object
-{
-public:
- //XMLAttr obj;
- int padding;
-#ifdef DEBUG_MEMORY_ALLOCATION
- xmlattr_as_object() {
- log_msg("\t\tCreating xmlattr_as_object at %p\n", this);
- };
- ~xmlattr_as_object() {
- log_msg("\tDeleting xmlattr_as_object at %p \n", this);
- };
-#endif
-};
-
-} // end of gnash namespace
-
-#endif // HAVE_LIBXML
-
-#endif // __XML_ATTRS_H__
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/xmlnode.cpp
===================================================================
RCS file: server/xmlnode.cpp
diff -N server/xmlnode.cpp
--- server/xmlnode.cpp 22 Nov 2006 15:19:51 -0000 1.22
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,449 +0,0 @@
-//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-//
-//
-//
-
-/* $Id: xmlnode.cpp,v 1.22 2006/11/22 15:19:51 strk Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <vector>
-#include "tu_config.h"
-#include "fn_call.h"
-
-#ifdef HAVE_LIBXML
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-
-#include "xmlnode.h"
-
-#ifdef DEBUG_MEMORY_ALLOCATION
- #include "log.h"
-#endif
-
-#include <unistd.h>
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlreader.h>
-
-using namespace std;
-
-namespace gnash {
-
-//std::vector<as_object *> _xmlobjs; // FIXME: hack alert
-
-XMLNode::XMLNode() :_name(0), _value(0), _type(XML_ELEMENT_NODE)
-{
- //log_msg("%s: %p \n", __PRETTY_FUNCTION__, this);
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_msg("\tCreating XMLNode data at %p \n", this);
-#endif
- _name = 0;
- _value = 0;
-}
-
-XMLNode::~XMLNode()
-{
- unsigned int i;
- //log_msg("%s: %p \n", __PRETTY_FUNCTION__, this);
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_msg("\tDeleting XMLNode data %s at %p\n", this->_name, this);
-#endif
-
- for (i=0; i<_children.size(); i++) {
- if (_children[i]->_name) {
- delete [] _children[i]->_name;
- }
- if (_children[i]->_value) {
- delete [] _children[i]->_value;
- }
- }
-
- for (i=0; i<_attributes.size(); i++) {
- if (_attributes[i]->_name) {
- delete [] _attributes[i]->_name;
- }
- if (_attributes[i]->_value) {
- delete [] _attributes[i]->_value;
- }
- }
-
- _children.clear();
- _attributes.clear();
-
- if (_name) {
- delete [] _name;
- }
- if (_value) {
- delete [] _value;
- }
- // _value.set_undefined();
-}
-
-void
-XMLNode::nodeNameSet(char *name)
-{
- int len = strlen(name) + 1;
-
- if (!_name) {
- _name = (char *)new char[len];
- memset(_name, 0, len);
- strcpy(_name, reinterpret_cast<const char *>(name));
- }
-}
-
-void
-XMLNode::nodeValueSet(char *value)
-{
- int len = strlen(value) + 1;
-
- if (!_value) {
- _value = (char *)new char[len];
- memset(_value, 0, len);
- strcpy(_value, reinterpret_cast<const char *>(value));
- }
-}
-
-/// \brief Get the type of an XML Node.
-///
-
-/// Read-only property; a nodeType value, either 1 for an XML element
-/// or 3 for a text node. The nodeType is a numeric value from the
-/// NodeType enumeration in the W3C DOM Level 1 recommendation:
-/// www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html.
-/// The following table lists the values.
-int
-XMLNode::nodeType()
-{
- switch (_type) {
- case XML_TEXT_NODE:
- return 3;
- break;
- case XML_ELEMENT_NODE:
- return 1;
- break;
- default:
- return 0;
- }
- // you should never get here
- return -1;
-}
-
-const char *
-XMLNode::nodeName()
-{
- if (_name) {
- return _name;
- }
- return "unknown";
-}
-
-const char *
-XMLNode::nodeValue()
-{
- if (_value) {
- return _value;
- }
- return "unknown";
-}
-
-/// \brief append a node the the XMLNode object
-///
-/// Method; appends the specified node to the XMLNode object's child
-/// list. This method operates directly on the node referenced by the
-/// childNode parameter; it does not append a copy of the node. If the
-/// node to be appended already exists in another tree structure,
-/// appending the node to the new location will remove it from its
-/// current location. If the childNode parameter refers to a node that
-/// already exists in another XMLNode tree structure, the appended child
-/// node is placed in the new tree structure after it is removed from
-/// its existing parent node.
-void
-XMLNode::appendChild(as_object *as, XMLNode *node)
-{
-// log_msg("%s: %p, as is %d, node is %d\n",
-// __PRETTY_FUNCTION__, this, _objects.size(), _children.size());
-
- if (node) {
- _children.push_back(node);
- }
-
- if (as) {
- _objects.push_back(as);
- }
-
-// log_msg("%s: partially unimplemented\n", __PRETTY_FUNCTION__);
-}
-
-/// \brief copy a node
-///
-/// Method; constructs and returns a new XML node of the same type,
-/// name, value, and attributes as the specified XML object. If deep
-/// is set to true, all child nodes are recursively cloned, resulting
-/// in an exact copy of the original object's document tree.
-XMLNode &
-XMLNode::cloneNode(XMLNode &newnode, bool deep)
-{
- log_msg("%s: deep is %d\n", __PRETTY_FUNCTION__, deep);
-
- if (deep) {
-// newnode = _nodes;
- } else {
- newnode.nodeNameSet(_name);
- newnode.nodeValueSet(_value);
- }
-
- return newnode;
-
- log_msg("%s: partially unimplemented \n", __PRETTY_FUNCTION__);
-}
-
-/// \brief insert a node before a node
-///
-/// Method; inserts a new child node into the XML object's child
-/// list, before the beforeNode node. If the beforeNode parameter is
-/// undefined or null, the node is added using the appendChild()
-/// method. If beforeNode is not a child of my_xml, the insertion
-/// fails.
-void
-XMLNode::insertBefore(XMLNode */* newnode */, XMLNode */* node */)
-{
- log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
-}
-/// \brief removes the specified XML object from its parent. Also
-/// deletes all descendants of the node.
-void
-XMLNode::removeNode()
-{
- log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
-}
-const char *
-XMLNode::toString()
-{
- XMLNode *node;
-
- vector<XMLNode *>::const_iterator it;
- for (it = _children.begin(); it != _children.end(); it++) {
- node = *it;
-// log_msg("Got something\n");
- if (node->_name) {
- log_msg("Node name is %s", node->_name);
- }
- if (node->_value) {
- log_msg("Node value is %s", node->_name);
- }
- }
-
- log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
- return "Hello World!";
-}
-
-as_object *
-XMLNode::previousSibling(int x)
-{
- log_msg("%s: partially implemented. " SIZET_FMT " objects\n",
- __PRETTY_FUNCTION__, _objects.size());
- if (_objects.size() > 0) {
- return _objects[x-1];
- }
-
- return NULL;
-}
-
-as_object *
-XMLNode::nextSibling(int x)
-{
- log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
- if (x < (int) _objects.size()) {
- return _objects[x];
- }
- return NULL;
-}
-
-void
-xmlnode_new(const fn_call& fn)
-{
- xmlnode_as_object *xml_obj;
- //const char *data;
-
-// log_msg("%s\n", __PRETTY_FUNCTION__);
-
- xml_obj = new xmlnode_as_object;
- // Methods
- xml_obj->set_member("appendChild", &xmlnode_appendchild);
- xml_obj->set_member("cloneNode", &xmlnode_clonenode);
- xml_obj->set_member("hasChildNodes", &xmlnode_haschildnodes);
- xml_obj->set_member("insertBefore", &xmlnode_insertbefore);
- xml_obj->set_member("removeNode", &xmlnode_removenode);
- xml_obj->set_member("toString", &xmlnode_tostring);
-
- // Properties
- xml_obj->set_member("nodeName", as_value(""));
- xml_obj->set_member("nodeValue", as_value(""));
- xml_obj->set_member("nodeType", as_value(""));
-
- // FIXME: these need real values
- // These two return an array of objects
- xml_obj->set_member("attributes", as_value(""));
- xml_obj->set_member("childNodes", as_value(""));
-
- //These return a reference to an object
-
- /// \fn MLNode::firstChild
- /// \brief XMLNode::firstChild property
- ///
- /// Read-only property; evaluates the specified XML object and
- /// references the first child in the parent node\ufffds child
- /// list. This property is null if the node does not have
- /// children. This property is undefined if the node is a text
- /// node. This is a read-only property and cannot be used to
- /// manipulate child nodes; use the appendChild(), insertBefore(),
- /// and removeNode() methods to manipulate child nodes.
-
- xml_obj->set_member("firstChild", as_value(""));
- /// \fn MLNode::lastChild
- /// \brief XMLNode::lastChild property
- ///
- /// Read-only property; an XMLNode value that references the last
- /// child in the node's child list. The XML.lastChild property
- /// is null if the node does not have children. This property cannot
- /// be used to manipulate child nodes; use the appendChild(),
- /// insertBefore(), and removeNode() methods to manipulate child
- /// nodes.
- xml_obj->set_member("lastChild", as_value(""));
- xml_obj->set_member("nextSibling", as_value(""));
- xml_obj->set_member("parentNode", as_value(""));
- xml_obj->set_member("previousSibling", as_value(""));
-
- fn.result->set_as_object(xml_obj);
-}
-
-void xmlnode_appendchild(const fn_call& fn)
-{
- xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
- assert(ptr);
-// log_msg("%s: %p, %d args\n", __PRETTY_FUNCTION__, ptr, fn.nargs);
-
- xmlnode_as_object *xml_obj =
(xmlnode_as_object*)fn.env->bottom(fn.first_arg_bottom_index).to_object();
-
-// log_msg("%s: %p \n", __PRETTY_FUNCTION__, xml_obj);
- XMLNode *node = &(xml_obj->obj);
- if (ptr->obj.hasChildNodes() == false) {
- ptr->set_member("firstChild", xml_obj);
- }
- int length = ptr->obj.length();
- if (length > 0) {
- as_object *ass = xml_obj->obj.previousSibling(length);
-// FIXME: This shouldn't always be NULL
-// log_msg("%s: ASS is %p, length is %d\n", __PRETTY_FUNCTION__,
-// ass, length);
- ptr->set_member("previousSibling", ass);
-// ptr->set_member("nextSibling",
xml_obj->obj.nextSibling(ptr->obj.length()));
- }
- ptr->obj.appendChild((as_object *)xml_obj, node);
- // The last child in the list is always the one we just appended
- ptr->set_member("lastChild", xml_obj);
-
-// ptr->obj.appendChild(&(xml_obj->obj));
-// ptr->obj.nodeValueSet((char *)xmlnode_obj->obj.nodeValue());
-}
-
-void xmlnode_clonenode(const fn_call& fn)
-{
- log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
- xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
- xmlnode_as_object *xmlnode_obj;
- assert(ptr);
-
- if (fn.nargs > 0) {
- bool deep = fn.env->bottom(fn.first_arg_bottom_index).to_bool();
- xmlnode_obj = new xmlnode_as_object;
- ptr->obj.cloneNode(xmlnode_obj->obj, deep);
- fn.result->set_as_object(xmlnode_obj);
- } else {
- log_msg("ERROR: no Depth paramater!\n");
- }
-
-}
-
-void xmlnode_insertbefore(const fn_call& fn)
-{
- xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
- assert(ptr);
-
-// fn.result->set_int(ptr->obj.getAllocated());
-// ptr->obj.insertBefore();
- log_msg("%s:unimplemented \n", __PRETTY_FUNCTION__);
-}
-void xmlnode_removenode(const fn_call& fn)
-{
- xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
- assert(ptr);
-
-// fn.result->set_int(ptr->obj.getAllocated());
- ptr->obj.removeNode();
-}
-void xmlnode_tostring(const fn_call& fn)
-{
- xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
- assert(ptr);
-
- fn.result->set_string(ptr->obj.toString());
-}
-
-void xmlnode_haschildnodes(const fn_call& fn)
-{
- xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
- assert(ptr);
- fn.result->set_bool(ptr->obj.hasChildNodes());
-}
-
-#ifdef ENABLE_TESTING
-void xmlnode_nodevalue(const fn_call& fn)
-{
- log_msg("%s: \n", __PRETTY_FUNCTION__);
- xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
- assert(ptr);
-
- fn.result->set_string(ptr->obj.nodeValue());
-}
-void xmlnode_nodename(const fn_call& fn)
-{
- log_msg("%s: \n", __PRETTY_FUNCTION__);
- xmlnode_as_object *ptr = (xmlnode_as_object*)fn.this_ptr;
- assert(ptr);
-
- fn.result->set_string(ptr->obj.nodeName());
-}
-#endif
-
-} // end of gnash namespace
-
-// HAVE_LIBXML
-#endif
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/xmlnode.h
===================================================================
RCS file: server/xmlnode.h
diff -N server/xmlnode.h
--- server/xmlnode.h 22 Nov 2006 15:19:51 -0000 1.11
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,167 +0,0 @@
-//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-//
-//
-//
-
-#ifndef __XML_NODE_H__
-#define __XML_NODE_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "tu_config.h"
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-#include <vector>
-#include "action.h"
-#include "impl.h"
-
-#ifdef HAVE_LIBXML
-
-#include "xmlattrs.h"
-
-#ifdef DEBUG_MEMORY_ALLOCATION
- #include "log.h"
-#endif
-
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/xmlreader.h>
-
-namespace gnash {
-
-/// XML Node
-class DSOLOCAL XMLNode
-{
-public:
- XMLNode();
- ~XMLNode();
-
- int length() { return _children.size(); }
- const char *nodeName();
- const char *nodeValue();
- int nodeType();
-
- // char *valueGet();
-
- void nodeNameSet(char *name);
- void nodeValueSet(char *value);
- // nodeType XML.nodeType
-
- bool hasChildNodes() {
- if (_children.size()) {
- return true;
- }
- return false;
- }
-
- XMLNode *firstChild() { return _children[0]; }
-
- std::vector<XMLNode *>childNodes() { return _children; }
-
- XMLNode *operator [] (int x) {
- gnash::log_msg("%s: get element %d\n", __PRETTY_FUNCTION__, x);
-
- return _children[x];
- }
-
- XMLNode *operator = (XMLNode &node) {
- gnash::log_msg("%s: \n", __PRETTY_FUNCTION__);
- _name = node._name;
- _value = node._value;
- _children = node._children;
- _attributes = node._attributes;
- return this;
- }
-
- XMLNode *operator = (XMLNode *node) {
- gnash::log_msg("%s: \n", __PRETTY_FUNCTION__);
- _name = node->_name;
- _value = node->_value;
- _children = node->_children;
- _attributes = node->_attributes;
- return this;
- }
-
- as_object *previousSibling(int x);
- as_object *nextSibling(int x);
- XMLNode &cloneNode(XMLNode &newnode, bool deep);
- void appendChild(as_object *as,XMLNode *node);
- void insertBefore(XMLNode *newnode, XMLNode *node);
- void removeNode();
- const char *toString();
-
- void change_stack_frame(int frame, gnash::as_object *xml,
gnash::as_environment *env);
-
-
- // why don't we use std::strings here ?
- // code would be much simpler and safer!
- char *_name;
- char *_value;
-
- xmlElementType _type;
- std::vector<as_object *> _objects;
- std::vector<XMLNode *> _children;
- std::vector<XMLAttr *> _attributes;
-};
-
-/// XML Node ActionScript object
-class DSOLOCAL xmlnode_as_object : public gnash::as_object
-{
-public:
- XMLNode obj;
-// int _padding;
-
-#ifdef DEBUG_MEMORY_ALLOCATION
- xmlnode_as_object() {
- // obj = new XMLNode;
- log_msg("\tCreating xmlnode_as_object at %p \n", this);
- };
- ~xmlnode_as_object() {
- log_msg("\tDeleting xmlnode_as_object at %p \n", this);
- };
-#endif
-};
-
-DSOEXPORT void xmlnode_new(const fn_call& fn);
-
-DSOEXPORT void xmlnode_haschildren(const fn_call& fn);
-DSOEXPORT void xmlnode_nodename(const fn_call& fn);
-DSOEXPORT void xmlnode_nodevalue(const fn_call& fn);
-DSOEXPORT void xmlnode_nodetype(const fn_call& fn);
-
-DSOEXPORT void xmlnode_appendchild(const fn_call& fn);
-DSOEXPORT void xmlnode_clonenode(const fn_call& fn);
-DSOEXPORT void xmlnode_haschildnodes(const fn_call& fn);
-DSOEXPORT void xmlnode_insertbefore(const fn_call& fn);
-DSOEXPORT void xmlnode_removenode(const fn_call& fn);
-DSOEXPORT void xmlnode_tostring(const fn_call& fn);
-
-} // end of gnash namespace
-
-
-#endif // HAVE_LIBXML
-
-#endif // __XMLNODE_NODE_H__
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/xmlsocket.cpp
===================================================================
RCS file: server/xmlsocket.cpp
diff -N server/xmlsocket.cpp
--- server/xmlsocket.cpp 21 Nov 2006 00:25:46 -0000 1.28
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,811 +0,0 @@
-//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-//
-//
-//
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "utility.h"
-#include "xml.h"
-#include "xmlsocket.h"
-#include "timers.h"
-#include "as_function.h"
-#include "fn_call.h"
-#include "sprite_instance.h"
-
-#ifdef HAVE_LIBXML
-
-#include "log.h"
-
-#include <sys/types.h>
-#include <fcntl.h>
-#ifdef HAVE_WINSOCK
-# include <WinSock2.h>
-# include <windows.h>
-# include <sys/stat.h>
-# include <io.h>
-#else
-# include <sys/time.h>
-# include <unistd.h>
-# include <sys/select.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <sys/socket.h>
-# include <netdb.h>
-# include <cerrno>
-# include <sys/param.h>
-# include <sys/select.h>
-#endif
-
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 256
-#endif
-
-int xml_fd = 0; // FIXME: This file descriptor is used by
- // XML::checkSocket() when called from the main
- // processing loop.
-
-namespace gnash {
-const int SOCKET_DATA = 1;
-
-const int INBUF = 10000;
-
-XMLSocket::XMLSocket() {
- //log_msg("%s: \n", __FUNCTION__);
- _data = false;
- _xmldata = false;
- _closed = false;
- _connect = false;
- _processing = false;
- _port = 0;
- _sockfd = 0;
- xml_fd = 0;
-}
-
-XMLSocket::~XMLSocket()
-{
- //log_msg("%s: \n", __FUNCTION__);
-}
-
-bool
-XMLSocket::connect(const char *host, int port)
-{
- struct sockaddr_in sock_in;
- fd_set fdset;
- struct timeval tval;
- int ret;
- int retries;
- char thishostname[MAXHOSTNAMELEN];
- struct protoent *proto;
-
- if (port < 1024) {
- log_error("Can't connect to priviledged port #%d!\n", port);
- _connect = false;
- return false;
- }
-
- log_msg("%s: to host %s at port %d\n", __FUNCTION__, host, port);
-
- memset(&sock_in, 0, sizeof(struct sockaddr_in));
- memset(&thishostname, 0, MAXHOSTNAMELEN);
- if (strlen(host) == 0) {
- if (gethostname(thishostname, MAXHOSTNAMELEN) == 0) {
- log_msg("The hostname for this machine is %s.\n", thishostname);
- } else {
- log_msg("Couldn't get the hostname for this machine!\n");
- return false;
- }
- }
- const struct hostent *hent = ::gethostbyname(host);
- if (hent > 0) {
- ::memcpy(&sock_in.sin_addr, hent->h_addr, hent->h_length);
- }
- sock_in.sin_family = AF_INET;
- sock_in.sin_port = ntohs(static_cast<short>(port));
-
-#if 0
- char ascip[32];
- inet_ntop(AF_INET, &sock_in.sin_addr.s_addr, ascip, INET_ADDRSTRLEN);
- log_msg("The IP address for this client socket is %s\n", ascip);
-#endif
-
- proto = ::getprotobyname("TCP");
-
- _sockfd = ::socket(PF_INET, SOCK_STREAM, proto->p_proto);
- if (_sockfd < 0)
- {
- log_error("unable to create socket : %s\n", strerror(errno));
- _sockfd = -1;
- return false;
- }
-
- retries = 2;
- while (retries-- > 0) {
- // We use select to wait for the read file descriptor to be
- // active, which means there is a client waiting to connect.
- FD_ZERO(&fdset);
- FD_SET(_sockfd, &fdset);
-
- // Reset the timeout value, since select modifies it on return. To
- // block, set the timeout to zero.
- tval.tv_sec = 5;
- tval.tv_usec = 0;
-
- ret = ::select(_sockfd+1, &fdset, NULL, NULL, &tval);
-
- // If interupted by a system call, try again
- if (ret == -1 && errno == EINTR)
- {
- log_msg("The connect() socket for fd #%d was interupted by a system
call!\n",
- _sockfd);
- continue;
- }
-
- if (ret == -1)
- {
- log_msg("The connect() socket for fd #%d never was available for
writing!\n",
- _sockfd);
-#ifdef HAVE_WINSOCK
- ::shutdown(_sockfd, SHUT_BOTH);
-#else
- ::shutdown(_sockfd, SHUT_RDWR);
-#endif
- _sockfd = -1;
- return false;
- }
- if (ret == 0) {
- log_error("The connect() socket for fd #%d timed out waiting to
write!\n",
- _sockfd);
- continue;
- }
-
- if (ret > 0) {
- ret = ::connect(_sockfd, reinterpret_cast<struct sockaddr *>(&sock_in),
sizeof(sock_in));
- if (ret == 0) {
- log_msg("\tport %d at IP %s for fd #%d\n", port,
- ::inet_ntoa(sock_in.sin_addr), _sockfd);
- _connect = true;
- xml_fd = _sockfd; // FIXME: This file descriptor is used
by
- // XML::checkSocket() when called from
- // the main processing loop.
- return true;
- }
- if (ret == -1) {
- log_msg("The connect() socket for fd #%d never was available for
writing!\n",
- _sockfd);
- _sockfd = -1;
- return false;
- }
- }
- }
- // ::close(_sockfd);
- // return false;
-
- printf("\tConnected at port %d on IP %s for fd #%d\n", port,
- ::inet_ntoa(sock_in.sin_addr), _sockfd);
-
-#ifndef HAVE_WINSOCK
- fcntl(_sockfd, F_SETFL, O_NONBLOCK);
-#endif
-
- _connect = true;
- return true;
-}
-
-void
-XMLSocket::close()
-{
- log_msg("%s: \n", __FUNCTION__);
- // Since the return code from close() doesn't get used by Shockwave,
- // we don't care either.
- if (_sockfd > 0) {
- ::close(_sockfd);
- }
-}
-
-// Return true if there is data in the socket, otherwise return false.
-bool
-XMLSocket::anydata(char **msgs)
-{
- //printf("%s: \n", __FUNCTION__);
- return anydata(_sockfd, msgs);
-}
-
-bool XMLSocket::processingData()
-{
- //printf("%s: processing flags is is %d\n", __FUNCTION__, _processing);
- return _processing;
-}
-
-void XMLSocket::processing(bool x)
-{
- //printf("%s: set processing flag to %d\n", __FUNCTION__, x);
- _processing = x;
-}
-
-bool
-XMLSocket::anydata(int fd, char **msgs)
-{
- fd_set fdset;
- struct timeval tval;
- int ret = 0;
- char buf[INBUF];
- char *packet;
- int retries = 10;
- char *ptr, *eom;
- int cr, index = 0;
- static char *leftover = 0;
- int adjusted_size;
-
- //log_msg("%s: \n", __FUNCTION__);
-
- if (fd <= 0) {
- return false;
- }
-
- //msgs = (char **)realloc(msgs, sizeof(char *));
-
- while (retries-- > 0) {
- FD_ZERO(&fdset);
- FD_SET(fd, &fdset);
-
- tval.tv_sec = 0;
- tval.tv_usec = 103;
-
- ret = ::select(fd+1, &fdset, NULL, NULL, &tval);
-
- // If interupted by a system call, try again
- if (ret == -1 && errno == EINTR) {
- log_msg("The socket for fd #%d was interupted by a system call!\n",
- fd);
- continue;
- }
- if (ret == -1) {
- log_error("The socket for fd #%d never was available!\n", fd);
- return false;
- }
- if (ret == 0) {
- //log_msg("There is no data in the socket for fd #%d!\n", fd);
- return false;
- }
- if (ret > 0) {
- //log_msg("There is data in the socket for fd #%d!\n", fd);
- //break;
- }
- memset(buf, 0, INBUF);
- ret = ::read(_sockfd, buf, INBUF-2);
- cr = strlen(buf);
- //log_msg("%s: read %d bytes, first msg terminates at %d\n", __FUNCTION__,
ret, cr);
- //log_msg("%s: read (%d,%d) %s\n", __FUNCTION__, buf[0], buf[1], buf);
- ptr = buf;
- // If we get a single XML message, do less work
- if (ret == cr + 1) {
- adjusted_size = memadjust(ret + 1);
- packet = new char[adjusted_size];
- //printf("Packet size is %d at %p\n", ret + 1, packet);
- memset(packet, 0, adjusted_size);
- strcpy(packet, ptr);
- eom = strrchr(packet, '\n'); // drop the CR off the end if there is one
- if (eom) {
- *eom = 0;
- }
- //data.push_back(packet);
- msgs[index] = packet;
- msgs[index+1] = 0;
- //printf("%d: Pushing Packet of size %d at %p\n", __LINE__,
strlen(packet), packet);
- processing(false);
- return true;
- }
-
- // If we get multiple messages in a single transmission, break the buffer
- // into separate messages.
- while (strchr(ptr, '\n') > 0) {
- if (leftover) {
- processing(false);
- //printf("%s: The remainder is: \"%s\"\n", __FUNCTION__, leftover);
- //printf("%s: The rest of the message is: \"%s\"\n", __FUNCTION__,
ptr);
- adjusted_size = memadjust(cr + strlen(leftover) + 1);
- packet = new char[adjusted_size];
- memset(packet, 0, adjusted_size);
- strcpy(packet, leftover);
- strcat(packet, ptr);
- eom = strrchr(packet, '\n'); // drop the CR off the end there is one
- if (eom) {
- *eom = 0;
- }
- //printf("%s: The whole message is: \"%s\"\n", __FUNCTION__, packet);
- ptr = strchr(ptr, '\n') + 2; // messages are delimited by a "\n\0"
- delete leftover;
- leftover = 0;
- } else {
- adjusted_size = memadjust(cr + 1);
- packet = new char[adjusted_size];
- memset(packet, 0, adjusted_size);
- strcpy(packet, ptr);
- ptr += cr + 1;
- } // end of if remainder
- if (*packet == '<') {
- //printf("%d: Pushing Packet #%d of size %d at %p: %s\n", __LINE__,
- // data.size(), strlen(packet), packet, packet);
- eom = strrchr(packet, '\n'); // drop the CR off the end there is one
- if (eom) {
- *eom = 0;
- }
- //printf("Allocating new packet at %p\n", packet);
- //data.push_back(packet);
- msgs[index++] = packet;
- } else {
- log_error("Throwing out partial packet %s\n", packet);
- }
-
- //log_msg("%d messages in array now\n", data.size());
- cr = strlen(ptr);
- } // end of while (cr)
-
- if (strlen(ptr) > 0) {
- leftover = new char[strlen(ptr) + 1];
- strcpy(leftover, ptr);
- processing(true);
- //printf("%s: Adding remainder: \"%s\"\n", __FUNCTION__, leftover);
- }
-
- processing(false);
- printf("Returning %d messages\n", index);
- return true;
-
- } // end of while (retires)
-
- return true;
-}
-
-bool
-XMLSocket::send(std::string str)
-{
- //GNASH_REPORT_FUNCTION;
-
- str += '\0';
- int ret = write(_sockfd, str.c_str(), str.size());
-
- //log_msg("%s: sent %d bytes, data was %s\n", __FUNCTION__, ret,
str.c_str());
- if (ret == static_cast<signed int>(str.size())) {
- return true;
- } else {
- return false;
- }
-}
-
-// Callbacks
-
-void
-XMLSocket::onClose(std::string /* str */)
-{
- log_msg("%s: \n", __FUNCTION__);
-}
-
-void
-XMLSocket::onConnect(std::string /* str */)
-{
- log_msg("%s: \n", __FUNCTION__);
-}
-
-void
-XMLSocket::onData(std::string /* str */)
-{
- log_msg("%s: \n", __FUNCTION__);
-}
-
-void
-XMLSocket::onXML(std::string /* str */)
-{
- log_msg("%s: \n", __FUNCTION__);
-}
-
-void
-XMLSocket::push(as_object *obj)
-{
- _nodes.push_back(obj);
-}
-
-void
-XMLSocket::clear()
-{
- unsigned int i;
- for (i=0; i< _nodes.size(); i++) {
- delete _nodes[i];
- }
-}
-
-int
-XMLSocket::count()
-{
- return _nodes.size();
-}
-
-int
-XMLSocket::checkSockets(void)
-{
- return checkSockets(_sockfd);
-}
-
-int
-XMLSocket::checkSockets(int fd)
-{
- fd_set fdset;
- int ret = 0;
- struct timeval tval;
-
- //log_msg("%s:\n", __FUNCTION__);
-
- FD_ZERO(&fdset);
- FD_SET(fd, &fdset);
-
- tval.tv_sec = 2;
- tval.tv_usec = 10;
-
- ret = ::select(fd+1, &fdset, NULL, NULL, &tval); // &tval
-
- // If interupted by a system call, try again
- if (ret == -1 && errno == EINTR) {
- log_msg("The socket for fd #%d was interupted by a system call in this
thread!\n",
- fd);
- }
- if (ret == -1) {
- log_error("The socket for fd #%d never was available!\n", fd);
- }
- if (ret == 0) {
- printf("There is no data in the socket for fd #%d!\n", fd);
- }
- if (ret > 0) {
- //printf("There is data in the socket for fd #%d!\n", fd);
- }
-
- return ret;
-}
-
-void
-xmlsocket_connect(const fn_call& fn)
-{
- as_value method;
- as_value val;
- static bool first = true; // This event handler should only be executed
once.
-
- if (!first) {
- fn.result->set_bool(true);
- return;
- }
-
- log_msg("%s: nargs=%d\n", __FUNCTION__, fn.nargs);
- xmlsocket_as_object* ptr = (xmlsocket_as_object*) (as_object*) fn.this_ptr;
- assert(ptr);
- const std::string host =
fn.env->bottom(fn.first_arg_bottom_index).to_string();
- std::string port_str =
fn.env->bottom(fn.first_arg_bottom_index-1).to_string();
- double port = atof(port_str.c_str());
-
- ptr->obj.connect(host.c_str(), static_cast<int>(port));
-
-#if 0 // use connect return as result
- // Push result onto stack for onConnect
- if (ret) {
- fn.env->push(as_value(true));
- }
- else {
- fn.env->push(as_value(false));
- }
-#endif
- fn.env->push(as_value(true));
- if (fn.this_ptr->get_member("onConnect", &method)) {
- // log_msg("FIXME: Found onConnect!\n");
- as_c_function_ptr func = method.to_c_function();
- first = false;
- //env->set_variable("success", true, 0);
-
- if (func) {
- // It's a C function. Call it.
- log_msg("Calling C function for onConnect\n");
- (*func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
- }
- else if (as_function* as_func = method.to_as_function()) {
- // It's an ActionScript function. Call it.
- log_msg("Calling ActionScript function for onConnect\n");
- (*as_func)(fn_call(&val, fn.this_ptr, fn.env, 2, 2));
- } else {
- log_error("error in call_method(): method is not a function\n");
- }
- } else {
- //ptr->set_event_handler(event_id::SOCK_CONNECT,
(as_c_function_ptr)&xmlsocket_event_connect);
- }
-
-#if 1
- sprite_instance* mov = fn.env->get_target()->get_root_movie();
- Timer *timer = new Timer;
- as_c_function_ptr ondata_handler =
- (as_c_function_ptr)&xmlsocket_event_ondata;
- timer->setInterval(ondata_handler, 50, ptr, fn.env);
- timer->setObject(ptr);
- mov->add_interval_timer(timer);
-#endif
-
- fn.env->pop();
-
- fn.result->set_bool(true);
-}
-
-
-void
-xmlsocket_send(const fn_call& fn)
-{
- as_value method;
- as_value val;
-
- xmlsocket_as_object* ptr = (xmlsocket_as_object*) (as_object*) fn.this_ptr;
- assert(ptr);
- const std::string object = fn.env->bottom(
fn.first_arg_bottom_index).to_string();
- // log_msg("%s: host=%s, port=%g\n", __FUNCTION__, host, port);
- fn.result->set_bool(ptr->obj.send(object));
-}
-
-void
-xmlsocket_close(const fn_call& fn)
-{
- as_value method;
- as_value val;
-
- xmlsocket_as_object* ptr = (xmlsocket_as_object*) (as_object*) fn.this_ptr;
- assert(ptr);
- // Since the return code from close() doesn't get used by Shockwave,
- // we don't care either.
- ptr->obj.close();
-}
-
-void
-xmlsocket_xml_new(const fn_call& fn)
-{
- //log_msg("%s: nargs=%d\n", __FUNCTION__, nargs);
-
- xml_new(fn);
-}
-
-void
-xmlsocket_new(const fn_call& fn)
-{
- //log_msg("%s: nargs=%d\n", __FUNCTION__, nargs);
-
- as_object* xmlsock_obj = new xmlsocket_as_object;
- //log_msg("\tCreated New XMLSocket object at 0x%X\n", (unsigned
int)xmlsock_obj);
- xmlsock_obj->set_member("connect", &xmlsocket_connect);
- xmlsock_obj->set_member("send", &xmlsocket_send);
- xmlsock_obj->set_member("close", &xmlsocket_close);
- xmlsock_obj->set_member("Connected", true);
- // swf_event* ev = new swf_event;
- // m_event_handlers.push_back(ev);
- // Setup event handlers
-#if 0
- xmlsock_obj->set_event_handler(event_id::SOCK_DATA,
- (as_c_function_ptr)&xmlsocket_event_ondata);
- xmlsock_obj->set_event_handler(event_id::SOCK_CLOSE,
- (as_c_function_ptr)&xmlsocket_event_close);
- //
xmlsock_obj->set_event_handler(event_id::SOCK_CONNECT,
- //
(as_c_function_ptr)&xmlsocket_event_connect);
- xmlsock_obj->set_event_handler(event_id::SOCK_XML,
- (as_c_function_ptr)&xmlsocket_event_xml);
-#endif
- //periodic_events.set_event_handler(xmlsock_obj);
-
-
-#if 1
- //as_c_function_ptr int_handler = (as_c_function_ptr)&timer_setinterval;
- //env->set_member("setInterval", int_handler);
- fn.env->set_member("setInterval", timer_setinterval);
-
- //as_c_function_ptr clr_handler = timer_clearinterval;
- fn.env->set_member("clearInterval", timer_clearinterval);
- //env->set_variable("setInterval", int_handler, 0);
- //xmlsock_obj->set_event_handler(event_id::TIMER,
- // (as_c_function_ptr)&timer_expire);
-#if 0
- Timer *timer = new Timer;
- as_c_function_ptr ondata_handler =
- (as_c_function_ptr)&xmlsocket_event_ondata;
- timer->setInterval(ondata_handler, 10);
- timer->setObject(xmlsock_obj);
- current_movie->add_interval_timer(timer);
-#endif
-
- fn.result->set_bool(xmlsock_obj);
-
- // Tune malloc for the best performance
- //mallopt(M_MMAP_MAX,0);
- //mallopt(M_TRIM_THRESHOLD,-1);
- //mallopt(M_MMAP_THRESHOLD,16);
-
-#endif
-}
-
-
-void
-xmlsocket_event_ondata(const fn_call& fn)
-{
- //log_msg("%s: nargs is %d\n", __FUNCTION__, nargs);
-
- as_value method;
- as_value val;
- as_value datain;
- std::vector<const char *> msgs;
- char *messages[200];
- int i;
- as_c_function_ptr func;
- as_function* as_func;
-
- xmlsocket_as_object* ptr = (xmlsocket_as_object*)fn.this_ptr;
- assert(ptr);
- if (ptr->obj.processingData()) {
- log_msg("Still processing data!\n");
- fn.result->set_bool(false);
- return;
- }
-
- memset(messages, 0, sizeof(char *)*200);
-
-#ifndef USE_DMALLOC
- //dump_memory_stats(__FUNCTION__, __LINE__, "memory checkpoint");
-#endif
-
- if (ptr->obj.anydata(messages)) {
- if (fn.this_ptr->get_member("onData", &method)) {
- func = method.to_c_function();
- as_func = method.to_as_function();
- //log_msg("Got %d messages from XMLsocket\n", msgs.size());
- // for (i=0; i<msgs.size(); i++) {
- for (i=0; messages[i] != 0; i++) {
-// log_msg("Got message #%d, %d bytes long at %p: %s: \n", i,
-// strlen(messages[i]), messages[i], messages[i]);
- datain = messages[i];
- //fn.env->push(datain);
-#ifndef USE_DMALLOC
- //dump_memory_stats(__FUNCTION__, __LINE__, "start");
-#endif
- as_environment *env = new as_environment;
- env->push(datain);
- if (func) {
- // It's a C function. Call it.
- //log_msg("Calling C function for onData\n");
- (*func)(fn_call(&val, fn.this_ptr, env, 1, 0));
- } else if (as_func) {
- // It's an ActionScript function. Call it.
- //log_msg("Calling ActionScript function for onData, processing msg
%d\n", i);
- (*as_func)(fn_call(&val, fn.this_ptr, env, 1, 0));
- } else {
- log_error("error in call_method(): method is not a function\n");
- }
- env->pop();
- delete env;
-#ifndef USE_DMALLOC
- //dump_memory_stats(__FUNCTION__, __LINE__, "end");
-#endif
- //log_msg("Deleting message #%d at %p\n", i, messages[i]);
- //delete messages[i];
- //fn.env->pop();
- datain.set_undefined();
- }
- ptr->obj.processing(false);
- } else {
- log_error("Couldn't find onData!\n");
- }
- // Delete this in a batch for now so we can track memory allocation
- for (i=0; messages[i] != 0; i++) {
- //log_msg("Deleting message #%d at %p\n", i, messages[i]);
- delete messages[i];
- }
- }
-
- //malloc_trim(0);
-
- //result->set(&data);
- fn.result->set_bool(true);
-}
-
-void
-xmlsocket_event_close(const fn_call& /* fn */)
-{
-#if 0
- as_value* result = fn.result;
- as_object* this_ptr = fn.this_ptr;
- int nargs = fn.nargs;
- int first_arg = fn.first_arg_bottom_index;
-#else
- log_error("%s: unimplemented!\n", __FUNCTION__);
-#endif
-}
-
-void
-xmlsocket_event_connect(const fn_call& fn)
-{
- as_value method;
- as_value val;
- static bool first = true; // This event handler should only be executed
once.
-
- if (!first) {
- fn.result->set_bool(true);
- return;
- }
-
- xmlsocket_as_object* ptr = (xmlsocket_as_object*) (as_object*) fn.this_ptr;
- assert(ptr);
-
- log_msg("%s: connected = %d\n", __FUNCTION__, ptr->obj.connected());
- if ((ptr->obj.connected()) && (first)) {
- first = false;
- //env->set_variable("success", true, 0);
- //env->bottom(0) = true;
-
- if (fn.this_ptr->get_member("onConnect", &method)) {
- as_c_function_ptr func = method.to_c_function();
- if (func)
- {
- // It's a C function. Call it.
- //log_msg("Calling C function for onConnect\n");
- (*func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
- }
- else if (as_function* as_func = method.to_as_function())
- {
- // It's an ActionScript function. Call it.
- //log_msg("Calling ActionScript function for onConnect\n");
- (*as_func)(fn_call(&val, fn.this_ptr, fn.env, 0, 0));
- }
- else
- {
- log_error("error in call_method(): method is not a function\n");
- }
- } else {
- log_msg("FIXME: Couldn't find onConnect!\n");
- }
- }
-
- fn.result->set_bool(val.to_bool());
-}
-void
-xmlsocket_event_xml(const fn_call& /* fn */)
-{
-#if 0
- as_value* result = fn.result;
- as_object* this_ptr = fn.this_ptr;
- int nargs = fn.nargs;
- int first_arg = fn.first_arg_bottom_index;
-#else
- log_error("%s: unimplemented!\n", __FUNCTION__);
-#endif
-}
-
-static XMLSocket xs;
-
-int
-check_sockets(int x)
-{
- if (xml_fd == 0) {
- return -1;
- }
-
- return xs.checkSockets(x);
-}
-
-} // end of gnaash namespace
-
-// HAVE_LIBXML
-#endif
Index: server/xmlsocket.h
===================================================================
RCS file: server/xmlsocket.h
diff -N server/xmlsocket.h
--- server/xmlsocket.h 3 Nov 2006 14:03:37 -0000 1.13
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,119 +0,0 @@
-//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-//
-//
-//
-
-#ifndef __XMLSOCKET_H__
-#define __XMLSOCKET_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "tu_config.h"
-#include "xml.h"
-#include "impl.h"
-
-#include <string>
-
-#ifdef HAVE_LIBXML
-
-namespace gnash {
-
-extern const int SOCKET_DATA;
-
-class DSOLOCAL XMLSocket {
- public:
- XMLSocket();
- ~XMLSocket();
-
- bool connect(const char *host, int port);
- bool send(std::string str);
- void close();
-
-
- bool anydata(char **msgs);
- bool anydata(int sockfd, char **msgs);
- bool connected() { return _connect; };
- bool fdclosed() { return _closed; }
- bool xmlmsg() { return _xmldata; }
-
- void messagesClear() { _messages.clear(); }
- void messageRemove(int x) { _messages.erase(_messages.begin() + x); }
- int messagesCount() { return _messages.size(); }
- std::string operator [] (int x) { return _messages[x]; }
-
- bool processingData();
- void processing(bool x);
-
- // Event Handlers
- void onClose(std::string);
- void onConnect(std::string);
- void onData(std::string);
- void onXML(std::string);
-
- // These handle the array of XML nodes
- void push(as_object *obj);
- void clear();
- int count();
-
- int checkSockets(void);
- int checkSockets(int x);
-
- private:
- std::string _host;
- short _port;
- int _sockfd;
- bool _data;
- bool _xmldata;
- bool _closed;
- bool _connect;
- bool _processing;
- std::vector<std::string> _messages;
- std::vector<as_object *> _nodes;
-};
-
-
-class DSOLOCAL xmlsocket_as_object : public gnash::as_object
-{
-public:
- XMLSocket obj;
-};
-
-DSOEXPORT void xmlsocket_connect(const fn_call& fn);
-DSOEXPORT void xmlsocket_send(const fn_call& fn);
-DSOEXPORT void xmlsocket_xml_new(const fn_call& fn);
-DSOEXPORT void xmlsocket_new(const fn_call& fn);
-DSOEXPORT void xmlsocket_close(const fn_call& fn);
-
-// These are the event handlers called for this object
-DSOEXPORT void xmlsocket_event_ondata(const fn_call& fn);
-DSOEXPORT void xmlsocket_event_close(const fn_call& fn);
-DSOEXPORT void xmlsocket_event_connect(const fn_call& fn);
-DSOEXPORT void xmlsocket_event_xml(const fn_call& fn);
-
-DSOEXPORT int check_sockets(int fd);
-
-} // end of gnash namespace
-
-// HAVE_LIBXML
-#endif
-
-// __XMLSOCKETSOCKET_H__
-#endif
-