gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r11050: Migrated SharedObject and St


From: Sharad Desai
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11050: Migrated SharedObject and Stage classes to new hierarchy
Date: Tue, 09 Jun 2009 09:51:03 -0600
User-agent: Bazaar (1.13.1)

------------------------------------------------------------
revno: 11050
committer: Sharad Desai <address@hidden>
branch nick: trunk
timestamp: Tue 2009-06-09 09:51:03 -0600
message:
  Migrated SharedObject and Stage classes to new hierarchy
removed:
  libcore/asobj/SharedObject_as.cpp
  libcore/asobj/SharedObject_as.h
  libcore/asobj/Stage_as.cpp
  libcore/asobj/Stage_as.h
modified:
  libcore/ClassHierarchy.cpp
  libcore/asobj/Global.cpp
  libcore/asobj/Makefile.am
  libcore/asobj/flash.am
  libcore/asobj/flash/display/Stage_as.cpp
  libcore/asobj/flash/display/Stage_as.h
  libcore/asobj/flash/display/display.am
  libcore/asobj/flash/net/SharedObject_as.cpp
  libcore/asobj/flash/net/SharedObject_as.h
  libcore/asobj/flash/net/net.am
  libcore/movie_root.cpp
  libcore/vm/VM.cpp
    ------------------------------------------------------------
    revno: 11040.1.1
    committer: Sharad Desai <address@hidden>
    branch nick: desaiMig
    timestamp: Mon 2009-06-08 15:22:11 -0600
    message:
      Migrated SharedObject_as and Stage_as classes
    removed:
      libcore/asobj/SharedObject_as.cpp
      libcore/asobj/SharedObject_as.h
      libcore/asobj/Stage_as.cpp
      libcore/asobj/Stage_as.h
    modified:
      libcore/ClassHierarchy.cpp
      libcore/asobj/Global.cpp
      libcore/asobj/Makefile.am
      libcore/asobj/flash.am
      libcore/asobj/flash/display/Stage_as.cpp
      libcore/asobj/flash/display/Stage_as.h
      libcore/asobj/flash/display/display.am
      libcore/asobj/flash/net/SharedObject_as.cpp
      libcore/asobj/flash/net/SharedObject_as.h
      libcore/asobj/flash/net/net.am
=== modified file 'libcore/ClassHierarchy.cpp'
--- a/libcore/ClassHierarchy.cpp        2009-06-09 11:38:31 +0000
+++ b/libcore/ClassHierarchy.cpp        2009-06-09 15:51:03 +0000
@@ -47,9 +47,9 @@
 #include "NetConnection_as.h"
 #include "NetStream_as.h"
 #include "Selection_as.h"
-#include "SharedObject_as.h"
+#include "flash/net/SharedObject_as.h"
 #include "Sound_as.h"
-#include "Stage_as.h"
+#include "flash/display/Stage_as.h"
 #include "System_as.h"
 #include "flash/text/TextSnapshot_as.h"
 #include "TextFormat_as.h"

=== modified file 'libcore/asobj/Global.cpp'
--- a/libcore/asobj/Global.cpp  2009-06-09 11:38:31 +0000
+++ b/libcore/asobj/Global.cpp  2009-06-09 15:51:03 +0000
@@ -50,8 +50,8 @@
 #include "movie_definition.h"
 #include "NetConnection_as.h"
 #include "NetStream_as.h"
-#include "SharedObject_as.h"
-#include "Stage_as.h"
+#include "flash/net/SharedObject_as.h"
+#include "flash/display/Stage_as.h"
 #include "System_as.h"
 #include "TextFormat_as.h"
 #include "flash/text/TextSnapshot_as.h"

=== modified file 'libcore/asobj/Makefile.am'
--- a/libcore/asobj/Makefile.am 2009-06-09 11:38:31 +0000
+++ b/libcore/asobj/Makefile.am 2009-06-09 15:51:03 +0000
@@ -72,7 +72,6 @@
        Number_as.cpp \
        PlayHead.cpp \
        Selection_as.cpp \
-       SharedObject_as.cpp\
        Namespace_as.cpp \
        Sound_as.cpp \
        Stage_as.cpp \
@@ -106,7 +105,6 @@
        Number_as.h \
        PlayHead.h \
        Selection_as.h \
-       SharedObject_as.h \
        Sound_as.h \
        Stage_as.h      \
        System_as.h \

=== removed file 'libcore/asobj/SharedObject_as.cpp'
--- a/libcore/asobj/SharedObject_as.cpp 2009-06-03 16:05:40 +0000
+++ b/libcore/asobj/SharedObject_as.cpp 1970-01-01 00:00:00 +0000
@@ -1,1108 +0,0 @@
-// SharedObject_as.cpp:  ActionScript "SharedObject" class, for Gnash.
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 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 3 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 "gnashconfig.h" // USE_SOL_READ_ONLY
-#endif
-
-#include "GnashSystemNetHeaders.h"
-#include "GnashFileUtilities.h" // stat
-#include "SimpleBuffer.h"
-#include "as_value.h"
-#include "amf.h"
-#include "element.h"
-#include "sol.h"
-#include "movie_root.h"
-#include "SharedObject_as.h"
-#include "as_object.h" // for inheritance
-#include "log.h"
-#include "fn_call.h"
-#include "smart_ptr.h" // for boost intrusive_ptr
-#include "builtin_function.h" // need builtin_function
-#include "Object.h" // for getObjectInterface
-#include "VM.h"
-#include "Property.h"
-#include "string_table.h"
-#include "URLAccessManager.h"
-#include "URL.h"
-#include "rc.h" // for use of rcfile
-
-#include <boost/tokenizer.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/shared_ptr.hpp>
-
-// Undefine this to use the Element-based AMF0 decoder/encoder.
-// May be useful to test libamf.
-#define BUFFERED_AMF_SOL
-
-namespace {
-gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
-}
-
-using namespace amf;
-
-namespace gnash {
-
-// Forward declarations
-namespace {
-
-    as_value sharedobject_connect(const fn_call& fn);
-    as_value sharedobject_send(const fn_call& fn);
-    as_value sharedobject_flush(const fn_call& fn);
-    as_value sharedobject_close(const fn_call& fn);
-    as_value sharedobject_getsize(const fn_call& fn);
-    as_value sharedobject_setFps(const fn_call& fn);
-    as_value sharedobject_clear(const fn_call& fn);
-    as_value sharedobject_deleteAll(const fn_call& fn);
-    as_value sharedobject_getDiskUsage(const fn_call& fn);
-    as_value sharedobject_getRemote(const fn_call& fn);
-    as_value sharedobject_data(const fn_call& fn);
-
-    as_value sharedobject_getLocal(const fn_call& fn);
-    as_value sharedobject_ctor(const fn_call& fn);
-
-    as_object* readSOL(VM& vm, const std::string& filespec);
-
-    as_object* getSharedObjectInterface();
-    void attachSharedObjectStaticInterface(as_object& o);
-    void flushSOL(SharedObjectLibrary::SoLib::value_type& sol);
-    bool validateName(const std::string& solName);
-}
-
-// Serializer helper
-namespace { 
-
-class PropsSerializer : public AbstractPropertyVisitor
-{
-public:
-
-    PropsSerializer(SOL& sol, VM& vm)
-        :
-        _sol(sol),
-        _st(vm.getStringTable())
-    {};
-
-    void accept(string_table::key key, const as_value& val) 
-    {
-        AMF amf;
-        boost::shared_ptr<amf::Element> el;
-        
-        const std::string& name = _st.string_table::value(key);
-
-        //log_debug("Serializing SharedObject property %s:%s", name, val);
-
-        if (val.is_string()) {
-            std::string str;
-            if (!val.is_undefined()) {
-                str = val.to_string();
-            }
-            el.reset(new amf::Element(name, str));
-        }
-        if (val.is_bool()) {
-            bool flag = val.to_bool();
-            el.reset(new amf::Element(name, flag));
-        }
-        if (val.is_number()) { 
-            double dub;
-            if (val.is_undefined()) {
-                dub = 0.0;
-            } else {
-                dub = val.to_number();
-            }
-            el.reset(new amf::Element(name, dub));
-        }
-
-        if (el) {
-            _sol.addObj(el);
-        }
-    }
-
-private:
-
-    SOL& _sol;
-    string_table& _st;
-};
-
-/// Class used to serialize properties of an object to a buffer in SOL format
-class SOLPropsBufSerializer : public AbstractPropertyVisitor
-{
-
-    typedef std::map<as_object*, size_t> PropertiesOffsetTable;
-
-public:
-
-    SOLPropsBufSerializer(SimpleBuffer& buf, VM& vm,
-            PropertiesOffsetTable& offsetTable)
-        :
-        _buf(buf),
-        _vm(vm),
-        _st(vm.getStringTable()),
-        _offsetTable(offsetTable),
-        _error(false)
-       {};
-    
-    bool success() const { return !_error; }
-
-    virtual void accept(string_table::key key, const as_value& val) 
-    {
-        if ( _error ) return;
-
-        if ( val.is_function() )
-        {
-            log_debug("SOL: skip serialization of FUNCTION property");
-            return;
-        }
-
-        // Test conducted with AMFPHP:
-        // '__proto__' and 'constructor' members
-        // of an object don't get back from an 'echo-service'.
-        // Dunno if they are not serialized or just not sent back.
-        // A '__constructor__' member gets back, but only if 
-        // not a function. Actually no function gets back.
-        // 
-        if ( key == NSV::PROP_uuPROTOuu || key == NSV::PROP_CONSTRUCTOR )
-        {
-#ifdef GNASH_DEBUG_AMF_SERIALIZE
-            log_debug(" skip serialization of specially-named property %s",
-                    _st.value(key));
-#endif
-            return;
-        }
-
-        // write property name
-        const std::string& name = _st.value(key);
-#ifdef GNASH_DEBUG_AMF_SERIALIZE
-        log_debug(" serializing property %s", name);
-#endif
-        boost::uint16_t namelen = name.size();
-        _buf.appendNetworkShort(namelen);
-        _buf.append(name.c_str(), namelen);
-        // Strict array are never encoded in SharedObject
-        if ( ! val.writeAMF0(_buf, _offsetTable, _vm, false) )
-        {
-            log_error("Problems serializing an object's member %s=%s",
-                    name, val);
-            _error = true;
-        }
-
-        _buf.appendByte(0); // SOL-specific
-    }
-
-private:
-
-    SimpleBuffer& _buf;
-
-    VM& _vm;
-
-    string_table& _st;
-
-    PropertiesOffsetTable& _offsetTable;
-
-    bool _error;
-};
-
-} // anonymous namespace
-
-class SharedObject_as: public as_object 
-{
-public:
-
-    ~SharedObject_as();
-
-    SharedObject_as()
-        :
-        as_object(getSharedObjectInterface()),
-        _data(0)
-    { 
-    }
-
-    bool flush(int space = 0) const;
-
-    const std::string& getFilespec() const {
-        return _sol.getFilespec();
-    }
-
-    void setFilespec(const std::string& s) {
-        _sol.setFilespec(s);
-    }
-
-    const std::string& getObjectName() const {
-        return _sol.getObjectName();
-    }
-
-    void setObjectName(const std::string& s) {
-        _sol.setObjectName(s);
-    }
-
-    /// This isn't correct, as the default implementation doesn't use SOL
-    /// for reading.
-    size_t size() const { 
-        return _sol.fileSize(); 
-    }
-
-    void setData(as_object* data) {
-
-        assert(data);
-        _data = data;
-
-        const int flags = as_prop_flags::dontDelete |
-                          as_prop_flags::readOnly;
-
-        init_property(NSV::PROP_DATA, &sharedobject_data, &sharedobject_data,
-                flags);
-
-    }
-
-    as_object* data() {
-        return _data;
-    }
-
-    const as_object* data() const {
-        return _data;
-    }
-
-protected:
-
-    void markReachableResources() const {
-        if (_data) _data->setReachable();
-    }
-
-private:
-
-    as_object* _data;
-
-    SOL _sol;
-};
-
-
-SharedObject_as::~SharedObject_as()
-{
-}
-
-
-bool
-SharedObject_as::flush(int space) const
-{
-
-    /// This is called on on destruction of the SharedObject, or (allegedly)
-    /// on a call to SharedObject.data, so _data is not guaranteed to exist.
-    //
-    /// The function should never be called from SharedObject.flush() when
-    /// _data is 0.
-    if (!_data) return false;
-
-    if (space > 0) {
-        log_unimpl("SharedObject.flush() called with a minimum disk space "
-                "argument (%d), which is currently ignored", space);
-    }
-
-    const std::string& filespec = _sol.getFilespec();
-
-    if (!mkdirRecursive(filespec))
-    {
-        log_error("Couldn't create dir for flushing SharedObject %s", 
filespec);
-        return false;
-    }
-
-#ifdef USE_SOL_READONLY
-    log_debug(_("SharedObject %s not flushed (compiled as read-only mode)"),
-            filespec);
-    return false;
-#endif
-
-    if (rcfile.getSOLReadOnly() ) {
-        log_security("Attempting to write object %s when it's SOL "
-                "Read Only is set! Refusing...", filespec);
-        return false;
-    }
-    
-#ifdef BUFFERED_AMF_SOL
-
-    gnash::SimpleBuffer buf;
-    // see http://osflash.org/documentation/amf/envelopes/sharedobject
-
-    // length field filled in later
-    buf.append("\x00\xbf\x00\x00\x00\x00TCSO\x00\x04\x00\x00\x00\x00", 16); 
-
-    // append object name
-    std::string object_name = getObjectName();
-    boost::uint16_t len = object_name.length();
-    buf.appendNetworkShort(len);
-    buf.append(object_name.c_str(), len);
-
-    // append padding
-    buf.append("\x00\x00\x00\x00", 4);
-
-    // append properties of object
-    VM& vm = getVM();
-
-    std::map<as_object*, size_t> offsetTable;
-    SOLPropsBufSerializer props(buf, vm, offsetTable);
-    _data->visitPropertyValues(props);
-    if ( ! props.success() ) 
-    {
-        log_error("Could not serialize object");
-        return false;
-    }
-
-    // fix length field
-    *(reinterpret_cast<uint32_t*>(buf.data() + 2)) = htonl(buf.size() - 6);
-    
-    // TODO write file
-    std::ofstream ofs(filespec.c_str(), std::ios::binary);
-    if (!ofs) {
-        log_error("SharedObject::flush(): Failed opening file '%s' in "
-                "binary mode", filespec.c_str());
-        return false;
-    }
-    
-    if (ofs.write(reinterpret_cast<const char*>(buf.data()), 
buf.size()).fail())
-    {
-        log_error("Error writing %d bytes to output file %s",
-                buf.size(), filespec.c_str());
-        ofs.close();
-        return false;
-    }
-    ofs.close();
-
-#else // amf::SOL-based serialization
-
-    // append properties of object
-    VM& vm = getVM();
-
-    SOL sol;
-    PropsSerializer props(sol, vm);
-    _data->visitPropertyValues(props);
-    // We only want to access files in this directory
-    bool ret = sol.writeFile(filespec, getObjectName().c_str());
-    if ( ! ret )
-    {
-        log_error("writing SharedObject file to %s", filespec);
-        return false;
-    }
-#endif
-
-    log_security("SharedObject '%s' written to filesystem.", filespec);
-    return true;
-}
-
-
-SharedObjectLibrary::SharedObjectLibrary(VM& vm)
-    :
-    _vm(vm)
-{
-    _solSafeDir = rcfile.getSOLSafeDir();
-    if (_solSafeDir.empty()) {
-        log_debug("Empty SOLSafeDir directive: we'll use '/tmp'");
-        _solSafeDir = "/tmp/";
-    }
-
-    // Check if the base dir exists here
-    struct stat statbuf;
-    if ( -1 == stat(_solSafeDir.c_str(), &statbuf) )
-    {
-       log_debug("Invalid SOL safe dir %s: %s. Will try to create on "
-               "flush/exit.", _solSafeDir, std::strerror(errno));
-    }
-
-    // Which URL we should use here is under research.
-    // The reference player uses the URL from which definition
-    // of the call to SharedObject.getLocal was parsed.
-    //
-    // There is in Gnash support for tracking action_buffer 
-    // urls but not yet an interface to fetch it from fn_call;
-    // also, it's not clear how good would the model be (think
-    // of movie A loading movie B creating the SharedObject).
-    //
-    // What we'll do for now is use the URL of the initially
-    // loaded SWF, so that in the A loads B scenario above the
-    // domain would be the one of A, not B.
-    //
-    // NOTE: using the base url RunInfo::baseURL() would mean
-    // blindly trusting the SWF publisher as base url is changed
-    // by the 'base' attribute of OBJECT or EMBED tags trough
-    // -P base=xxx
-    //
-    const movie_root& mr = _vm.getRoot();
-    const std::string& swfURL = mr.getOriginalURL();
-
-    URL url(swfURL);
-
-    // Remember the hostname of our SWF URL. This can be empty if loaded
-    // from the filesystem
-    _baseDomain = url.hostname();
-
-    const std::string& urlPath = url.path();
-
-    // Get the path part. If loaded from the filesystem, the pp stupidly
-    // removes the first directory.
-    if (!_baseDomain.empty()) {
-        _basePath = urlPath;
-    }
-    else if (!urlPath.empty()) {
-        // _basePath should be empty if there are no slashes or just one.
-        std::string::size_type pos = urlPath.find('/', 1);
-        if (pos != std::string::npos) {
-            _basePath = urlPath.substr(pos);
-        }
-    }
-
-}
-
-void
-SharedObjectLibrary::markReachableResources() const
-{
-    for (SoLib::const_iterator it = _soLib.begin(), itE = _soLib.end();
-            it != itE; ++it)
-    {
-        SharedObject_as* sh = it->second;
-        sh->setReachable();
-    }
-}
-
-/// The SharedObjectLibrary keeps all known SharedObjects alive. They must
-/// be flushed on clear(). This is called at the latest by the dtor, which
-/// is called at the latest by VM's dtor (currently earlier to avoid problems
-/// with the GC).
-void
-SharedObjectLibrary::clear()
-{
-    std::for_each(_soLib.begin(), _soLib.end(), &flushSOL);
-    _soLib.clear();
-}
-
-SharedObjectLibrary::~SharedObjectLibrary()
-{
-    clear();
-}
-
-SharedObject_as*
-SharedObjectLibrary::getLocal(const std::string& objName,
-        const std::string& root)
-{
-    assert (!objName.empty());
-
-    // already warned about it at construction time
-    if (_solSafeDir.empty()) return 0;
-
-    if (rcfile.getSOLLocalDomain() && !_baseDomain.empty()) 
-    {
-        log_security("Attempting to open SOL file from non "
-                "localhost-loaded SWF");
-        return 0;
-    }
-
-    // Check that the name is valid; if not, return null
-    if (!validateName(objName)) return 0;
-
-    // The 'root' argument, otherwise known as localPath, specifies where
-    // in the SWF path the SOL should be stored. It cannot be outside this
-    // path.
-    std::string requestedPath;
-
-    // If a root is specified, check it first for validity
-    if (!root.empty()) {
-
-        const movie_root& mr = _vm.getRoot();
-        const std::string& swfURL = mr.getOriginalURL();
-        // The specified root may or may not have a domain. If it doesn't,
-        // this constructor will add the SWF's domain.
-        URL localPath(root, swfURL);
-        
-        StringNoCaseEqual noCaseCompare;
-
-        // All we care about is whether the domains match. They may be 
-        // empty filesystem-loaded.
-        if (!noCaseCompare(localPath.hostname(), _baseDomain)) {
-            log_security(_("SharedObject path %s is outside the SWF domain "
-                        "%s. Cannot access this object."), localPath, 
-                        _baseDomain);
-            return 0;
-        }
-
-        requestedPath = localPath.path();
-
-        // The domains match. Now check that the path is a sub-path of 
-        // the SWF's URL. It is done by case-insensitive string comparison,
-        // so a double slash in the requested path will fail.
-        if (!noCaseCompare(requestedPath,
-                    _basePath.substr(0, requestedPath.size()))) {
-            log_security(_("SharedObject path %s is not part of the SWF path "
-                        "%s. Cannot access this object."), requestedPath, 
-                        _basePath);
-            return 0;
-        }
-
-    }
-
-    // A leading slash is added later
-    std::ostringstream solPath;
-
-    // If the domain name is empty, the SWF was loaded from the filesystem.
-    // Use "localhost".
-    solPath << (_baseDomain.empty() ? "localhost" : _baseDomain);
-
-    // Paths should start with a '/', so we shouldn't have to add another
-    // one.
-    assert(requestedPath.empty() ? _basePath[0] == '/' :
-                                    requestedPath[0] == '/');
-
-    // If no path was requested, use the SWF's path.
-    solPath << (requestedPath.empty() ? _basePath : requestedPath) << "/"
-            << objName;
-
-    // TODO: normalize key!
-
-    const std::string& key = solPath.str();
-
-    // If the shared object was already opened, use it.
-    SoLib::iterator it = _soLib.find(key);
-    if ( it != _soLib.end() )
-    {
-        log_debug("SharedObject %s already known, returning it", key);
-        return it->second;
-    }
-
-    log_debug("SharedObject %s not loaded. Loading it now", key);
-
-    // Otherwise create a new one and register to the lib
-    SharedObject_as* obj = new SharedObject_as;
-    _soLib[key] = obj;
-
-    obj->setObjectName(objName);
-
-    std::string newspec = _solSafeDir;
-    newspec += "/";
-    newspec += key;
-    newspec += ".sol";
-    obj->setFilespec(newspec);
-
-    log_debug("SharedObject path: %s", newspec);
-        
-    boost::intrusive_ptr<as_object> data = readSOL(_vm, newspec);
-
-    /// Don't set to 0, or it will initialize a property.
-    if (data) obj->setData(data.get());
-
-    return obj;
-}
-
-void
-sharedobject_class_init(as_object& global)
-{
-    static boost::intrusive_ptr<builtin_function> cl;
-    
-    if (cl == NULL) {
-        cl=new builtin_function(&sharedobject_ctor, 
getSharedObjectInterface());
-        attachSharedObjectStaticInterface(*cl);
-    }
-    
-    // Register _global.SharedObject
-    global.init_member("SharedObject", cl.get());    
-}
-
-void
-registerSharedObjectNative(as_object& o)
-{
-    VM& vm = o.getVM();
-
-    // ASnative table registration
-       vm.registerNative(sharedobject_connect, 2106, 0);
-       vm.registerNative(sharedobject_send, 2106, 1);
-       vm.registerNative(sharedobject_flush, 2106, 2);
-       vm.registerNative(sharedobject_close, 2106, 3);
-       vm.registerNative(sharedobject_getsize, 2106, 4);
-       vm.registerNative(sharedobject_setFps, 2106, 5);
-       vm.registerNative(sharedobject_clear, 2106, 6);
-
-    // FIXME: getRemote and getLocal use both these methods,
-    // but aren't identical with either of them.
-    // TODO: The first method looks in a library and returns either a
-    // SharedObject or null. The second takes a new SharedObject as
-    // its first argument and populates its data member (more or less
-    // like readSOL). This is only important for ASNative compatibility.
-       vm.registerNative(sharedobject_getLocal, 2106, 202);
-       vm.registerNative(sharedobject_getRemote, 2106, 203);
-       vm.registerNative(sharedobject_getLocal, 2106, 204);
-       vm.registerNative(sharedobject_getRemote, 2106, 205);
-
-       vm.registerNative(sharedobject_deleteAll, 2106, 206);
-       vm.registerNative(sharedobject_getDiskUsage, 2106, 207);
-}
-
-
-/// SharedObject AS interface
-namespace {
-
-void
-attachSharedObjectInterface(as_object& o)
-{
-
-    VM& vm = o.getVM();
-
-    const int flags = as_prop_flags::dontEnum |
-                      as_prop_flags::dontDelete |
-                      as_prop_flags::onlySWF6Up;
-
-    o.init_member("connect", vm.getNative(2106, 0), flags);
-    o.init_member("send", vm.getNative(2106, 1), flags);
-    o.init_member("flush", vm.getNative(2106, 2), flags);
-    o.init_member("close", vm.getNative(2106, 3), flags);
-    o.init_member("getSize", vm.getNative(2106, 4), flags);
-    o.init_member("setFps", vm.getNative(2106, 5), flags);
-    o.init_member("clear", vm.getNative(2106, 6), flags);
-
-}
-
-
-void
-attachSharedObjectStaticInterface(as_object& o)
-{
-    VM& vm = o.getVM();
-
-    const int flags = 0;
-
-    o.init_member("getLocal", 
-            new builtin_function(sharedobject_getLocal), flags);
-    o.init_member("getRemote",
-            new builtin_function(sharedobject_getRemote), flags);
-
-    const int hiddenOnly = as_prop_flags::dontEnum;
-
-    o.init_member("deleteAll",  vm.getNative(2106, 206), hiddenOnly);
-    o.init_member("getDiskUsage",  vm.getNative(2106, 207), hiddenOnly);
-}
-
-
-as_object*
-getSharedObjectInterface()
-{
-
-    static boost::intrusive_ptr<as_object> o;
-    if ( ! o ) {
-        o = new as_object(getObjectInterface());
-        attachSharedObjectInterface(*o);
-    }
-    return o.get();
-}
-
-
-as_value
-sharedobject_clear(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj = 
-        ensureType<SharedObject_as>(fn.this_ptr);
-    UNUSED(obj);
-    
-    LOG_ONCE(log_unimpl (__FUNCTION__));
-
-    return as_value();
-}
-
-as_value
-sharedobject_connect(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-    UNUSED(obj);
-
-    LOG_ONCE(log_unimpl("SharedObject.connect"));
-    return as_value();
-}
-
-as_value
-sharedobject_close(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-    UNUSED(obj);
-
-    LOG_ONCE(log_unimpl("SharedObject.close"));
-    return as_value();
-}
-
-as_value
-sharedobject_setFps(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-    UNUSED(obj);
-
-    LOG_ONCE(log_unimpl("SharedObject.setFps"));
-    return as_value();
-}
-
-as_value
-sharedobject_send(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-    UNUSED(obj);
-
-    LOG_ONCE(log_unimpl("SharedObject.send"));
-    return as_value();
-}
-
-as_value
-sharedobject_flush(const fn_call& fn)
-{
-    
-    GNASH_REPORT_FUNCTION;
-
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-
-    IF_VERBOSE_ASCODING_ERRORS(
-        if (fn.nargs > 1)
-        {
-            std::ostringstream ss;
-            fn.dump_args(ss);
-            log_aserror(_("Arguments to SharedObject.flush(%s) will be "
-                    "ignored"), ss.str());
-        }
-    );
-
-    int space = 0;
-    if (fn.nargs) {
-        space = fn.arg(0).to_int();
-    }
-
-    /// If there is no data member, returns undefined.
-    if (!obj->data()) return as_value();
-
-    // If there is an object data member, returns the success of flush().
-    return as_value(obj->flush(space));
-}
-
-// Set the file name
-as_value
-sharedobject_getLocal(const fn_call& fn)
-{
-
-    VM& vm = fn.env().getVM();
-    int swfVersion = vm.getSWFVersion();
-
-    as_value objNameVal;
-    if (fn.nargs > 0) objNameVal = fn.arg(0);
-    std::string objName = objNameVal.to_string_versioned(swfVersion);
-    if ( objName.empty() )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-            std::ostringstream ss;
-            fn.dump_args(ss);
-            log_aserror("SharedObject.getLocal(%s): %s", 
-                _("missing object name"));
-        );
-        as_value ret;
-        ret.set_null();
-        return ret;
-    }
-
-    std::string root;
-    if (fn.nargs > 1)
-    {
-        root = fn.arg(1).to_string_versioned(swfVersion);
-    }
-
-    log_debug("SO name:%s, root:%s", objName, root);
-
-    SharedObject_as* obj = vm.getSharedObjectLibrary().getLocal(objName, root);
-
-    as_value ret(obj);
-    log_debug("SharedObject.getLocal returning %s", ret);
-    return ret;
-}
-
-/// Undocumented
-as_value
-sharedobject_getRemote(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-
-    UNUSED(obj);
-
-    LOG_ONCE(log_unimpl("SharedObject.getRemote()"));
-    return as_value();
-}
-
-
-/// Undocumented
-//
-/// Takes a URL argument and deletes all SharedObjects under that URL.
-as_value
-sharedobject_deleteAll(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-
-    UNUSED(obj);
-
-    LOG_ONCE(log_unimpl("SharedObject.deleteAll()"));
-    return as_value();
-}
-
-/// Undocumented
-//
-/// Should be quite obvious what it does.
-as_value
-sharedobject_getDiskUsage(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-
-    UNUSED(obj);
-
-    LOG_ONCE(log_unimpl("SharedObject.getDiskUsage()"));
-    return as_value();
-}
-
-
-as_value
-sharedobject_data(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-    return as_value(obj->data());
-}
-
-as_value
-sharedobject_getsize(const fn_call& fn)
-{
-    boost::intrusive_ptr<SharedObject_as> obj =
-        ensureType<SharedObject_as>(fn.this_ptr);
-    return as_value(obj->size());
-}
-
-as_value
-sharedobject_ctor(const fn_call& /* fn */)
-{
-    boost::intrusive_ptr<as_object> obj = new SharedObject_as;
-    
-    return as_value(obj.get()); // will keep alive
-}
-
-/// Return true if the name is a valid SOL name.
-//
-/// The official docs claim that '%' is also an invalid DisplayObject,
-/// but that is incorrect (see actionscript.all/SharedObject.as)
-bool
-validateName(const std::string& solName)
-{
-    // A double forward slash isn't allowed
-    std::string::size_type pos = solName.find("//");
-    if (pos != std::string::npos) return false;
-
-    // These DisplayObjects are also illegal
-    pos = solName.find_first_of(",~;\"'<&>?#:\\ ");
-
-    return (pos == std::string::npos);
-}
-
-as_object*
-readSOL(VM& vm, const std::string& filespec)
-{
-
-#ifdef BUFFERED_AMF_SOL
-
-    // The 'data' member is initialized only on getLocal() (and probably
-    // getRemote()): i.e. when there is some data, or when it's ready to
-    // be added.
-    as_object* data = new as_object(getObjectInterface());
-
-    struct stat st;
-
-    if (stat(filespec.c_str(), &st) != 0)
-    {
-        // No existing SOL file. A new one will be created.
-        log_debug("No existing SOL %s found. Will create on flush/exit.",
-                filespec);
-        return data;
-    }
-
-    if (st.st_size < 28)
-    {
-        // A SOL file exists, but it was invalid. Count it as not existing.
-        log_error("SharedObject::readSOL: SOL file %s is too short "
-                "(only %s bytes long) to be valid.", filespec, st.st_size);
-        return data;
-    }
-
-    boost::scoped_array<boost::uint8_t> sbuf(new boost::uint8_t[st.st_size]);
-    const boost::uint8_t *buf = sbuf.get();
-    const boost::uint8_t *end = buf + st.st_size;
-
-    try
-    {
-        std::ifstream ifs(filespec.c_str(), std::ios::binary);
-        ifs.read(reinterpret_cast<char*>(sbuf.get()), st.st_size);
-
-        // TODO check initial bytes, and print warnings if they are fishy
-
-        buf += 16; // skip const-length headers
-
-        // skip past name   TODO add sanity check
-        buf += ntohs(*(reinterpret_cast<const boost::uint16_t*>(buf)));
-        buf += 2;
-        
-        buf += 4; // skip past padding
-
-        if (buf >= end)
-        {
-            // In this case there is no data member.
-            log_error("SharedObject::readSOL: file ends before data segment");
-            return data;
-        }
-
-        std::vector<as_object*> objRefs;
-
-        while (buf < end)
-        {
-            log_debug("SharedObject::readSOL: reading property name at "
-                    "byte %s", buf - sbuf.get());
-            // read property name
-            boost::uint16_t len = 
-                ntohs(*(reinterpret_cast<const boost::uint16_t*>(buf)));
-            buf += 2;
-
-            if( buf + len >= end )
-            {
-                log_error("SharedObject::readSOL: premature end of input");
-                break;
-            }
-            if ( ! len ) {
-                log_error("SharedObject::readSOL: empty property name");
-                break;
-            }
-            std::string prop_name(reinterpret_cast<const char*>(buf), len);
-            buf += len;
-
-            // read value
-            as_value as;
-            if (!as.readAMF0(buf, end, -1, objRefs, vm)) {
-                log_error("SharedObject::readSOL: Parsing SharedObject '%s'",
-                        filespec);
-                return false;
-            }
-
-            log_debug("parsed sol member named '%s' (len %s),  value '%s'",
-                    prop_name, len, as);
-
-            // set name/value as a member of this (SharedObject) object
-            string_table& st = vm.getStringTable();
-            data->set_member(st.find(prop_name), as);
-            
-            buf += 1; // skip null byte after each property
-        }
-        return data;
-    }
-    catch (std::exception& e)
-    {
-        log_error("SharedObject::readSOL: Reading SharedObject %s: %s", 
-                filespec, e.what());
-        return 0;
-    }
-
-#else
-    SOL sol;
-    log_security("Opening SharedObject file: %s", filespec);
-    if (sol.readFile(filespec) == false) {
-        log_security("empty or non-existing SOL file \"%s\", will be "
-                "created on flush/exit", filespec);
-        return false;
-    }
-    
-    std::vector<boost::shared_ptr<amf::Element> >::const_iterator it, e;
-    std::vector<boost::shared_ptr<amf::Element> > els = sol.getElements();
-    log_debug("Read %d AMF objects from %s", els.size(), filespec);
-
-    as_value as = getMember(NSV::PROP_DATA);
-    boost::intrusive_ptr<as_object> ptr = as.to_object();
-    
-    for (it = els.begin(), e = els.end(); it != e; it++) {
-        boost::shared_ptr<amf::Element> el = *it;
-
-#if 0 // this would be using as_value::as_value(const Element&)
-
-        std::string name(el->getName());
-        as_value val(*el);
-        ptr->set_member(st.find(name), val);
-
-#else // this is original code 
-
-        switch (el->getType())
-        {
-            case Element::NUMBER_AMF0:
-            {
-                double dub =  *(reinterpret_cast<double*>(el->getData()));
-                ptr->set_member(st.string_table::find(el->getName()),
-                        as_value(dub));
-                break;
-            }
-
-            case Element::BOOLEAN_AMF0:
-                ptr->set_member(st.string_table::find(el->getName()),
-                                            as_value(el->to_bool()));
-                break;
-
-            case Element::STRING_AMF0:
-            {
-                if (el->getLength() == 0) {
-                    ptr->set_member(st.string_table::find(el->getName()), "");
-                    break;
-                }
-                
-                std::string str(reinterpret_cast<const char*>(el->getData()),
-                        el->getLength());
-                ptr->set_member(st.string_table::find(el->getName()), str);
-                break;
-            }
-
-            case Element::OBJECT_AMF0:
-                // TODO: implement!
-                log_unimpl("Reading OBJECT type from SharedObject");
-                //data.convert_to_object();
-                //ptr->set_member(st.string_table::find(el->name), data);
-                return false;
-                break;
-
-            default:
-                // TODO: what about other types?
-                log_unimpl("Reading SOL type %d", el->getType());
-                return false;
-                break;
-        } 
-
-#endif
-
-    }
-
-    return true;
-#endif
-}
-
-
-void
-flushSOL(SharedObjectLibrary::SoLib::value_type& sol)
-{
-    sol.second->flush();
-}
-
-} // anonymous namespace
-} // end of gnash namespace

=== removed file 'libcore/asobj/SharedObject_as.h'
--- a/libcore/asobj/SharedObject_as.h   2009-01-22 20:10:39 +0000
+++ b/libcore/asobj/SharedObject_as.h   1970-01-01 00:00:00 +0000
@@ -1,84 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 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 3 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 GNASH_ASOBJ_SHAREDOBJECT_H
-#define GNASH_ASOBJ_SHAREDOBJECT_H
-
-#include <string>
-#include <map>
-
-// Forward declarations
-namespace gnash {
-    class as_object;
-    class SharedObject_as;
-    class VM;
-}
-
-namespace gnash {
-
-class SharedObjectLibrary
-{
-public:
-
-    typedef std::map<std::string, SharedObject_as*> SoLib;
-
-    SharedObjectLibrary(VM& vm);
-
-    ~SharedObjectLibrary();
-
-    /// Return a local shared object with given name and with given root
-    //
-    /// May return NULL if name is invalid or can't access the given root
-    ///
-    SharedObject_as* getLocal(const std::string& name, const std::string& 
root);
-
-    void markReachableResources() const;
-
-    // Drop all library items
-    void clear();
-
-private:
-
-    VM& _vm;
-
-    /// Domain component of the VM SWF url
-    std::string _baseDomain;
-
-    /// Path component of the VM SWF url
-    std::string _basePath;
-
-    /// Base SOL dir
-    std::string _solSafeDir; 
-
-    SoLib _soLib;
-};
-
-/// Initialize the global SharedObject class
-void sharedobject_class_init(as_object& global);
-
-void registerSharedObjectNative(as_object& o);
-
-  
-} // end of gnash namespace
-
-#endif
-
-// local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:

=== removed file 'libcore/asobj/Stage_as.cpp'
--- a/libcore/asobj/Stage_as.cpp        2009-03-02 12:12:43 +0000
+++ b/libcore/asobj/Stage_as.cpp        1970-01-01 00:00:00 +0000
@@ -1,301 +0,0 @@
-// Stage_as.cpp:  All the world is one, for Gnash.
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 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 3 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 "gnashconfig.h"
-#endif
-
-#include "Stage_as.h"
-#include "movie_root.h"
-#include "as_object.h" // for inheritance
-#include "log.h"
-#include "fn_call.h"
-#include "smart_ptr.h" // for boost intrusive_ptr
-#include "builtin_function.h" // need builtin_function
-#include "VM.h"
-#include "Object.h" // for getObjectInterface()
-#include "AsBroadcaster.h" // for initializing self as a broadcaster
-#include "namedStrings.h"
-#include "StringPredicates.h"
-
-#include <string>
-
-namespace gnash {
-
-static as_value stage_scalemode_getset(const fn_call& fn);
-static as_value stage_align_getset(const fn_call& fn);
-static as_value stage_showMenu_getset(const fn_call& fn);
-static as_value stage_width_getset(const fn_call& fn);
-static as_value stage_height_getset(const fn_call& fn);
-static as_value stage_displaystate_getset(const fn_call& fn);
-static const char* getScaleModeString(movie_root::ScaleMode sm);
-static const char* getDisplayStateString(movie_root::DisplayState ds);
-
-void registerStageNative(as_object& o)
-{
-       VM& vm = o.getVM();
-       
-       vm.registerNative(stage_scalemode_getset, 666, 1);
-    vm.registerNative(stage_scalemode_getset, 666, 2);
-    vm.registerNative(stage_align_getset, 666, 3);
-       vm.registerNative(stage_align_getset, 666, 4);
-       vm.registerNative(stage_width_getset, 666, 5);
-    vm.registerNative(stage_width_getset, 666, 6);
-       vm.registerNative(stage_height_getset, 666, 7);
-    vm.registerNative(stage_height_getset, 666, 8);
-       vm.registerNative(stage_showMenu_getset, 666, 9);
-    vm.registerNative(stage_showMenu_getset, 666, 10);
-}
-
-static void
-attachStageInterface(as_object& o)
-{
-    const int version = o.getVM().getSWFVersion();
-
-    if ( version < 5 ) return;
-
-    o.init_property("scaleMode", &stage_scalemode_getset, 
&stage_scalemode_getset);
-    o.init_property("align", &stage_align_getset, &stage_align_getset);
-    o.init_property("width", &stage_width_getset, &stage_width_getset);
-    o.init_property("height", &stage_height_getset, &stage_height_getset);
-    o.init_property("showMenu", &stage_showMenu_getset, 
&stage_showMenu_getset);
-    o.init_property("displayState", &stage_displaystate_getset, 
&stage_displaystate_getset);
-
-}
-
-
-Stage_as::Stage_as()
-       :
-       as_object(getObjectInterface())
-{
-       attachStageInterface(*this);
-
-       const int swfversion = _vm.getSWFVersion();
-       if ( swfversion > 5 )
-       {
-               AsBroadcaster::initialize(*this);
-       }
-}
-
-
-void
-Stage_as::notifyFullScreen(bool fs)
-{
-    // Should we notify resize here, or does movie_root do it anyway
-    // when the gui changes size?
-       log_debug("notifying Stage listeners about fullscreen state");
-       callMethod(NSV::PROP_BROADCAST_MESSAGE, "onFullScreen", fs);
-}
-
-
-void
-Stage_as::notifyResize()
-{
-       log_debug("notifying Stage listeners about a resize");
-       callMethod(NSV::PROP_BROADCAST_MESSAGE, "onResize");
-}
-
-
-const char*
-getDisplayStateString(movie_root::DisplayState ds)
-{
-       static const char* displayStateName[] = {
-               "normal",
-               "fullScreen" };
-
-       return displayStateName[ds];
-}
-
-
-const char*
-getScaleModeString(movie_root::ScaleMode sm)
-{
-       static const char* modeName[] = {
-               "showAll",
-               "noScale",
-               "exactFit",
-               "noBorder" };
-
-       return modeName[sm];
-}
-
-
-as_value
-stage_scalemode_getset(const fn_call& fn)
-{
-
-    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr);
-
-    movie_root& m = obj->getVM().getRoot();
-
-       if ( fn.nargs == 0 ) // getter
-       {
-               return as_value(getScaleModeString(m.getStageScaleMode()));
-       }
-       else // setter
-       {
-           // Defaults to showAll if the string is invalid.
-               movie_root::ScaleMode mode = movie_root::showAll;
-
-               const std::string& str = fn.arg(0).to_string();
-               
-               StringNoCaseEqual noCaseCompare;
-               
-               if ( noCaseCompare(str, "noScale") ) mode = movie_root::noScale;
-               else if ( noCaseCompare(str, "exactFit") ) mode = 
movie_root::exactFit;
-               else if ( noCaseCompare(str, "noBorder") ) mode = 
movie_root::noBorder;
-
-        if ( m.getStageScaleMode() == mode ) return as_value(); // nothing to 
do
-
-           m.setStageScaleMode(mode);
-               return as_value();
-       }
-}
-
-as_value
-stage_width_getset(const fn_call& fn)
-{
-    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr);
-
-       if ( fn.nargs > 0 ) // setter
-       {
-               IF_VERBOSE_ASCODING_ERRORS(
-                   log_aserror(_("Stage.width is a read-only property!"));
-               );
-               return as_value();
-       }
-
-    // getter
-    movie_root& m = obj->getVM().getRoot();
-    return as_value(m.getStageWidth());
-}
-
-as_value
-stage_height_getset(const fn_call& fn)
-{
-    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr);
-
-       if ( fn.nargs > 0 ) // setter
-       {
-               IF_VERBOSE_ASCODING_ERRORS(
-            log_aserror(_("Stage.height is a read-only property!"));
-               );
-               return as_value();
-       }
-
-    // getter
-    movie_root& m = obj->getVM().getRoot();
-    return as_value(m.getStageHeight());
-}
-
-
-as_value
-stage_align_getset(const fn_call& fn)
-{
-    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr); 
- 
-    movie_root& m = obj->getVM().getRoot();
-    
-       if ( fn.nargs == 0 ) // getter
-       {
-           return as_value (m.getStageAlignMode());
-       }
-       else // setter
-       {
-               const std::string& str = fn.arg(0).to_string();
-        short am = 0;
-
-        // Easy enough to do bitwise - std::bitset is not
-        // really necessary!
-        if (str.find_first_of("lL") != std::string::npos)
-        {
-            am |= 1 << movie_root::STAGE_ALIGN_L;
-        } 
-
-        if (str.find_first_of("tT") != std::string::npos)
-        {
-            am |= 1 << movie_root::STAGE_ALIGN_T;
-        } 
-
-        if (str.find_first_of("rR") != std::string::npos)
-        {
-            am |= 1 << movie_root::STAGE_ALIGN_R;
-        } 
-    
-        if (str.find_first_of("bB") != std::string::npos)
-        {
-            am |= 1 << movie_root::STAGE_ALIGN_B;
-        }
-
-        m.setStageAlignment(am);
-
-               return as_value();
-       }
-}
-
-as_value
-stage_showMenu_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<Stage_as> stage = 
ensureType<Stage_as>(fn.this_ptr);
-
-       if ( fn.nargs == 0 ) // getter
-       {
-               LOG_ONCE(log_unimpl("Stage.showMenu getter"));
-               return as_value();
-       }
-       else // setter
-       {
-               LOG_ONCE(log_unimpl("Stage.showMenu setter"));
-               return as_value();
-       }
-}
-
-as_value
-stage_displaystate_getset(const fn_call& fn)
-{
-    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr);
-
-    movie_root& m = obj->getVM().getRoot();
-
-       if (!fn.nargs) {
-               return getDisplayStateString(m.getStageDisplayState());
-       }
-
-    StringNoCaseEqual noCaseCompare;
-
-    const std::string& str = fn.arg(0).to_string();
-    if (noCaseCompare(str, "normal")) {
-        m.setStageDisplayState(movie_root::DISPLAYSTATE_NORMAL);
-    }
-    else if (noCaseCompare(str, "fullScreen")) {
-        m.setStageDisplayState(movie_root::DISPLAYSTATE_FULLSCREEN);
-    }
-
-    // If invalid, do nothing.
-    return as_value();
-}
-
-// extern (used by Global.cpp)
-void stage_class_init(as_object& global)
-{
-       static boost::intrusive_ptr<as_object> obj = new Stage_as();
-       global.init_member("Stage", obj.get());
-}
-
-} // end of gnash namespace

=== removed file 'libcore/asobj/Stage_as.h'
--- a/libcore/asobj/Stage_as.h  2009-03-02 12:12:43 +0000
+++ b/libcore/asobj/Stage_as.h  1970-01-01 00:00:00 +0000
@@ -1,69 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 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 3 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 GNASH_ASOBJ_STAGE_H
-#define GNASH_ASOBJ_STAGE_H
-
-#include "as_object.h" // for inheritance
-#include "movie_root.h" // for access to scaleMode
-
-#include <list>
-
-namespace gnash {
-
-/// This is the Stage ActionScript object.
-//
-/// Some Stage methods are implemented in movie_root, because
-/// it provides the interface to the Gui and/or all the values
-/// required are necessarily in movie_root:
-///
-/// - scaleMode
-/// - width
-/// - height
-/// - displayState
-/// - alignMode
-//
-/// Most functions are ASnative, which means they cannot rely on
-/// the existence of a load-on-demand Stage object. Only resize events
-/// appear to need this (not ASnative). The ASnative functions
-/// are available from SWF5
-
-class Stage_as: public as_object
-{
-
-public:
-    
-       Stage_as();
-       
-       /// Notify all listeners about a resize event
-       void notifyResize();
-       
-       void notifyFullScreen(bool fs);
-
-};
-
-/// Register native functions with the VM.
-void registerStageNative(as_object& o);
-
-/// Initialize the global Stage class
-void stage_class_init(as_object& global);
-  
-} // end of gnash namespace
-
-#endif
-

=== modified file 'libcore/asobj/flash.am'
--- a/libcore/asobj/flash.am    2009-06-09 11:38:31 +0000
+++ b/libcore/asobj/flash.am    2009-06-09 15:51:03 +0000
@@ -46,10 +46,8 @@
        asobj/Number_as.cpp \
        asobj/PlayHead.cpp \
        asobj/Selection_as.cpp \
-       asobj/SharedObject_as.cpp\
        asobj/Namespace_as.cpp \
        asobj/Sound_as.cpp \
-       asobj/Stage_as.cpp \
        asobj/System_as.cpp \
        asobj/TextFormat_as.cpp \
        asobj/MovieClipLoader.cpp\
@@ -79,9 +77,7 @@
        asobj/Number_as.h \
        asobj/PlayHead.h \
        asobj/Selection_as.h \
-       asobj/SharedObject_as.h \
        asobj/Sound_as.h \
-       asobj/Stage_as.h        \
        asobj/System_as.h \
        asobj/TextFormat_as.h \
        asobj/String_as.h \

=== modified file 'libcore/asobj/flash/display/Stage_as.cpp'
--- a/libcore/asobj/flash/display/Stage_as.cpp  2009-05-28 17:10:05 +0000
+++ b/libcore/asobj/flash/display/Stage_as.cpp  2009-06-09 15:51:03 +0000
@@ -28,8 +28,46 @@
 #include "builtin_function.h" // need builtin_function
 #include "GnashException.h" // for ActionException
 
+// ADDED
+#include "movie_root.h"
+#include "as_object.h" // for inheritance
+#include "VM.h"
+#include "Object.h" // for getObjectInterface()
+#include "AsBroadcaster.h" // for initializing self as a broadcaster
+#include "namedStrings.h"
+#include "StringPredicates.h"
+
+#include <string>
+// END ADDED SECTION
+
 namespace gnash {
 
+static as_value stage_scalemode_getset(const fn_call& fn);
+static as_value stage_align_getset(const fn_call& fn);
+static as_value stage_showMenu_getset(const fn_call& fn);
+static as_value stage_width_getset(const fn_call& fn);
+static as_value stage_height_getset(const fn_call& fn);
+static as_value stage_displaystate_getset(const fn_call& fn);
+static const char* getScaleModeString(movie_root::ScaleMode sm);
+static const char* getDisplayStateString(movie_root::DisplayState ds);
+       
+void registerStageNative(as_object& o)
+{
+       VM& vm = o.getVM();
+       
+       vm.registerNative(stage_scalemode_getset, 666, 1);
+    vm.registerNative(stage_scalemode_getset, 666, 2);
+    vm.registerNative(stage_align_getset, 666, 3);
+       vm.registerNative(stage_align_getset, 666, 4);
+       vm.registerNative(stage_width_getset, 666, 5);
+    vm.registerNative(stage_width_getset, 666, 6);
+       vm.registerNative(stage_height_getset, 666, 7);
+    vm.registerNative(stage_height_getset, 666, 8);
+       vm.registerNative(stage_showMenu_getset, 666, 9);
+    vm.registerNative(stage_showMenu_getset, 666, 10);
+}
+
+
 // Forward declarations
 namespace {
     as_value stage_addChildAt(const fn_call& fn);
@@ -49,19 +87,225 @@
     void attachStageInterface(as_object& o);
     void attachStageStaticInterface(as_object& o);
     as_object* getStageInterface();
-
-}
-
-class Stage_as : public as_object
-{
-
-public:
-
-    Stage_as()
-        :
-        as_object(getStageInterface())
-    {}
-};
+    
+// ADDED
+
+}
+
+Stage_as::Stage_as()
+       :
+       as_object(getObjectInterface())
+{
+       attachStageInterface(*this);
+
+       const int swfversion = _vm.getSWFVersion();
+       if ( swfversion > 5 )
+       {
+               AsBroadcaster::initialize(*this);
+       }
+}
+
+void
+Stage_as::notifyFullScreen(bool fs)
+{
+    // Should we notify resize here, or does movie_root do it anyway
+    // when the gui changes size?
+       log_debug("notifying Stage listeners about fullscreen state");
+       callMethod(NSV::PROP_BROADCAST_MESSAGE, "onFullScreen", fs);
+}
+
+
+void
+Stage_as::notifyResize()
+{
+       log_debug("notifying Stage listeners about a resize");
+       callMethod(NSV::PROP_BROADCAST_MESSAGE, "onResize");
+}
+
+// ADDED
+const char*
+getDisplayStateString(movie_root::DisplayState ds)
+{
+       static const char* displayStateName[] = {
+               "normal",
+               "fullScreen" };
+
+       return displayStateName[ds];
+}
+
+// ADDED
+const char*
+getScaleModeString(movie_root::ScaleMode sm)
+{
+       static const char* modeName[] = {
+               "showAll",
+               "noScale",
+               "exactFit",
+               "noBorder" };
+
+       return modeName[sm];
+}
+
+// ADDED
+as_value
+stage_scalemode_getset(const fn_call& fn)
+{
+
+    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr);
+
+    movie_root& m = obj->getVM().getRoot();
+
+       if ( fn.nargs == 0 ) // getter
+       {
+               return as_value(getScaleModeString(m.getStageScaleMode()));
+       }
+       else // setter
+       {
+           // Defaults to showAll if the string is invalid.
+               movie_root::ScaleMode mode = movie_root::showAll;
+
+               const std::string& str = fn.arg(0).to_string();
+               
+               StringNoCaseEqual noCaseCompare;
+               
+               if ( noCaseCompare(str, "noScale") ) mode = movie_root::noScale;
+               else if ( noCaseCompare(str, "exactFit") ) mode = 
movie_root::exactFit;
+               else if ( noCaseCompare(str, "noBorder") ) mode = 
movie_root::noBorder;
+
+        if ( m.getStageScaleMode() == mode ) return as_value(); // nothing to 
do
+
+           m.setStageScaleMode(mode);
+               return as_value();
+       }
+}
+
+
+// ADDED
+as_value
+stage_width_getset(const fn_call& fn)
+{
+    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr);
+
+       if ( fn.nargs > 0 ) // setter
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+                   log_aserror(_("Stage.width is a read-only property!"));
+               );
+               return as_value();
+       }
+
+    // getter
+    movie_root& m = obj->getVM().getRoot();
+    return as_value(m.getStageWidth());
+}
+
+// ADDED
+as_value
+stage_height_getset(const fn_call& fn)
+{
+    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr);
+
+       if ( fn.nargs > 0 ) // setter
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+            log_aserror(_("Stage.height is a read-only property!"));
+               );
+               return as_value();
+       }
+
+    // getter
+    movie_root& m = obj->getVM().getRoot();
+    return as_value(m.getStageHeight());
+}
+
+// ADDED
+as_value
+stage_align_getset(const fn_call& fn)
+{
+    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr); 
+ 
+    movie_root& m = obj->getVM().getRoot();
+    
+       if ( fn.nargs == 0 ) // getter
+       {
+           return as_value (m.getStageAlignMode());
+       }
+       else // setter
+       {
+               const std::string& str = fn.arg(0).to_string();
+        short am = 0;
+
+        // Easy enough to do bitwise - std::bitset is not
+        // really necessary!
+        if (str.find_first_of("lL") != std::string::npos)
+        {
+            am |= 1 << movie_root::STAGE_ALIGN_L;
+        } 
+
+        if (str.find_first_of("tT") != std::string::npos)
+        {
+            am |= 1 << movie_root::STAGE_ALIGN_T;
+        } 
+
+        if (str.find_first_of("rR") != std::string::npos)
+        {
+            am |= 1 << movie_root::STAGE_ALIGN_R;
+        } 
+    
+        if (str.find_first_of("bB") != std::string::npos)
+        {
+            am |= 1 << movie_root::STAGE_ALIGN_B;
+        }
+
+        m.setStageAlignment(am);
+
+               return as_value();
+       }
+}
+
+// ADDED
+as_value
+stage_showMenu_getset(const fn_call& fn)
+{
+       boost::intrusive_ptr<Stage_as> stage = 
ensureType<Stage_as>(fn.this_ptr);
+
+       if ( fn.nargs == 0 ) // getter
+       {
+               LOG_ONCE(log_unimpl("Stage.showMenu getter"));
+               return as_value();
+       }
+       else // setter
+       {
+               LOG_ONCE(log_unimpl("Stage.showMenu setter"));
+               return as_value();
+       }
+}
+
+// ADDED
+as_value
+stage_displaystate_getset(const fn_call& fn)
+{
+    boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr);
+
+    movie_root& m = obj->getVM().getRoot();
+
+       if (!fn.nargs) {
+               return getDisplayStateString(m.getStageDisplayState());
+       }
+
+    StringNoCaseEqual noCaseCompare;
+
+    const std::string& str = fn.arg(0).to_string();
+    if (noCaseCompare(str, "normal")) {
+        m.setStageDisplayState(movie_root::DISPLAYSTATE_NORMAL);
+    }
+    else if (noCaseCompare(str, "fullScreen")) {
+        m.setStageDisplayState(movie_root::DISPLAYSTATE_FULLSCREEN);
+    }
+
+    // If invalid, do nothing.
+    return as_value();
+}
 
 // extern (used by Global.cpp)
 void stage_class_init(as_object& global)
@@ -82,6 +326,18 @@
 void
 attachStageInterface(as_object& o)
 {
+       const int version = o.getVM().getSWFVersion();
+
+    if ( version < 5 ) return;
+
+    o.init_property("scaleMode", &stage_scalemode_getset, 
&stage_scalemode_getset);
+    o.init_property("align", &stage_align_getset, &stage_align_getset);
+    o.init_property("width", &stage_width_getset, &stage_width_getset);
+    o.init_property("height", &stage_height_getset, &stage_height_getset);
+    o.init_property("showMenu", &stage_showMenu_getset, 
&stage_showMenu_getset);
+    o.init_property("displayState", &stage_displaystate_getset, 
&stage_displaystate_getset);
+
+
     o.init_member("addChildAt", new builtin_function(stage_addChildAt));
     o.init_member("addEventListener", new 
builtin_function(stage_addEventListener));
     o.init_member("dispatchEvent", new builtin_function(stage_dispatchEvent));

=== modified file 'libcore/asobj/flash/display/Stage_as.h'
--- a/libcore/asobj/flash/display/Stage_as.h    2009-05-28 17:29:17 +0000
+++ b/libcore/asobj/flash/display/Stage_as.h    2009-06-08 21:22:11 +0000
@@ -24,15 +24,55 @@
 #include "gnashconfig.h"
 #endif
 
+// ADDED
+#include "as_object.h" // for inheritance
+#include "movie_root.h" // for access to scaleMode
+
+#include <list>
 
 // Forward declarations
 class as_object;
 
 namespace gnash {
+       
+// ADDED
+/// This is the Stage ActionScript object.
+//
+/// Some Stage methods are implemented in movie_root, because
+/// it provides the interface to the Gui and/or all the values
+/// required are necessarily in movie_root:
+///
+/// - scaleMode
+/// - width
+/// - height
+/// - displayState
+/// - alignMode
+//
+/// Most functions are ASnative, which means they cannot rely on
+/// the existence of a load-on-demand Stage object. Only resize events
+/// appear to need this (not ASnative). The ASnative functions
+/// are available from SWF5
+
+class Stage_as: public as_object
+{
+
+public:
+    
+       Stage_as();
+       
+       /// Notify all listeners about a resize event
+       void notifyResize();
+       
+       void notifyFullScreen(bool fs);
+
+};
 
 /// Initialize the global Stage class
 void stage_class_init(as_object& global);
 
+// ADDED
+void registerStageNative(as_object& o);
+
 } // gnash namespace
 
 // GNASH_ASOBJ3_STAGE_H

=== modified file 'libcore/asobj/flash/display/display.am'
--- a/libcore/asobj/flash/display/display.am    2009-06-07 18:12:15 +0000
+++ b/libcore/asobj/flash/display/display.am    2009-06-08 21:22:11 +0000
@@ -184,10 +184,10 @@
 endif
 
 # FIXME: already exists
-# if BUILD_STAGE_AS3
-# DISPLAY_SOURCES += asobj/flash/display/Stage_as.cpp
+if BUILD_STAGE_AS3
+DISPLAY_SOURCES += asobj/flash/display/Stage_as.cpp
 DISPLAY_HEADERS += asobj/flash/display/Stage_as.h
-# endif
+endif
 
 libgnashasobjs_la_SOURCES += $(DISPLAY_SOURCES) $(DISPLAY_SOURCES_AS2)
 noinst_HEADERS +=  $(DISPLAY_HEADERS) $(DISPLAY_HEADERS_AS2) \

=== modified file 'libcore/asobj/flash/net/SharedObject_as.cpp'
--- a/libcore/asobj/flash/net/SharedObject_as.cpp       2009-05-28 17:12:46 
+0000
+++ b/libcore/asobj/flash/net/SharedObject_as.cpp       2009-06-08 21:22:11 
+0000
@@ -21,48 +21,600 @@
 #include "gnashconfig.h"
 #endif
 
-#include "net/SharedObject_as.h"
+#include "flash/net/SharedObject_as.h"
 #include "log.h"
 #include "fn_call.h"
 #include "smart_ptr.h" // for boost intrusive_ptr
 #include "builtin_function.h" // need builtin_function
 #include "GnashException.h" // for ActionException
 
+// ADDED
+#include "GnashSystemNetHeaders.h"
+#include "GnashFileUtilities.h" // stat
+#include "SimpleBuffer.h"
+#include "as_value.h"
+#include "amf.h"
+#include "element.h"
+#include "sol.h"
+#include "movie_root.h"
+#include "as_object.h" // for inheritance
+#include "Object.h" // for getObjectInterface
+#include "VM.h"
+#include "Property.h"
+#include "string_table.h"
+#include "URLAccessManager.h"
+#include "URL.h"
+#include "rc.h" // for use of rcfile
+
+#include <boost/tokenizer.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/shared_ptr.hpp>
+
+// Undefine this to use the Element-based AMF0 decoder/encoder.
+// May be useful to test libamf.
+#define BUFFERED_AMF_SOL
+
+namespace {
+gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
+}
+
+using namespace amf;
+
 namespace gnash {
 
 // Forward declarations
 namespace {
-    as_value sharedobject_close(const fn_call& fn);
-    as_value sharedobject_connect(const fn_call& fn);
-    as_value sharedobject_flush(const fn_call& fn);
-    as_value sharedobject_getLocal(const fn_call& fn);
-    as_value sharedobject_getRemote(const fn_call& fn);
-    as_value sharedobject_send(const fn_call& fn);
-    as_value sharedobject_setDirty(const fn_call& fn);
-    as_value sharedobject_setProperty(const fn_call& fn);
-    as_value sharedobject_asyncError(const fn_call& fn);
-    as_value sharedobject_netStatus(const fn_call& fn);
-    as_value sharedobject_sync(const fn_call& fn);
-    as_value sharedobject_ctor(const fn_call& fn);
-    void attachSharedObjectInterface(as_object& o);
-    void attachSharedObjectStaticInterface(as_object& o);
+           as_value sharedobject_close(const fn_call& fn);
+           as_value sharedobject_connect(const fn_call& fn);
+           as_value sharedobject_flush(const fn_call& fn);
+           as_value sharedobject_getLocal(const fn_call& fn);
+           as_value sharedobject_getRemote(const fn_call& fn);
+           as_value sharedobject_send(const fn_call& fn);
+           as_value sharedobject_setDirty(const fn_call& fn);
+           as_value sharedobject_setProperty(const fn_call& fn);
+           as_value sharedobject_asyncError(const fn_call& fn);
+           as_value sharedobject_netStatus(const fn_call& fn);
+           as_value sharedobject_sync(const fn_call& fn);
+           as_value sharedobject_ctor(const fn_call& fn);
+           void attachSharedObjectInterface(as_object& o);
+           void attachSharedObjectStaticInterface(as_object& o);
     as_object* getSharedObjectInterface();
 
+       // ADDED
+               as_value sharedobject_getsize(const fn_call& fn);
+           as_value sharedobject_setFps(const fn_call& fn);
+           as_value sharedobject_clear(const fn_call& fn);
+           as_value sharedobject_deleteAll(const fn_call& fn);
+           as_value sharedobject_getDiskUsage(const fn_call& fn);
+           as_value sharedobject_data(const fn_call& fn);
+    
+               as_object* readSOL(VM& vm, const std::string& filespec);
+
+           as_object* getSharedObjectInterface();
+           void flushSOL(SharedObjectLibrary::SoLib::value_type& sol);
+           bool validateName(const std::string& solName);
+    
+       
 }
 
-class SharedObject_as : public as_object
-{
-
-public:
+// ADDED
+// Serializer helper
+class PropsSerializer : public AbstractPropertyVisitor
+{
+public:
+
+    PropsSerializer(SOL& sol, VM& vm)
+        :
+        _sol(sol),
+        _st(vm.getStringTable())
+    {};
+
+    void accept(string_table::key key, const as_value& val) 
+    {
+        AMF amf;
+        boost::shared_ptr<amf::Element> el;
+        
+        const std::string& name = _st.string_table::value(key);
+
+        //log_debug("Serializing SharedObject property %s:%s", name, val);
+
+        if (val.is_string()) {
+            std::string str;
+            if (!val.is_undefined()) {
+                str = val.to_string();
+            }
+            el.reset(new amf::Element(name, str));
+        }
+        if (val.is_bool()) {
+            bool flag = val.to_bool();
+            el.reset(new amf::Element(name, flag));
+        }
+        if (val.is_number()) { 
+            double dub;
+            if (val.is_undefined()) {
+                dub = 0.0;
+            } else {
+                dub = val.to_number();
+            }
+            el.reset(new amf::Element(name, dub));
+        }
+
+        if (el) {
+            _sol.addObj(el);
+        }
+    }
+
+private:
+
+    SOL& _sol;
+    string_table& _st;
+};
+
+/// Class used to serialize properties of an object to a buffer in SOL format
+class SOLPropsBufSerializer : public AbstractPropertyVisitor
+{
+
+    typedef std::map<as_object*, size_t> PropertiesOffsetTable;
+
+public:
+
+    SOLPropsBufSerializer(SimpleBuffer& buf, VM& vm,
+            PropertiesOffsetTable& offsetTable)
+        :
+        _buf(buf),
+        _vm(vm),
+        _st(vm.getStringTable()),
+        _offsetTable(offsetTable),
+        _error(false)
+       {};
+    
+    bool success() const { return !_error; }
+
+    virtual void accept(string_table::key key, const as_value& val) 
+    {
+        if ( _error ) return;
+
+        if ( val.is_function() )
+        {
+            log_debug("SOL: skip serialization of FUNCTION property");
+            return;
+        }
+
+        // Test conducted with AMFPHP:
+        // '__proto__' and 'constructor' members
+        // of an object don't get back from an 'echo-service'.
+        // Dunno if they are not serialized or just not sent back.
+        // A '__constructor__' member gets back, but only if 
+        // not a function. Actually no function gets back.
+        // 
+        if ( key == NSV::PROP_uuPROTOuu || key == NSV::PROP_CONSTRUCTOR )
+        {
+#ifdef GNASH_DEBUG_AMF_SERIALIZE
+            log_debug(" skip serialization of specially-named property %s",
+                    _st.value(key));
+#endif
+            return;
+        }
+
+        // write property name
+        const std::string& name = _st.value(key);
+#ifdef GNASH_DEBUG_AMF_SERIALIZE
+        log_debug(" serializing property %s", name);
+#endif
+        boost::uint16_t namelen = name.size();
+        _buf.appendNetworkShort(namelen);
+        _buf.append(name.c_str(), namelen);
+        // Strict array are never encoded in SharedObject
+        if ( ! val.writeAMF0(_buf, _offsetTable, _vm, false) )
+        {
+            log_error("Problems serializing an object's member %s=%s",
+                    name, val);
+            _error = true;
+        }
+
+        _buf.appendByte(0); // SOL-specific
+    }
+
+private:
+
+    SimpleBuffer& _buf;
+
+    VM& _vm;
+
+    string_table& _st;
+
+    PropertiesOffsetTable& _offsetTable;
+
+    bool _error;
+};
+
+// MODIFIED
+class SharedObject_as: public as_object 
+{
+public:
+
+    ~SharedObject_as();
 
     SharedObject_as()
         :
-        as_object(getSharedObjectInterface())
-    {}
+        as_object(getSharedObjectInterface()),
+        _data(0)
+    { 
+    }
+
+    bool flush(int space = 0) const;
+
+    const std::string& getFilespec() const {
+        return _sol.getFilespec();
+    }
+
+    void setFilespec(const std::string& s) {
+        _sol.setFilespec(s);
+    }
+
+    const std::string& getObjectName() const {
+        return _sol.getObjectName();
+    }
+
+    void setObjectName(const std::string& s) {
+        _sol.setObjectName(s);
+    }
+
+    /// This isn't correct, as the default implementation doesn't use SOL
+    /// for reading.
+    size_t size() const { 
+        return _sol.fileSize(); 
+    }
+
+    void setData(as_object* data) {
+
+        assert(data);
+        _data = data;
+
+        const int flags = as_prop_flags::dontDelete |
+                          as_prop_flags::readOnly;
+
+        init_property(NSV::PROP_DATA, &sharedobject_data, &sharedobject_data,
+                flags);
+
+    }
+
+    as_object* data() {
+        return _data;
+    }
+
+    const as_object* data() const {
+        return _data;
+    }
+
+protected:
+
+    void markReachableResources() const {
+        if (_data) _data->setReachable();
+    }
+
+private:
+
+    as_object* _data;
+
+    SOL _sol;
 };
 
+SharedObject_as::~SharedObject_as()
+{
+}
+
+bool
+SharedObject_as::flush(int space) const
+{
+
+    /// This is called on on destruction of the SharedObject, or (allegedly)
+    /// on a call to SharedObject.data, so _data is not guaranteed to exist.
+    //
+    /// The function should never be called from SharedObject.flush() when
+    /// _data is 0.
+    if (!_data) return false;
+
+    if (space > 0) {
+        log_unimpl("SharedObject.flush() called with a minimum disk space "
+                "argument (%d), which is currently ignored", space);
+    }
+
+    const std::string& filespec = _sol.getFilespec();
+
+    if (!mkdirRecursive(filespec))
+    {
+        log_error("Couldn't create dir for flushing SharedObject %s", 
filespec);
+        return false;
+    }
+
+#ifdef USE_SOL_READONLY
+    log_debug(_("SharedObject %s not flushed (compiled as read-only mode)"),
+            filespec);
+    return false;
+#endif
+
+    if (rcfile.getSOLReadOnly() ) {
+        log_security("Attempting to write object %s when it's SOL "
+                "Read Only is set! Refusing...", filespec);
+        return false;
+    }
+    
+#ifdef BUFFERED_AMF_SOL
+
+    gnash::SimpleBuffer buf;
+    // see http://osflash.org/documentation/amf/envelopes/sharedobject
+
+    // length field filled in later
+    buf.append("\x00\xbf\x00\x00\x00\x00TCSO\x00\x04\x00\x00\x00\x00", 16); 
+
+    // append object name
+    std::string object_name = getObjectName();
+    boost::uint16_t len = object_name.length();
+    buf.appendNetworkShort(len);
+    buf.append(object_name.c_str(), len);
+
+    // append padding
+    buf.append("\x00\x00\x00\x00", 4);
+
+    // append properties of object
+    VM& vm = getVM();
+
+    std::map<as_object*, size_t> offsetTable;
+    SOLPropsBufSerializer props(buf, vm, offsetTable);
+    _data->visitPropertyValues(props);
+    if ( ! props.success() ) 
+    {
+        log_error("Could not serialize object");
+        return false;
+    }
+
+    // fix length field
+    *(reinterpret_cast<uint32_t*>(buf.data() + 2)) = htonl(buf.size() - 6);
+    
+    // TODO write file
+    std::ofstream ofs(filespec.c_str(), std::ios::binary);
+    if (!ofs) {
+        log_error("SharedObject::flush(): Failed opening file '%s' in "
+                "binary mode", filespec.c_str());
+        return false;
+    }
+    
+    if (ofs.write(reinterpret_cast<const char*>(buf.data()), 
buf.size()).fail())
+    {
+        log_error("Error writing %d bytes to output file %s",
+                buf.size(), filespec.c_str());
+        ofs.close();
+        return false;
+    }
+    ofs.close();
+
+#else // amf::SOL-based serialization
+
+    // append properties of object
+    VM& vm = getVM();
+
+    SOL sol;
+    PropsSerializer props(sol, vm);
+    _data->visitPropertyValues(props);
+    // We only want to access files in this directory
+    bool ret = sol.writeFile(filespec, getObjectName().c_str());
+    if ( ! ret )
+    {
+        log_error("writing SharedObject file to %s", filespec);
+        return false;
+    }
+#endif
+
+    log_security("SharedObject '%s' written to filesystem.", filespec);
+    return true;
+}
+
+SharedObjectLibrary::SharedObjectLibrary(VM& vm)
+    :
+    _vm(vm)
+{
+    _solSafeDir = rcfile.getSOLSafeDir();
+    if (_solSafeDir.empty()) {
+        log_debug("Empty SOLSafeDir directive: we'll use '/tmp'");
+        _solSafeDir = "/tmp/";
+    }
+
+    // Check if the base dir exists here
+    struct stat statbuf;
+    if ( -1 == stat(_solSafeDir.c_str(), &statbuf) )
+    {
+       log_debug("Invalid SOL safe dir %s: %s. Will try to create on "
+               "flush/exit.", _solSafeDir, std::strerror(errno));
+    }
+
+    // Which URL we should use here is under research.
+    // The reference player uses the URL from which definition
+    // of the call to SharedObject.getLocal was parsed.
+    //
+    // There is in Gnash support for tracking action_buffer 
+    // urls but not yet an interface to fetch it from fn_call;
+    // also, it's not clear how good would the model be (think
+    // of movie A loading movie B creating the SharedObject).
+    //
+    // What we'll do for now is use the URL of the initially
+    // loaded SWF, so that in the A loads B scenario above the
+    // domain would be the one of A, not B.
+    //
+    // NOTE: using the base url RunInfo::baseURL() would mean
+    // blindly trusting the SWF publisher as base url is changed
+    // by the 'base' attribute of OBJECT or EMBED tags trough
+    // -P base=xxx
+    //
+    const movie_root& mr = _vm.getRoot();
+    const std::string& swfURL = mr.getOriginalURL();
+
+    URL url(swfURL);
+
+    // Remember the hostname of our SWF URL. This can be empty if loaded
+    // from the filesystem
+    _baseDomain = url.hostname();
+
+    const std::string& urlPath = url.path();
+
+    // Get the path part. If loaded from the filesystem, the pp stupidly
+    // removes the first directory.
+    if (!_baseDomain.empty()) {
+        _basePath = urlPath;
+    }
+    else if (!urlPath.empty()) {
+        // _basePath should be empty if there are no slashes or just one.
+        std::string::size_type pos = urlPath.find('/', 1);
+        if (pos != std::string::npos) {
+            _basePath = urlPath.substr(pos);
+        }
+    }
+
+}
+
+void
+SharedObjectLibrary::markReachableResources() const
+{
+    for (SoLib::const_iterator it = _soLib.begin(), itE = _soLib.end();
+            it != itE; ++it)
+    {
+        SharedObject_as* sh = it->second;
+        sh->setReachable();
+    }
+}
+
+/// The SharedObjectLibrary keeps all known SharedObjects alive. They must
+/// be flushed on clear(). This is called at the latest by the dtor, which
+/// is called at the latest by VM's dtor (currently earlier to avoid problems
+/// with the GC).
+void
+SharedObjectLibrary::clear()
+{
+    std::for_each(_soLib.begin(), _soLib.end(), &flushSOL);
+    _soLib.clear();
+}
+
+SharedObjectLibrary::~SharedObjectLibrary()
+{
+    clear();
+}
+
+SharedObject_as*
+SharedObjectLibrary::getLocal(const std::string& objName,
+        const std::string& root)
+{
+    assert (!objName.empty());
+
+    // already warned about it at construction time
+    if (_solSafeDir.empty()) return 0;
+
+    if (rcfile.getSOLLocalDomain() && !_baseDomain.empty()) 
+    {
+        log_security("Attempting to open SOL file from non "
+                "localhost-loaded SWF");
+        return 0;
+    }
+
+    // Check that the name is valid; if not, return null
+    if (!validateName(objName)) return 0;
+
+    // The 'root' argument, otherwise known as localPath, specifies where
+    // in the SWF path the SOL should be stored. It cannot be outside this
+    // path.
+    std::string requestedPath;
+
+    // If a root is specified, check it first for validity
+    if (!root.empty()) {
+
+        const movie_root& mr = _vm.getRoot();
+        const std::string& swfURL = mr.getOriginalURL();
+        // The specified root may or may not have a domain. If it doesn't,
+        // this constructor will add the SWF's domain.
+        URL localPath(root, swfURL);
+        
+        StringNoCaseEqual noCaseCompare;
+
+        // All we care about is whether the domains match. They may be 
+        // empty filesystem-loaded.
+        if (!noCaseCompare(localPath.hostname(), _baseDomain)) {
+            log_security(_("SharedObject path %s is outside the SWF domain "
+                        "%s. Cannot access this object."), localPath, 
+                        _baseDomain);
+            return 0;
+        }
+
+        requestedPath = localPath.path();
+
+        // The domains match. Now check that the path is a sub-path of 
+        // the SWF's URL. It is done by case-insensitive string comparison,
+        // so a double slash in the requested path will fail.
+        if (!noCaseCompare(requestedPath,
+                    _basePath.substr(0, requestedPath.size()))) {
+            log_security(_("SharedObject path %s is not part of the SWF path "
+                        "%s. Cannot access this object."), requestedPath, 
+                        _basePath);
+            return 0;
+        }
+
+    }
+
+    // A leading slash is added later
+    std::ostringstream solPath;
+
+    // If the domain name is empty, the SWF was loaded from the filesystem.
+    // Use "localhost".
+    solPath << (_baseDomain.empty() ? "localhost" : _baseDomain);
+
+    // Paths should start with a '/', so we shouldn't have to add another
+    // one.
+    assert(requestedPath.empty() ? _basePath[0] == '/' :
+                                    requestedPath[0] == '/');
+
+    // If no path was requested, use the SWF's path.
+    solPath << (requestedPath.empty() ? _basePath : requestedPath) << "/"
+            << objName;
+
+    // TODO: normalize key!
+
+    const std::string& key = solPath.str();
+
+    // If the shared object was already opened, use it.
+    SoLib::iterator it = _soLib.find(key);
+    if ( it != _soLib.end() )
+    {
+        log_debug("SharedObject %s already known, returning it", key);
+        return it->second;
+    }
+
+    log_debug("SharedObject %s not loaded. Loading it now", key);
+
+    // Otherwise create a new one and register to the lib
+    SharedObject_as* obj = new SharedObject_as;
+    _soLib[key] = obj;
+
+    obj->setObjectName(objName);
+
+    std::string newspec = _solSafeDir;
+    newspec += "/";
+    newspec += key;
+    newspec += ".sol";
+    obj->setFilespec(newspec);
+
+    log_debug("SharedObject path: %s", newspec);
+        
+    boost::intrusive_ptr<as_object> data = readSOL(_vm, newspec);
+
+    /// Don't set to 0, or it will initialize a property.
+    if (data) obj->setData(data.get());
+
+    return obj;
+}
+
+
+// UNCHANGED
 // extern (used by Global.cpp)
-void sharedobject_class_init(as_object& global)
+void 
+sharedobject_class_init(as_object& global)
 {
     static boost::intrusive_ptr<builtin_function> cl;
 
@@ -80,25 +632,60 @@
 void
 attachSharedObjectInterface(as_object& o)
 {
-    o.init_member("close", new builtin_function(sharedobject_close));
-    o.init_member("connect", new builtin_function(sharedobject_connect));
-    o.init_member("flush", new builtin_function(sharedobject_flush));
-    o.init_member("getLocal", new builtin_function(sharedobject_getLocal));
-    o.init_member("getRemote", new builtin_function(sharedobject_getRemote));
-    o.init_member("send", new builtin_function(sharedobject_send));
-    o.init_member("setDirty", new builtin_function(sharedobject_setDirty));
-    o.init_member("setProperty", new 
builtin_function(sharedobject_setProperty));
-    o.init_member("asyncError", new builtin_function(sharedobject_asyncError));
-    o.init_member("netStatus", new builtin_function(sharedobject_netStatus));
-    o.init_member("sync", new builtin_function(sharedobject_sync));
+       //VM& vm = o.getVM();
+
+       o.init_member("close", new builtin_function(sharedobject_close));
+       o.init_member("connect", new builtin_function(sharedobject_connect));
+       o.init_member("flush", new builtin_function(sharedobject_flush));
+       o.init_member("getLocal", new builtin_function(sharedobject_getLocal));
+       o.init_member("getRemote", new 
builtin_function(sharedobject_getRemote));
+       o.init_member("send", new builtin_function(sharedobject_send));
+       o.init_member("setDirty", new builtin_function(sharedobject_setDirty));
+       o.init_member("setProperty", new 
builtin_function(sharedobject_setProperty));
+       o.init_member("asyncError", new 
builtin_function(sharedobject_asyncError));
+       o.init_member("netStatus", new 
builtin_function(sharedobject_netStatus));
+       o.init_member("sync", new builtin_function(sharedobject_sync));
+       
+       // ADDED
+       o.init_member("getSize", new builtin_function(sharedobject_getsize));
+    o.init_member("setFps", new builtin_function(sharedobject_setFps));
+    o.init_member("clear", new builtin_function(sharedobject_clear));
+
 }
 
 void
 attachSharedObjectStaticInterface(as_object& o)
 {
-
-}
-
+       // MODIFIED
+       VM& vm = o.getVM();
+
+    const int flags = 0;
+
+    o.init_member("getLocal", 
+            new builtin_function(sharedobject_getLocal), flags);
+    o.init_member("getRemote",
+            new builtin_function(sharedobject_getRemote), flags);
+
+    const int hiddenOnly = as_prop_flags::dontEnum;
+
+    o.init_member("deleteAll",  vm.getNative(2106, 206), hiddenOnly);
+    o.init_member("getDiskUsage",  vm.getNative(2106, 207), hiddenOnly);
+}
+
+// ADDED
+as_value
+sharedobject_clear(const fn_call& fn)
+{
+    boost::intrusive_ptr<SharedObject_as> obj = 
+        ensureType<SharedObject_as>(fn.this_ptr);
+    UNUSED(obj);
+    
+    LOG_ONCE(log_unimpl (__FUNCTION__));
+
+    return as_value();
+}
+
+// UNCHANGED
 as_object*
 getSharedObjectInterface()
 {
@@ -110,6 +697,7 @@
     return o.get();
 }
 
+// UNCHANGED
 as_value
 sharedobject_close(const fn_call& fn)
 {
@@ -120,6 +708,7 @@
     return as_value();
 }
 
+// UNCHANGED
 as_value
 sharedobject_connect(const fn_call& fn)
 {
@@ -130,26 +719,76 @@
     return as_value();
 }
 
+// MODIFIED
 as_value
 sharedobject_flush(const fn_call& fn)
 {
-    boost::intrusive_ptr<SharedObject_as> ptr =
+    GNASH_REPORT_FUNCTION;
+
+    boost::intrusive_ptr<SharedObject_as> obj =
         ensureType<SharedObject_as>(fn.this_ptr);
-    UNUSED(ptr);
-    log_unimpl (__FUNCTION__);
-    return as_value();
+
+    IF_VERBOSE_ASCODING_ERRORS(
+        if (fn.nargs > 1)
+        {
+            std::ostringstream ss;
+            fn.dump_args(ss);
+            log_aserror(_("Arguments to SharedObject.flush(%s) will be "
+                    "ignored"), ss.str());
+        }
+    );
+
+    int space = 0;
+    if (fn.nargs) {
+        space = fn.arg(0).to_int();
+    }
+
+    /// If there is no data member, returns undefined.
+    if (!obj->data()) return as_value();
+
+    // If there is an object data member, returns the success of flush().
+    return as_value(obj->flush(space));
 }
 
+// MODIFIED
 as_value
 sharedobject_getLocal(const fn_call& fn)
 {
-    boost::intrusive_ptr<SharedObject_as> ptr =
-        ensureType<SharedObject_as>(fn.this_ptr);
-    UNUSED(ptr);
-    log_unimpl (__FUNCTION__);
-    return as_value();
+    VM& vm = fn.env().getVM();
+    int swfVersion = vm.getSWFVersion();
+
+    as_value objNameVal;
+    if (fn.nargs > 0) objNameVal = fn.arg(0);
+    std::string objName = objNameVal.to_string_versioned(swfVersion);
+    if ( objName.empty() )
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+            std::ostringstream ss;
+            fn.dump_args(ss);
+            log_aserror("SharedObject.getLocal(%s): %s", 
+                _("missing object name"));
+        );
+        as_value ret;
+        ret.set_null();
+        return ret;
+    }
+
+    std::string root;
+    if (fn.nargs > 1)
+    {
+        root = fn.arg(1).to_string_versioned(swfVersion);
+    }
+
+    log_debug("SO name:%s, root:%s", objName, root);
+
+    SharedObject_as* obj = vm.getSharedObjectLibrary().getLocal(objName, root);
+
+    as_value ret(obj);
+    log_debug("SharedObject.getLocal returning %s", ret);
+    return ret;
 }
 
+// UNCHANGED
 as_value
 sharedobject_getRemote(const fn_call& fn)
 {
@@ -160,6 +799,7 @@
     return as_value();
 }
 
+// UNCHANGED
 as_value
 sharedobject_send(const fn_call& fn)
 {
@@ -170,6 +810,7 @@
     return as_value();
 }
 
+// UNCHANGED
 as_value
 sharedobject_setDirty(const fn_call& fn)
 {
@@ -180,6 +821,7 @@
     return as_value();
 }
 
+// UNCHANGED
 as_value
 sharedobject_setProperty(const fn_call& fn)
 {
@@ -190,6 +832,7 @@
     return as_value();
 }
 
+// UNCHANGED
 as_value
 sharedobject_asyncError(const fn_call& fn)
 {
@@ -200,6 +843,7 @@
     return as_value();
 }
 
+// UNCHANGED
 as_value
 sharedobject_netStatus(const fn_call& fn)
 {
@@ -210,6 +854,7 @@
     return as_value();
 }
 
+// UNCHANGED
 as_value
 sharedobject_sync(const fn_call& fn)
 {
@@ -220,6 +865,7 @@
     return as_value();
 }
 
+// UNCHANGED
 as_value
 sharedobject_ctor(const fn_call& fn)
 {
@@ -228,7 +874,304 @@
     return as_value(obj.get()); // will keep alive
 }
 
+// ADDED
+/// Undocumented
+/// Takes a URL argument and deletes all SharedObjects under that URL.
+as_value
+sharedobject_deleteAll(const fn_call& fn)
+{
+    boost::intrusive_ptr<SharedObject_as> obj =
+        ensureType<SharedObject_as>(fn.this_ptr);
+
+    UNUSED(obj);
+
+    LOG_ONCE(log_unimpl("SharedObject.deleteAll()"));
+    return as_value();
+}
+
+// ADDED
+/// Undocumented
+/// Should be quite obvious what it does.
+as_value
+sharedobject_getDiskUsage(const fn_call& fn)
+{
+    boost::intrusive_ptr<SharedObject_as> obj =
+        ensureType<SharedObject_as>(fn.this_ptr);
+
+    UNUSED(obj);
+
+    LOG_ONCE(log_unimpl("SharedObject.getDiskUsage()"));
+    return as_value();
+}
+
+// ADDED
+as_value
+sharedobject_data(const fn_call& fn)
+{
+    boost::intrusive_ptr<SharedObject_as> obj =
+        ensureType<SharedObject_as>(fn.this_ptr);
+    return as_value(obj->data());
+}
+
+// ADDED
+as_value
+sharedobject_getsize(const fn_call& fn)
+{
+    boost::intrusive_ptr<SharedObject_as> obj =
+        ensureType<SharedObject_as>(fn.this_ptr);
+    return as_value(obj->size());
+}
+
+// ADDED
+as_value
+sharedobject_setFps(const fn_call& fn)
+{
+    boost::intrusive_ptr<SharedObject_as> obj =
+        ensureType<SharedObject_as>(fn.this_ptr);
+    UNUSED(obj);
+
+    LOG_ONCE(log_unimpl("SharedObject.setFps"));
+    return as_value();
+}
+
+// ADDED
+as_object*
+readSOL(VM& vm, const std::string& filespec)
+{
+
+#ifdef BUFFERED_AMF_SOL
+
+    // The 'data' member is initialized only on getLocal() (and probably
+    // getRemote()): i.e. when there is some data, or when it's ready to
+    // be added.
+    as_object* data = new as_object(getObjectInterface());
+
+    struct stat st;
+
+    if (stat(filespec.c_str(), &st) != 0)
+    {
+        // No existing SOL file. A new one will be created.
+        log_debug("No existing SOL %s found. Will create on flush/exit.",
+                filespec);
+        return data;
+    }
+
+    if (st.st_size < 28)
+    {
+        // A SOL file exists, but it was invalid. Count it as not existing.
+        log_error("SharedObject::readSOL: SOL file %s is too short "
+                "(only %s bytes long) to be valid.", filespec, st.st_size);
+        return data;
+    }
+
+    boost::scoped_array<boost::uint8_t> sbuf(new boost::uint8_t[st.st_size]);
+    const boost::uint8_t *buf = sbuf.get();
+    const boost::uint8_t *end = buf + st.st_size;
+
+    try
+    {
+        std::ifstream ifs(filespec.c_str(), std::ios::binary);
+        ifs.read(reinterpret_cast<char*>(sbuf.get()), st.st_size);
+
+        // TODO check initial bytes, and print warnings if they are fishy
+
+        buf += 16; // skip const-length headers
+
+        // skip past name   TODO add sanity check
+        buf += ntohs(*(reinterpret_cast<const boost::uint16_t*>(buf)));
+        buf += 2;
+        
+        buf += 4; // skip past padding
+
+        if (buf >= end)
+        {
+            // In this case there is no data member.
+            log_error("SharedObject::readSOL: file ends before data segment");
+            return data;
+        }
+
+        std::vector<as_object*> objRefs;
+
+        while (buf < end)
+        {
+            log_debug("SharedObject::readSOL: reading property name at "
+                    "byte %s", buf - sbuf.get());
+            // read property name
+            boost::uint16_t len = 
+                ntohs(*(reinterpret_cast<const boost::uint16_t*>(buf)));
+            buf += 2;
+
+            if( buf + len >= end )
+            {
+                log_error("SharedObject::readSOL: premature end of input");
+                break;
+            }
+            if ( ! len ) {
+                log_error("SharedObject::readSOL: empty property name");
+                break;
+            }
+            std::string prop_name(reinterpret_cast<const char*>(buf), len);
+            buf += len;
+
+            // read value
+            as_value as;
+            if (!as.readAMF0(buf, end, -1, objRefs, vm)) {
+                log_error("SharedObject::readSOL: Parsing SharedObject '%s'",
+                        filespec);
+                return false;
+            }
+
+            log_debug("parsed sol member named '%s' (len %s),  value '%s'",
+                    prop_name, len, as);
+
+            // set name/value as a member of this (SharedObject) object
+            string_table& st = vm.getStringTable();
+            data->set_member(st.find(prop_name), as);
+            
+            buf += 1; // skip null byte after each property
+        }
+        return data;
+    }
+    catch (std::exception& e)
+    {
+        log_error("SharedObject::readSOL: Reading SharedObject %s: %s", 
+                filespec, e.what());
+        return 0;
+    }
+
+#else
+    SOL sol;
+    log_security("Opening SharedObject file: %s", filespec);
+    if (sol.readFile(filespec) == false) {
+        log_security("empty or non-existing SOL file \"%s\", will be "
+                "created on flush/exit", filespec);
+        return false;
+    }
+    
+    std::vector<boost::shared_ptr<amf::Element> >::const_iterator it, e;
+    std::vector<boost::shared_ptr<amf::Element> > els = sol.getElements();
+    log_debug("Read %d AMF objects from %s", els.size(), filespec);
+
+    as_value as = getMember(NSV::PROP_DATA);
+    boost::intrusive_ptr<as_object> ptr = as.to_object();
+    
+    for (it = els.begin(), e = els.end(); it != e; it++) {
+        boost::shared_ptr<amf::Element> el = *it;
+
+#if 0 // this would be using as_value::as_value(const Element&)
+
+        std::string name(el->getName());
+        as_value val(*el);
+        ptr->set_member(st.find(name), val);
+
+#else // this is original code 
+
+        switch (el->getType())
+        {
+            case Element::NUMBER_AMF0:
+            {
+                double dub =  *(reinterpret_cast<double*>(el->getData()));
+                ptr->set_member(st.string_table::find(el->getName()),
+                        as_value(dub));
+                break;
+            }
+
+            case Element::BOOLEAN_AMF0:
+                ptr->set_member(st.string_table::find(el->getName()),
+                                            as_value(el->to_bool()));
+
+            case Element::STRING_AMF0:
+            {
+                if (el->getLength() == 0) {
+                    ptr->set_member(st.string_table::find(el->getName()), "");
+                    break;
+                }
+                
+                std::string str(reinterpret_cast<const char*>(el->getData()),
+                        el->getLength());
+                ptr->set_member(st.string_table::find(el->getName()), str);
+                break;
+            }
+
+            case Element::OBJECT_AMF0:
+                // TODO: implement!
+                log_unimpl("Reading OBJECT type from SharedObject");
+                //data.convert_to_object();
+                //ptr->set_member(st.string_table::find(el->name), data);
+                return false;
+                break;
+
+            default:
+                // TODO: what about other types?
+                log_unimpl("Reading SOL type %d", el->getType());
+                return false;
+                break;
+        } 
+
+#endif
+
+    }
+
+    return true;
+#endif
+}
+
+// ADDED
+void
+flushSOL(SharedObjectLibrary::SoLib::value_type& sol)
+{
+    sol.second->flush();
+}
+
+// ADDED
+/// Return true if the name is a valid SOL name.
+/// The official docs claim that '%' is also an invalid DisplayObject,
+/// but that is incorrect (see actionscript.all/SharedObject.as)
+bool
+validateName(const std::string& solName)
+{
+    // A double forward slash isn't allowed
+    std::string::size_type pos = solName.find("//");
+    if (pos != std::string::npos) return false;
+
+    // These DisplayObjects are also illegal
+    pos = solName.find_first_of(",~;\"'<&>?#:\\ ");
+
+    return (pos == std::string::npos);
+}
+
+
+
 } // anonymous namespace 
+
+void
+registerSharedObjectNative(as_object& o)
+{
+    VM& vm = o.getVM();
+
+    // ASnative table registration
+       vm.registerNative(sharedobject_connect, 2106, 0);
+       vm.registerNative(sharedobject_send, 2106, 1);
+       vm.registerNative(sharedobject_flush, 2106, 2);
+       vm.registerNative(sharedobject_close, 2106, 3);
+       vm.registerNative(sharedobject_getsize, 2106, 4);
+       vm.registerNative(sharedobject_setFps, 2106, 5);
+       vm.registerNative(sharedobject_clear, 2106, 6);
+
+    // FIXME: getRemote and getLocal use both these methods,
+    // but aren't identical with either of them.
+    // TODO: The first method looks in a library and returns either a
+    // SharedObject or null. The second takes a new SharedObject as
+    // its first argument and populates its data member (more or less
+    // like readSOL). This is only important for ASNative compatibility.
+       vm.registerNative(sharedobject_getLocal, 2106, 202);
+       vm.registerNative(sharedobject_getRemote, 2106, 203);
+       vm.registerNative(sharedobject_getLocal, 2106, 204);
+       vm.registerNative(sharedobject_getRemote, 2106, 205);
+
+       vm.registerNative(sharedobject_deleteAll, 2106, 206);
+       vm.registerNative(sharedobject_getDiskUsage, 2106, 207);
+}
 } // gnash namespace
 
 // local Variables:

=== modified file 'libcore/asobj/flash/net/SharedObject_as.h'
--- a/libcore/asobj/flash/net/SharedObject_as.h 2009-05-28 17:29:17 +0000
+++ b/libcore/asobj/flash/net/SharedObject_as.h 2009-06-08 21:22:11 +0000
@@ -24,19 +24,81 @@
 #include "gnashconfig.h"
 #endif
 
-
-namespace gnash {
+#include <string>
+#include <map>
+
+// Forward declarations
+namespace gnash {
+    class as_object;
+    class SharedObject_as;
+    class VM;
+}
+
+namespace gnash {
+
+class SharedObjectLibrary
+{
+public:
+
+    typedef std::map<std::string, SharedObject_as*> SoLib;
+
+    SharedObjectLibrary(VM& vm);
+
+    ~SharedObjectLibrary();
+
+    /// Return a local shared object with given name and with given root
+    //
+    /// May return NULL if name is invalid or can't access the given root
+    ///
+    SharedObject_as* getLocal(const std::string& name, const std::string& 
root);
+
+    void markReachableResources() const;
+
+    // Drop all library items
+    void clear();
+
+private:
+
+    VM& _vm;
+
+    /// Domain component of the VM SWF url
+    std::string _baseDomain;
+
+    /// Path component of the VM SWF url
+    std::string _basePath;
+
+    /// Base SOL dir
+    std::string _solSafeDir; 
+
+    SoLib _soLib;
+};
+
+/// Initialize the global SharedObject class
+void sharedobject_class_init(as_object& global);
+
+void registerSharedObjectNative(as_object& o);
+
+  
+} // end of gnash namespace
+
+#endif
+
+
+/*namespace gnash {
 
 // Forward declarations
 class as_object;
 
 /// Initialize the global SharedObject class
 void sharedobject_class_init(as_object& global);
+void attachSharedObjectInterface(as_object& o);
+void attachSharedObjectStaticInterface(as_object& o);
+
 
 } // gnash namespace
 
 // GNASH_ASOBJ3_SHAREDOBJECT_H
-#endif
+#endif*/
 
 // local Variables:
 // mode: C++

=== modified file 'libcore/asobj/flash/net/net.am'
--- a/libcore/asobj/flash/net/net.am    2009-06-07 18:12:15 +0000
+++ b/libcore/asobj/flash/net/net.am    2009-06-08 21:22:11 +0000
@@ -80,7 +80,7 @@
 
 FIXME: already exists
 if BUILD_SHAREDOBJECT_AS3
-# NET_SOURCES += asobj/flash/net/SharedObject_as.cpp
+NET_SOURCES += asobj/flash/net/SharedObject_as.cpp
 NET_HEADERS += asobj/flash/net/SharedObject_as.h
 endif
 

=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp    2009-06-08 21:40:22 +0000
+++ b/libcore/movie_root.cpp    2009-06-09 15:51:03 +0000
@@ -27,7 +27,7 @@
 #include "render.h"
 #include "VM.h"
 #include "ExecutableCode.h"
-#include "Stage_as.h"
+#include "flash/display/Stage_as.h"
 #include "URL.h"
 #include "namedStrings.h"
 #include "GnashException.h"

=== modified file 'libcore/vm/VM.cpp'
--- a/libcore/vm/VM.cpp 2009-05-29 06:50:02 +0000
+++ b/libcore/vm/VM.cpp 2009-06-09 15:51:03 +0000
@@ -22,7 +22,7 @@
 #endif
 
 #include "VM.h"
-#include "SharedObject_as.h" // for SharedObjectLibrary
+#include "flash/net/SharedObject_as.h" // for SharedObjectLibrary
 #include "smart_ptr.h" // GNASH_USE_GC
 #include "builtin_function.h"
 #include "movie_definition.h"


reply via email to

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