From 7293844e4a2c204f558d60c630b52d7bc79fe43a Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 29 Jul 2009 19:58:26 +0000 Subject: [PATCH] better download rules --- direct/src/plugin/load_plugin.cxx | 24 +--- direct/src/plugin/load_plugin.h | 3 +- direct/src/plugin/make_contents.py | 12 +- direct/src/plugin/make_package.py | 11 +- direct/src/plugin/mkdir_complete.cxx | 8 +- direct/src/plugin/p3dDownload.cxx | 4 +- direct/src/plugin/p3dFileParams.cxx | 51 ++++--- direct/src/plugin/p3dFileParams.h | 7 +- direct/src/plugin/p3dInstance.cxx | 23 ++-- direct/src/plugin/p3dInstance.h | 5 +- direct/src/plugin/p3dInstanceManager.I | 11 ++ direct/src/plugin/p3dInstanceManager.cxx | 165 ++++++++++++++++++++--- direct/src/plugin/p3dInstanceManager.h | 24 +++- direct/src/plugin/p3dPackage.cxx | 125 ++++++++++++++--- direct/src/plugin/p3dPackage.h | 9 +- direct/src/plugin/p3dWinSplashWindow.cxx | 52 +++---- direct/src/plugin/p3d_plugin.cxx | 56 +++++--- direct/src/plugin/p3d_plugin.h | 46 +++---- direct/src/plugin_npapi/ppInstance.cxx | 120 +++++++++++------ direct/src/plugin_npapi/ppInstance.h | 3 +- direct/src/plugin_standalone/panda3d.cxx | 29 ++-- direct/src/plugin_standalone/panda3d.h | 5 +- direct/src/showutil/FreezeTool.py | 4 +- 23 files changed, 548 insertions(+), 249 deletions(-) diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index a7a45befc9..c5c21fe9dd 100755 --- a/direct/src/plugin/load_plugin.cxx +++ b/direct/src/plugin/load_plugin.cxx @@ -123,7 +123,8 @@ static void unload_dso(); // path. //////////////////////////////////////////////////////////////////// bool -load_plugin(const string &p3d_plugin_filename) { +load_plugin(const string &p3d_plugin_filename, + const string &contents_filename) { string filename = p3d_plugin_filename; if (filename.empty()) { // Look for the plugin along the path. @@ -292,26 +293,7 @@ load_plugin(const string &p3d_plugin_filename) { // Successfully loaded. plugin_loaded = true; -#ifdef P3D_PLUGIN_LOGFILE2 - string logfilename = P3D_PLUGIN_LOGFILE2; -#else - string logfilename; -#endif // P3D_PLUGIN_LOGFILE2 - - if (logfilename.empty()) { -#ifdef _WIN32 - static const size_t buffer_size = 4096; - char buffer[buffer_size]; - if (GetTempPath(buffer_size, buffer) != 0) { - logfilename = buffer; - logfilename += "panda3d.2.log"; - } -#else - logfilename = "/tmp/panda3d.2.log"; -#endif // _WIN32 - } - - if (!P3D_initialize(P3D_API_VERSION, logfilename.c_str())) { + if (!P3D_initialize(P3D_API_VERSION, contents_filename.c_str())) { // Oops, failure to initialize. cerr << "Failed to initialize plugin (wrong API version?)\n"; unload_plugin(); diff --git a/direct/src/plugin/load_plugin.h b/direct/src/plugin/load_plugin.h index 4edf19ecd7..59562f31df 100755 --- a/direct/src/plugin/load_plugin.h +++ b/direct/src/plugin/load_plugin.h @@ -58,7 +58,8 @@ extern P3D_instance_feed_url_stream_func *P3D_instance_feed_url_stream; extern P3D_instance_handle_event_func *P3D_instance_handle_event; string get_plugin_basename(); -bool load_plugin(const string &p3d_plugin_filename); +bool load_plugin(const string &p3d_plugin_filename, + const string &contents_filename); void unload_plugin(); bool is_plugin_loaded(); diff --git a/direct/src/plugin/make_contents.py b/direct/src/plugin/make_contents.py index cfb7408e3f..a4ce5d88cf 100755 --- a/direct/src/plugin/make_contents.py +++ b/direct/src/plugin/make_contents.py @@ -54,9 +54,9 @@ class ContentsMaker: print >> f, '' print >> f, '' print >> f, '' - for packageName, packageVersion, packagePlatform, file in self.packages: - print >> f, ' ' % ( - packageName, packageVersion, packagePlatform or '', file.getParams()) + for packageName, packagePlatform, packageVersion, file in self.packages: + print >> f, ' ' % ( + packageName, packagePlatform or '', packageVersion, file.getParams()) print >> f, '' f.close() @@ -93,14 +93,14 @@ class ContentsMaker: file = FileSpec(localpath + xml, Filename(self.stageDir, localpath + xml)) print file.filename - self.packages.append((packageName, packageVersion, packagePlatform, file)) + self.packages.append((packageName, packagePlatform, packageVersion, file)) if localpath.count('/') == 3: - packageName, packageVersion, packagePlatform, junk = localpath.split('/') + packageName, packagePlatform, packageVersion, junk = localpath.split('/') file = FileSpec(localpath + xml, Filename(self.stageDir, localpath + xml)) print file.filename - self.packages.append((packageName, packageVersion, packagePlatform, file)) + self.packages.append((packageName, packagePlatform, packageVersion, file)) def makeContents(args): diff --git a/direct/src/plugin/make_package.py b/direct/src/plugin/make_package.py index f4ea98b00e..e9933a6424 100755 --- a/direct/src/plugin/make_package.py +++ b/direct/src/plugin/make_package.py @@ -77,8 +77,9 @@ class PackageMaker: self.packageStageDir = Filename(self.stageDir, '%s/%s' % (self.packageName, self.packageVersion)) if self.packagePlatform: - self.packageFullname += '_%s' % (self.packagePlatform) - self.packageStageDir = Filename(self.packageStageDir, self.packagePlatform) + self.packageFullname = '%s_%s_%s' % ( + self.packageName, self.packagePlatform, self.packageVersion) + self.packageStageDir = Filename(self.stageDir, '%s/%s/%s' % (self.packageName, self.packagePlatform, self.packageVersion)) Filename(self.packageStageDir, '.').makeDir() self.cleanDir(self.packageStageDir) @@ -121,7 +122,7 @@ class PackageMaker: f = open(descFilePathname.toOsSpecific(), 'w') print >> f, '' print >> f, '' - print >> f, '' % (self.packageName, self.packageVersion, self.packagePlatform or '') + print >> f, '' % (self.packageName, self.packagePlatform or '', self.packageVersion) print >> f, ' ' % (uncompressedArchive.getParams()) print >> f, ' ' % (compressedArchive.getParams()) for file in self.components: @@ -209,9 +210,9 @@ def makePackage(args): if len(tokens) >= 1: pm.packageName = tokens[0] if len(tokens) >= 2: - pm.packageVersion = tokens[1] - if len(tokens) >= 3: pm.packagePlatform = tokens[2] + if len(tokens) >= 3: + pm.packageVersion = tokens[1] if len(tokens) >= 4: raise ArgumentError, 'Too many tokens in string: %s' % (value) diff --git a/direct/src/plugin/mkdir_complete.cxx b/direct/src/plugin/mkdir_complete.cxx index 56b0179925..bdcded13a2 100755 --- a/direct/src/plugin/mkdir_complete.cxx +++ b/direct/src/plugin/mkdir_complete.cxx @@ -85,7 +85,7 @@ mkdir_complete(const string &dirname, ostream &logfile) { return false; #else //_WIN32 - if (mkdir(dirname.c_str(), 0777) == 0) { + if (mkdir(dirname.c_str(), 0755) == 0) { // Success! return true; } @@ -101,7 +101,7 @@ mkdir_complete(const string &dirname, ostream &logfile) { string parent = get_dirname(dirname); if (!parent.empty() && mkdir_complete(parent, logfile)) { // Parent successfully created. Try again to make the child. - if (mkdir(dirname.c_str(), 0777) == 0) { + if (mkdir(dirname.c_str(), 0755) == 0) { // Got it! return true; } @@ -147,13 +147,13 @@ mkfile_complete(const string &filename, ostream &logfile) { return true; #else // _WIN32 - int fd = creat(filename.c_str(), 0777); + int fd = creat(filename.c_str(), 0755); if (fd == -1) { // Try to make the parent directory first. string parent = get_dirname(filename); if (!parent.empty() && mkdir_complete(parent, logfile)) { // Parent successfully created. Try again to make the file. - fd = creat(filename.c_str(), 0777); + fd = creat(filename.c_str(), 0755); } if (fd == -1) { logfile diff --git a/direct/src/plugin/p3dDownload.cxx b/direct/src/plugin/p3dDownload.cxx index d925d8ca06..bc19c3e3b4 100755 --- a/direct/src/plugin/p3dDownload.cxx +++ b/direct/src/plugin/p3dDownload.cxx @@ -131,6 +131,8 @@ download_progress() { if (now != _last_reported_time || true) { _last_reported_time = now; } + nout << "Downloading " << get_url() << ": " + << int(get_download_progress() * 1000.0) / 10.0 << "\n"; } //////////////////////////////////////////////////////////////////// @@ -143,6 +145,6 @@ download_progress() { //////////////////////////////////////////////////////////////////// void P3DDownload:: download_finished(bool success) { - nout << "Downloading " << get_url() << ": " + nout << "Downloaded " << get_url() << ": " << int(get_download_progress() * 1000.0) / 10.0 << "\n"; } diff --git a/direct/src/plugin/p3dFileParams.cxx b/direct/src/plugin/p3dFileParams.cxx index 7f953fafe0..38325b92cb 100644 --- a/direct/src/plugin/p3dFileParams.cxx +++ b/direct/src/plugin/p3dFileParams.cxx @@ -25,15 +25,47 @@ P3DFileParams() { } //////////////////////////////////////////////////////////////////// -// Function: P3DFileParams::Constructor +// Function: P3DFileParams::Copy Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// P3DFileParams:: -P3DFileParams(const string &p3d_filename, - const P3D_token tokens[], size_t num_tokens) : - _p3d_filename(p3d_filename) +P3DFileParams(const P3DFileParams ©) : + _p3d_filename(copy._p3d_filename), + _tokens(copy._tokens) { +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DFileParams::Copy Assignment +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void P3DFileParams:: +operator = (const P3DFileParams &other) { + _p3d_filename = other._p3d_filename; + _tokens = other._tokens; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DFileParams::set_p3d_filename +// Access: Public +// Description: Specifies the file that contains the instance data. +//////////////////////////////////////////////////////////////////// +void P3DFileParams:: +set_p3d_filename(const string &p3d_filename) { + _p3d_filename = p3d_filename; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DFileParams::set_tokens +// Access: Public +// Description: Specifies the tokens associated with the instance. +//////////////////////////////////////////////////////////////////// +void P3DFileParams:: +set_tokens(const P3D_token tokens[], size_t num_tokens) { + _tokens.clear(); + for (size_t i = 0; i < num_tokens; ++i) { Token token; if (tokens[i]._keyword != NULL) { @@ -50,17 +82,6 @@ P3DFileParams(const string &p3d_filename, } } -//////////////////////////////////////////////////////////////////// -// Function: P3DFileParams::Copy Assignment -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void P3DFileParams:: -operator = (const P3DFileParams &other) { - _p3d_filename = other._p3d_filename; - _tokens = other._tokens; -} - //////////////////////////////////////////////////////////////////// // Function: P3DFileParams::lookup_token // Access: Public diff --git a/direct/src/plugin/p3dFileParams.h b/direct/src/plugin/p3dFileParams.h index 674affea7c..7495d3631c 100644 --- a/direct/src/plugin/p3dFileParams.h +++ b/direct/src/plugin/p3dFileParams.h @@ -27,11 +27,12 @@ class P3DFileParams { public: P3DFileParams(); - P3DFileParams(const string &p3d_filename, - const P3D_token tokens[], size_t num_tokens); - + P3DFileParams(const P3DFileParams ©); void operator = (const P3DFileParams &other); + void set_p3d_filename(const string &p3d_filename); + void set_tokens(const P3D_token tokens[], size_t num_tokens); + inline const string &get_p3d_filename() const; string lookup_token(const string &keyword) const; bool has_token(const string &keyword) const; diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 6e858cd26f..f2fbd1df80 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -49,7 +49,8 @@ typedef P3DSplashWindow SplashWindowType; // Description: //////////////////////////////////////////////////////////////////// P3DInstance:: -P3DInstance(P3D_request_ready_func *func, void *user_data) : +P3DInstance(P3D_request_ready_func *func, + const P3D_token tokens[], size_t num_tokens, void *user_data) : _func(func) { _browser_script_object = NULL; @@ -59,6 +60,8 @@ P3DInstance(P3D_request_ready_func *func, void *user_data) : _got_fparams = false; _got_wparams = false; + _fparams.set_tokens(tokens, num_tokens); + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); _instance_id = inst_mgr->get_unique_id(); @@ -137,16 +140,17 @@ P3DInstance:: // download is still running? Who will crash when this happens? } + //////////////////////////////////////////////////////////////////// -// Function: P3DInstance::set_fparams +// Function: P3DInstance::set_p3d_filename // Access: Public -// Description: Sets up the initial file parameters for the instance. +// Description: Specifies the file that contains the instance data. // Normally this is only called once. //////////////////////////////////////////////////////////////////// void P3DInstance:: -set_fparams(const P3DFileParams &fparams) { +set_p3d_filename(const string &p3d_filename) { _got_fparams = true; - _fparams = fparams; + _fparams.set_p3d_filename(p3d_filename); // This also sets up some internal data based on the contents of the // above file and the associated tokens. @@ -176,13 +180,6 @@ set_fparams(const P3DFileParams &fparams) { P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str()); P3D_OBJECT_XDECREF(result); } - - // Maybe create the splash window. - if (!_instance_window_opened && _got_wparams) { - if (_splash_window == NULL) { - make_splash_window(); - } - } } //////////////////////////////////////////////////////////////////// @@ -198,7 +195,7 @@ set_wparams(const P3DWindowParams &wparams) { _wparams = wparams; // Update or create the splash window. - if (!_instance_window_opened && _got_fparams) { + if (!_instance_window_opened) { if (_splash_window == NULL) { make_splash_window(); } diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index 33c8b09a0d..71ac83145c 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -44,10 +44,11 @@ class P3DToplevelObject; //////////////////////////////////////////////////////////////////// class P3DInstance : public P3D_instance, public P3DReferenceCount { public: - P3DInstance(P3D_request_ready_func *func, void *user_data); + P3DInstance(P3D_request_ready_func *func, + const P3D_token tokens[], size_t num_tokens, void *user_data); ~P3DInstance(); - void set_fparams(const P3DFileParams &fparams); + void set_p3d_filename(const string &p3d_filename); inline const P3DFileParams &get_fparams() const; void set_wparams(const P3DWindowParams &wparams); diff --git a/direct/src/plugin/p3dInstanceManager.I b/direct/src/plugin/p3dInstanceManager.I index b816349824..706b69120f 100644 --- a/direct/src/plugin/p3dInstanceManager.I +++ b/direct/src/plugin/p3dInstanceManager.I @@ -60,6 +60,17 @@ get_platform() const { return _platform; } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::has_contents_file +// Access: Public +// Description: Returns true if a contents.xml file has been +// successfully read, false otherwise. +//////////////////////////////////////////////////////////////////// +inline bool P3DInstanceManager:: +has_contents_file() const { + return (_xcontents != NULL); +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstanceManager::get_num_instances // Access: Public diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index f4c7cb0e20..df51e23c76 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -22,6 +22,9 @@ #include "p3dNoneObject.h" #include "p3dBoolObject.h" #include "find_root_dir.h" +#include "mkdir_complete.h" +#include "fileSpec.h" +#include "get_tinyxml.h" #ifdef _WIN32 #include @@ -40,6 +43,7 @@ P3DInstanceManager:: P3DInstanceManager() { _is_initialized = false; _unique_id = 0; + _xcontents = NULL; _notify_thread_continue = false; _started_notify_thread = false; @@ -77,6 +81,10 @@ P3DInstanceManager:: _started_notify_thread = false; } + if (_xcontents != NULL) { + delete _xcontents; + } + assert(_instances.empty()); assert(_sessions.empty()); @@ -112,13 +120,14 @@ P3DInstanceManager:: // redownloaded. //////////////////////////////////////////////////////////////////// bool P3DInstanceManager:: -initialize() { +initialize(const string &contents_filename) { _root_dir = find_root_dir(); _download_url = P3D_PLUGIN_DOWNLOAD; _platform = P3D_PLUGIN_PLATFORM; - nout << "_root_dir = " << _root_dir << ", download = " - << _download_url << "\n"; + nout << "_root_dir = " << _root_dir + << ", download = " << _download_url + << ", contents = " << contents_filename << "\n"; if (_root_dir.empty()) { nout << "Could not find root directory.\n"; @@ -127,6 +136,47 @@ initialize() { _is_initialized = true; + // Attempt to read the supplied contents.xml file. + if (!contents_filename.empty()) { + if (!read_contents_file(contents_filename)) { + nout << "Couldn't read " << contents_filename << "\n"; + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::read_contents_file +// Access: Public +// Description: Reads the contents.xml file in the indicated +// filename. On success, copies the contents.xml file +// into the standard location. +// +// Returns true on success, false on failure. +//////////////////////////////////////////////////////////////////// +bool P3DInstanceManager:: +read_contents_file(const string &contents_filename) { + TiXmlDocument doc(contents_filename.c_str()); + if (!doc.LoadFile()) { + return false; + } + + TiXmlElement *xcontents = doc.FirstChildElement("contents"); + if (xcontents == NULL) { + return false; + } + + if (_xcontents != NULL) { + delete _xcontents; + } + _xcontents = (TiXmlElement *)xcontents->Clone(); + + string standard_filename = _root_dir + "/contents.xml"; + if (standard_filename != contents_filename) { + copy_file(contents_filename, standard_filename); + } + return true; } @@ -137,8 +187,10 @@ initialize() { // indicated startup information. //////////////////////////////////////////////////////////////////// P3DInstance *P3DInstanceManager:: -create_instance(P3D_request_ready_func *func, void *user_data) { - P3DInstance *inst = new P3DInstance(func, user_data); +create_instance(P3D_request_ready_func *func, + const P3D_token tokens[], size_t num_tokens, + void *user_data) { + P3DInstance *inst = new P3DInstance(func, tokens, num_tokens, user_data); inst->ref(); _instances.insert(inst); @@ -154,13 +206,12 @@ create_instance(P3D_request_ready_func *func, void *user_data) { // particular instance. //////////////////////////////////////////////////////////////////// bool P3DInstanceManager:: -start_instance(P3DInstance *inst, const string &p3d_filename, - const P3D_token tokens[], size_t num_tokens) { +start_instance(P3DInstance *inst, const string &p3d_filename) { if (inst->is_started()) { nout << "Instance started twice: " << inst << "\n"; return false; } - inst->set_fparams(P3DFileParams(p3d_filename, tokens, num_tokens)); + inst->set_p3d_filename(p3d_filename); P3DSession *session; Sessions::iterator si = _sessions.find(inst->get_session_key()); @@ -192,16 +243,17 @@ finish_instance(P3DInstance *inst) { _instances.erase(ii); Sessions::iterator si = _sessions.find(inst->get_session_key()); - assert(si != _sessions.end()); - P3DSession *session = (*si).second; - session->terminate_instance(inst); + if (si != _sessions.end()) { + P3DSession *session = (*si).second; + session->terminate_instance(inst); - // If that was the last instance in this session, terminate the - // session. - if (session->get_num_instances() == 0) { - _sessions.erase(session->get_session_key()); - session->shutdown(); - unref_delete(session); + // If that was the last instance in this session, terminate the + // session. + if (session->get_num_instances() == 0) { + _sessions.erase(session->get_session_key()); + session->shutdown(); + unref_delete(session); + } } unref_delete(inst); @@ -284,20 +336,61 @@ P3DPackage *P3DInstanceManager:: get_package(const string &package_name, const string &package_version, const string &package_display_name) { string package_platform = get_platform(); - string key = package_name + "_" + package_version + "_" + package_platform; + string key = package_name + "_" + package_platform + "_" + package_version; Packages::iterator pi = _packages.find(key); if (pi != _packages.end()) { return (*pi).second; } - P3DPackage *package = new P3DPackage(package_name, package_version, - package_platform, package_display_name); + P3DPackage *package = new P3DPackage(package_name, package_platform, + package_version, package_display_name); bool inserted = _packages.insert(Packages::value_type(key, package)).second; assert(inserted); return package; } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::get_package_desc_file +// Access: Public +// Description: Fills the indicated FileSpec with the hash +// information for the package's desc file. Returns +// true if successful, false if the package is unknown. +// This requires has_contents_file() to return true in +// order to be successful. +//////////////////////////////////////////////////////////////////// +bool P3DInstanceManager:: +get_package_desc_file(FileSpec &desc_file, + const string &package_name, + const string &package_version) { + if (_xcontents == NULL) { + return false; + } + + string package_platform = get_platform(); + + // Scan the contents data for the indicated package. + TiXmlElement *xpackage = _xcontents->FirstChildElement("package"); + while (xpackage != NULL) { + const char *name = xpackage->Attribute("name"); + const char *platform = xpackage->Attribute("platform"); + const char *version = xpackage->Attribute("version"); + if (name != NULL && platform != NULL && version != NULL && + package_name == name && + package_platform == platform && + package_version == version) { + // Here's the matching package definition. + desc_file.load_xml(xpackage); + return true; + } + + xpackage = xpackage->NextSiblingElement("package"); + } + + // Couldn't find the named package. + return false; +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstanceManager::get_unique_id // Access: Public @@ -384,6 +477,38 @@ delete_global_ptr() { } } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::copy_file +// Access: Private +// Description: Copies the data in the file named by from_filename +// into the file named by to_filename. +//////////////////////////////////////////////////////////////////// +bool P3DInstanceManager:: +copy_file(const string &from_filename, const string &to_filename) { + ifstream in(from_filename.c_str(), ios::in | ios::binary); + ofstream out(to_filename.c_str(), ios::out | ios::binary); + + static const size_t buffer_size = 4096; + char buffer[buffer_size]; + + in.read(buffer, buffer_size); + size_t count = in.gcount(); + while (count != 0) { + out.write(buffer, count); + if (out.fail()) { + return false; + } + in.read(buffer, buffer_size); + count = in.gcount(); + } + + if (!in.eof()) { + return false; + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstanceManager::nt_thread_run // Access: Private diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h index d09cc7f69e..f2abc6b55d 100644 --- a/direct/src/plugin/p3dInstanceManager.h +++ b/direct/src/plugin/p3dInstanceManager.h @@ -25,6 +25,8 @@ class P3DInstance; class P3DSession; class P3DPackage; +class FileSpec; +class TiXmlElement; //////////////////////////////////////////////////////////////////// // Class : P3DInstanceManager @@ -37,7 +39,7 @@ private: ~P3DInstanceManager(); public: - bool initialize(); + bool initialize(const string &contents_xml_filename); inline bool is_initialized() const; @@ -45,11 +47,15 @@ public: inline const string &get_download_url() const; inline const string &get_platform() const; - P3DInstance * - create_instance(P3D_request_ready_func *func, void *user_data); + inline bool has_contents_file() const; + bool read_contents_file(const string &contents_filename); - bool start_instance(P3DInstance *inst, const string &p3d_filename, - const P3D_token tokens[], size_t num_tokens); + P3DInstance * + create_instance(P3D_request_ready_func *func, + const P3D_token tokens[], size_t num_tokens, + void *user_data); + + bool start_instance(P3DInstance *inst, const string &p3d_filename); void finish_instance(P3DInstance *inst); P3DInstance *validate_instance(P3D_instance *instance); @@ -60,6 +66,9 @@ public: P3DPackage *get_package(const string &package_name, const string &package_version, const string &package_display_name); + bool get_package_desc_file(FileSpec &desc_file, + const string &package_name, + const string &package_version); inline int get_num_instances() const; @@ -75,6 +84,9 @@ public: static P3DInstanceManager *get_global_ptr(); static void delete_global_ptr(); +private: + bool copy_file(const string &from_filename, const string &to_filename); + private: // The notify thread. This thread runs only for the purpose of // generating asynchronous notifications of requests, to callers who @@ -88,6 +100,8 @@ private: string _download_url; string _platform; + TiXmlElement *_xcontents; + P3D_object *_undefined_object; P3D_object *_none_object; P3D_object *_true_object; diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx index f4daafe86f..c487785102 100755 --- a/direct/src/plugin/p3dPackage.cxx +++ b/direct/src/plugin/p3dPackage.cxx @@ -35,23 +35,25 @@ static const double extract_portion = 0.05; // Description: //////////////////////////////////////////////////////////////////// P3DPackage:: -P3DPackage(const string &package_name, const string &package_version, +P3DPackage(const string &package_name, const string &package_platform, + const string &package_version, const string &package_display_name) : _package_name(package_name), - _package_version(package_version), _package_platform(package_platform), + _package_version(package_version), _package_display_name(package_display_name) { P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); - _package_fullname = _package_name + "_" + _package_version; + _package_fullname = _package_name; _package_dir = inst_mgr->get_root_dir() + string("/") + _package_name; - if (!_package_platform.empty()) { - _package_fullname += "_" + _package_platform; - _package_dir += "/" + _package_platform; + _package_fullname += string("_") + _package_platform; + _package_dir += string("/") + _package_platform; } + _package_fullname += string("_") + _package_version; + _package_dir += string("/") + _package_version; _ready = false; _failed = false; @@ -59,7 +61,6 @@ P3DPackage(const string &package_name, const string &package_version, _partial_download = false; // Ensure the package directory exists; create it if it does not. - _package_dir += string("/") + _package_version; mkdir_complete(_package_dir, nout); _desc_file_basename = _package_fullname + ".xml"; @@ -186,20 +187,68 @@ begin_download() { return; } - // TODO: we should check the desc file for updates with the server. - // Perhaps this should be done in a parent class. + download_contents_file(); +} - // TODO: if the desc file exists, and is consistent with the server - // contents file, don't re-download it. - /* - // Load the desc file, if it exists. - TiXmlDocument doc(_desc_file_pathname.c_str()); - if (!doc.LoadFile()) { +//////////////////////////////////////////////////////////////////// +// Function: P3DPackage::download_contents_file +// Access: Private +// Description: Starts downloading the root-level contents.xml file. +// This is only done for the first package, and only if +// the instance manager doesn't have the file already. +//////////////////////////////////////////////////////////////////// +void P3DPackage:: +download_contents_file() { + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + + if (inst_mgr->has_contents_file()) { + // We've already got a contents.xml file; go straight to the + // package desc file. download_desc_file(); - } else { - got_desc_file(&doc, false); + return; } - */ + + string url = inst_mgr->get_download_url(); + url += "contents.xml"; + + // Download contents.xml to a temporary filename first, in case + // multiple packages are downloading it simultaneously. + _contents_file_pathname = tempnam(NULL, "p3d_"); + + cerr << "starting contents download\n"; + start_download(DT_contents_file, url, _contents_file_pathname, false); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPackage::contents_file_download_finished +// Access: Private +// Description: Called when the desc file has been fully downloaded. +//////////////////////////////////////////////////////////////////// +void P3DPackage:: +contents_file_download_finished(bool success) { + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + cerr << "done contents download: " << success + << ", has_contents = " << inst_mgr->has_contents_file() + << "\n"; + + if (!inst_mgr->has_contents_file()) { + if (!success || !inst_mgr->read_contents_file(_contents_file_pathname)) { + nout << "Couldn't read " << _contents_file_pathname << "\n"; + + // Maybe we can read an already-downloaded contents.xml file. + string standard_filename = inst_mgr->get_root_dir() + "/contents.xml"; + if (!inst_mgr->read_contents_file(standard_filename)) { + // Couldn't even read that. Fail. + report_done(false); + unlink(_contents_file_pathname.c_str()); + return; + } + } + } + + // The file is correctly installed by now; we can remove the + // temporary file. + unlink(_contents_file_pathname.c_str()); download_desc_file(); } @@ -212,12 +261,40 @@ begin_download() { void P3DPackage:: download_desc_file() { P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + + // Attempt to check the desc file for freshness. If it already + // exists, and is consistent with the server contents file, we don't + // need to re-download it. + string root_dir = inst_mgr->get_root_dir(); + FileSpec desc_file; + if (!inst_mgr->get_package_desc_file(desc_file, _package_name, _package_version)) { + nout << "Couldn't find package " << _package_fullname + << " in contents file.\n"; + + } else if (desc_file.get_pathname(root_dir) != _desc_file_pathname) { + nout << "Wrong pathname for desc file: " + << desc_file.get_pathname(root_dir) + << " instead of " << _desc_file_pathname << "\n"; + + } else if (!desc_file.quick_verify(root_dir)) { + nout << _desc_file_pathname << " is stale.\n"; + + } else { + // The desc file is current. Attempt to read it. + TiXmlDocument doc(_desc_file_pathname.c_str()); + if (doc.LoadFile()) { + got_desc_file(&doc, false); + return; + } + } + + // The desc file is not current. Go download it. string url = inst_mgr->get_download_url(); - url += _package_name + "/" + _package_version; + url += _package_name; if (!_package_platform.empty()) { url += "/" + _package_platform; } - + url += "/" + _package_version; url += "/" + _desc_file_basename; start_download(DT_desc_file, url, _desc_file_pathname, false); @@ -321,11 +398,11 @@ void P3DPackage:: download_compressed_archive(bool allow_partial) { P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); string url = inst_mgr->get_download_url(); - url += _package_name + "/" + _package_version; + url += _package_name; if (!_package_platform.empty()) { url += "/" + _package_platform; } - + url += "/" + _package_version; url += "/" + _compressed_archive.get_filename(); string target_pathname = _package_dir + "/" + _compressed_archive.get_filename(); @@ -667,6 +744,10 @@ download_finished(bool success) { _package->_active_download = NULL; switch (_dtype) { + case DT_contents_file: + _package->contents_file_download_finished(success); + break; + case DT_desc_file: _package->desc_file_download_finished(success); break; diff --git a/direct/src/plugin/p3dPackage.h b/direct/src/plugin/p3dPackage.h index eafff27fa9..b394e5248a 100755 --- a/direct/src/plugin/p3dPackage.h +++ b/direct/src/plugin/p3dPackage.h @@ -36,8 +36,9 @@ class P3DInstance; //////////////////////////////////////////////////////////////////// class P3DPackage { public: - P3DPackage(const string &package_name, const string &package_version, + P3DPackage(const string &package_name, const string &package_platform, + const string &package_version, const string &package_display_name); ~P3DPackage(); @@ -63,6 +64,7 @@ public: private: enum DownloadType { + DT_contents_file, DT_desc_file, DT_compressed_archive }; @@ -81,6 +83,9 @@ private: }; void begin_download(); + void download_contents_file(); + void contents_file_download_finished(bool success); + void download_desc_file(); void desc_file_download_finished(bool success); void got_desc_file(TiXmlDocument *doc, bool freshly_downloaded); @@ -105,6 +110,8 @@ private: string _package_fullname; string _package_dir; + string _contents_file_pathname; + string _desc_file_basename; string _desc_file_pathname; diff --git a/direct/src/plugin/p3dWinSplashWindow.cxx b/direct/src/plugin/p3dWinSplashWindow.cxx index e0446cf4c5..80984419ca 100755 --- a/direct/src/plugin/p3dWinSplashWindow.cxx +++ b/direct/src/plugin/p3dWinSplashWindow.cxx @@ -82,6 +82,7 @@ set_wparams(const P3DWindowParams &wparams) { void P3DWinSplashWindow:: set_image_filename(const string &image_filename, bool image_filename_temp) { + nout << "image_filename = " << image_filename << ", thread_id = " << _thread_id << "\n"; ACQUIRE_LOCK(_install_lock); if (_image_filename != image_filename) { _image_filename = image_filename; @@ -261,34 +262,33 @@ thread_run() { TranslateMessage(&msg); DispatchMessage(&msg); - if (_got_install) { - ACQUIRE_LOCK(_install_lock); - double install_progress = _install_progress; - if (_image_filename_changed) { - update_image_filename(_image_filename, _image_filename_temp); - } - _image_filename_changed = false; - if (_install_label_changed && _progress_bar != NULL) { - update_install_label(_install_label); - } - _install_label_changed = false; - RELEASE_LOCK(_install_lock); + ACQUIRE_LOCK(_install_lock); + bool got_install = _got_install; + double install_progress = _install_progress; + if (_image_filename_changed) { + update_image_filename(_image_filename, _image_filename_temp); + } + _image_filename_changed = false; + if (_install_label_changed && _progress_bar != NULL) { + update_install_label(_install_label); + } + _install_label_changed = false; + RELEASE_LOCK(_install_lock); - if (install_progress != last_progress) { - if (_progress_bar == NULL) { - // Is it time to create the progress bar? - int now = GetTickCount(); - if (now - _loop_started > 2000) { - make_progress_bar(); - } - } else { - // Update the progress bar. We do this only within the - // thread, to ensure we don't get a race condition when - // starting or closing the thread. - SendMessage(_progress_bar, PBM_SETPOS, (int)(install_progress * 100.0), 0); - - last_progress = install_progress; + if (got_install && install_progress != last_progress) { + if (_progress_bar == NULL) { + // Is it time to create the progress bar? + int now = GetTickCount(); + if (now - _loop_started > 2000) { + make_progress_bar(); } + } else { + // Update the progress bar. We do this only within the + // thread, to ensure we don't get a race condition when + // starting or closing the thread. + SendMessage(_progress_bar, PBM_SETPOS, (int)(install_progress * 100.0), 0); + + last_progress = install_progress; } } diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index 95c66e80b0..94aed438ce 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -13,6 +13,7 @@ //////////////////////////////////////////////////////////////////// #include "p3d_plugin_common.h" +#include "p3d_plugin_config.h" #include "p3dInstanceManager.h" #include "p3dInstance.h" #include "p3dWindowParams.h" @@ -37,7 +38,7 @@ ostream *nout_stream; bool -P3D_initialize(int api_version, const char *output_filename) { +P3D_initialize(int api_version, const char *contents_filename) { if (api_version != P3D_API_VERSION) { // Can't accept an incompatible version. return false; @@ -49,21 +50,40 @@ P3D_initialize(int api_version, const char *output_filename) { } ACQUIRE_LOCK(_api_lock); - plugin_output_filename = string(); - if (output_filename != NULL) { - plugin_output_filename = output_filename; + if (contents_filename == NULL){ + contents_filename = ""; } - nout_stream = &cerr; - if (!plugin_output_filename.empty()) { - logfile.open(plugin_output_filename.c_str(), ios::out | ios::trunc); - if (logfile) { - logfile.setf(ios::unitbuf); - nout_stream = &logfile; + +#ifdef P3D_PLUGIN_LOGFILE2 + string logfilename = P3D_PLUGIN_LOGFILE2; +#else + string logfilename; +#endif // P3D_PLUGIN_LOGFILE2 + + if (logfilename.empty()) { +#ifdef _WIN32 + static const size_t buffer_size = 4096; + char buffer[buffer_size]; + if (GetTempPath(buffer_size, buffer) != 0) { + logfilename = buffer; + logfilename += "panda3d.2.log"; } +#else + logfilename = "/tmp/panda3d.2.log"; +#endif // _WIN32 + } + + cerr << "logfile: " << logfilename << "\n"; + + nout_stream = &cerr; + logfile.open(logfilename.c_str(), ios::out | ios::trunc); + if (logfile) { + logfile.setf(ios::unitbuf); + nout_stream = &logfile; } P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); - bool result = inst_mgr->initialize(); + bool result = inst_mgr->initialize(contents_filename); RELEASE_LOCK(_api_lock); return result; } @@ -74,18 +94,21 @@ P3D_finalize() { } P3D_instance * -P3D_new_instance(P3D_request_ready_func *func, void *user_data) { +P3D_new_instance(P3D_request_ready_func *func, + const P3D_token tokens[], size_t num_tokens, + void *user_data) { + nout << "new_instance\n"; assert(P3DInstanceManager::get_global_ptr()->is_initialized()); ACQUIRE_LOCK(_api_lock); P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); - P3DInstance *result = inst_mgr->create_instance(func, user_data); + P3DInstance *result = inst_mgr->create_instance(func, tokens, num_tokens, user_data); RELEASE_LOCK(_api_lock); return result; } bool -P3D_instance_start(P3D_instance *instance, const char *p3d_filename, - const P3D_token tokens[], size_t num_tokens) { +P3D_instance_start(P3D_instance *instance, const char *p3d_filename) { + nout << "instance_start\n"; assert(P3DInstanceManager::get_global_ptr()->is_initialized()); if (p3d_filename == NULL) { p3d_filename = ""; @@ -95,7 +118,7 @@ P3D_instance_start(P3D_instance *instance, const char *p3d_filename, P3DInstance *inst = inst_mgr->validate_instance(instance); bool result = false; if (inst != NULL) { - result = inst_mgr->start_instance(inst, p3d_filename, tokens, num_tokens); + result = inst_mgr->start_instance(inst, p3d_filename); } RELEASE_LOCK(_api_lock); return result; @@ -119,6 +142,7 @@ P3D_instance_setup_window(P3D_instance *instance, int win_x, int win_y, int win_width, int win_height, P3D_window_handle parent_window) { + nout << "setup_window\n"; assert(P3DInstanceManager::get_global_ptr()->is_initialized()); P3DWindowParams wparams(window_type, win_x, win_y, win_width, win_height, parent_window); diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index c6adc037f2..329efb0828 100644 --- a/direct/src/plugin/p3d_plugin.h +++ b/direct/src/plugin/p3d_plugin.h @@ -79,7 +79,7 @@ extern "C" { (below). This number will be incremented whenever there are changes to any of the interface specifications defined in this header file. */ -#define P3D_API_VERSION 4 +#define P3D_API_VERSION 5 /************************ GLOBAL FUNCTIONS **************************/ @@ -91,17 +91,16 @@ extern "C" { the DLL can verify that it has been built with the same version of the API as the host. - The output_filename is usually NULL, but if you put a filename - here, it will be used as the log file for the output from the core - API. This is useful for debugging, particularly when running - within a browser that squelches stderr. + The contents_filename, if not NULL or empty, names a contents.xml + file that has already been downloaded and verified from the server. + If this is NULL, a new file will be downloaded as needed. This function returns true if the core API is valid and uses a compatible API, false otherwise. If it returns false, the host should not call any more functions in this API, and should immediately unload the DLL and (if possible) download a new one. */ typedef bool -P3D_initialize_func(int api_version, const char *output_filename); +P3D_initialize_func(int api_version, const char *contents_filename); /* This function should be called to unload the core API. It will release all internally-allocated memory and return the core API to @@ -210,16 +209,25 @@ typedef struct { /* This function creates a new Panda3D instance. + For tokens, pass an array of P3D_token elements (above), which + correspond to the user-supplied keyword/value pairs that may appear + in the embed token within the HTML syntax; the host is responsible + for allocating this array, and for deallocating it after this call + (the core API will make its own copy of the array). The tokens are + passed to the application, who is free to decide how to interpret + them; they have no meaning at the system level. + The user_data pointer is any arbitrary pointer value; it will be copied into the _user_data member of the new P3D_instance object. This pointer is intended for the host to use to store private data associated with each instance; the core API will not do anything with this data. - */ typedef P3D_instance * -P3D_new_instance_func(P3D_request_ready_func *func, void *user_data); +P3D_new_instance_func(P3D_request_ready_func *func, + const P3D_token tokens[], size_t num_tokens, + void *user_data); /* This function should be called at some point after P3D_new_instance(); it actually starts the instance running. @@ -230,29 +238,9 @@ P3D_new_instance_func(P3D_request_ready_func *func, void *user_data); instance. If this is empty or NULL, the "src" token (below) will be downloaded instead. - For tokens, pass an array of P3D_token elements (above), which - correspond to the user-supplied keyword/value pairs that may appear - in the embed token within the HTML syntax; the host is responsible - for allocating this array, and for deallocating it after this call - (the core API will make its own copy of the array). - - Most tokens are implemented by the application and are undefined at - the system level. However, two tokens in particular are - system-defined: - - "src" : names a URL that will be loaded for the contents of the - p3d file, if p3d_filename is empty or NULL. - - "output_filename" : names a file to create on disk which contains - the console output from the application. This may be useful in - debugging. If this is omitted, or an empty string, the console - output is written to the standard error output, which may be - NULL on a gui application. - The return value is true on success, false on failure. */ typedef bool -P3D_instance_start_func(P3D_instance *instance, const char *p3d_filename, - const P3D_token tokens[], size_t num_tokens); +P3D_instance_start_func(P3D_instance *instance, const char *p3d_filename); /* Call this function to interrupt a particular instance and stop it diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index afca7e10f0..cdbef6e617 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -51,6 +51,8 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode, _tokens.push_back(token); } + _root_dir = find_root_dir(); + _started_instance_data = false; _got_instance_data = false; _got_window = false; @@ -313,7 +315,15 @@ url_notify(const char *url, NPReason reason, void *notifyData) { case PPDownloadRequest::RT_contents_file: if (reason != NPRES_DONE) { nout << "Failure downloading " << url << "\n"; - // TODO: fail + + // Couldn't download a fresh contents.xml for some reason. If + // there's an outstanding contents.xml file on disk, try to load + // that one as a fallback. + string contents_filename = _root_dir + "/contents.xml"; + if (!read_contents_file(contents_filename)) { + nout << "Unable to read contents file " << contents_filename << "\n"; + // TODO: fail + } } break; @@ -361,11 +371,11 @@ stream_as_file(NPStream *stream, const char *fname) { // Looks like we've converted it successfully. filename = fname2; - // Here's another temporary hack. In addition to the weird - // filename format, the file that Safari tells us about appears - // to be a temporary file that Safari's about to delete. In - // order to protect ourselves from this, we need to temporarily - // copy the file somewhere else. + // Here's another crazy hack. In addition to the weird filename + // format, the file that Safari tells us about appears to be a + // temporary file that Safari's about to delete. In order to + // protect ourselves from this, we need to temporarily copy the + // file somewhere else. char *name = tempnam(NULL, "p3d_"); // We prefer just making a hard link; it's quick and easy. @@ -373,19 +383,7 @@ stream_as_file(NPStream *stream, const char *fname) { // But sometimes the hard link might fail, particularly if these // are two different file systems. In this case we have to open // the files and copy the data by hand. - ifstream in(filename.c_str(), ios::in | ios::binary); - ofstream out(name, ios::out | ios::binary); - - static const size_t buffer_size = 4096; - char buffer[buffer_size]; - - in.read(buffer, buffer_size); - size_t count = in.gcount(); - while (count != 0) { - out.write(buffer, count); - in.read(buffer, buffer_size); - count = in.gcount(); - } + copy_file(filename, name); } filename = name; @@ -439,7 +437,7 @@ handle_request(P3D_request *request) { if (strcmp(request->_request._notify._message, "onwindowopen") == 0) { _python_window_open = true; if (_got_window) { - NPRect rect = { 0, 0, _window.height, _window.width }; + NPRect rect = { 0, 0, (unsigned short)_window.height, (unsigned short)_window.width }; browser->invalidaterect(_npp_instance, &rect); } } @@ -447,7 +445,7 @@ handle_request(P3D_request *request) { case P3D_RT_refresh: if (_got_window) { - NPRect rect = { 0, 0, _window.height, _window.width }; + NPRect rect = { 0, 0, (unsigned short)_window.height, (unsigned short)_window.width }; browser->invalidaterect(_npp_instance, &rect); } break; @@ -700,8 +698,8 @@ start_download(const string &url, PPDownloadRequest *req) { // DLL downloading, if necessary. //////////////////////////////////////////////////////////////////// bool PPInstance:: -read_contents_file(const string &filename) { - TiXmlDocument doc(filename.c_str()); +read_contents_file(const string &contents_filename) { + TiXmlDocument doc(contents_filename.c_str()); if (!doc.LoadFile()) { return false; } @@ -765,9 +763,23 @@ downloaded_file(PPDownloadRequest *req, const string &filename) { case PPDownloadRequest::RT_contents_file: // Now we have the contents.xml file. Read this to get the // filename and md5 hash of our core API DLL. - if (!read_contents_file(filename)) { - nout << "Unable to read contents file\n"; - // TODO: fail + if (read_contents_file(filename)) { + // Successfully read. Copy it into its normal place. + string contents_filename = _root_dir + "/contents.xml"; + copy_file(filename, contents_filename); + + } else { + // Error reading the contents.xml file, or in loading the core + // API that it references. + nout << "Unable to read contents file " << filename << "\n"; + + // If there's an outstanding contents.xml file on disk, try to + // load that one as a fallback. + string contents_filename = _root_dir + "/contents.xml"; + if (!read_contents_file(contents_filename)) { + nout << "Unable to read contents file " << contents_filename << "\n"; + // TODO: fail + } } break; @@ -782,7 +794,10 @@ downloaded_file(PPDownloadRequest *req, const string &filename) { // launch the instance. _got_instance_data = true; _p3d_filename = filename; - create_instance(); + + if (_p3d_inst != NULL) { + P3D_instance_start(_p3d_inst, _p3d_filename.c_str()); + } break; case PPDownloadRequest::RT_user: @@ -821,8 +836,6 @@ void PPInstance:: get_core_api(TiXmlElement *xpackage) { _core_api_dll.load_xml(xpackage); - _root_dir = find_root_dir(); - if (_core_api_dll.quick_verify(_root_dir)) { // The DLL file is good. Just load it. do_load_plugin(); @@ -919,7 +932,7 @@ do_load_plugin() { } #endif // P3D_PLUGIN_P3D_PLUGIN - if (!load_plugin(pathname)) { + if (!load_plugin(pathname, "")) { nout << "Unable to launch core API in " << pathname << "\n"; return; } @@ -944,12 +957,11 @@ create_instance() { return; } - if (!_got_instance_data) { - // No instance data yet. - return; + P3D_token *tokens = NULL; + if (!_tokens.empty()) { + tokens = &_tokens[0]; } - - _p3d_inst = P3D_new_instance(request_ready, this); + _p3d_inst = P3D_new_instance(request_ready, tokens, _tokens.size(), this); if (_p3d_inst != NULL) { // Now get the browser's window object, to pass to the plugin. @@ -971,11 +983,7 @@ create_instance() { } if (_got_instance_data) { - P3D_token *tokens = NULL; - if (!_tokens.empty()) { - tokens = &_tokens[0]; - } - P3D_instance_start(_p3d_inst, _p3d_filename.c_str(), tokens, _tokens.size()); + P3D_instance_start(_p3d_inst, _p3d_filename.c_str()); } if (_got_window) { @@ -1062,6 +1070,38 @@ send_window() { parent_window); } +//////////////////////////////////////////////////////////////////// +// Function: PPInstance::copy_file +// Access: Public +// Description: Copies the data in the file named by from_filename +// into the file named by to_filename. +//////////////////////////////////////////////////////////////////// +bool PPInstance:: +copy_file(const string &from_filename, const string &to_filename) { + ifstream in(from_filename.c_str(), ios::in | ios::binary); + ofstream out(to_filename.c_str(), ios::out | ios::binary); + + static const size_t buffer_size = 4096; + char buffer[buffer_size]; + + in.read(buffer, buffer_size); + size_t count = in.gcount(); + while (count != 0) { + out.write(buffer, count); + if (out.fail()) { + return false; + } + in.read(buffer, buffer_size); + count = in.gcount(); + } + + if (!in.eof()) { + return false; + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: PPInstance::output_np_variant // Access: Public diff --git a/direct/src/plugin_npapi/ppInstance.h b/direct/src/plugin_npapi/ppInstance.h index 690ab841ee..92c6ff7a18 100644 --- a/direct/src/plugin_npapi/ppInstance.h +++ b/direct/src/plugin_npapi/ppInstance.h @@ -71,13 +71,14 @@ private: static string get_filename_from_url(const string &url); void feed_file(PPDownloadRequest *req, const string &filename); - bool read_contents_file(const string &filename); + bool read_contents_file(const string &contents_filename); void get_core_api(TiXmlElement *xpackage); void downloaded_plugin(const string &filename); void do_load_plugin(); void create_instance(); void send_window(); + bool copy_file(const string &from_filename, const string &to_filename); static void handle_request_loop(); static void browser_sync_callback(void *); diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index caa25a828a..e1aa016192 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -286,8 +286,8 @@ run(int argc, char *argv[]) { bool Panda3D:: get_plugin(const string &root_url, const string &this_platform, bool force_download) { // First, look for the existing contents.xml file. - Filename contents = Filename(Filename::from_os_specific(_root_dir), "contents.xml"); - if (!force_download && read_contents_file(contents, root_url, this_platform)) { + Filename contents_filename = Filename(Filename::from_os_specific(_root_dir), "contents.xml"); + if (!force_download && read_contents_file(contents_filename, root_url, this_platform)) { // Got the file, and it's good. return true; } @@ -299,13 +299,13 @@ get_plugin(const string &root_url, const string &this_platform, bool force_downl HTTPClient *http = HTTPClient::get_global_ptr(); PT(HTTPChannel) channel = http->get_document(url); - contents.make_dir(); - if (!channel->download_to_file(contents)) { + contents_filename.make_dir(); + if (!channel->download_to_file(contents_filename)) { cerr << "Unable to download " << url << "\n"; return false; } - return read_contents_file(contents, root_url, this_platform); + return read_contents_file(contents_filename, root_url, this_platform); } //////////////////////////////////////////////////////////////////// @@ -316,12 +316,12 @@ get_plugin(const string &root_url, const string &this_platform, bool force_downl // possible. Returns true on success, false on failure. //////////////////////////////////////////////////////////////////// bool Panda3D:: -read_contents_file(Filename contents, const string &root_url, +read_contents_file(Filename contents_filename, const string &root_url, const string &this_platform) { ifstream in; - contents.set_text(); - if (!contents.open_read(in)) { - cerr << "Couldn't read " << contents.to_os_specific() << "\n"; + contents_filename.set_text(); + if (!contents_filename.open_read(in)) { + cerr << "Couldn't read " << contents_filename.to_os_specific() << "\n"; return false; } @@ -336,7 +336,7 @@ read_contents_file(Filename contents, const string &root_url, if (name != NULL && strcmp(name, "coreapi") == 0) { const char *xplatform = xpackage->Attribute("platform"); if (xplatform != NULL && strcmp(xplatform, this_platform.c_str()) == 0) { - return get_core_api(root_url, xpackage); + return get_core_api(contents_filename, root_url, xpackage); } } @@ -359,7 +359,8 @@ read_contents_file(Filename contents, const string &root_url, // if necessary. //////////////////////////////////////////////////////////////////// bool Panda3D:: -get_core_api(const string &root_url, TiXmlElement *xpackage) { +get_core_api(const Filename &contents_filename, const string &root_url, + TiXmlElement *xpackage) { _core_api_dll.load_xml(xpackage); if (!_core_api_dll.quick_verify(_root_dir)) { @@ -397,7 +398,7 @@ get_core_api(const string &root_url, TiXmlElement *xpackage) { } #endif // P3D_PLUGIN_P3D_PLUGIN - if (!load_plugin(pathname)) { + if (!load_plugin(pathname, contents_filename.to_os_specific())) { cerr << "Unable to launch core API in " << pathname << "\n" << flush; return false; } @@ -592,12 +593,12 @@ create_instance(const string &arg, P3D_window_type window_type, os_p3d_filename = p3d_filename.to_os_specific(); } - P3D_instance *inst = P3D_new_instance(NULL, NULL); + P3D_instance *inst = P3D_new_instance(NULL, tokens, num_tokens, NULL); if (inst != NULL) { P3D_instance_setup_window (inst, window_type, win_x, win_y, win_width, win_height, parent_window); - P3D_instance_start(inst, os_p3d_filename.c_str(), tokens, num_tokens); + P3D_instance_start(inst, os_p3d_filename.c_str()); } return inst; diff --git a/direct/src/plugin_standalone/panda3d.h b/direct/src/plugin_standalone/panda3d.h index 119ed632fe..aac2547a61 100755 --- a/direct/src/plugin_standalone/panda3d.h +++ b/direct/src/plugin_standalone/panda3d.h @@ -44,9 +44,10 @@ public: private: bool get_plugin(const string &root_url, const string &this_platform, bool force_download); - bool read_contents_file(Filename contents, const string &root_url, + bool read_contents_file(Filename contents_filename, const string &root_url, const string &this_platform); - bool get_core_api(const string &root_url, TiXmlElement *xpackage); + bool get_core_api(const Filename &contents_filename, const string &root_url, + TiXmlElement *xpackage); void run_getters(); void handle_request(P3D_request *request); void make_parent_window(P3D_window_handle &parent_window, diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py index 54d9d507e2..5ef62cc191 100644 --- a/direct/src/showutil/FreezeTool.py +++ b/direct/src/showutil/FreezeTool.py @@ -55,7 +55,7 @@ if sys.platform == 'win32': MSVC = Filename('/c/Program Files/Microsoft Visual Studio .NET 2003/Vc7').toOsSpecific() else: print 'Could not locate Microsoft Visual C++ Compiler! Try running from the Visual Studio Command Prompt.' - exit(1) + sys.exit(1) if ('WindowsSdkDir' in os.environ): PSDK = os.environ['WindowsSdkDir'] @@ -65,7 +65,7 @@ if sys.platform == 'win32': PSDK = os.path.join(MSVC, 'PlatformSDK') else: print 'Could not locate the Microsoft Windows Platform SDK! Try running from the Visual Studio Command Prompt.' - exit(1) + sys.exit(1) # If it is run by makepanda, it handles the MSVC and PlatformSDK paths itself. if ('MAKEPANDA' in os.environ):