From 3e34233b1c86638c903c4574c7c7e0b5babf1e1c Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 14 Aug 2015 15:57:56 +0200 Subject: [PATCH] Implement extracted files for packp3d and pdeploy (only when used together) This also changes start_dir for pdeployed applications to point to the application directory, no longer to ~/.panda3d/start --- direct/src/p3d/DeploymentTools.py | 78 ++++++++-- direct/src/p3d/Packager.py | 4 + direct/src/p3d/packp3d.py | 10 ++ direct/src/plugin/load_plugin.cxx | 23 ++- direct/src/plugin/load_plugin.h | 6 +- direct/src/plugin/p3dAuthSession.cxx | 2 +- direct/src/plugin/p3dInstance.cxx | 2 +- direct/src/plugin/p3dInstanceManager.I | 12 ++ direct/src/plugin/p3dInstanceManager.cxx | 19 ++- direct/src/plugin/p3dInstanceManager.h | 5 +- direct/src/plugin/p3dSession.cxx | 2 +- direct/src/plugin/p3d_plugin.cxx | 9 +- direct/src/plugin/p3d_plugin.h | 5 +- direct/src/plugin_activex/PPInstance.cpp | 6 +- direct/src/plugin_npapi/ppInstance.cxx | 4 +- direct/src/plugin_standalone/p3dEmbed.cxx | 29 +++- direct/src/plugin_standalone/panda3d.cxx | 171 ++++++++++++--------- direct/src/plugin_standalone/panda3d.h | 1 + direct/src/plugin_standalone/panda3dBase.h | 1 + 19 files changed, 271 insertions(+), 118 deletions(-) diff --git a/direct/src/p3d/DeploymentTools.py b/direct/src/p3d/DeploymentTools.py index 5bb3f3a159..78b2378eda 100644 --- a/direct/src/p3d/DeploymentTools.py +++ b/direct/src/p3d/DeploymentTools.py @@ -444,6 +444,7 @@ class Installer: notify = directNotify.newCategory("Installer") def __init__(self, p3dfile, shortname, fullname, version, tokens = {}): + self.p3dFilename = p3dfile if not shortname: shortname = p3dfile.getBasenameWoExtension() self.shortname = shortname @@ -477,22 +478,16 @@ class Installer: if not self.authoremail and ' ' not in uname: self.authoremail = "%s@%s" % (uname, socket.gethostname()) - self.standalone = Standalone(p3dfile, tokens) - self.tempDir = Filename.temporary("", self.shortname, "") + "/" - self.tempDir.makeDir() - self.__tempRoots = {} - # Load the p3d file to read out the required packages mf = Multifile() - if not mf.openRead(p3dfile): + if not mf.openRead(self.p3dFilename): Installer.notify.error("Not a Panda3D application: %s" % (p3dfile)) return # Now load the p3dInfo file. - self.hostUrl = PandaSystem.getPackageHostUrl() - if not self.hostUrl: - self.hostUrl = self.standalone.host.hostUrl + self.hostUrl = None self.requires = [] + self.extracts = [] i = mf.findSubfile('p3d_info.xml') if i >= 0: stream = mf.openReadSubfile(i) @@ -511,14 +506,54 @@ class Installer: p3dRequires.Attribute('host'))) p3dRequires = p3dRequires.NextSiblingElement('requires') + p3dExtract = p3dPackage.FirstChildElement('extract') + while p3dExtract: + filename = p3dExtract.Attribute('filename') + self.extracts.append(filename) + p3dExtract = p3dExtract.NextSiblingElement('extract') + if not self.fullname: p3dConfig = p3dPackage.FirstChildElement('config') if p3dConfig: self.fullname = p3dConfig.Attribute('display_name') + else: + Installer.notify.warning("No p3d_info.xml was found in .p3d archive.") + + mf.close() + + if not self.hostUrl: + self.hostUrl = PandaSystem.getPackageHostUrl() + if not self.hostUrl: + self.hostUrl = self.standalone.host.hostUrl + Installer.notify.warning("No host URL was specified by .p3d archive. Falling back to %s" % (self.hostUrl)) if not self.fullname: self.fullname = self.shortname + self.tempDir = Filename.temporary("", self.shortname, "") + "/" + self.tempDir.makeDir() + self.__tempRoots = {} + + if self.extracts: + # Copy .p3d to a temporary file so we can remove the extracts. + p3dfile = Filename(self.tempDir, self.p3dFilename.getBasename()) + shutil.copyfile(self.p3dFilename.toOsSpecific(), p3dfile.toOsSpecific()) + mf = Multifile() + if not mf.openReadWrite(p3dfile): + Installer.notify.error("Failure to open %s for writing." % (p3dfile)) + + # We don't really need this silly thing when embedding, anyway. + mf.setHeaderPrefix("") + + for fn in self.extracts: + if not mf.removeSubfile(fn): + Installer.notify.error("Failure to remove %s from multifile." % (p3dfile)) + + mf.repack() + mf.close() + + self.standalone = Standalone(p3dfile, tokens) + def __del__(self): try: appRunner.rmtree(self.tempDir) @@ -533,6 +568,22 @@ class Installer: if not self.includeRequires: return + # Write out the extracts from the original .p3d. + if self.extracts: + mf = Multifile() + if not mf.openRead(self.p3dFilename): + Installer.notify.error("Failed to open .p3d archive: %s" % (filename)) + + for filename in self.extracts: + i = mf.findSubfile(filename) + if i < 0: + Installer.notify.error("Cannot find extract in .p3d archive: %s" % (filename)) + continue + + if not mf.extractSubfile(i, Filename(hostDir, filename)): + Installer.notify.error("Failed to extract file from .p3d archive: %s" % (filename)) + mf.close() + pkgTree = PackageTree(platform, hostDir, self.hostUrl) pkgTree.installPackage("images", None, self.standalone.host.hostUrl) @@ -660,7 +711,8 @@ class Installer: Filename(tempdir, "usr/bin/").makeDir() if self.includeRequires: - extraTokens = {"host_dir" : "/usr/lib/" + self.shortname.lower()} + extraTokens = {"host_dir" : "/usr/lib/" + self.shortname.lower(), + "start_dir" : "/usr/lib/" + self.shortname.lower()} else: extraTokens = {} self.standalone.build(Filename(tempdir, "usr/bin/" + self.shortname.lower()), platform, extraTokens) @@ -712,7 +764,7 @@ class Installer: print >>desktop, "Type=Application" desktop.close() - if self.includeRequires: + if self.includeRequires or self.extracts: hostDir = Filename(tempdir, "usr/lib/%s/" % self.shortname.lower()) hostDir.makeDir() self.installPackagesInto(hostDir, platform) @@ -853,7 +905,7 @@ class Installer: exefile = Filename(output, "Contents/MacOS/" + self.shortname) exefile.makeDir() if self.includeRequires: - extraTokens = {"host_dir" : "../Resources"} + extraTokens = {"host_dir": "../Resources", "start_dir": "../Resources"} else: extraTokens = {} self.standalone.build(exefile, platform, extraTokens) @@ -1064,7 +1116,7 @@ class Installer: exefile = Filename(Filename.getTempDirectory(), self.shortname + ".exe") exefile.unlink() if self.includeRequires: - extraTokens = {"host_dir" : "."} + extraTokens = {"host_dir": ".", "start_dir": "."} else: extraTokens = {} self.standalone.build(exefile, platform, extraTokens) diff --git a/direct/src/p3d/Packager.py b/direct/src/p3d/Packager.py index 40c30d8485..b0a44d7fa2 100644 --- a/direct/src/p3d/Packager.py +++ b/direct/src/p3d/Packager.py @@ -1496,6 +1496,10 @@ class Packager: xhost = he.makeXml(packager = self.packager) xpackage.InsertEndChild(xhost) + self.extracts.sort() + for name, xextract in self.extracts: + xpackage.InsertEndChild(xextract) + doc.InsertEndChild(xpackage) # Write the xml file to a temporary file on disk, so we diff --git a/direct/src/p3d/packp3d.py b/direct/src/p3d/packp3d.py index 3544022fd6..b26c6d5b22 100755 --- a/direct/src/p3d/packp3d.py +++ b/direct/src/p3d/packp3d.py @@ -57,6 +57,14 @@ Options: instead of -e for files that are uncompressible by their nature (e.g. mpg files). This option may be repeated as necessary. + -x ext + Marks files with the given extensions of needing to be physically + extracted to disk before they can be loaded. This is used for + file types that cannot be loaded via the virtual file system, + such as .ico files on Windows. + This option is currently only implemented when deploying the + application with pdeploy. + -p python_lib_dir Adds a directory to search for additional Python modules. You can use this to add your system's Python path, to allow packp3d @@ -134,6 +142,8 @@ def makePackedApp(args): packager.binaryExtensions.append(value) elif option == '-n': packager.uncompressibleExtensions.append(value) + elif option == '-x': + packager.extractExtensions.append(value) elif option == '-p': sys.path.append(value) elif option == '-c': diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index a9276b9e99..8a8e5ef179 100644 --- a/direct/src/plugin/load_plugin.cxx +++ b/direct/src/plugin/load_plugin.cxx @@ -140,7 +140,7 @@ load_plugin(const string &p3d_plugin_filename, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, const string &root_dir, const string &host_dir, - ostream &logfile) { + const string &start_dir, ostream &logfile) { if (plugin_loaded) { return true; } @@ -259,7 +259,7 @@ load_plugin(const string &p3d_plugin_filename, verify_contents, platform, log_directory, log_basename, trusted_environment, console_environment, - root_dir, host_dir, logfile)) { + root_dir, host_dir, start_dir, logfile)) { unload_dso(); return false; } @@ -283,7 +283,7 @@ init_plugin(const string &contents_filename, const string &host_url, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, const string &root_dir, const string &host_dir, - ostream &logfile) { + const string &start_dir, ostream &logfile) { // Ensure that all of the function pointers have been found. if (P3D_initialize_ptr == NULL || @@ -371,15 +371,26 @@ init_plugin(const string &contents_filename, const string &host_url, return false; } - if (!P3D_initialize_ptr(P3D_API_VERSION, contents_filename.c_str(), + // A bit of extra hand-hacked compatibility for using newer plug-ins + // with an older version of the core API. + int api_version = P3D_API_VERSION; + if (api_version == 17 && start_dir.empty()) { + api_version = 16; + if (host_dir.empty()) { + api_version = 15; + } + } + + if (!P3D_initialize_ptr(api_version, contents_filename.c_str(), host_url.c_str(), verify_contents, platform.c_str(), log_directory.c_str(), log_basename.c_str(), trusted_environment, console_environment, - root_dir.c_str(), host_dir.c_str())) { + root_dir.c_str(), host_dir.c_str(), + start_dir.c_str())) { // Oops, failure to initialize. logfile << "Failed to initialize plugin (passed API version " - << P3D_API_VERSION << ")\n"; + << api_version << ")\n"; return false; } diff --git a/direct/src/plugin/load_plugin.h b/direct/src/plugin/load_plugin.h index 985eef7261..f9f89565e5 100644 --- a/direct/src/plugin/load_plugin.h +++ b/direct/src/plugin/load_plugin.h @@ -67,13 +67,15 @@ load_plugin(const string &p3d_plugin_filename, P3D_verify_contents verify_contents, const string &platform, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, - const string &root_dir, const string &host_dir, ostream &logfile); + const string &root_dir, const string &host_dir, + const string &start_dir, ostream &logfile); bool init_plugin(const string &contents_filename, const string &host_url, P3D_verify_contents verify_contents, const string &platform, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, - const string &root_dir, const string &host_dir, ostream &logfile); + const string &root_dir, const string &host_dir, + const string &start_dir, ostream &logfile); void unload_plugin(ostream &logfile); bool is_plugin_loaded(); diff --git a/direct/src/plugin/p3dAuthSession.cxx b/direct/src/plugin/p3dAuthSession.cxx index 6130119223..103c372f0a 100644 --- a/direct/src/plugin/p3dAuthSession.cxx +++ b/direct/src/plugin/p3dAuthSession.cxx @@ -163,7 +163,7 @@ start_p3dcert() { P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); - _start_dir = inst_mgr->get_root_dir() + "/start"; + _start_dir = inst_mgr->get_start_dir(); string root_dir = _inst->_p3dcert_package->get_package_dir(); mkdir_complete(_start_dir, nout); diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index d81a271d1e..3f84bb441e 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -1564,7 +1564,7 @@ uninstall_packages() { if (inst_mgr->get_verify_contents() != P3D_VC_never) { string start_dir_suffix = get_start_dir_suffix(); if (!start_dir_suffix.empty()) { - string start_dir = inst_mgr->get_root_dir() + "/start" + start_dir_suffix; + string start_dir = inst_mgr->get_start_dir() + start_dir_suffix; nout << "Cleaning up start directory " << start_dir << "\n"; inst_mgr->delete_directory_recursively(start_dir); } diff --git a/direct/src/plugin/p3dInstanceManager.I b/direct/src/plugin/p3dInstanceManager.I index caadc083b3..af5b6de16c 100644 --- a/direct/src/plugin/p3dInstanceManager.I +++ b/direct/src/plugin/p3dInstanceManager.I @@ -111,6 +111,18 @@ get_root_dir() const { return _root_dir; } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::get_start_dir +// Access: Public +// Description: Returns the directory that the .p3d file should be +// mounted to and run from. This is usually the +// "start" subdirectory of the root_dir. +//////////////////////////////////////////////////////////////////// +inline const string &P3DInstanceManager:: +get_start_dir() const { + return _start_dir; +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstanceManager::get_platform // Access: Public diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index 793e6cf36e..fa8c70def2 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -201,7 +201,8 @@ initialize(int api_version, const string &contents_filename, const string &platform, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, - const string &root_dir, const string &host_dir) { + const string &root_dir, const string &host_dir, + const string &start_dir) { _api_version = api_version; _host_url = host_url; _verify_contents = verify_contents; @@ -298,12 +299,18 @@ initialize(int api_version, const string &contents_filename, } else { _root_dir = root_dir; } - + _host_dir = host_dir; + if (start_dir.empty()) { + _start_dir = _root_dir + "/start"; + } else { + _start_dir = start_dir; + } + // Allow the caller (e.g. panda3d.exe) to specify a log directory. // Or, allow the developer to compile one in. - + // // Failing that, we write logfiles to Panda3D/log. if (_log_directory.empty()) { _log_directory = _root_dir + "/log"; @@ -1515,8 +1522,10 @@ create_runtime_environment() { // Make the certificate directory. _certs_dir = _root_dir + "/certs"; - if (!mkdir_complete(_certs_dir, nout)) { - nout << "Couldn't mkdir " << _certs_dir << "\n"; + if (!get_trusted_environment()) { + if (!mkdir_complete(_certs_dir, nout)) { + nout << "Couldn't mkdir " << _certs_dir << "\n"; + } } _created_runtime_environment = true; diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h index 78cfcfbdce..b051c01310 100644 --- a/direct/src/plugin/p3dInstanceManager.h +++ b/direct/src/plugin/p3dInstanceManager.h @@ -59,7 +59,8 @@ public: bool trusted_environment, bool console_environment, const string &root_dir = "", - const string &host_dir = ""); + const string &host_dir = "", + const string &start_dir = ""); inline bool is_initialized() const; inline void reconsider_runtime_environment(); @@ -69,6 +70,7 @@ public: inline int get_api_version() const; inline const string &get_host_url() const; inline const string &get_root_dir() const; + inline const string &get_start_dir() const; inline const string &get_platform() const; inline const string &get_temp_directory() const; inline const string &get_log_directory() const; @@ -173,6 +175,7 @@ private: string _host_url; string _root_dir; string _host_dir; + string _start_dir; string _certs_dir; P3D_verify_contents _verify_contents; string _platform; diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index e0b9c73f08..3e6189ce4d 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -717,7 +717,7 @@ start_p3dpython(P3DInstance *inst) { _keep_user_env = true; } if (!_keep_user_env) { - _start_dir = inst_mgr->get_root_dir() + "/start" + inst->get_start_dir_suffix(); + _start_dir = inst_mgr->get_start_dir() + inst->get_start_dir_suffix(); mkdir_complete(_start_dir, nout); } replace_slashes(_start_dir); diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index 8641a72121..241a59d253 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -39,7 +39,8 @@ P3D_initialize(int api_version, const char *contents_filename, const char *platform, const char *log_directory, const char *log_basename, bool trusted_environment, bool console_environment, - const char *root_dir, const char *host_dir) { + const char *root_dir, const char *host_dir, + const char *start_dir) { if (api_version < 10 || api_version > P3D_API_VERSION) { // Can't accept an incompatible version. return false; @@ -89,12 +90,16 @@ P3D_initialize(int api_version, const char *contents_filename, host_dir = ""; } + if (api_version < 17 || start_dir == NULL) { + start_dir = ""; + } + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); bool result = inst_mgr->initialize(api_version, contents_filename, host_url, verify_contents, platform, log_directory, log_basename, trusted_environment, console_environment, - root_dir, host_dir); + root_dir, host_dir, start_dir); RELEASE_LOCK(_api_lock); return result; } diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index e053e6e21b..916763c036 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 16 +#define P3D_API_VERSION 17 /************************ GLOBAL FUNCTIONS **************************/ @@ -161,7 +161,8 @@ P3D_initialize_func(int api_version, const char *contents_filename, const char *platform, const char *log_directory, const char *log_basename, bool trusted_environment, bool console_environment, - const char *root_dir, const char *host_dir); + const char *root_dir, const char *host_dir, + const char *start_dir); /* This function should be called to unload the core API. It will release all internally-allocated memory and return the core API to diff --git a/direct/src/plugin_activex/PPInstance.cpp b/direct/src/plugin_activex/PPInstance.cpp index a0984a27f6..2151fc63f1 100644 --- a/direct/src/plugin_activex/PPInstance.cpp +++ b/direct/src/plugin_activex/PPInstance.cpp @@ -581,12 +581,12 @@ int PPInstance::LoadPlugin( const std::string& dllFilename ) pathname = override_filename; } #endif // P3D_PLUGIN_P3D_PLUGIN - + nout << "Attempting to load core API from " << pathname << "\n"; string contents_filename = m_rootDir + "/contents.xml"; if (!load_plugin(pathname, contents_filename, PANDA_PACKAGE_HOST_URL, - P3D_VC_normal, "", "", "", false, false, - m_rootDir, "", nout)) { + P3D_VC_normal, "", "", "", false, false, + m_rootDir, "", "", nout)) { nout << "Unable to launch core API in " << pathname << "\n"; error = 1; } else { diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 55b9757a04..209204652d 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -1738,8 +1738,8 @@ do_load_plugin() { nout << "Attempting to load core API from " << pathname << "\n"; string contents_filename = _root_dir + "/contents.xml"; if (!load_plugin(pathname, contents_filename, PANDA_PACKAGE_HOST_URL, - P3D_VC_normal, "", "", "", false, false, - _root_dir, "", nout)) { + P3D_VC_normal, "", "", "", false, false, + _root_dir, "", "", nout)) { nout << "Unable to launch core API in " << pathname << "\n"; set_failed(); return; diff --git a/direct/src/plugin_standalone/p3dEmbed.cxx b/direct/src/plugin_standalone/p3dEmbed.cxx index 4ee1ff31ca..a09c13423b 100644 --- a/direct/src/plugin_standalone/p3dEmbed.cxx +++ b/direct/src/plugin_standalone/p3dEmbed.cxx @@ -53,7 +53,8 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { // the + 1 from the test. _read_offset_check = read_offset + (streampos)1; if (_read_offset_check == (streampos)0xFF3D3D01) { - cerr << "This program is not intended to be run directly.\nIt is used by pdeploy to construct an embedded Panda3D application.\n"; + cerr << "This program is not intended to be run directly.\nIt is used " + "by pdeploy to construct an embedded Panda3D application.\n"; return 1; } @@ -86,22 +87,30 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { string value; string root_dir; string host_dir; + string start_dir; + while (true) { if (curchr == EOF) { cerr << "Truncated stream\n"; - return(1); + return 1; } else if (curchr == 0) { // Two null bytes in a row means we've reached the end of the data. if (havenull) { break; } - + // This means we haven't seen an '=' character yet. if (keyword == "") { if (curstr != "") { cerr << "Ignoring token '" << curstr << "' without value\n"; } + + } else if (keyword == "start_dir") { + // Don't pass this on as a token, since it has slightly different + // semantics when used as an HTML token. + start_dir = curstr; + } else { value.assign(curstr); P3D_token token; @@ -118,6 +127,8 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { _got_win_size = true; } else if (keyword == "log_basename") { _log_basename = value; + } else if (keyword == "log_directory") { + _log_dirname = value; } else if (keyword == "root_dir") { root_dir = value; } else if (keyword == "host_dir") { @@ -168,6 +179,13 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { _host_dir = host_dir_f.to_os_specific(); } + // Make the start directory absolute + if (!start_dir.empty()) { + Filename start_dir_f(start_dir); + start_dir_f.make_absolute(f.get_dirname()); + _start_dir = start_dir_f.to_os_specific(); + } + // Initialize the core API by directly assigning all of the function // pointers. P3D_initialize_ptr = &P3D_initialize; @@ -229,18 +247,17 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { // function pointers. This will also call P3D_initialize(). if (!init_plugin("", _host_url, _verify_contents, _this_platform, _log_dirname, _log_basename, true, _console_environment, - _root_dir, _host_dir, cerr)) { + _root_dir, _host_dir, _start_dir, cerr)) { cerr << "Unable to launch core API\n"; return 1; } - + // Create a plugin instance and run the program P3D_instance *inst = create_instance(f, true, argv, argc, read_offset); _instances.insert(inst); run_main_loop(); - unload_plugin(cerr); return 0; } diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index ab0219f7cf..fd0d2f44b7 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -690,7 +690,6 @@ choose_random_mirrors(vector_string &result, int num_mirrors) { } } - //////////////////////////////////////////////////////////////////// // Function: Panda3D::get_core_api // Access: Protected @@ -700,78 +699,12 @@ choose_random_mirrors(vector_string &result, int num_mirrors) { //////////////////////////////////////////////////////////////////// bool Panda3D:: get_core_api() { + bool is_fresh = false; if (!_coreapi_dll.quick_verify(_root_dir)) { - // The DLL file needs to be downloaded. Build up our list of - // URL's to attempt to download it from, in reverse order. - string url; - vector_string core_urls; - - // Our last act of desperation: hit the original host, with a - // query uniquifier, to break through any caches. - ostringstream strm; - strm << _download_url_prefix << _coreapi_dll.get_filename() - << "?" << time(NULL); - url = strm.str(); - core_urls.push_back(url); - - // Before we try that, we'll hit the original host, without a - // uniquifier. - url = _download_url_prefix; - url += _coreapi_dll.get_filename(); - core_urls.push_back(url); - - // And before we try that, we'll try two mirrors, at random. - vector_string mirrors; - choose_random_mirrors(mirrors, 2); - for (vector_string::iterator si = mirrors.begin(); - si != mirrors.end(); - ++si) { - url = (*si) + _coreapi_dll.get_filename(); - core_urls.push_back(url); - } - - // The very first thing we'll try is the super_mirror, if we have - // one. - if (!_super_mirror_url_prefix.empty()) { - url = _super_mirror_url_prefix + _coreapi_dll.get_filename(); - core_urls.push_back(url); - } - - // Now pick URL's off the list, and try them, until we have - // success. - Filename pathname = Filename::from_os_specific(_coreapi_dll.get_pathname(_root_dir)); - pathname.make_dir(); - HTTPClient *http = HTTPClient::get_global_ptr(); - - bool success = false; - while (!core_urls.empty()) { - url = core_urls.back(); - core_urls.pop_back(); - - PT(HTTPChannel) channel = http->get_document(url); - if (!channel->download_to_file(pathname)) { - cerr << "Unable to download " << url << "\n"; - - } else if (!_coreapi_dll.full_verify(_root_dir)) { - cerr << "Mismatched download for " << url << "\n"; - - } else { - // successfully downloaded! - success = true; - break; - } - } - - if (!success) { - cerr << "Couldn't download core API.\n"; + if (!download_core_api()) { return false; } - - // Since we had to download some of it, might as well ask the core - // API to check all of it. - if (_verify_contents == P3D_VC_none) { - _verify_contents = P3D_VC_normal; - } + is_fresh = true; } // Now we've got the DLL. Load it. @@ -795,9 +728,19 @@ get_core_api() { if (!load_plugin(pathname, contents_filename.to_os_specific(), _host_url, _verify_contents, _this_platform, _log_dirname, _log_basename, trusted_environment, _console_environment, - _root_dir, "", cerr)) { - cerr << "Unable to launch core API in " << pathname << "\n"; - return false; + _root_dir, _host_dir, _start_dir, cerr)) { + + // If we're not sure this is the latest version, make sure it is + // up-to-date, and then try again. + if (is_fresh || !download_core_api() || + !load_plugin(pathname, contents_filename.to_os_specific(), + _host_url, _verify_contents, _this_platform, _log_dirname, + _log_basename, trusted_environment, _console_environment, + _root_dir, _host_dir, _start_dir, cerr)) { + + cerr << "Unable to launch core API in " << pathname << "\n"; + return false; + } } // Successfully loaded. @@ -822,6 +765,88 @@ get_core_api() { return true; } +//////////////////////////////////////////////////////////////////// +// Function: Panda3D::download_core_api +// Access: Protected +// Description: Downloads the latest version of the core API from +// the plug-in server. +//////////////////////////////////////////////////////////////////// +bool Panda3D:: +download_core_api() { + // The DLL file needs to be downloaded. Build up our list of + // URL's to attempt to download it from, in reverse order. + string url; + vector_string core_urls; + + // Our last act of desperation: hit the original host, with a + // query uniquifier, to break through any caches. + ostringstream strm; + strm << _download_url_prefix << _coreapi_dll.get_filename() + << "?" << time(NULL); + url = strm.str(); + core_urls.push_back(url); + + // Before we try that, we'll hit the original host, without a + // uniquifier. + url = _download_url_prefix; + url += _coreapi_dll.get_filename(); + core_urls.push_back(url); + + // And before we try that, we'll try two mirrors, at random. + vector_string mirrors; + choose_random_mirrors(mirrors, 2); + for (vector_string::iterator si = mirrors.begin(); + si != mirrors.end(); + ++si) { + url = (*si) + _coreapi_dll.get_filename(); + core_urls.push_back(url); + } + + // The very first thing we'll try is the super_mirror, if we have + // one. + if (!_super_mirror_url_prefix.empty()) { + url = _super_mirror_url_prefix + _coreapi_dll.get_filename(); + core_urls.push_back(url); + } + + // Now pick URL's off the list, and try them, until we have + // success. + Filename pathname = Filename::from_os_specific(_coreapi_dll.get_pathname(_root_dir)); + pathname.make_dir(); + HTTPClient *http = HTTPClient::get_global_ptr(); + + bool success = false; + while (!core_urls.empty()) { + url = core_urls.back(); + core_urls.pop_back(); + + PT(HTTPChannel) channel = http->get_document(url); + if (!channel->download_to_file(pathname)) { + cerr << "Unable to download " << url << "\n"; + + } else if (!_coreapi_dll.full_verify(_root_dir)) { + cerr << "Mismatched download for " << url << "\n"; + + } else { + // successfully downloaded! + success = true; + break; + } + } + + if (!success) { + cerr << "Couldn't download core API.\n"; + return false; + } + + // Since we had to download some of it, might as well ask the core + // API to check all of it. + if (_verify_contents == P3D_VC_none) { + _verify_contents = P3D_VC_normal; + } + return true; +} + //////////////////////////////////////////////////////////////////// // Function: Panda3D::usage // Access: Protected diff --git a/direct/src/plugin_standalone/panda3d.h b/direct/src/plugin_standalone/panda3d.h index 36603b93e6..94efc0c41f 100644 --- a/direct/src/plugin_standalone/panda3d.h +++ b/direct/src/plugin_standalone/panda3d.h @@ -48,6 +48,7 @@ protected: void add_mirror(string mirror_url); void choose_random_mirrors(vector_string &result, int num_mirrors); bool get_core_api(); + bool download_core_api(); void usage(); diff --git a/direct/src/plugin_standalone/panda3dBase.h b/direct/src/plugin_standalone/panda3dBase.h index 0f577f39fe..f53e59b14c 100644 --- a/direct/src/plugin_standalone/panda3dBase.h +++ b/direct/src/plugin_standalone/panda3dBase.h @@ -74,6 +74,7 @@ protected: string _host_url; string _root_dir; string _host_dir; + string _start_dir; string _log_dirname; string _log_basename; string _this_platform;