gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r10558: Allow users the option of sa


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10558: Allow users the option of saving loaded or streamed media, currently
Date: Thu, 29 Jan 2009 09:45:09 -0700
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10558
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Thu 2009-01-29 09:45:09 -0700
message:
  Allow users the option of saving loaded or streamed media, currently 
  using a fairly rudimentary an inflexible system of naming files.
  
  The naming system will be improved by using a functor, and the naming
  code may be moved somewhere more suitable.
modified:
  gui/gtk.cpp
  libbase/NetworkAdapter.h
  libbase/curl_adapter.cpp
  libbase/rc.cpp
  libbase/rc.h
  libcore/StreamProvider.cpp
  libcore/StreamProvider.h
  libcore/asobj/NetConnection_as.cpp
  libcore/impl.cpp
    ------------------------------------------------------------
    revno: 10555.1.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: savemedia
    timestamp: Tue 2009-01-27 10:49:22 +0100
    message:
      Allow saving cached media streams permanently on disk (NetConnection
      only at present).
      
      RcInitFile support for target directory and on/off toggle.
      
      GUI support for turning on/of and setting target directory.
      
      Target directory is currently ignored.
      
      Use GnashSystemFileHeaders.h for stat(), dup() includes.
    added:
      libbase/GnashSystemFileHeaders.h
    modified:
      gui/gtk.cpp
      libbase/NetworkAdapter.h
      libbase/curl_adapter.cpp
      libbase/rc.cpp
      libbase/rc.h
      libcore/StreamProvider.cpp
      libcore/StreamProvider.h
      libcore/asobj/NetConnection_as.cpp
    ------------------------------------------------------------
    revno: 10555.1.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: savemedia
    timestamp: Tue 2009-01-27 13:39:39 +0100
    message:
      Use user-specified target directory for saving media streams. Save
      rcfile values properly.
    modified:
      libbase/rc.cpp
      libcore/StreamProvider.cpp
    ------------------------------------------------------------
    revno: 10555.1.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: savemedia
    timestamp: Tue 2009-01-27 13:40:24 +0100
    message:
      Write values to rcfile, correct typo.
    modified:
      gui/gtk.cpp
    ------------------------------------------------------------
    revno: 10555.1.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: savemedia
    timestamp: Tue 2009-01-27 13:40:44 +0100
    message:
      Correct typo.
    modified:
      libbase/curl_adapter.cpp
    ------------------------------------------------------------
    revno: 10555.1.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: savemedia
    timestamp: Tue 2009-01-27 14:53:00 +0100
    message:
      Split saveMedia into saveStreamingMedia and saveLoadedMedia. Save in
      directories based on hostname.
    removed:
      libbase/GnashSystemFileHeaders.h
    added:
      libbase/GnashFileUtilities.cpp
      libbase/GnashFileUtilities.h
    modified:
      gui/gtk.cpp
      libbase/GnashSystemIOHeaders.h
      libbase/Makefile.am
      libbase/curl_adapter.cpp
      libbase/rc.cpp
      libbase/rc.h
      libcore/StreamProvider.cpp
      libcore/asobj/NetConnection_as.cpp
      libcore/asobj/SharedObject_as.cpp
      libcore/impl.cpp
    ------------------------------------------------------------
    revno: 10555.1.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: savemedia
    timestamp: Tue 2009-01-27 17:40:28 +0100
    message:
      Use StreamProvider to get current NamingPolicy; may be moved somewhere 
      else eventually.
    modified:
      libcore/StreamProvider.cpp
      libcore/StreamProvider.h
      libcore/asobj/NetConnection_as.cpp
      libcore/impl.cpp
    ------------------------------------------------------------
    revno: 10555.1.7
    committer: Benjamin Wolsey <address@hidden>
    branch nick: savemedia
    timestamp: Tue 2009-01-27 18:20:50 +0100
    message:
      Add an overwrite-existing naming policy.
    modified:
      libcore/StreamProvider.cpp
=== modified file 'gui/gtk.cpp'
--- a/gui/gtk.cpp       2009-01-22 20:10:39 +0000
+++ b/gui/gtk.cpp       2009-01-27 13:53:00 +0000
@@ -931,7 +931,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
-namespace { // anonimous
+namespace { // anonymous
 
 class PreferencesDialog {
 
@@ -968,6 +968,9 @@
         GtkWidget *urlOpenerText;
         GtkWidget *librarySize;
         GtkWidget *startStoppedToggle;
+        GtkWidget *mediaDir;
+        GtkWidget *saveStreamingMediaToggle;
+        GtkWidget *saveLoadedMediaToggle;
 #ifdef USE_DEBUGGER
         GtkWidget *DebuggerToggle;
 #endif
@@ -995,7 +998,10 @@
                versionText(0),
                urlOpenerText(0),
                librarySize(0),
-               startStoppedToggle(0)
+               startStoppedToggle(0),
+            mediaDir(0),
+            saveStreamingMediaToggle(0),
+            saveLoadedMediaToggle(0)
 #ifdef USE_DEBUGGER
                ,DebuggerToggle(0)
 #endif
@@ -1045,17 +1051,40 @@
         // For getting from const gchar* to std::string&
         std::string tmp;
     
-        if ( prefs->soundToggle )
-            
_rcfile.useSound(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs->soundToggle)));
-    
-        if ( prefs->actionDumpToggle )
+        if (prefs->soundToggle) {
+            _rcfile.useSound(gtk_toggle_button_get_active(
+                        GTK_TOGGLE_BUTTON(prefs->soundToggle)));
+        }
+
+        if (prefs->saveLoadedMediaToggle) {
+            _rcfile.saveLoadedMedia(
+                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+                        prefs->saveLoadedMediaToggle)));
+        }
+
+        if (prefs->saveStreamingMediaToggle) {
+            _rcfile.saveStreamingMedia(
+                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+                        prefs->saveStreamingMediaToggle)));
+        }
+
+        if (prefs->mediaDir) {
+           tmp = gtk_entry_get_text(GTK_ENTRY(prefs->mediaDir));
+            _rcfile.setMediaDir(tmp);
+        }
+
+        if (prefs->actionDumpToggle) {
             _rcfile.useActionDump(
-                   
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs->actionDumpToggle)));
-
-        if ( prefs->parserDumpToggle )
+                   gtk_toggle_button_get_active(
+                    GTK_TOGGLE_BUTTON(prefs->actionDumpToggle)));
+        }
+        
+        if (prefs->parserDumpToggle) {
             _rcfile.useParserDump(
-                   
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs->parserDumpToggle)));
-       
+                   gtk_toggle_button_get_active(
+                    GTK_TOGGLE_BUTTON(prefs->parserDumpToggle)));
+        }
+
         if ( prefs->logfileName ) {
            tmp = gtk_entry_get_text(GTK_ENTRY(prefs->logfileName));
             _rcfile.setDebugLog(tmp);
@@ -1063,7 +1092,8 @@
         
         if ( prefs->writeLogToggle ) {
             _rcfile.useWriteLog(
-                   
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs->writeLogToggle)));
+                   gtk_toggle_button_get_active(
+                    GTK_TOGGLE_BUTTON(prefs->writeLogToggle)));
         }
                
         if ( prefs->verbosityScale ) {
@@ -1079,22 +1109,26 @@
 
         if ( prefs->ASCodingErrorToggle ) {
             _rcfile.showASCodingErrors(
-                
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs->ASCodingErrorToggle)));
+                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+                        prefs->ASCodingErrorToggle)));
         }
 
         if ( prefs->malformedSWFToggle ) {
             _rcfile.showMalformedSWFErrors(
-                
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs->malformedSWFToggle)));
+                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+                        prefs->malformedSWFToggle)));
         }
 
         if ( prefs->localHostToggle ) {
             _rcfile.useLocalHost(
-                
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs->localHostToggle)));
+                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+                        prefs->localHostToggle)));
         }
 
         if ( prefs->localDomainToggle ) {
             _rcfile.useLocalDomain(
-                
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs->localDomainToggle)));
+                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+                        prefs->localDomainToggle)));
         }
 
         if ( prefs->solLocalDomainToggle ) {
@@ -1374,30 +1408,36 @@
     gtk_box_pack_start (GTK_BOX(securityvbox), privacylabel, FALSE, FALSE, 0);
 
     GtkWidget *solsandboxlabel = gtk_label_new (_("Shared objects 
directory:"));
-    gtk_box_pack_start (GTK_BOX(securityvbox), solsandboxlabel, FALSE, FALSE, 
0);
+    gtk_box_pack_start (GTK_BOX(securityvbox), solsandboxlabel, FALSE,
+            FALSE, 0);
     gtk_misc_set_alignment (GTK_MISC (solsandboxlabel), 0, 0.5);
 
     _prefs->solSandbox = gtk_entry_new();
-    gtk_entry_set_text(GTK_ENTRY(_prefs->solSandbox), 
_rcfile.getSOLSafeDir().c_str());
-    gtk_box_pack_start (GTK_BOX(securityvbox), _prefs->solSandbox, FALSE, 
FALSE, 0);
+    gtk_entry_set_text(GTK_ENTRY(_prefs->solSandbox), 
+            _rcfile.getSOLSafeDir().c_str());
+    gtk_box_pack_start (GTK_BOX(securityvbox), _prefs->solSandbox, FALSE,
+            FALSE, 0);
 
-    _prefs->solReadOnlyToggle = gtk_check_button_new_with_mnemonic ( 
+    _prefs->solReadOnlyToggle = gtk_check_button_new_with_mnemonic( 
                                _("Do _not write Shared Object files"));
-    gtk_box_pack_start (GTK_BOX(securityvbox), _prefs->solReadOnlyToggle, 
FALSE, FALSE, 0);
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON 
(_prefs->solReadOnlyToggle),
+    gtk_box_pack_start (GTK_BOX(securityvbox), _prefs->solReadOnlyToggle,
+            FALSE, FALSE, 0);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(_prefs->solReadOnlyToggle),
                        _rcfile.getSOLReadOnly());
 
-    _prefs->solLocalDomainToggle = gtk_check_button_new_with_mnemonic (
+    _prefs->solLocalDomainToggle = gtk_check_button_new_with_mnemonic(
                                _("Only _access local Shared Object files"));
-    gtk_box_pack_start (GTK_BOX(securityvbox), _prefs->solLocalDomainToggle, 
FALSE, FALSE, 0);
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON 
(_prefs->solLocalDomainToggle),
-                       _rcfile.getSOLLocalDomain());
+    gtk_box_pack_start(GTK_BOX(securityvbox), _prefs->solLocalDomainToggle,
+            FALSE, FALSE, 0);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
+                _prefs->solLocalDomainToggle), _rcfile.getSOLLocalDomain());
 
     _prefs->localConnectionToggle = gtk_check_button_new_with_mnemonic (
                                _("Disable Local _Connection object"));
-    gtk_box_pack_start (GTK_BOX(securityvbox), _prefs->localConnectionToggle, 
FALSE, FALSE, 0);
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON 
(_prefs->localConnectionToggle),
-                       _rcfile.getLocalConnection()); 
+    gtk_box_pack_start (GTK_BOX(securityvbox), _prefs->localConnectionToggle,
+            FALSE, FALSE, 0);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
+                _prefs->localConnectionToggle), _rcfile.getLocalConnection()); 
 }
 
 void
@@ -1409,17 +1449,57 @@
     // Media tab title
     GtkWidget *mediatablabel = gtk_label_new_with_mnemonic (_("_Media"));
     
-    gtk_notebook_append_page(GTK_NOTEBOOK(_notebook), GTK_WIDGET(mediavbox), 
mediatablabel); 
+    gtk_notebook_append_page(GTK_NOTEBOOK(_notebook),
+            GTK_WIDGET(mediavbox), mediatablabel); 
     
     // Sound
     GtkWidget *soundlabel = gtk_label_new (_("<b>Sound</b>"));
     gtk_label_set_use_markup (GTK_LABEL (soundlabel), TRUE);
     gtk_box_pack_start(GTK_BOX(mediavbox), soundlabel, FALSE, FALSE, 0);
    
-    _prefs->soundToggle = gtk_check_button_new_with_mnemonic (_("Use sound 
_handler"));
-    gtk_box_pack_start (GTK_BOX(mediavbox), _prefs->soundToggle, FALSE, FALSE, 
0);
-    // Align button state with rcfile
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_prefs->soundToggle), 
_rcfile.useSound());
+    _prefs->soundToggle = gtk_check_button_new_with_mnemonic(
+            _("Use sound _handler"));
+    gtk_box_pack_start (GTK_BOX(mediavbox), _prefs->soundToggle, FALSE,
+            FALSE, 0);
+    // Align button state with rcfile
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(_prefs->soundToggle),
+            _rcfile.useSound());
+
+    // Save Media
+    GtkWidget *savemedia = gtk_label_new(_("<b>Media Streams</b>"));
+    gtk_label_set_use_markup(GTK_LABEL(savemedia), TRUE);
+    gtk_box_pack_start(GTK_BOX(mediavbox), savemedia, FALSE, FALSE, 0);
+   
+    // Save streamed media Toggle
+    _prefs->saveStreamingMediaToggle = gtk_check_button_new_with_mnemonic(
+            _("Save media streams to disk"));
+    gtk_box_pack_start (GTK_BOX(mediavbox), _prefs->saveStreamingMediaToggle,
+            FALSE, FALSE, 0);
+    // Align button state with rcfile
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
+            _prefs->saveStreamingMediaToggle), _rcfile.saveStreamingMedia());
+
+    // Save loaded media Toggle
+    _prefs->saveLoadedMediaToggle = gtk_check_button_new_with_mnemonic(
+            _("Save dynamically loaded media to disk"));
+    gtk_box_pack_start (GTK_BOX(mediavbox), _prefs->saveLoadedMediaToggle,
+            FALSE, FALSE, 0);
+    // Align button state with rcfile
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
+                _prefs->saveLoadedMediaToggle), _rcfile.saveLoadedMedia());
+
+    // Directory for saving media
+    GtkWidget *mediastreamslabel = gtk_label_new(_("Saved media directory:"));
+    gtk_box_pack_start(GTK_BOX(mediavbox), mediastreamslabel, FALSE,
+            FALSE, 0);
+    gtk_misc_set_alignment (GTK_MISC (mediastreamslabel), 0, 0.5);
+
+    _prefs->mediaDir = gtk_entry_new();
+    gtk_entry_set_text(GTK_ENTRY(_prefs->mediaDir), 
+            _rcfile.getMediaDir().c_str());
+    gtk_box_pack_start(GTK_BOX(mediavbox), _prefs->mediaDir, FALSE,
+            FALSE, 0);
+
 }
 
 void
@@ -1468,7 +1548,7 @@
                                           "detect your OS</i>"));
     gtk_label_set_use_markup (GTK_LABEL (OSadvicelabel), TRUE);
     gtk_misc_set_alignment (GTK_MISC (OSadvicelabel), 0, 0.5);
-    gtk_box_pack_start(GTK_BOX(playervbox), OSadvicelabel, FALSE, FALSE, 0);   
  
+    gtk_box_pack_start(GTK_BOX(playervbox), OSadvicelabel, FALSE, FALSE, 0);
 
     // URL opener
     GtkWidget *urlopenerbox = gtk_hbox_new (FALSE, 2);
@@ -1479,9 +1559,11 @@
     gtk_box_pack_start(GTK_BOX(urlopenerbox), urlopenerlabel, FALSE, FALSE, 0);
     
     _prefs->urlOpenerText = gtk_entry_new ();
-    gtk_box_pack_start(GTK_BOX(urlopenerbox), _prefs->urlOpenerText, FALSE, 
FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(urlopenerbox), _prefs->urlOpenerText, FALSE,
+            FALSE, 0);
     // Put text in the entry box      
-    gtk_entry_set_text(GTK_ENTRY(_prefs->urlOpenerText), 
_rcfile.getURLOpenerFormat().c_str());
+    gtk_entry_set_text(GTK_ENTRY(_prefs->urlOpenerText),
+            _rcfile.getURLOpenerFormat().c_str());
 
     // Performance
     GtkWidget *performancelabel = gtk_label_new (_("<b>Performance</b>"));
@@ -1497,16 +1579,19 @@
     gtk_box_pack_start(GTK_BOX(libraryhbox), librarylabel, FALSE, FALSE, 0);
 
     _prefs->librarySize = gtk_spin_button_new_with_range(0, 100, 1);
-    gtk_box_pack_start(GTK_BOX(libraryhbox), _prefs->librarySize, FALSE, 
FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(libraryhbox), _prefs->librarySize, FALSE,
+            FALSE, 0);
     // Align to _rcfile value:
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(_prefs->librarySize), 
_rcfile.getMovieLibraryLimit());
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(_prefs->librarySize),
+            _rcfile.getMovieLibraryLimit());
 
     _prefs->startStoppedToggle = gtk_check_button_new_with_mnemonic (
                                _("Start _Gnash in pause mode"));
-    gtk_box_pack_start (GTK_BOX(playervbox), _prefs->startStoppedToggle, 
FALSE, FALSE, 0);
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON 
(_prefs->startStoppedToggle),
+    gtk_box_pack_start(GTK_BOX(playervbox), _prefs->startStoppedToggle,
+            FALSE, FALSE, 0);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(_prefs->startStoppedToggle),
                        _rcfile.startStopped());
-} // end of ::addPlayerTab
+} 
 
 
 

=== modified file 'libbase/NetworkAdapter.h'
--- a/libbase/NetworkAdapter.h  2009-01-26 09:05:11 +0000
+++ b/libbase/NetworkAdapter.h  2009-01-27 09:49:22 +0000
@@ -47,7 +47,7 @@
     //
     /// @param url      The url to fetch data from.
     DSOEXPORT static std::auto_ptr<IOChannel> makeStream(
-            const std::string& url);
+            const std::string& url, const std::string& cachefile);
 
     /// \brief
     /// Returns a read-only IOChannel that fetches data
@@ -58,7 +58,8 @@
     /// @param url      The url to post to.
     /// @param postdata The url-encoded post data
     DSOEXPORT static std::auto_ptr<IOChannel> makeStream(
-            const std::string& url, const std::string& postdata);
+            const std::string& url, const std::string& postdata,
+            const std::string& cachefile);
 
     /// \brief
     /// Returns a read-only IOChannel that fetches data
@@ -70,8 +71,11 @@
     /// @param postdata The url-encoded post data
     /// @param headers  A RequestHeaders map of custom headers to send.
     DSOEXPORT static std::auto_ptr<IOChannel> makeStream(const std::string& 
url,
-           const std::string& postdata, const RequestHeaders& headers);
-
+           const std::string& postdata, const RequestHeaders& headers,
+           const std::string& cachefile);
+
+
+    typedef std::set<std::string, StringNoCaseLessThan> ReservedNames;
 
     /// Check whether a RequestHeader is permitted.
     //
@@ -80,12 +84,13 @@
     /// @return true if the name is allowed.
     DSOEXPORT static bool isHeaderAllowed(const std::string& headerName)
     {
-        return (_reservedNames.find(headerName) == _reservedNames.end());
+        const ReservedNames& names = reservedNames();
+        return (names.find(headerName) == names.end());
     }
 
 private:
 
-    static std::set<std::string, StringNoCaseLessThan> _reservedNames;
+    static const ReservedNames& reservedNames();
 
 };
 

=== modified file 'libbase/curl_adapter.cpp'
--- a/libbase/curl_adapter.cpp  2009-01-26 09:05:11 +0000
+++ b/libbase/curl_adapter.cpp  2009-01-27 13:53:00 +0000
@@ -41,7 +41,8 @@
 // Stub for warning about access when no libcurl is defined.
 
 std::auto_ptr<IOChannel>
-NetworkAdapter::makeStream(const std::string& /*url*/)
+NetworkAdapter::makeStream(const std::string& /*url*/, const std::string&,
+        const std::string& /*cachefile*/)
 {
        log_error(_("libcurl is not available, but "
                    "Gnash has attempted to use the curl adapter"));
@@ -49,14 +50,15 @@
 }
 
 std::auto_ptr<IOChannel>
-NetworkAdapter::makeStream(const std::string& url, const std::string& postdata)
+NetworkAdapter::makeStream(const std::string& url, const std::string& postdata,
+        const std::string& cachefile)
 {
     return makeStream(url);
 }
 
 std::auto_ptr<IOChannel>
 NetworkAdapter::makeStream(const std::string& url, const std::string& postdata,
-                            const RequestHeaders& headers)
+        const RequestHeaders& headers, const std::string& cachefile)
 {
     return makeStream(url);
 }
@@ -168,23 +170,28 @@
        void exportCookies();
 
        /// Shared handle data locking function
-       void lockSharedHandle(CURL* handle, curl_lock_data data, 
curl_lock_access access);
+       void lockSharedHandle(CURL* handle, curl_lock_data data,
+            curl_lock_access access);
 
        /// Shared handle data unlocking function
        void unlockSharedHandle(CURL* handle, curl_lock_data data);
 
        /// Shared handle locking function
-       static void lockSharedHandleWrapper(CURL* handle, curl_lock_data data, 
curl_lock_access access, void* userptr)
+       static void lockSharedHandleWrapper(CURL* handle, curl_lock_data data,
+            curl_lock_access access, void* userptr)
        {
                CurlSession* ci = static_cast<CurlSession*>(userptr);
                ci->lockSharedHandle(handle, data, access);
        }
 
        /// Shared handle unlocking function
-       static void unlockSharedHandleWrapper(CURL* handle, curl_lock_data 
data, void* userptr)
+       static void unlockSharedHandleWrapper(CURL* handle, curl_lock_data data,
+            void* userptr)
        {
-               //data defines what data libcurl wants to unlock, and you must 
make sure that only one lick is given at any time for each kind of data.
-               //userptr is the pointer you set with CURLSHOPT_USERDATA. 
+               // data defines what data libcurl wants to unlock, and you must
+        // make sure that only one lock is given at any time for each kind
+        // of data.
+               // userptr is the pointer you set with CURLSHOPT_USERDATA. 
                CurlSession* ci = static_cast<CurlSession*>(userptr);
                ci->unlockSharedHandle(handle, data);
        }
@@ -209,10 +216,12 @@
        {
                if ( ++retries > 10 )
                {
-                       log_error("Failed cleaning up share handle: %s. Giving 
up after %d retries.", curl_share_strerror(code), retries);
+                       log_error("Failed cleaning up share handle: %s. Giving 
up after "
+                    "%d retries.", curl_share_strerror(code), retries);
                        break;
                }
-               log_error("Failed cleaning up share handle: %s. Will try again 
in a second.", curl_share_strerror(code));
+               log_error("Failed cleaning up share handle: %s. Will try again 
in "
+                "a second.", curl_share_strerror(code));
                gnashSleep(1000000);
        }
        _shandle = 0;
@@ -239,50 +248,55 @@
        curl_global_init(CURL_GLOBAL_ALL);
 
        _shandle = curl_share_init();
-       if ( ! _shandle )
-               throw gnash::GnashException("Failure initializing curl share 
handle");
+       if (! _shandle) {
+               throw GnashException("Failure initializing curl share handle");
+    }
 
        CURLSHcode ccode;
 
        // Register share locking function
-       ccode = curl_share_setopt(_shandle, CURLSHOPT_LOCKFUNC, 
lockSharedHandleWrapper);
+       ccode = curl_share_setopt(_shandle, CURLSHOPT_LOCKFUNC,
+            lockSharedHandleWrapper);
        if ( ccode != CURLSHE_OK ) {
-               throw gnash::GnashException(curl_share_strerror(ccode));
+               throw GnashException(curl_share_strerror(ccode));
        }
 
        // Register share unlocking function
-       ccode = curl_share_setopt(_shandle, CURLSHOPT_UNLOCKFUNC, 
unlockSharedHandleWrapper);
+       ccode = curl_share_setopt(_shandle, CURLSHOPT_UNLOCKFUNC,
+            unlockSharedHandleWrapper);
        if ( ccode != CURLSHE_OK ) {
-               throw gnash::GnashException(curl_share_strerror(ccode));
+               throw GnashException(curl_share_strerror(ccode));
        }
 
        // Activate sharing of cookies and DNS cache
        ccode = curl_share_setopt(_shandle, CURLSHOPT_SHARE, 
CURL_LOCK_DATA_COOKIE);
        if ( ccode != CURLSHE_OK ) {
-               throw gnash::GnashException(curl_share_strerror(ccode));
+               throw GnashException(curl_share_strerror(ccode));
        }
 
        // Activate sharing of DNS cache (since we're there..)
        ccode = curl_share_setopt(_shandle, CURLSHOPT_SHARE, 
CURL_LOCK_DATA_DNS);
        if ( ccode != CURLSHE_OK ) {
-               throw gnash::GnashException(curl_share_strerror(ccode));
+               throw GnashException(curl_share_strerror(ccode));
        }
 
        // Pass ourselves as the userdata
        ccode = curl_share_setopt(_shandle, CURLSHOPT_USERDATA, this);
        if ( ccode != CURLSHE_OK ) {
-               throw gnash::GnashException(curl_share_strerror(ccode));
+               throw GnashException(curl_share_strerror(ccode));
        }
 
        importCookies();
 }
 
 void
-CurlSession::lockSharedHandle(CURL* handle, curl_lock_data data, 
curl_lock_access access)
+CurlSession::lockSharedHandle(CURL* handle, curl_lock_data data,
+        curl_lock_access access)
 {
        UNUSED(handle); // possibly being the 'easy' handle triggering the 
request ?
 
-       // data defines what data libcurl wants to lock, and you must make sure 
that only one lock is given at any time for each kind of data.
+       // data defines what data libcurl wants to lock, and you must make
+    // sure that only one lock is given at any time for each kind of data.
        // access defines what access type libcurl wants, shared or single.
 
        // TODO: see if we may make use of the 'access' parameter
@@ -306,16 +320,17 @@
                        //log_debug("Share mutex locked");
                        break;
                case CURL_LOCK_DATA_SSL_SESSION:
-                       gnash::log_error("lockSharedHandle: SSL session locking 
unsupported");
+                       log_error("lockSharedHandle: SSL session locking "
+                    "unsupported");
                        break;
                case CURL_LOCK_DATA_CONNECT:
-                       gnash::log_error("lockSharedHandle: connect locking 
unsupported");
+                       log_error("lockSharedHandle: connect locking 
unsupported");
                        break;
                case CURL_LOCK_DATA_LAST:
-                       gnash::log_error("lockSharedHandle: last locking 
unsupported ?!");
+                       log_error("lockSharedHandle: last locking unsupported 
?!");
                        break;
                default:
-                       gnash::log_error("lockSharedHandle: unknown shared data 
%d", data);
+                       log_error("lockSharedHandle: unknown shared data %d", 
data);
                        break;
        }
 }
@@ -325,7 +340,8 @@
 {
        UNUSED(handle); // possibly being the 'easy' handle triggering the 
request ?
 
-       // data defines what data libcurl wants to lock, and you must make sure 
that only one lock is given at any time for each kind of data.
+       // data defines what data libcurl wants to lock, and you must make
+    // sure that only one lock is given at any time for each kind of data.
        switch (data)
        {
                case CURL_LOCK_DATA_DNS:
@@ -341,16 +357,18 @@
                        _shareMutexLock.unlock();
                        break;
                case CURL_LOCK_DATA_SSL_SESSION:
-                       gnash::log_error("unlockSharedHandle: SSL session 
locking unsupported");
+                       log_error("unlockSharedHandle: SSL session locking "
+                    "unsupported");
                        break;
                case CURL_LOCK_DATA_CONNECT:
-                       gnash::log_error("unlockSharedHandle: connect locking 
unsupported");
+                       log_error("unlockSharedHandle: connect locking 
unsupported");
                        break;
                case CURL_LOCK_DATA_LAST:
-                       gnash::log_error("unlockSharedHandle: last locking 
unsupported ?!");
+                       log_error("unlockSharedHandle: last locking unsupported 
?!");
                        break;
                default:
-                       std::cerr << "unlockSharedHandle: unknown shared data " 
<< data << std::endl;
+                       std::cerr << "unlockSharedHandle: unknown shared data " 
<<
+                data << std::endl;
                        break;
        }
 }
@@ -371,7 +389,7 @@
        typedef std::map<std::string, std::string> PostData;
 
        /// Open a stream from the specified URL
-       CurlStreamFile(const std::string& url);
+       CurlStreamFile(const std::string& url, const std::string& cachefile);
 
        /// Open a stream from the specified URL posting the specified variables
        //
@@ -381,10 +399,12 @@
        /// @param vars
        ///     The url-encoded post data.
        ///
-       CurlStreamFile(const std::string& url, const std::string& vars);
+       CurlStreamFile(const std::string& url, const std::string& vars,
+            const std::string& cachefile);
        
        CurlStreamFile(const std::string& url, const std::string& vars,
-                      const NetworkAdapter::RequestHeaders& headers);
+                      const NetworkAdapter::RequestHeaders& headers,
+                   const std::string& cachefile);
 
        ~CurlStreamFile();
 
@@ -424,7 +444,7 @@
 
 private:
 
-       void init(const std::string& url);
+       void init(const std::string& url, const std::string& cachefile);
 
        // Use this file to cache data
        FILE* _cache;
@@ -501,7 +521,7 @@
        void *userp)
 {
 #ifdef GNASH_CURL_VERBOSE
-       gnash::log_debug("curl write callback called for (%d) bytes",
+       log_debug("curl write callback called for (%d) bytes",
                size * nmemb);
 #endif
        CurlStreamFile* stream = static_cast<CurlStreamFile*>(userp);
@@ -526,7 +546,7 @@
         boost::format fmt = boost::format("writing to cache file: requested "
                                           "%d, wrote %d (%s)") %
                                           size % wrote % std::strerror(errno);
-               throw gnash::GnashException(fmt.str());
+               throw GnashException(fmt.str());
        }
 
        // Set the size of cached data
@@ -545,7 +565,7 @@
        if ( ! _running )
        {
 #if GNASH_CURL_VERBOSE
-               gnash::log_debug("Not running: fillCacheNonBlocking returning");
+               log_debug("Not running: fillCacheNonBlocking returning");
 #endif
                return;
        }
@@ -559,7 +579,7 @@
 
        if (mcode != CURLM_OK)
        {
-               throw gnash::GnashException(curl_multi_strerror(mcode));
+               throw GnashException(curl_multi_strerror(mcode));
        }
 
        // handle 404
@@ -573,13 +593,13 @@
 {
 
 #if GNASH_CURL_VERBOSE
-    gnash::log_debug("fillCache(%d), called, currently cached: %d", size, 
_cached);
+    log_debug("fillCache(%d), called, currently cached: %d", size, _cached);
 #endif 
 
        if ( ! _running || _cached >= size ) {
 #if GNASH_CURL_VERBOSE
-        if (!_running) gnash::log_debug("Not running: returning");
-        else gnash::log_debug("Already enough bytes cached: returning");
+        if (!_running) log_debug("Not running: returning");
+        else log_debug("Already enough bytes cached: returning");
 #endif
            return;
        }
@@ -595,13 +615,13 @@
        const long maxSleepUsec = 10000;  // 1/100 of a second
 
        const unsigned int userTimeout = static_cast<unsigned int>(
-                       
gnash::RcInitFile::getDefaultInstance().getStreamsTimeout()*1000);
+                       
RcInitFile::getDefaultInstance().getStreamsTimeout()*1000);
 
 #ifdef GNASH_CURL_VERBOSE
-        gnash::log_debug("User timeout is %u milliseconds", userTimeout);
+        log_debug("User timeout is %u milliseconds", userTimeout);
 #endif
 
-       gnash::WallClockTimer lastProgress; // timer since last progress
+       WallClockTimer lastProgress; // timer since last progress
        while (_running)
        {
 
@@ -613,24 +633,24 @@
                if (_cached >= size || !_running) break; // || _error ?
 
 #if GNASH_CURL_VERBOSE
-               //gnash::log_debug("cached: %d, size: %d", _cached, size);
+               //log_debug("cached: %d, size: %d", _cached, size);
 #endif
 
                mcode = curl_multi_fdset(_mhandle, &readfd, &writefd, 
&exceptfd, &maxfd);
                if (mcode != CURLM_OK) {
                        // This is a serious error, not just a failure to add 
any
                        // fds.
-                       throw gnash::GnashException(curl_multi_strerror(mcode));
+                       throw GnashException(curl_multi_strerror(mcode));
                }
 
 #ifdef GNASH_CURL_VERBOSE
-               gnash::log_debug("Max fd: %d", maxfd);
+               log_debug("Max fd: %d", maxfd);
 #endif
 
                // A value of -1 means no file descriptors were added.
                if (maxfd < 0) {
 #if GNASH_CURL_VERBOSE
-                       gnash::log_debug("No filedescriptors; breaking");
+                       log_debug("No filedescriptors; breaking");
 #endif
                        break;
                }
@@ -643,7 +663,7 @@
                tv.tv_usec = maxSleepUsec;
 
 #ifdef GNASH_CURL_VERBOSE
-               gnash::log_debug("select() with %d milliseconds timeout", 
maxSleepUsec*1000);
+               log_debug("select() with %d milliseconds timeout", 
maxSleepUsec*1000);
 #endif
 
                // Wait for data on the filedescriptors until a timeout set
@@ -655,18 +675,18 @@
                        boost::format fmt = boost::format(
                                "error polling data from connection to %s: %s ")
                                % _url % strerror(errno);
-                       throw gnash::GnashException(fmt.str());
+                       throw GnashException(fmt.str());
                }
                if ( ! ret )
                {
                        // timeout
 #ifdef GNASH_CURL_VERBOSE
-            gnash::log_debug("select() timed out, elapsed is %u",
+            log_debug("select() timed out, elapsed is %u",
                     lastProgress.elapsed());
 #endif
             if (userTimeout && lastProgress.elapsed() > userTimeout)
             {
-                gnash::log_error(_("Timeout (%u milliseconds) while loading "
+                log_error(_("Timeout (%u milliseconds) while loading "
                             "from url %s"), userTimeout, _url);
                                // TODO: should we set _error here ?
                 return;
@@ -675,7 +695,7 @@
                else
                {
 #ifdef GNASH_CURL_VERBOSE
-            gnash::log_debug("FD activity, resetting progress timer");
+            log_debug("FD activity, resetting progress timer");
 #endif
             lastProgress.restart();
                }
@@ -718,13 +738,13 @@
                                                  CURLINFO_RESPONSE_CODE, 
&code);
 
                                if ( code >= 400 ) {
-                                       gnash::log_error ("HTTP response %ld 
from url %s",
+                                       log_error ("HTTP response %ld from url 
%s",
                                                                    code, _url);
                                        _error = TU_FILE_OPEN_ERROR;
                                        _running = false;
                                }
                                else {
-                                       gnash::log_debug ("HTTP response %ld 
from url %s",
+                                       log_debug ("HTTP response %ld from url 
%s",
                                                                    code, _url);
                                }
 
@@ -732,7 +752,7 @@
                        else {
 
                                // Transaction failed, pass on curl error.
-                               gnash::log_error("CURL: %s", curl_easy_strerror(
+                               log_error("CURL: %s", curl_easy_strerror(
                                                            
curl_msg->data.result));
                                _error = TU_FILE_OPEN_ERROR;
                        }
@@ -745,7 +765,7 @@
 
 /*private*/
 void
-CurlStreamFile::init(const std::string& url)
+CurlStreamFile::init(const std::string& url, const std::string& cachefile)
 {
     _customHeaders = 0;
 
@@ -759,11 +779,21 @@
        _handle = curl_easy_init();
        _mhandle = curl_multi_init();
 
-       /// later on we might want to accept a filename
-       /// in the constructor
-       _cache = std::tmpfile();
+    const RcInitFile& rcfile = RcInitFile::getDefaultInstance();
+       
+    if (!cachefile.empty()) {
+        _cache = std::fopen(cachefile.c_str(), "w+b");
+        if (!_cache) {
+
+            log_error("Could not open specified path as cache file. Using "
+                    "a temporary file instead");
+            _cache = std::tmpfile();
+        }
+    }
+    else _cache = std::tmpfile();
+
        if ( ! _cache ) {
-               throw gnash::GnashException("Could not create temporary cache 
file");
+               throw GnashException("Could not create temporary cache file");
        }
        _cachefd = fileno(_cache);
 
@@ -772,26 +802,28 @@
        // Override cURL's default verification of SSL certificates
        // This is insecure, so log security warning.
        // Equivalent to curl -k or curl --insecure.
-       if (gnash::RcInitFile::getDefaultInstance().insecureSSL())
+       if (rcfile.insecureSSL())
        {
-                gnash::log_security(_("Allowing connections to SSL sites with 
invalid "
-                                "certificates"));              
+        log_security(_("Allowing connections to SSL sites with invalid "
+         "certificates"));             
 
                ccode = curl_easy_setopt(_handle, CURLOPT_SSL_VERIFYPEER, 0);
                if ( ccode != CURLE_OK ) {
-                       throw gnash::GnashException(curl_easy_strerror(ccode));
+                       throw GnashException(curl_easy_strerror(ccode));
                }
 
                ccode = curl_easy_setopt(_handle, CURLOPT_SSL_VERIFYHOST, 0);
                if ( ccode != CURLE_OK ) {
-                       throw gnash::GnashException(curl_easy_strerror(ccode));
+                       throw GnashException(curl_easy_strerror(ccode));
                }
        }
 
        // Get shared data
-       ccode = curl_easy_setopt(_handle, CURLOPT_SHARE, 
CurlSession::get().getSharedHandle());
+       ccode = curl_easy_setopt(_handle, CURLOPT_SHARE,
+            CurlSession::get().getSharedHandle());
+
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // Set expiration time for DNS cache entries, in seconds
@@ -804,19 +836,19 @@
        //
        ccode = curl_easy_setopt(_handle, CURLOPT_DNS_CACHE_TIMEOUT, 60);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        ccode = curl_easy_setopt(_handle, CURLOPT_USERAGENT, "Gnash-" VERSION);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
 #ifdef GNASH_CURL_VERBOSE
        // for verbose operations
        ccode = curl_easy_setopt(_handle, CURLOPT_VERBOSE, 1);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 #endif
 
@@ -827,13 +859,13 @@
 */
        ccode = curl_easy_setopt(_handle, CURLOPT_NOSIGNAL, true);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // set url
        ccode = curl_easy_setopt(_handle, CURLOPT_URL, _url.c_str());
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        //curl_easy_setopt(_handle, CURLOPT_NOPROGRESS, false);
@@ -842,18 +874,18 @@
        // set write data and function
        ccode = curl_easy_setopt(_handle, CURLOPT_WRITEDATA, this);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        ccode = curl_easy_setopt(_handle, CURLOPT_WRITEFUNCTION,
                CurlStreamFile::recv);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        ccode = curl_easy_setopt(_handle, CURLOPT_FOLLOWLOCATION, 1);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        //fillCache(32); // pre-cache 32 bytes
@@ -861,23 +893,25 @@
 }
 
 /*public*/
-CurlStreamFile::CurlStreamFile(const std::string& url)
+CurlStreamFile::CurlStreamFile(const std::string& url,
+        const std::string& cachefile)
 {
        log_debug("CurlStreamFile %p created", this);
-       init(url);
+       init(url, cachefile);
 
        // CURLMcode ret =
        CURLMcode mcode = curl_multi_add_handle(_mhandle, _handle);
        if ( mcode != CURLM_OK ) {
-               throw gnash::GnashException(curl_multi_strerror(mcode));
+               throw GnashException(curl_multi_strerror(mcode));
        }
 }
 
 /*public*/
-CurlStreamFile::CurlStreamFile(const std::string& url, const std::string& vars)
+CurlStreamFile::CurlStreamFile(const std::string& url, const std::string& vars,
+       const std::string& cachefile)
 {
        log_debug("CurlStreamFile %p created", this);
-       init(url);
+       init(url, cachefile);
 
        _postdata = vars;
 
@@ -885,7 +919,7 @@
 
        ccode = curl_easy_setopt(_handle, CURLOPT_POST, 1);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // libcurl needs to access the POSTFIELDS during 'perform' operations,
@@ -894,7 +928,7 @@
        // The _postdata member should meet this requirement
        ccode = curl_easy_setopt(_handle, CURLOPT_POSTFIELDS, 
_postdata.c_str());
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // This is to support binary strings as postdata
@@ -903,7 +937,7 @@
        //
        ccode = curl_easy_setopt(_handle, CURLOPT_POSTFIELDSIZE, 
_postdata.size());
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
     // Disable sending an Expect: header, as some older HTTP/1.1
@@ -914,21 +948,23 @@
     _customHeaders = curl_slist_append(_customHeaders, "Expect:");
     ccode = curl_easy_setopt(_handle, CURLOPT_HTTPHEADER, _customHeaders);
     if ( ccode != CURLE_OK ) {
-        throw gnash::GnashException(curl_easy_strerror(ccode));
+        throw GnashException(curl_easy_strerror(ccode));
     }
 
        CURLMcode mcode = curl_multi_add_handle(_mhandle, _handle);
        if ( mcode != CURLM_OK ) {
-               throw gnash::GnashException(curl_multi_strerror(mcode));
+               throw GnashException(curl_multi_strerror(mcode));
        }
 
 }
 
 /*public*/
-CurlStreamFile::CurlStreamFile(const std::string& url, const std::string& 
vars, const NetworkAdapter::RequestHeaders& headers)
+CurlStreamFile::CurlStreamFile(const std::string& url, const std::string& vars,
+        const NetworkAdapter::RequestHeaders& headers,
+        const std::string& cachefile)
 {
        log_debug("CurlStreamFile %p created", this);
-       init(url);
+       init(url, cachefile);
 
        _postdata = vars;
 
@@ -957,12 +993,12 @@
 
     ccode = curl_easy_setopt(_handle, CURLOPT_HTTPHEADER, _customHeaders);
     if ( ccode != CURLE_OK ) {
-        throw gnash::GnashException(curl_easy_strerror(ccode));
+        throw GnashException(curl_easy_strerror(ccode));
     }
 
        ccode = curl_easy_setopt(_handle, CURLOPT_POST, 1);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // libcurl needs to access the POSTFIELDS during 'perform' operations,
@@ -971,7 +1007,7 @@
        // The _postdata member should meet this requirement
        ccode = curl_easy_setopt(_handle, CURLOPT_POSTFIELDS, 
_postdata.c_str());
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // This is to support binary strings as postdata
@@ -980,12 +1016,12 @@
        //
        ccode = curl_easy_setopt(_handle, CURLOPT_POSTFIELDSIZE, 
_postdata.size());
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        CURLMcode mcode = curl_multi_add_handle(_mhandle, _handle);
        if ( mcode != CURLM_OK ) {
-               throw gnash::GnashException(curl_multi_strerror(mcode));
+               throw GnashException(curl_multi_strerror(mcode));
        }
 
 }
@@ -1009,14 +1045,14 @@
        if ( eof() || _error ) return 0;
 
 #ifdef GNASH_CURL_VERBOSE
-       gnash::log_debug ("read(%d) called", bytes);
+       log_debug ("read(%d) called", bytes);
 #endif
 
        fillCache(tell() + bytes);
        if ( _error ) return 0; // error can be set by fillCache
 
 #ifdef GNASH_CURL_VERBOSE
-       gnash::log_debug("_cache.tell = %d", tell());
+       log_debug("_cache.tell = %d", tell());
 #endif
 
        return std::fread(dst, 1, bytes, _cache);
@@ -1035,7 +1071,7 @@
        }
 
 #ifdef GNASH_CURL_VERBOSE
-       gnash::log_debug ("readNonBlocking(%d) called", bytes);
+       log_debug ("readNonBlocking(%d) called", bytes);
 #endif
 
        fillCacheNonBlocking();
@@ -1065,7 +1101,7 @@
        bool ret = ( ! _running && feof(_cache) );
 
 #ifdef GNASH_CURL_VERBOSE
-       gnash::log_debug("eof() returning %d", ret);
+       log_debug("eof() returning %d", ret);
 #endif
        return ret;
 
@@ -1078,7 +1114,7 @@
        int ret =  std::ftell(_cache);
 
 #ifdef GNASH_CURL_VERBOSE
-       gnash::log_debug("tell() returning %ld", ret);
+       log_debug("tell() returning %ld", ret);
 #endif
 
        return ret;
@@ -1091,7 +1127,7 @@
 {
 #ifdef GNASH_CURL_WARN_SEEKSBACK
        if ( pos < tell() ) {
-               gnash::log_debug("Warning: seek backward requested (%ld from 
%ld)",
+               log_debug("Warning: seek backward requested (%ld from %ld)",
                        pos, tell());
        }
 #endif
@@ -1101,12 +1137,12 @@
 
        if ( _cached < (unsigned int)pos )
        {
-               gnash::log_error ("Warning: could not cache anough bytes on 
seek: %d requested, %d cached", pos, _cached);
+               log_error ("Warning: could not cache anough bytes on seek: %d 
requested, %d cached", pos, _cached);
                return -1; // couldn't cache so many bytes
        }
 
        if (std::fseek(_cache, pos, SEEK_SET) == -1) {
-               gnash::log_error("Warning: fseek failed");
+               log_error("Warning: fseek failed");
                return -1;
        } else {
                return 0;
@@ -1128,15 +1164,15 @@
 
                if ( mcode != CURLM_OK )
                {
-                       throw gnash::IOException(curl_multi_strerror(mcode));
+                       throw IOException(curl_multi_strerror(mcode));
                }
 
                 long code;
                 curl_easy_getinfo(_handle, CURLINFO_RESPONSE_CODE, &code);
                 if ( code == 404 ) // file not found!
                 {
-                       throw gnash::IOException("File not found");
-                        //gnash::log_error(_("404 response from url %s"), 
_url);
+                       throw IOException("File not found");
+                        //log_error(_("404 response from url %s"), _url);
                         //_error = TU_FILE_OPEN_ERROR;
                         //return;
                 }
@@ -1144,8 +1180,8 @@
        }
 
        if (std::fseek(_cache, 0, SEEK_END) == -1) {
-               throw gnash::IOException("NetworkAdapter: fseek to end failed");
-               //gnash::log_error("Warning: fseek to end failed");
+               throw IOException("NetworkAdapter: fseek to end failed");
+               //log_error("Warning: fseek to end failed");
                //return -1;
        } 
 }
@@ -1162,7 +1198,7 @@
        }
 
 #ifdef GNASH_CURL_VERBOSE
-       gnash::log_debug("get_stream_size() returning %lu", _size);
+       log_debug("get_stream_size() returning %lu", _size);
 #endif
 
        return _size;
@@ -1200,20 +1236,20 @@
        // Configure the fake handle to use the share (shared cookies in 
particular..)
        ccode = curl_easy_setopt(fakeHandle, CURLOPT_SHARE, getSharedHandle());
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // Configure the fake handle to read cookies from the specified file
        ccode = curl_easy_setopt(fakeHandle, CURLOPT_COOKIEFILE, cookiesIn);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // need to pass a non-zero URL string for COOKIEFILE to
        // be really parsed
        ccode = curl_easy_setopt(fakeHandle, CURLOPT_URL, "");
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // perform, to activate actual cookie file parsing
@@ -1257,13 +1293,13 @@
        // Configure the fake handle to use the share (shared cookies in 
particular..)
        ccode = curl_easy_setopt(fakeHandle, CURLOPT_SHARE, getSharedHandle());
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // Configure the fake handle to write cookies to the specified file
        ccode = curl_easy_setopt(fakeHandle, CURLOPT_COOKIEJAR , cookiesOut);
        if ( ccode != CURLE_OK ) {
-               throw gnash::GnashException(curl_easy_strerror(ccode));
+               throw GnashException(curl_easy_strerror(ccode));
        }
 
        // Cleanup, to trigger actual cookie file flushing
@@ -1280,62 +1316,64 @@
 //-------------------------------------------
 
 std::auto_ptr<IOChannel>
-NetworkAdapter::makeStream(const std::string& url)
-{
-#ifdef GNASH_CURL_VERBOSE
-       gnash::log_debug("making curl stream for %s", url);
-#endif
-
-       std::auto_ptr<IOChannel> stream;
-
-       try {
-               stream.reset(new CurlStreamFile(url));
-       }
-       catch (const std::exception& ex) {
-               gnash::log_error("curl stream: %s", ex.what());
-       }
-       return stream;
-}
-
-std::auto_ptr<IOChannel>
-NetworkAdapter::makeStream(const std::string& url, const std::string& postdata)
-{
-#ifdef GNASH_CURL_VERBOSE
-       gnash::log_debug("making curl stream for %s", url);
-#endif
-
-       std::auto_ptr<IOChannel> stream;
-
-       try {
-               stream.reset(new CurlStreamFile(url, postdata));
-       }
-       catch (const std::exception& ex) {
-               gnash::log_error("curl stream: %s", ex.what());
-       }
-       return stream;
-}
-
-std::auto_ptr<IOChannel>
-NetworkAdapter::makeStream(const std::string& url, const std::string& postdata,
-                                const RequestHeaders& headers)
-{
-
-       std::auto_ptr<IOChannel> stream;
-
-       try {
-               stream.reset(new CurlStreamFile(url, postdata, headers));
-       }
-       catch (const std::exception& ex) {
-               gnash::log_error("curl stream: %s", ex.what());
+NetworkAdapter::makeStream(const std::string& url, const std::string& 
cachefile)
+{
+#ifdef GNASH_CURL_VERBOSE
+       log_debug("making curl stream for %s", url);
+#endif
+
+       std::auto_ptr<IOChannel> stream;
+
+       try {
+               stream.reset(new CurlStreamFile(url, cachefile));
+       }
+       catch (const std::exception& ex) {
+               log_error("curl stream: %s", ex.what());
+       }
+       return stream;
+}
+
+std::auto_ptr<IOChannel>
+NetworkAdapter::makeStream(const std::string& url, const std::string& postdata,
+        const std::string& cachefile)
+{
+#ifdef GNASH_CURL_VERBOSE
+       log_debug("making curl stream for %s", url);
+#endif
+
+       std::auto_ptr<IOChannel> stream;
+
+       try {
+               stream.reset(new CurlStreamFile(url, postdata, cachefile));
+       }
+       catch (const std::exception& ex) {
+               log_error("curl stream: %s", ex.what());
+       }
+       return stream;
+}
+
+std::auto_ptr<IOChannel>
+NetworkAdapter::makeStream(const std::string& url, const std::string& postdata,
+        const RequestHeaders& headers, const std::string& cachefile)
+{
+
+       std::auto_ptr<IOChannel> stream;
+
+       try {
+               stream.reset(new CurlStreamFile(url, postdata, headers, 
cachefile));
+       }
+       catch (const std::exception& ex) {
+               log_error("curl stream: %s", ex.what());
        }
 
     return stream;
 
 }
 
-/// Define static member.
-std::set<std::string, StringNoCaseLessThan>
-NetworkAdapter::_reservedNames = boost::assign::list_of
+const NetworkAdapter::ReservedNames&
+NetworkAdapter::reservedNames()
+{
+    static const ReservedNames names = boost::assign::list_of
     ("Accept-Ranges")
     ("Age")
     ("Allow")
@@ -1368,6 +1406,9 @@
     ("Warning")
     ("WWW-Authenticate");
 
+    return names;
+}
+
 } // namespace gnash
 
 #endif // def USE_CURL

=== modified file 'libbase/rc.cpp'
--- a/libbase/rc.cpp    2009-01-22 20:10:39 +0000
+++ b/libbase/rc.cpp    2009-01-27 13:53:00 +0000
@@ -101,7 +101,9 @@
     // TODO: give a  default value, and let 0 mean "disabled" -- 0 currently 
is overridden by libbase/shm.cpp 
     _lcshmkey(0),
     _ignoreFSCommand(true),
-    _quality(-1)
+    _quality(-1),
+    _saveStreamingMedia(false),
+    _saveLoadedMedia(false)
 {
     expandPath(_solsandbox);
 
@@ -418,6 +420,12 @@
                 continue;
             }
 
+            if (noCaseCompare(variable, "mediaDir") ) {
+                expandPath(value);
+                _mediaCacheDir = value;
+                continue;
+            }
+            
             if (noCaseCompare(variable, "documentroot") ) {
                 _wwwroot = value;
                 continue;
@@ -506,6 +514,12 @@
             ||
                  extractNumber(_quality, "quality", variable, value)
             ||
+                 extractSetting(_saveLoadedMedia, "saveLoadedMedia",
+                         variable, value)
+            ||
+                 extractSetting(_saveStreamingMedia, "saveStreamingMedia",
+                         variable, value)
+            || 
                  extractSetting(_ignoreFSCommand, "ignoreFsCommand", variable,
                          value)
             ||
@@ -656,6 +670,8 @@
     cmd << "LCTrace " << _lctrace << endl <<
     cmd << "LCShmkey " << std::hex << (boost::uint32_t) _lcshmkey << endl <<
     cmd << "ignoreFSCommand " << _ignoreFSCommand << endl <<    
+    cmd << "saveStreamingMedia " << _saveStreamingMedia << endl <<    
+    cmd << "saveLoadedMedia " << _saveLoadedMedia << endl <<    
    
     // Strings.
 
@@ -666,6 +682,7 @@
     // debuglog to nothing, only to find it returns to "gnash-debug.log"
     // at the next run (even though that's not the way to use it...)
 
+    cmd << "mediaDir " << _mediaCacheDir << endl <<    
     cmd << "debuglog " << _log << endl <<
     cmd << "documentroot " << _wwwroot << endl <<
     cmd << "flashSystemOS " << _flashSystemOS << endl <<

=== modified file 'libbase/rc.h'
--- a/libbase/rc.h      2009-01-22 20:10:39 +0000
+++ b/libbase/rc.h      2009-01-27 13:53:00 +0000
@@ -158,7 +158,9 @@
     /// Sets the RcInitFile blacklist of domains to block
     //
     /// @param list a std::vector of strings containing domains without 
protocol
-    void setBlacklist (const std::vector<std::string>& list) { _blacklist = 
list; }
+    void setBlacklist (const std::vector<std::string>& list) { 
+        _blacklist = list;
+    }
 
     /// Return the list of directories to be used as the 'local' sandbox
     //
@@ -183,24 +185,42 @@
         _localSandboxPath = path;
     }
 
-    const std::string& getFlashVersionString() const { return 
_flashVersionString; }
-    void setFlashVersionString(const std::string& value) { _flashVersionString 
= value; }
-
-    const std::string& getFlashSystemOS() const { return _flashSystemOS; }
-    void setFlashSystemOS(const std::string& value) { _flashSystemOS = value; }
-
-    const std::string& getFlashSystemManufacturer() const { return 
_flashSystemManufacturer; }
-    void setFlashSystemManufacturer(const std::string& value) { 
_flashSystemManufacturer = value; }
+    const std::string& getFlashVersionString() const {
+        return _flashVersionString;
+    }
+    
+    void setFlashVersionString(const std::string& value) {
+        _flashVersionString = value;
+    }
+
+    const std::string& getFlashSystemOS() const {
+        return _flashSystemOS;
+    }
+    
+    void setFlashSystemOS(const std::string& value) {
+        _flashSystemOS = value;
+    }
+
+    const std::string& getFlashSystemManufacturer() const {
+        return _flashSystemManufacturer;
+    }
+    
+    void setFlashSystemManufacturer(const std::string& value) {
+        _flashSystemManufacturer = value;
+    }
     
     const std::string& getGstAudioSink() const { return _gstaudiosink; }
+    
     void setGstAudioSink(const std::string& value) { _gstaudiosink = value; }
 
     int getRetries() const { return _retries; }
+    
     void setRetries(int x) { _retries = x; }
 
-    /// Return the number of seconds of inactivity before timing out streams 
downloads
+    /// The number of seconds of inactivity before timing out streams downloads
     double getStreamsTimeout() const { return _streamsTimeout; }
-    /// Set the number of seconds of inactivity before timing out streams 
downloads
+
+    /// Set seconds of inactivity before timing out streams downloads
     void setStreamsTimeout(const double &x) { _streamsTimeout = x; }
 
     /// Get the URL opener command format
@@ -225,25 +245,125 @@
     void setSOLSafeDir(const std::string &x) { _solsandbox = x; }
 
     bool getSOLLocalDomain() const { return _sollocaldomain; }
+    
     void setSOLLocalDomain(bool x) { _sollocaldomain = x; }
+    
     bool getSOLReadOnly() const { return _solreadonly; }
+    
     void setSOLReadOnly(bool x) { _solreadonly = x; }
+    
     bool getLocalConnection() const { return _lcdisabled; }
+    
     void setLocalConnection(bool x) { _lcdisabled = x; }
+    
     // Enable tracing all LocalConnection traffic
     bool getLCTrace() const { return _lctrace; }
+    
     void setLCTrace(bool x) { _lctrace = x; }
 
-    // 
     key_t getLCShmKey() const { return static_cast<key_t>(_lcshmkey); }
+    
     void setLCShmKey(bool x) { _lcshmkey = x; }
 
     bool ignoreFSCommand() const { return _ignoreFSCommand; }
+    
     void ignoreFSCommand(bool value) { _ignoreFSCommand = value; }
-        
+    
+    void saveStreamingMedia(bool value) { _saveStreamingMedia = value; }
+
+    bool saveStreamingMedia() const { return _saveStreamingMedia; }
+
+    void saveLoadedMedia(bool value) { _saveLoadedMedia = value; }
+
+    bool saveLoadedMedia() const { return _saveLoadedMedia; }
+
+    void setMediaDir(const std::string& value) { _mediaCacheDir = value; }
+
+    const std::string& getMediaDir() const { return _mediaCacheDir; }
+
     void dump();    
 
 protected:
+    
+    // A function only for writing path lists to an outstream.
+    void writeList(const PathList& list, std::ostream& o);
+
+    /// Construct only by getDefaultInstance()
+    RcInitFile();
+
+    /// Never destroy (TODO: add a destroyDefaultInstance)
+    ~RcInitFile();
+
+    /// Substitutes user's home directory for ~ on a path string
+    /// according to POSIX standard.
+    ///
+    /// @param path the path to expand.
+    static void expandPath(std::string& path);
+
+    /// \brief
+    /// If variable matches pattern (case-insensitive)
+    /// set var according to value
+    //
+    /// @return true if variable matches pattern, false otherwise
+    /// @param var the variable to change
+    /// @param pattern the pattern for matching
+    /// @variable the variable to match to pattern
+    /// @value the value to adopt if variable matches pattern.
+    static bool extractSetting(bool &var, const std::string& pattern,
+                        const std::string &variable, const std::string &value);
+
+    /// \brief
+    /// If variable matches pattern (case-insensitive)
+    /// set num according to value
+    //
+    /// @return true if variable matches pattern, false otherwise
+    /// @param num the variable to change
+    /// @param pattern the pattern for matching
+    /// @variable the variable to match to pattern
+    /// @value the value to adopt if variable matches pattern.
+    template<typename T>
+    static bool extractNumber(T& num, const std::string& pattern,
+                        const std::string &variable, const std::string &value)
+    {
+
+        StringNoCaseEqual noCaseCompare;
+
+        if (noCaseCompare(variable, pattern)) {
+            std::istringstream in(value);
+            if (in >> num) return true;
+            
+            // If conversion fails, set value to 0 rather than leaving
+            // it as the default.
+            std::cerr << "Conversion overflow in extractNumber: " << 
+                value << std::endl;
+            num = 0;
+            return true;
+        }
+        
+        return false;
+    }
+
+    /// \brief
+    /// If variable matches pattern (case-insensitive)
+    /// set out according to value
+    //
+    /// @return true if variable matches pattern, false otherwise
+    /// @param out the variable to change
+    /// @param pattern the pattern for matching
+    /// @variable the variable to match to pattern
+    /// @value the value to adopt if variable matches pattern.
+    static bool extractDouble(double &out, const std::string& pattern,
+                        const std::string &variable, const std::string &value);
+
+
+    /// \brief parses a space-separated list into std::vector list 
+    //
+    /// @param list the vector to modify or generate.
+    /// @param action either 'set' or 'append': whether to add to or
+    ///         clear the vector.
+    /// @param items string of space-separated values. This gets nuked.
+    void parseList(std::vector<std::string>& list, const std::string &action,
+                               const std::string &items);
 
     typedef boost::char_separator<char> Sep;
     typedef boost::tokenizer< Sep > Tok;
@@ -375,87 +495,11 @@
     /// The quality to display SWFs in. -1 to allow the SWF to override.
     int _quality;
 
-protected:
+    bool _saveStreamingMedia;
     
-    // A function only for writing path lists to an outstream.
-    void writeList(const PathList& list, std::ostream& o);
-
-    /// Construct only by getDefaultInstance()
-    RcInitFile();
-
-    /// Never destroy (TODO: add a destroyDefaultInstance)
-    ~RcInitFile();
-
-    /// Substitutes user's home directory for ~ on a path string
-    /// according to POSIX standard.
-    ///
-    /// @param path the path to expand.
-    static void expandPath(std::string& path);
-
-    /// \brief
-    /// If variable matches pattern (case-insensitive)
-    /// set var according to value
-    //
-    /// @return true if variable matches pattern, false otherwise
-    /// @param var the variable to change
-    /// @param pattern the pattern for matching
-    /// @variable the variable to match to pattern
-    /// @value the value to adopt if variable matches pattern.
-    static bool extractSetting(bool &var, const std::string& pattern,
-                        const std::string &variable, const std::string &value);
-
-    /// \brief
-    /// If variable matches pattern (case-insensitive)
-    /// set num according to value
-    //
-    /// @return true if variable matches pattern, false otherwise
-    /// @param num the variable to change
-    /// @param pattern the pattern for matching
-    /// @variable the variable to match to pattern
-    /// @value the value to adopt if variable matches pattern.
-    template<typename T>
-    static bool extractNumber(T& num, const std::string& pattern,
-                        const std::string &variable, const std::string &value)
-    {
-
-        StringNoCaseEqual noCaseCompare;
-
-        if (noCaseCompare(variable, pattern)) {
-            std::istringstream in(value);
-            if (in >> num) return true;
-            
-            // If conversion fails, set value to 0 rather than leaving
-            // it as the default.
-            std::cerr << "Conversion overflow in extractNumber: " << 
-                value << std::endl;
-            num = 0;
-            return true;
-        }
-        
-        return false;
-    }
-
-    /// \brief
-    /// If variable matches pattern (case-insensitive)
-    /// set out according to value
-    //
-    /// @return true if variable matches pattern, false otherwise
-    /// @param out the variable to change
-    /// @param pattern the pattern for matching
-    /// @variable the variable to match to pattern
-    /// @value the value to adopt if variable matches pattern.
-    static bool extractDouble(double &out, const std::string& pattern,
-                        const std::string &variable, const std::string &value);
-
-
-    /// \brief parses a space-separated list into std::vector list 
-    //
-    /// @param list the vector to modify or generate.
-    /// @param action either 'set' or 'append': whether to add to or
-    ///         clear the vector.
-    /// @param items string of space-separated values. This gets nuked.
-    void parseList(std::vector<std::string>& list, const std::string &action,
-                               const std::string &items);
+    bool _saveLoadedMedia;
+
+    std::string _mediaCacheDir;
 
 };
 

=== modified file 'libcore/StreamProvider.cpp'
--- a/libcore/StreamProvider.cpp        2009-01-27 12:23:12 +0000
+++ b/libcore/StreamProvider.cpp        2009-01-29 16:45:09 +0000
@@ -35,9 +35,22 @@
 #include <map>
 #include <string>
 #include <vector>
-
-namespace gnash
-{
+#include <boost/algorithm/string/replace.hpp>
+
+namespace gnash {
+
+namespace {
+    
+    std::string urlToDirectory(const std::string& path);
+    
+    /// Make a unique cachefile name from the supplied name.
+    /// If all possible filenames are taken, return an empty string.
+    std::string incrementalRename(const URL& url);
+    
+    /// Make a non-unique cachefile name from the supplied name.
+    /// If the directory cannot be created, return an empty string.
+    std::string overwriteExisting(const URL& url);
+}
 
 StreamProvider&
 StreamProvider::getDefaultInstance()
@@ -46,8 +59,15 @@
        return inst;
 }
 
+StreamProvider::NamingPolicy
+StreamProvider::currentNamingPolicy() const
+{
+    //return overwriteExisting;
+    return incrementalRename;
+}
+
 std::auto_ptr<IOChannel>
-StreamProvider::getStream(const URL& url)
+StreamProvider::getStream(const URL& url, NamingPolicy np)
 {
 
     std::auto_ptr<IOChannel> stream;
@@ -72,7 +92,7 @@
                else
                {
             // check security here !!
-                   if ( ! URLAccessManager::allow(url) ) return stream;
+                   if (!URLAccessManager::allow(url)) return stream;
 
                        FILE *newin = std::fopen(path.c_str(), "rb");
                        if (!newin)  { 
@@ -85,8 +105,9 @@
        }
        else
        {
-               if ( URLAccessManager::allow(url) ) {
-                       stream = NetworkAdapter::makeStream(url.str());
+               if (URLAccessManager::allow(url)) {
+                       stream = NetworkAdapter::makeStream(url.str(),
+                    np ?  np(url) : std::string());
                }
 
         // Will return 0 auto_ptr if not allowed.
@@ -96,7 +117,7 @@
 
 std::auto_ptr<IOChannel>
 StreamProvider::getStream(const URL& url, const std::string& postdata,
-                          const NetworkAdapter::RequestHeaders& headers)
+        const NetworkAdapter::RequestHeaders& headers, NamingPolicy np)
 {
 
     if (url.protocol() == "file")
@@ -110,7 +131,8 @@
     }
 
        if ( URLAccessManager::allow(url) ) {
-               return NetworkAdapter::makeStream(url.str(), postdata, headers);
+               return NetworkAdapter::makeStream(url.str(), postdata, headers,
+                np ? np(url) : std::string());
        }
 
        return std::auto_ptr<IOChannel>();
@@ -118,7 +140,8 @@
 }
 
 std::auto_ptr<IOChannel>
-StreamProvider::getStream(const URL& url, const std::string& postdata)
+StreamProvider::getStream(const URL& url, const std::string& postdata,
+       NamingPolicy np)
 {
 
     std::auto_ptr<IOChannel> stream;
@@ -151,8 +174,9 @@
        }
        else
        {
-               if ( URLAccessManager::allow(url) ) {
-                       stream = NetworkAdapter::makeStream(url.str(), 
postdata);
+               if (URLAccessManager::allow(url)) {
+                       stream = NetworkAdapter::makeStream(url.str(), postdata,
+                    np ? np(url) : std::string());
                }
         // Will return 0 auto_ptr if not allowed.
                return stream;          
@@ -160,5 +184,97 @@
        }
 }
 
+
+namespace {
+
+/// Transform a URL into a directory and create it.
+//
+/// @return     an empty string if the directory cannot be created, otherwise
+///             the name of the created directory with a trailing slash.
+/// @param url  The path to transform. Anything after the last '/' is ignored.
+std::string
+urlToDirectory(const std::string& path)
+{
+
+    const RcInitFile& rcfile = RcInitFile::getDefaultInstance();
+    const std::string& dir = rcfile.getMediaDir() + "/" + path;
+ 
+    // Create the user-specified directory if possible.
+    // An alternative would be to use the 'host' part and create a 
+    // directory tree.
+    if (!mkdirRecursive(dir)) {
+        // Error
+        return std::string();
+    }
+
+    return dir;
+
+}
+
+std::string
+overwriteExisting(const URL& url)
+{
+    std::string path = url.path().substr(1);
+    
+    // Replace all slashes with a _ for a flat directory structure.
+    boost::replace_all(path, "/", "_");
+
+    const std::string& dir = urlToDirectory(url.hostname() + "/");
+
+    if (dir.empty()) return std::string();
+
+    return dir + path;
+}
+
+std::string
+incrementalRename(const URL& url)
+{
+
+    const std::string& path = url.path();
+    assert(!path.empty());
+    assert(path[0] == '/');
+    
+    // Find the last dot, but not if it's first in the path (after the
+    // initial '/').
+    std::string::size_type dot = path.rfind('.');
+    if (dot == 1) dot = std::string::npos;
+
+    // Take the path from after the initial '/' to the last '.' for
+    // manipulation. It doesn't matter if dot is npos.
+    std::string pre = path.substr(1, dot - 1);
+
+    // Replace all slashes with a _ for a flat directory structure.
+    boost::replace_all(pre, "/", "_");
+
+    const std::string& suffix = (dot == std::string::npos) ? "" : 
+        path.substr(dot);
+
+    // Add a trailing slash.
+    const std::string& dir = urlToDirectory(url.hostname() + "/");
+    if (dir.empty()) return std::string();
+
+    std::ostringstream s(dir + pre + suffix);
+
+    size_t i = 0;
+
+    const size_t m = std::numeric_limits<size_t>::max();
+
+    struct stat st;
+    while (stat(s.str().c_str(), &st) >= 0 && i < m) {
+        s.str("");
+        s << dir << pre << i << suffix;
+        ++i;
+    }
+
+    // If there are no options left, return an empty string.
+    if (i == m) {
+        return std::string();
+    }
+
+    return s.str();
+
+}
+
+} // anonymous namespace
 } // namespace gnash
 

=== modified file 'libcore/StreamProvider.h'
--- a/libcore/StreamProvider.h  2009-01-26 09:03:34 +0000
+++ b/libcore/StreamProvider.h  2009-01-27 16:40:28 +0000
@@ -39,6 +39,8 @@
 
 public:
 
+    typedef std::string (*NamingPolicy) (const URL&);
+
        StreamProvider() {}
 
        virtual ~StreamProvider() {}
@@ -50,7 +52,8 @@
        /// On error NULL is returned
        /// Derive from this for a CachingStreamProvider
        ///
-       virtual std::auto_ptr<IOChannel> getStream(const URL& url);
+       virtual std::auto_ptr<IOChannel> getStream(const URL& url,
+            NamingPolicy np = 0);
 
        /// Get a stream from the response of a POST operation
        //
@@ -67,12 +70,15 @@
        ///
        ///
        virtual std::auto_ptr<IOChannel> getStream(const URL& url,
-            const std::string& postdata);
+            const std::string& postdata, NamingPolicy np = 0);
        
        virtual std::auto_ptr<IOChannel> getStream(const URL& url,
             const std::string& postdata,
-            const NetworkAdapter::RequestHeaders& headers);
+            const NetworkAdapter::RequestHeaders& headers, NamingPolicy np = 
0);
        
+    /// Return the currently selected policy for converting URL to filename
+    virtual NamingPolicy currentNamingPolicy() const;
+
 };
 
 } // namespace gnash

=== modified file 'libcore/asobj/NetConnection_as.cpp'
--- a/libcore/asobj/NetConnection_as.cpp        2009-01-22 20:10:39 +0000
+++ b/libcore/asobj/NetConnection_as.cpp        2009-01-27 16:40:28 +0000
@@ -589,7 +589,8 @@
 #endif
         queued_count = 0;
 
-        _connection.reset(StreamProvider::getDefaultInstance().getStream(_url, 
postdata_str, _headers).release());
+        _connection.reset(StreamProvider::getDefaultInstance().getStream(
+                    _url, postdata_str, _headers).release());
 
         _postdata.resize(6);
 #ifdef GNASH_DEBUG_REMOTING
@@ -959,7 +960,14 @@
     // If name is a full or relative URL passed from NetStream.play(), it
     // must be constructed against the base URL, not the NetConnection uri,
     // which should always be null in this case.
-    return streamProvider.getStream(URL(name, ri.baseURL()));
+    const URL url(name, ri.baseURL());
+
+    const RcInitFile& rcfile = RcInitFile::getDefaultInstance();
+
+    StreamProvider::NamingPolicy cacheNamer = rcfile.saveStreamingMedia() ? 
+        streamProvider.currentNamingPolicy() : 0;
+
+    return streamProvider.getStream(url, cacheNamer);
 
 }
 

=== modified file 'libcore/impl.cpp'
--- a/libcore/impl.cpp  2009-01-22 20:10:39 +0000
+++ b/libcore/impl.cpp  2009-01-27 16:40:28 +0000
@@ -324,8 +324,15 @@
 
   StreamProvider& streamProvider = runInfo.streamProvider();
 
-  if ( postdata ) in = streamProvider.getStream(url, *postdata);
-  else in = streamProvider.getStream(url);
+  const RcInitFile& rcfile = RcInitFile::getDefaultInstance();
+
+  StreamProvider::NamingPolicy cacheNamer = rcfile.saveLoadedMedia() ? 
+      streamProvider.currentNamingPolicy() : 0;
+
+  if ( postdata ) in = streamProvider.getStream(url, *postdata,
+          cacheNamer);
+  else in = streamProvider.getStream(url, cacheNamer);
+
   if ( ! in.get() )
   {
       log_error(_("failed to open '%s'; can't create movie"), url);


reply via email to

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