gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gnash-commit] /srv/bzr/gnash/trunk r9754: Allow XML.sendAndLoad to


From: Benjamin Wolsey
Subject: Re: [Gnash-commit] /srv/bzr/gnash/trunk r9754: Allow XML.sendAndLoad to take any object as second argument (tested in
Date: Tue, 16 Sep 2008 16:10:58 +0200

> Diff too large for email (1050 lines, the limit is 1000).

This is annoying!

I would like all my commits to be easily reviewable, and I don't think
1000 lines is too much to include, particularly as an attachment.

I'm pasting a diff of that commit below for info, and voting for the
limit to be raised significantly. 

bwy


=== modified file 'libbase/Makefile.am'
--- libbase/Makefile.am 2008-09-11 22:51:32 +0000
+++ libbase/Makefile.am 2008-09-16 12:36:54 +0000
@@ -150,7 +150,7 @@
        WallClockTimer.h \
        utf8.h \
        utility.h \
-       curl_adapter.h \
+       NetworkAdapter.h \
        noseek_fd_adapter.h \
        zlib_adapter.h \
        URL.h \

=== renamed file 'libbase/curl_adapter.h' => 'libbase/NetworkAdapter.h'
--- libbase/curl_adapter.h      2008-06-12 11:12:46 +0000
+++ libbase/NetworkAdapter.h    2008-09-16 12:36:54 +0000
@@ -16,20 +16,25 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301  USA
 
 
-#ifndef CURL_ADAPTER_H
-#define CURL_ADAPTER_H
+#ifndef NETWORK_ADAPTER_H
+#define NETWORK_ADAPTER_H
 
 #include "dsodefs.h"
 
+#include <map>
 #include <string>
-
+#include "StringPredicates.h"
 
 namespace gnash {
 class IOChannel;
 
-
 /// Code to use libcurl as an IOChannel stream.
-namespace curl_adapter {
+namespace NetworkAdapter {
+
+/// Custom headers for addRequestHeader. These are case insensitive,
and
+/// subsequent addition of a header already there replaces any previous
one.
+/// Some values are not allowed.
+typedef std::map<std::string, std::string, StringNoCaseLessThen>
RequestHeaders;
 
 /// \brief
 /// Returns a read-only IOChannel that fetches data
@@ -53,7 +58,10 @@
 ///
 DSOEXPORT IOChannel* make_stream(const char* url, const std::string&
postdata);
 
-} // namespace gnash::curl_adaptar
+DSOEXPORT IOChannel* makeStream(const std::string& url, const
std::string& postdata,
+                                const RequestHeaders& headers);
+
+}
 } // namespace gnash
 
 #endif // CURL_ADAPTER_H

=== modified file 'libbase/curl_adapter.cpp'
--- libbase/curl_adapter.cpp    2008-09-04 11:15:51 +0000
+++ libbase/curl_adapter.cpp    2008-09-16 12:36:54 +0000
@@ -1,4 +1,4 @@
-// curl_adapter.cpp:  Interface to libcurl to read HTTP streams, for
Gnash.
+// NetworkAdapter.cpp:  Interface to libcurl to read HTTP streams, for
Gnash.
 //
 //   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation,
Inc.
 //
@@ -25,9 +25,9 @@
 #include <pthread.h>
 #endif
 
+#include "NetworkAdapter.h"
 #include "utility.h" // UNUSED macro
 #include "IOChannel.h"
-#include "curl_adapter.h"
 #include "log.h"
 #include "WallClockTimer.h"
 
@@ -42,15 +42,26 @@
 #ifndef USE_CURL
 // Stub for warning about access when no libcurl is defined.
 
-namespace curl_adapter
+namespace NetworkAdapter
 {
        IOChannel* make_stream(const char * /*url */)
        {
                log_error(_("ERROR: libcurl is not available, but "
                            "Gnash has attempted to use the curl adapter"));
-               // Should abort instead?
                return NULL;
        }
+       
+    IOChannel* make_stream(const char* url, const std::string&
postdata)
+    {
+        return make_stream(url);
+    }
+
+    IOChannel* makeStream(const std::string& url, const std::string&
postdata,
+                                const RequestHeaders& headers)
+    {
+        return make_stream(url);
+    }
+
 }
 
 #else // def USE_CURL
@@ -83,7 +94,7 @@
 
 
 namespace gnash {
-namespace curl_adapter {
+namespace NetworkAdapter {
 
 /***********************************************************************
  *
@@ -364,6 +375,9 @@
        ///     The url-encoded post data.
        ///
        CurlStreamFile(const std::string& url, const std::string& vars);
+       
+       CurlStreamFile(const std::string& url, const std::string& vars,
+                      const NetworkAdapter::RequestHeaders& headers);
 
        ~CurlStreamFile();
 
@@ -889,6 +903,61 @@
 }
 
 /*public*/
+CurlStreamFile::CurlStreamFile(const std::string& url, const
std::string& vars, const NetworkAdapter::RequestHeaders& headers)
+{
+       log_debug("CurlStreamFile %p created", this);
+       init(url);
+       
+    curl_slist *headerList = 0;
+    
+    for (NetworkAdapter::RequestHeaders::const_iterator i =
headers.begin(),
+         e = headers.end(); i != e; ++i)
+    {
+        std::ostringstream os;
+        os << i->first << ": " << i->second;
+        headerList = curl_slist_append(headerList, os.str().c_str());
+    }
+
+    curl_easy_setopt(_handle, CURLOPT_HTTPHEADER, headerList);
+
+//    curl_slist_free_all(headerList);
+
+       _postdata = vars;
+
+       CURLcode ccode;
+
+       ccode = curl_easy_setopt(_handle, CURLOPT_POST, 1);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
+       }
+
+       // libcurl needs to access the POSTFIELDS during 'perform' operations,
+       // so we must use a string whose lifetime is ensured to be longer then
+       // the multihandle itself.
+       // The _postdata member should meet this requirement
+       ccode = curl_easy_setopt(_handle, CURLOPT_POSTFIELDS,
_postdata.c_str());
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
+       }
+
+       // This is to support binary strings as postdata
+       // NOTE: in version 7.11.1 CURLOPT_POSTFIELDSIZE_LARGE was added
+       //       this one takes a long, that one takes a curl_off_t
+       //
+       ccode = curl_easy_setopt(_handle, CURLOPT_POSTFIELDSIZE,
_postdata.size());
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
+       }
+
+       CURLMcode mcode = curl_multi_add_handle(_mhandle, _handle);
+       if ( mcode != CURLM_OK ) {
+               throw gnash::GnashException(curl_multi_strerror(mcode));
+       }
+
+}
+
+
+/*public*/
 CurlStreamFile::~CurlStreamFile()
 {
        log_debug("CurlStreamFile %p deleted", this);
@@ -1040,7 +1109,7 @@
        }
 
        if (std::fseek(_cache, 0, SEEK_END) == -1) {
-               throw gnash::IOException("curl_adapter: fseek to end failed");
+               throw gnash::IOException("NetworkAdapter: fseek to end failed");
                //gnash::log_error("Warning: fseek to end failed");
                //return -1;
        } 
@@ -1214,7 +1283,25 @@
        return stream;
 }
 
-} // namespace curl_adapter
+DSOEXPORT IOChannel* makeStream(const std::string& url, const
std::string& postdata,
+                                const RequestHeaders& headers)
+{
+
+       std::auto_ptr<CurlStreamFile> stream;
+
+       try {
+               stream.reset(new CurlStreamFile(url, postdata, headers));
+       }
+       catch (const std::exception& ex) {
+               gnash::log_error("curl stream: %s", ex.what());
+       }
+
+    return stream.release();
+
+}
+
+
+} // namespace NetworkAdapter
 } // namespace gnash
 
 #endif // def USE_CURL

=== modified file 'libcore/StreamProvider.cpp'
--- libcore/StreamProvider.cpp  2008-08-18 23:53:04 +0000
+++ libcore/StreamProvider.cpp  2008-09-16 12:36:54 +0000
@@ -29,10 +29,7 @@
 #include "StreamProvider.h"
 #include "URL.h"
 #include "tu_file.h"
-#ifdef USE_CURL
-//# include <curl/curl.h>
-# include "curl_adapter.h"
-#endif
+#include "NetworkAdapter.h"
 #include "URLAccessManager.h"
 #include "log.h"
 #include "rc.h" // for rcfile
@@ -63,7 +60,6 @@
 IOChannel*
 StreamProvider::getStream(const URL& url)
 {
-//    GNASH_REPORT_FUNCTION;
 
        if (url.protocol() == "file")
        {
@@ -93,26 +89,40 @@
        }
        else
        {
-#ifdef USE_CURL
                std::string url_str = url.str();
                const char* c_url = url_str.c_str();
                if ( URLAccessManager::allow(url) ) {
-                       return curl_adapter::make_stream(c_url);
+                       return NetworkAdapter::make_stream(c_url);
                } else {
                        return NULL;
                }
-#else
-               log_error(_("Unsupported network connection %s"),
-                                url.str().c_str());
-               return NULL;
-#endif
-       }
+       }
+}
+
+std::auto_ptr<IOChannel>
+StreamProvider::getStream(const URL& url, const std::string& postdata,
+                          const NetworkAdapter::RequestHeaders&
headers)
+{
+    if (url.protocol() == "file")
+    {
+        log_error("Request Headers discarded while getting stream from
file: uri");
+        return std::auto_ptr<IOChannel>(getStream(url, postdata));
+    }
+
+    std::auto_ptr<IOChannel> ret;
+
+       std::string url_str = url.str();
+       const char* c_url = url_str.c_str();
+       if ( URLAccessManager::allow(url) ) {
+               ret.reset(NetworkAdapter::makeStream(c_url, postdata, headers));
+       }
+       return ret;
+
 }
 
 IOChannel*
 StreamProvider::getStream(const URL& url, const std::string& postdata)
 {
-//    GNASH_REPORT_FUNCTION;
 
        if (url.protocol() == "file")
        {
@@ -135,19 +145,13 @@
        }
        else
        {
-#ifdef USE_CURL
                std::string url_str = url.str();
                const char* c_url = url_str.c_str();
                if ( URLAccessManager::allow(url) ) {
-                       return curl_adapter::make_stream(c_url, postdata);
+                       return NetworkAdapter::make_stream(c_url, postdata);
                } else {
                        return NULL;
                }
-#else
-               log_error(_("Unsupported network connection %s"),
-                               url.str().c_str());
-               return NULL;
-#endif
        }
 }
 

=== modified file 'libcore/StreamProvider.h'
--- libcore/StreamProvider.h    2008-06-09 13:31:51 +0000
+++ libcore/StreamProvider.h    2008-09-16 12:36:54 +0000
@@ -15,10 +15,12 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301  USA
 
-#ifndef _GNASH_STREAMPROVIDER_H
-#define _GNASH_STREAMPROVIDER_H
+#ifndef GNASH_STREAMPROVIDER_H
+#define GNASH_STREAMPROVIDER_H
 
-#include <string>
+#include <map>
+#include <memory>
+#include "NetworkAdapter.h"
 
 // Forward declarations
 namespace gnash {
@@ -64,6 +66,9 @@
        ///
        virtual IOChannel* getStream(const URL& url, const std::string&
postdata);
        
+       virtual std::auto_ptr<IOChannel> getStream(const URL& url,
+                           const std::string& postdata, const
NetworkAdapter::RequestHeaders& headers);
+       
 };
 
 } // namespace gnash

=== modified file 'libcore/as_object.h'
--- libcore/as_object.h 2008-09-12 10:37:09 +0000
+++ libcore/as_object.h 2008-09-16 12:36:54 +0000
@@ -47,6 +47,7 @@
        class as_environment;
        class VM;
        class Machine;
+       class IOChannel;
 }
 
 namespace gnash {
@@ -221,6 +222,10 @@
        /// to a string.
        virtual bool useCustomToString() const { return true; }
 
+    /// Loads data from an IOChannel. The default implementation
+    /// does nothing.
+    virtual void queueLoad(std::auto_ptr<IOChannel> /*str*/) {};
+
        /// Return the numeric value of this object
        //
        /// The default implementation converts the text value

=== modified file 'libcore/asobj/LoadVars.cpp'
--- libcore/asobj/LoadVars.cpp  2008-08-25 13:48:20 +0000
+++ libcore/asobj/LoadVars.cpp  2008-09-16 12:36:55 +0000
@@ -95,6 +95,8 @@
        ///
        void sendAndLoad(const std::string& urlstr, LoadVars& target, bool
post=true);
 
+    void queueLoad(std::auto_ptr<IOChannel> str);
+
        static as_object* getLoadVarsInterface();
 
        static void attachLoadVarsInterface(as_object& o);
@@ -331,23 +333,37 @@
        URL url(urlstr, get_base_url());
 
        std::auto_ptr<IOChannel> str;
-       if ( postdata ) str.reset
( StreamProvider::getDefaultInstance().getStream(url,
std::string(postdata)) );
-       else str.reset
( StreamProvider::getDefaultInstance().getStream(url) );
+       if ( postdata )
+    {
+        str.reset (StreamProvider::getDefaultInstance().getStream(
+                    url, std::string(postdata)) );
+    }
+       else
+    {
+        str.reset
(StreamProvider::getDefaultInstance().getStream(url));
+    }
 
-       if ( ! str.get() ) 
+       if (!str.get()) 
        {
-               log_error(_("Can't load variables from %s (security?)"),
url.str().c_str());
+               log_error(_("Can't load variables from %s (security?)"), 
url.str());
                return;
                // TODO: check if this is correct
                //as_value nullValue; nullValue.set_null();
                
//callMethod(VM::get().getStringTable().find(PROPNAME("onData")),
nullValue);
        }
 
-       log_security(_("Loading variables file from url: '%s'"),
url.str().c_str());
+       log_security(_("Loading variables file from url: '%s'"), url.str());
+    queueLoad(str);
+
+}
+
+void
+LoadVars::queueLoad(std::auto_ptr<IOChannel> str)
+{
 
        bool startTimer = _loadThreads.empty();
 
-       std::auto_ptr<LoadThread> lt ( new LoadThread(str) );
+       std::auto_ptr<LoadThread> lt (new LoadThread(str));
 
        // we push on the front to avoid invalidating
        // iterators when queueLoad is called as effect
@@ -355,14 +371,14 @@
        // Doing so also avoids processing queued load
        // request immediately
        // 
-       _loadThreads.push_front(lt.get());
+       _loadThreads.push_front(lt.release());
 #ifdef DEBUG_LOADS
-       log_debug("Pushed thread %p to _loadThreads, number of LoadVars load
threads now: %d", (void*)lt.get(),  _loadThreads.size());
+       log_debug("Pushed thread %p to _loadThreads, number of "
+            "LoadVars load threads now: %d",
+            static_cast<void*>(_loadThreads.front()),
_loadThreads.size());
 #endif
-       lt.release();
-
-
-       if ( startTimer )
+
+       if (startTimer)
        {
                boost::intrusive_ptr<builtin_function> loadsChecker = 
                        new builtin_function(&LoadVars::checkLoads_wrapper);
@@ -373,9 +389,9 @@
                log_debug("Registered LoadVars loads interval %d",
_loadCheckerTimer);
 #endif
     }
-
 }
 
+
 void
 LoadVars::load(const std::string& urlstr)
 {

=== modified file 'libcore/asobj/LoadVars.h'
--- libcore/asobj/LoadVars.h    2008-08-25 13:48:20 +0000
+++ libcore/asobj/LoadVars.h    2008-09-16 12:36:55 +0000
@@ -31,6 +31,5 @@
   
 } // end of gnash namespace
 
-// __GNASH_ASOBJ_LOADVARS_H__
 #endif
 

=== modified file 'libcore/asobj/xml.cpp'
--- libcore/asobj/xml.cpp       2008-08-29 14:29:54 +0000
+++ libcore/asobj/xml.cpp       2008-09-16 12:36:55 +0000
@@ -49,6 +49,7 @@
 #include <vector>
 #include <boost/algorithm/string/case_conv.hpp>
 #include <memory>
+#include <functional> // std::make_pair
 
 namespace gnash {
   
@@ -92,11 +93,10 @@
     _bytesTotal(-1),
     _bytesLoaded(-1)
 {
-    //GNASH_REPORT_FUNCTION;
 #ifdef DEBUG_MEMORY_ALLOCATION
     log_debug(_("Creating XML data at %p"), this);
 #endif
-    //log_debug("%s: %p", __FUNCTION__, this);
+
     attachXMLProperties(*this);
 }
 
@@ -114,10 +114,10 @@
     _bytesTotal(-1),
     _bytesLoaded(-1)
 {
-    //GNASH_REPORT_FUNCTION;
 #ifdef DEBUG_MEMORY_ALLOCATION
     log_debug(_("Creating XML data at %p"), this);
 #endif
+
     parseXML(xml_in);
 }
 
@@ -366,13 +366,6 @@
 void
 XML::queueLoad(std::auto_ptr<IOChannel> str)
 {
-    //GNASH_REPORT_FUNCTION;
-
-    // Set the "loaded" parameter to false
-    VM& vm = getVM();
-    string_table& st = vm.getStringTable();
-    string_table::key loadedKey = st.find("loaded");
-    set_member(loadedKey, as_value(false));
 
     bool startTimer = _loadThreads.empty();
 
@@ -521,8 +514,9 @@
 XML::load(const URL& url)
 {
     GNASH_REPORT_FUNCTION;
-  
-    //log_debug(_("%s: mem is %d"), __FUNCTION__, mem);
+
+    // Set a loaded property to false before starting the load.
+    set_member(NSV::PROP_LOADED, false);
 
     std::auto_ptr<IOChannel> str
( StreamProvider::getDefaultInstance().getStream(url) );
     if ( ! str.get() ) 
@@ -566,9 +560,10 @@
 /// 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
*/)
+XML::addRequestHeader(const NetworkAdapter::RequestHeaders::value_type&
headerPair)
 {
-    log_unimpl (__FUNCTION__);
+    /// Replace existing values.
+    _headers[headerPair.first] = headerPair.second;
 }
 
 
@@ -578,10 +573,12 @@
     log_unimpl (__FUNCTION__);
 }
 
-bool
-XML::sendAndLoad(const URL& url, XML& target)
+void
+XML::sendAndLoad(const URL& url, as_object& target)
 {
-    //GNASH_REPORT_FUNCTION;
+
+    /// All objects get a loaded member, set to false.
+    target.set_member(NSV::PROP_LOADED, false);
 
     std::stringstream ss;
     toString(ss);
@@ -595,23 +592,32 @@
     {
        log_unimpl ("Custom ContentType (%s) in XML.sendAndLoad",
ctypeVal);
     }
-  
-    //log_debug(_("%s: mem is %d"), __FUNCTION__, mem);
-
-    std::auto_ptr<IOChannel> str
( StreamProvider::getDefaultInstance().getStream(url, data) );
-    if ( ! str.get() ) 
+
+    std::auto_ptr<IOChannel> stream;
+
+    if (_headers.empty())
+    {
+
stream.reset(StreamProvider::getDefaultInstance().getStream(url, data));
+    }
+    else
+    {
+        log_debug("With headers");
+        stream = StreamProvider::getDefaultInstance().getStream(url,
data, _headers);
+        // Clear the headers for next send and load? Probably not.
+    }
+
+    if (!stream.get()) 
     {
         log_error(_("Can't load XML file: %s (security?)"), url.str());
-        return false;
+        return;
         // TODO: this is still not correct.. we should still send
onData later...
         //as_value nullValue; nullValue.set_null();
         //callMethod(NSV::PROP_ON_DATA, nullValue);
     }
 
     log_security(_("Loading XML file from url: '%s'"), url.str());
-    target.queueLoad(str);
-
-    return true;
+    target.queueLoad(stream);
+    
 }
 
 
@@ -697,9 +703,6 @@
 {
     as_value      inum;
     boost::intrusive_ptr<XML> xml_obj;
-    //const char    *data;
-  
-    // log_debug(_("%s: nargs=%d"), __FUNCTION__, fn.nargs);
   
     if ( fn.nargs > 0 )
     {
@@ -709,7 +712,7 @@
             xml_obj = boost::dynamic_pointer_cast<XML>(obj);
             if ( xml_obj )
             {
-                log_debug(_("\tCloned the XML object at %p"), (void
*)xml_obj.get());
+                log_debug(_("Cloned the XML object at %p"), (void
*)xml_obj.get());
                 return as_value(xml_obj->cloneNode(true).get());
             }
         }
@@ -735,22 +738,47 @@
     return as_value(xml_obj.get());
 }
 
-//
-// SWF Property of this class. These are "accessors" into the private
data
-// of the class.
-//
-
-as_value xml_addrequestheader(const fn_call& fn)
+/// Can take either a list of strings as arguments, alternately header
+/// and value, or an array.
+as_value
+xml_addrequestheader(const fn_call& fn)
 {
+
     GNASH_REPORT_FUNCTION;
-    log_debug(_("%s: %d args"), __PRETTY_FUNCTION__, fn.nargs);
-    
-//    return as_value(ptr->getAllocated());
-//    ptr->addRequestHeader();
-    log_unimpl (__FUNCTION__);
+    
+       boost::intrusive_ptr<XML> ptr = ensureType<XML>(fn.this_ptr);   
+
+    std::ostringstream ss;
+    fn.dump_args(ss);
+    log_debug ("addRequestHeader: %s", ss.str());
+
+    if (fn.nargs == 0)
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+            log_aserror(_("XML.addRequestHeader requires at least one
argument"));
+        );
+        return as_value();
+    }
+    
+    if (fn.nargs < 2)
+    {
+        // TODO: handle array.
+        log_unimpl(_("Array argument to XML.addRequestHeader"));
+        return as_value();
+    }
+
+    // TODO: should we ignore orphaned arguments like this?
+    for (size_t i = 0, e = fn.nargs / 2; i != e; ++i)
+    {
+        const std::string& name = fn.arg(i * 2).to_string();
+        const std::string& val = fn.arg(i * 2 + 1).to_string();
+        ptr->addRequestHeader(std::make_pair(name, val));
+    }
+    
     return as_value();
 }
 
+
 /// \brief create a new XML element
 ///
 /// Method; creates a new XML element with the name specified in the
@@ -759,11 +787,9 @@
 /// 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. 
-
 static as_value
 xml_createelement(const fn_call& fn)
 {
-//    GNASH_REPORT_FUNCTION;
     
     if (fn.nargs > 0) {
         const std::string& text = fn.arg(0).to_string();
@@ -779,6 +805,7 @@
     return as_value();
 }
 
+
 /// \brief Create a new XML node
 /// 
 /// Method; creates a new XML text node with the specified text. The
@@ -787,23 +814,21 @@
 /// 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.
-
 as_value
 xml_createtextnode(const fn_call& fn)
 {
-//    GNASH_REPORT_FUNCTION;
 
     XMLNode *xml_obj;
 
     if (fn.nargs > 0) {
-       const std::string& text = fn.arg(0).to_string();
-       xml_obj = new XMLNode;
-       xml_obj->nodeValueSet(text);
-       xml_obj->nodeTypeSet(XMLNode::tText);
-       return as_value(xml_obj);
-//     log_debug(_("%s: xml obj is %p"), __PRETTY_FUNCTION__, xml_obj);
-    } else {
-       log_error(_("no text for text node creation"));
+        const std::string& text = fn.arg(0).to_string();
+        xml_obj = new XMLNode;
+        xml_obj->nodeValueSet(text);
+        xml_obj->nodeTypeSet(XMLNode::tText);
+        return as_value(xml_obj);
+    }
+    else {
+        log_error(_("no text for text node creation"));
     }
     return as_value();
 }
@@ -826,7 +851,7 @@
 
 as_value xml_parsexml(const fn_call& fn)
 {
-    //GNASH_REPORT_FUNCTION;
+
     as_value   method;
     as_value   val;    
     boost::intrusive_ptr<XML> ptr = ensureType<XML>(fn.this_ptr);
@@ -847,17 +872,19 @@
 
 /// \brief removes the specified XML object from its parent. Also
 /// deletes all descendants of the node.
-    
 as_value xml_send(const fn_call& fn)
 {
     GNASH_REPORT_FUNCTION;
     boost::intrusive_ptr<XML> ptr = ensureType<XML>(fn.this_ptr);
     
-//    return as_value(ptr->getAllocated());
     ptr->send();
     return as_value();
 }
 
+/// Returns true if the arguments are valid, otherwise false. The
+/// success of the connection is irrelevant.
+/// The second argument must be an object, but does not have to 
+/// be an XML object.
 static as_value
 xml_sendandload(const fn_call& fn)
 {
@@ -877,35 +904,26 @@
 
     const std::string& filespec = fn.arg(0).to_string();
 
+    if (!fn.arg(1).is_object())
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+        std::ostringstream ss;
+        fn.dump_args(ss);
+        log_aserror(_("XML.sendAndLoad(%s): second argument is not "
+                "an object"), ss.str());
+        );
+
+        return as_value(false);
+    }
+
     boost::intrusive_ptr<as_object> targetObj = fn.arg(1).to_object();
-    if ( ! targetObj )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        std::stringstream ss;
-        fn.dump_args(ss);
-        log_aserror(_("XML.sendAndLoad(%s): second argument doesn't
cast to an object"),
-               ss.str());
-        );
-        return as_value(false);
-    }
-    XML* target = dynamic_cast<XML*>(targetObj.get());
-    if ( ! target )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        std::stringstream ss;
-        fn.dump_args(ss);
-        log_aserror(_("XML.sendAndLoad(%s): second argument is not an
XML object"),
-               ss.str());
-        );
-        return as_value(false);
-    }
+    assert(targetObj);
 
     URL url(filespec, get_base_url());
 
-//    return as_value(ptr->getAllocated());
-    bool ret = ptr->sendAndLoad(url, *target);
+    ptr->sendAndLoad(url, *targetObj);
 
-    return ret; // TODO: check expected return values
+    return as_value(true);
 }
 
 static as_value
@@ -942,12 +960,6 @@
     return as_value();
 }
 
-int
-memadjust(int x)
-{
-    return (x + (4 - x % 4));
-}
-
 // extern (used by Global.cpp)
 void xml_class_init(as_object& global)
 {

=== modified file 'libcore/asobj/xml.h'
--- libcore/asobj/xml.h 2008-08-29 14:29:54 +0000
+++ libcore/asobj/xml.h 2008-09-16 12:36:55 +0000
@@ -24,6 +24,7 @@
 #include "xmlnode.h"
 #include "log.h"
 #include "dsodefs.h"
+#include "NetworkAdapter.h"
 
 #include <vector>
 #include <sstream>
@@ -131,12 +132,11 @@
     
     XMLNode *processNode(xmlTextReaderPtr reader, XMLNode *node);
 
-    void  change_stack_frame(int frame, gnash::as_object *xml,
gnash::as_environment *env);
-
-    void  cleanupStackFrames( XMLNode *data);
-
-    // These 6 have to 
-    void addRequestHeader(const char *name, const char *value);
+    void change_stack_frame(int frame, gnash::as_object *xml,
gnash::as_environment *env);
+
+    void cleanupStackFrames( XMLNode *data);
+
+    void addRequestHeader(const
NetworkAdapter::RequestHeaders::value_type&);
 
     XMLNode *createElement(const char *name);
 
@@ -144,7 +144,8 @@
 
     void send();
 
-    bool sendAndLoad(const URL& url, XML& target);
+    /// ActionScript doesn't care about the success of the connection.
+    void sendAndLoad(const URL& url, as_object& target);
 
     /// @return -1 if no loaded was started yet
     long int getBytesLoaded() const;
@@ -222,6 +223,9 @@
 
     long int _bytesTotal;
     long int _bytesLoaded;
+    
+    NetworkAdapter::RequestHeaders _headers;
+    
 };
 
 

=== modified file 'testsuite/actionscript.all/XML.as'
--- testsuite/actionscript.all/XML.as   2008-04-08 09:09:20 +0000
+++ testsuite/actionscript.all/XML.as   2008-09-16 12:36:56 +0000
@@ -26,12 +26,14 @@
 //#include "dejagnu.as"
 #include "utils.as"
 
+#if OUTPUT_VERSION < 6
+Object.prototype.hasOwnProperty = ASnative(101, 5);
+#endif
+
 var existtests = true;
 
 check(XML);
 
-#if OUTPUT_VERSION >= 6 // {
-
 check(! XML.prototype.hasOwnProperty("appendChild") );
 check(! XML.prototype.hasOwnProperty("cloneNode") );
 check(! XML.prototype.hasOwnProperty("hasChildNodes") );
@@ -102,8 +104,6 @@
 check(! XMLNode.hasOwnProperty("cloneNode") );
 check(! XMLNode.hasOwnProperty("nodeValue"));
 
-#endif // OUTPUT_VERSION >= 6 }
-
 check(XML.prototype instanceof XMLNode);
 
 var tmp = new XML();
@@ -120,11 +120,7 @@
 
 check_equals(typeof(tmp.status), 'number');
 check(! tmp.hasOwnProperty("status"));
-#if OUTPUT_VERSION < 6
- check(! tmp.__proto__.hasOwnProperty('status') );
-#else
- xcheck(tmp.__proto__.hasOwnProperty('status') );
-#endif
+xcheck(tmp.__proto__.hasOwnProperty('status') );
 
 check_equals(tmp.status, 0);
 tmp.status = -1;
@@ -637,6 +633,62 @@
 // #endif
 
 
+// Test sendAndLoad return;
+// Any object can be passed as second argument.
+
+x = new XML;
+r = new Object;
+check(!r.hasOwnProperty("loaded"));
+check_equals(x.sendAndLoad("some server name", r), true);
+check(r.hasOwnProperty("loaded"));
+
+r = new XML;
+check(!r.hasOwnProperty("loaded"));
+check_equals(x.sendAndLoad("some server name", r), true);
+check(!r.hasOwnProperty("loaded"));
+check_equals(typeof(r.loaded), "boolean");
+check_equals(r.loaded, false);
+
+#if OUTPUT_VERSION > 5
+// No LoadVars in SWF 5.
+r = new LoadVars;
+check(!r.hasOwnProperty("loaded"));
+check_equals(x.sendAndLoad("some server name", r), true);
+check(r.hasOwnProperty("loaded"));
+check_equals(typeof(r.loaded), "boolean");
+check_equals(r.loaded, false);
+#endif
+
+r = new Date(1);
+check(!r.hasOwnProperty("loaded"));
+check_equals(x.sendAndLoad("some server name", r), true);
+check(r.hasOwnProperty("loaded"));
+check_equals(typeof(r.loaded), "boolean");
+check_equals(r.loaded, false);
+t = new Date(1);
+check_equals(r.toString(), t.toString());
+check(r instanceOf Date);
+
+r = 3;
+check(!r.hasOwnProperty("loaded"));
+check_equals(x.sendAndLoad("some server name", r), false);
+check(!r.hasOwnProperty("loaded"));
+check_equals(typeof(r.loaded), "undefined");
+check_equals(r.loaded, undefined);
+
+r = "string";
+check(!r.hasOwnProperty("loaded"));
+check_equals(x.sendAndLoad("some server name", r), false);
+check(!r.hasOwnProperty("loaded"));
+check_equals(typeof(r.loaded), "undefined");
+check_equals(r.loaded, undefined);
+
+r = {};
+check(!r.hasOwnProperty("loaded"));
+check_equals(x.sendAndLoad("some server name", r), true);
+check(r.hasOwnProperty("loaded"));
+check_equals(typeof(r.loaded), "boolean");
+check_equals(r.loaded, false);
 //--------------------------------------------------------------------
 // Test loading an XML locally
 //--------------------------------------------------------------------
@@ -702,8 +754,13 @@
        check_equals(myxml.nodeName, null);
 
        topnode = myxml.firstChild;
+#if OUTPUT_VERSION == 5
+       xcheck_equals(topnode.nodeName, null);
+       xcheck_equals(topnode.attributes.attr1, undefined);
+#else
        check_equals(topnode.nodeName, 'XML');
        check_equals(topnode.attributes.attr1, 'attr1 value');
+#endif
 
        // XML, comment, NULL 
        if ( typeof(myxml.lastChildNodesCount) == 'undefined' )
@@ -714,7 +771,11 @@
        {
                check_equals(myxml.childNodes.length, 
myxml.lastChildNodesCount);
        }
+#if OUTPUT_VERSION == 5
+       xcheck_equals(myxml.childNodes.length, 4); // gnash fails discarding
the comment and the ending blanks
+#else
        check_equals(myxml.childNodes.length, 3); // gnash fails discarding
the comment and the ending blanks
+#endif
 
        // We're done
        ++this.onLoadCalls;
@@ -722,9 +783,9 @@
        if ( this.onLoadCalls == 2 )
        {
 #if OUTPUT_VERSION < 6
-               check_totals(265);
+               check_totals(360);
 #else
-               check_totals(341);
+               check_totals(376);
 #endif
                play();
        }

=== modified file 'testsuite/misc-ming.all/XMLSocketTest.c'
--- testsuite/misc-ming.all/XMLSocketTest.c     2008-08-25 15:16:42 +0000
+++ testsuite/misc-ming.all/XMLSocketTest.c     2008-09-16 12:41:21 +0000
@@ -35,7 +35,7 @@
     SWFMovie mo;
        const char* srcdir = ".";
 
-    char longString[15000];
+    char longString[15001];
 
        if ( argc>1 ) srcdir=argv[1];
        else
@@ -126,6 +126,7 @@
     strncpy(longString, "xmlArray[11] = '", 16);
     longString[14998] = '\'';
     longString[14999] = ';';
+    longString[15000] = 0;
 
     add_actions(mo, longString);
 

Attachment: signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil


reply via email to

[Prev in Thread] Current Thread [Next in Thread]