From 60973fdb7b0d6044224ae0e9e2af3456aab6e87d Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 22 Sep 2010 19:52:14 +0000 Subject: [PATCH] Lots of changes to the plugin and pdeploy to make packaged games run without needing write access or internet access --- direct/src/p3d/AppRunner.py | 6 + direct/src/p3d/DeploymentTools.py | 172 ++++++++++++++------- direct/src/p3d/HostInfo.py | 29 ++-- direct/src/p3d/PackageInfo.py | 76 ++++++--- direct/src/p3d/pdeploy.py | 2 + direct/src/plugin/load_plugin.cxx | 10 +- direct/src/plugin/load_plugin.h | 4 +- direct/src/plugin/p3dHost.cxx | 75 +++++---- direct/src/plugin/p3dHost.h | 2 +- direct/src/plugin/p3dInstance.cxx | 29 ++-- direct/src/plugin/p3dInstanceManager.cxx | 11 +- direct/src/plugin/p3dInstanceManager.h | 4 +- direct/src/plugin/p3dPackage.cxx | 77 +++++++-- direct/src/plugin/p3d_plugin.cxx | 11 +- direct/src/plugin/p3d_plugin.h | 21 ++- direct/src/plugin_activex/PPInstance.cpp | 2 +- direct/src/plugin_npapi/ppInstance.cxx | 2 +- direct/src/plugin_standalone/p3dEmbed.cxx | 27 +++- direct/src/plugin_standalone/panda3d.cxx | 2 +- direct/src/plugin_standalone/panda3dBase.h | 1 + 20 files changed, 394 insertions(+), 169 deletions(-) diff --git a/direct/src/p3d/AppRunner.py b/direct/src/p3d/AppRunner.py index 5ba23797a3..e616d615d0 100644 --- a/direct/src/p3d/AppRunner.py +++ b/direct/src/p3d/AppRunner.py @@ -79,6 +79,7 @@ class AppRunner(DirectObject): P3DVCNone = 0 P3DVCNormal = 1 P3DVCForce = 2 + P3DVCNever = 3 # Also from p3d_plugin.h P3D_CONTENTS_DEFAULT_MAX_AGE = 5 @@ -570,6 +571,11 @@ class AppRunner(DirectObject): totalSize += packageData.totalSize self.notify.info("Total Panda3D disk space used: %s MB" % ( (totalSize + 524288) / 1048576)) + + if self.verifyContents == self.P3DVCNever: + # We're not allowed to delete anything anyway. + return + self.notify.info("Configured max usage is: %s MB" % ( (self.maxDiskUsage + 524288) / 1048576)) if totalSize <= self.maxDiskUsage: diff --git a/direct/src/p3d/DeploymentTools.py b/direct/src/p3d/DeploymentTools.py index c9f9135b1c..b3717ffa56 100644 --- a/direct/src/p3d/DeploymentTools.py +++ b/direct/src/p3d/DeploymentTools.py @@ -6,7 +6,9 @@ __all__ = ["Standalone", "Installer"] import os, sys, subprocess, tarfile, shutil, time, zipfile, glob from direct.directnotify.DirectNotifyGlobal import * -from pandac.PandaModules import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile, readXmlStream +from direct.showbase.AppRunnerGlobal import appRunner +from pandac.PandaModules import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile +from pandac.PandaModules import TiXmlDocument, TiXmlDeclaration, TiXmlElement, readXmlStream from direct.p3d.HostInfo import HostInfo class CachedFile: @@ -27,7 +29,7 @@ class Standalone: hostDir = Filename(Filename.getTempDirectory(), 'pdeploy/') hostDir.makeDir() - self.host = HostInfo(PandaSystem.getPackageHostUrl(), appRunner = base.appRunner, hostDir = hostDir, asMirror = False, perPlatform = True) + self.host = HostInfo(PandaSystem.getPackageHostUrl(), appRunner = appRunner, hostDir = hostDir, asMirror = False, perPlatform = True) self.http = HTTPClient.getGlobalPtr() if not self.host.hasContentsFile: @@ -61,6 +63,9 @@ class Standalone: if platform == None: platform = PandaSystem.getPlatform() + + vfs = VirtualFileSystem.getGlobalPtr() + for package in self.host.getPackages(name = "p3dembed", platform = platform): if not package.downloadDescFile(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) @@ -75,7 +80,7 @@ class Standalone: else: p3dembed = Filename(self.host.hostDir, "p3dembed/%s/p3dembed" % package.platform) - if not p3dembed.exists(): + if not vfs.exists(p3dembed): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue @@ -104,7 +109,11 @@ class Standalone: output.makeDir() ohandle = open(output.toOsSpecific(), "wb") ohandle.write(p3dembed_data) - for token in self.tokens.items(): + + # Write out the tokens. Set log_basename to the basename by default + tokens = {"log_basename" : self.basename} + tokens.update(self.tokens) + for token in tokens.items(): ohandle.write("\0%s=%s" % token) ohandle.write("\0\0") @@ -134,11 +143,12 @@ class Standalone: return [] filenames = [] + vfs = VirtualFileSystem.getGlobalPtr() for e in package.extracts: if e.basename not in ["p3dembed", "p3dembed.exe"]: filename = Filename(package.getPackageDir(), e.filename) filename.makeAbsolute() - if filename.exists(): + if vfs.exists(filename): filenames.append(filename) else: Standalone.notify.error("%s mentioned in xml, but does not exist" % e.filename) @@ -187,14 +197,16 @@ class Installer: self.requirements.append((p3dRequires.Attribute('name'), p3dRequires.Attribute('version'))) p3dRequires = p3dRequires.NextSiblingElement('requires') - def installPackagesInto(self, rootDir, platform): + def installPackagesInto(self, hostDir, platform): """ Installs the packages required by the .p3d file into - the specified root directory, for the given platform. """ + the specified directory, for the given platform. """ if not self.includeRequires: return - host = HostInfo(self.hostUrl, appRunner = base.appRunner, rootDir = rootDir, asMirror = True, perPlatform = False) + packages = [] + + host = HostInfo(self.hostUrl, appRunner = appRunner, hostDir = hostDir, asMirror = False, perPlatform = False) if not host.hasContentsFile: if not host.readContentsFile(): if not host.downloadContentsFile(self.http): @@ -203,15 +215,17 @@ class Installer: for name, version in self.requirements: package = host.getPackage(name, version, platform) + package.installed = True # Hack not to let it install itself + packages.append(package) if not package.downloadDescFile(self.http): - Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) + Installer.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue if not package.downloadPackage(self.http): - Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) + Installer.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue # Also install the 'images' package from the same host that p3dembed was downloaded from. - host = HostInfo(self.standalone.host.hostUrl, appRunner = base.appRunner, rootDir = rootDir, asMirror = False, perPlatform = False) + host = HostInfo(self.standalone.host.hostUrl, appRunner = appRunner, hostDir = hostDir, asMirror = False, perPlatform = False) if not host.hasContentsFile: if not host.readContentsFile(): if not host.downloadContentsFile(self.http): @@ -219,13 +233,71 @@ class Installer: return for package in host.getPackages(name = "images"): + package.installed = True # Hack not to let it install itself + packages.append(package) if not package.downloadDescFile(self.http): - Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) + Installer.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue if not package.downloadPackage(self.http): - Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) + Installer.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue break + + # Remove the extracted files from the compressed archive, to save space. + vfs = VirtualFileSystem.getGlobalPtr() + for package in packages: + if package.uncompressedArchive: + archive = Filename(package.getPackageDir(), package.uncompressedArchive.filename) + if not archive.exists(): + continue + + print archive + mf = Multifile() + # Make sure that it isn't mounted before altering it, just to be safe + vfs.unmount(archive) + if not mf.openRead(archive): + Installer.notify.warning("Failed to open archive " + archive) + continue + + # We don't iterate over getNumSubfiles because we're + # removing subfiles while we're iterating over them. + subfiles = mf.getSubfileNames() + for subfile in subfiles: + # We do *NOT* call vfs.exists here in case the package is mounted. + if Filename(package.getPackageDir(), subfile).exists(): + mf.removeSubfile(subfile) + + # This seems essential for mf.close() not to crash later. + mf.repack() + + # If we have no subfiles left, we can just remove the multifile. + if mf.getNumSubfiles() == 0: + Installer.notify.info("Removing empty archive " + package.uncompressedArchive.filename) + mf.close() + archive.unlink() + else: + mf.close() + + # Write out our own contents.xml file. + doc = TiXmlDocument() + decl = TiXmlDeclaration("1.0", "utf-8", "") + doc.InsertEndChild(decl) + + xcontents = TiXmlElement("contents") + for package in packages: + xpackage = TiXmlElement('package') + xpackage.SetAttribute('name', package.packageName) + if package.platform: + xpackage.SetAttribute('platform', package.platform) + if package.packageVersion: + xpackage.SetAttribute('version', version) + xpackage.SetAttribute('filename', package.packageName + "/" + package.packageVersion + "/" + package.descFileBasename) + else: + xpackage.SetAttribute('filename', package.packageName + "/" + package.descFileBasename) + xcontents.InsertEndChild(xpackage) + + doc.InsertEndChild(xcontents) + doc.SaveFile(Filename(hostDir, "contents.xml").toOsSpecific()) def buildAll(self, outputDir = "."): """ Creates a (graphical) installer for every known platform. @@ -289,45 +361,26 @@ class Installer: print >>controlfile, "Description: %s" % self.fullname print >>controlfile, "Depends: libc6, libgcc1, libstdc++6, libx11-6, libssl0.9.8" controlfile.close() - postinst = open(Filename(tempdir, "postinst").toOsSpecific(), "w") - print >>postinst, "#!/bin/sh" - print >>postinst, "/usr/bin/%s --prep" % self.shortname.lower() - print >>postinst, "chmod -R 777 /usr/share/%s" % self.shortname.lower() - print >>postinst, "chmod -R 555 /usr/share/%s/hosts" % self.shortname.lower() - postinst.close() - os.chmod(Filename(tempdir, "postinst").toOsSpecific(), 0755) - postrmfile = open(Filename(tempdir, "postrm").toOsSpecific(), "w") - print >>postrmfile, "#!/bin/sh" - print >>postrmfile, "rm -rf /usr/share/%s" % self.shortname.lower() - postrmfile.close() - os.chmod(Filename(tempdir, "postrm").toOsSpecific(), 0755) Filename(tempdir, "usr/bin/").makeDir() - self.standalone.tokens["root_dir"] = "/usr/share/" + self.shortname.lower() + if self.includeRequires: + self.standalone.tokens["host_dir"] = "/usr/lib/" + self.shortname.lower() + elif "host_dir" in self.standalone.tokens: + del self.standalone.tokens["host_dir"] self.standalone.build(Filename(tempdir, "usr/bin/" + self.shortname.lower()), platform) if not self.licensefile.empty(): Filename(tempdir, "usr/share/doc/%s/" % self.shortname.lower()).makeDir() shutil.copyfile(self.licensefile.toOsSpecific(), Filename(tempdir, "usr/share/doc/%s/copyright" % self.shortname.lower()).toOsSpecific()) - rootDir = Filename(tempdir, "usr/share/" + self.shortname.lower()) - rootDir.makeDir() - Filename(rootDir, "log").makeDir() - Filename(rootDir, "prc").makeDir() - Filename(rootDir, "start").makeDir() - Filename(rootDir, "certs").makeDir() - self.installPackagesInto(rootDir, platform) + hostDir = Filename(tempdir, "usr/lib/" + self.shortname.lower()) + hostDir.makeDir() + self.installPackagesInto(hostDir, platform) # Create a control.tar.gz file in memory controlfile = Filename(tempdir, "control") - postinstfile = Filename(tempdir, "postinst") - postrmfile = Filename(tempdir, "postrm") controltargz = CachedFile() controltarfile = tarfile.TarFile.gzopen("control.tar.gz", "w", controltargz, 9) controltarfile.add(controlfile.toOsSpecific(), "control") - controltarfile.add(postinstfile.toOsSpecific(), "postinst") - controltarfile.add(postrmfile.toOsSpecific(), "postrm") controltarfile.close() controlfile.unlink() - postinstfile.unlink() - postrmfile.unlink() # Create the data.tar.gz file in the temporary directory datatargz = CachedFile() @@ -352,7 +405,7 @@ class Installer: if (len(datatargz.str) & 1): debfile.write("\x0A") debfile.close() try: - base.appRunner.rmtree(tempdir) + appRunner.rmtree(tempdir) except: try: shutil.rmtree(tempdir.toOsSpecific()) except: pass @@ -367,11 +420,14 @@ class Installer: # Create the executable for the application bundle exefile = Filename(output, "Contents/MacOS/" + self.shortname) exefile.makeDir() - self.standalone.tokens["root_dir"] = "../Resources" + if self.includeRequires: + self.standalone.tokens["host_dir"] = "../Resources" + elif "host_dir" in self.standalone.tokens: + del self.standalone.tokens["host_dir"] self.standalone.build(exefile, platform) - rootDir = Filename(output, "Contents/Resources/") - rootDir.makeDir() - self.installPackagesInto(rootDir, platform) + hostDir = Filename(output, "Contents/Resources/") + hostDir.makeDir() + self.installPackagesInto(hostDir, platform) # Create the application plist file. # Although it might make more sense to use Python's plistlib module here, @@ -510,13 +566,6 @@ class Installer: plist.write('\n') plist.close() - postflight = open(Filename(output, "Contents/Resources/postflight").toOsSpecific(), "w") - print >>postflight, '#!/bin/sh' - print >>postflight, 'chmod -R 777 "%s"' % appname - print >>postflight, 'chmod -R 755 "%s/hosts/"' % appname - postflight.close() - os.chmod(Filename(output, "Contents/Resources/postflight").toOsSpecific(), 0755) - if hasattr(tarfile, "PAX_FORMAT"): archive = tarfile.open(Filename(output, "Contents/Archive.pax.gz").toOsSpecific(), "w:gz", format = tarfile.PAX_FORMAT) else: @@ -569,13 +618,16 @@ class Installer: exefile = Filename(Filename.getTempDirectory(), self.shortname + ".exe") exefile.unlink() - self.standalone.tokens["root_dir"] = "." + if self.includeRequires: + self.standalone.tokens["host_dir"] = "." + elif "host_dir" in self.standalone.tokens: + del self.standalone.tokens["host_dir"] self.standalone.build(exefile, platform) - # Temporary directory to store the rootdir in - rootDir = Filename.temporary("", self.shortname.lower() + "_exe_", "") + "/" - rootDir.makeDir() - self.installPackagesInto(rootDir, platform) + # Temporary directory to store the hostdir in + hostDir = Filename.temporary("", self.shortname.lower() + "_exe_", "") + "/" + hostDir.makeDir() + self.installPackagesInto(hostDir, platform) nsifile = Filename(Filename.getTempDirectory(), self.shortname + ".nsi") nsifile.unlink() @@ -625,11 +677,11 @@ class Installer: for f in extrafiles: nsi.write(' File "%s"\n' % f.toOsSpecific()) curdir = "" - for root, dirs, files in os.walk(rootDir.toOsSpecific()): + for root, dirs, files in os.walk(hostDir.toOsSpecific()): for name in files: file = Filename.fromOsSpecific(os.path.join(root, name)) file.makeAbsolute() - file.makeRelativeTo(rootDir) + file.makeRelativeTo(hostDir) outdir = file.getDirname().replace('/', '\\') if curdir != outdir: nsi.write(' SetOutPath "$INSTDIR\\%s"\n' % outdir) @@ -670,8 +722,8 @@ class Installer: nsifile.unlink() try: - base.appRunner.rmtree(rootDir) + appRunner.rmtree(hostDir) except: - try: shutil.rmtree(rootDir.toOsSpecific()) + try: shutil.rmtree(hostDir.toOsSpecific()) except: pass return output diff --git a/direct/src/p3d/HostInfo.py b/direct/src/p3d/HostInfo.py index 7ca0e47760..2287f24f07 100644 --- a/direct/src/p3d/HostInfo.py +++ b/direct/src/p3d/HostInfo.py @@ -118,6 +118,10 @@ class HostInfo: # We've already got one. return True + if self.appRunner.verifyContents == self.appRunner.P3DVCNever: + # Not allowed to. + return False + rf = None if http: if not redownload and self.appRunner and self.appRunner.superMirrorUrl: @@ -183,6 +187,10 @@ class HostInfo: not. """ assert self.hasContentsFile + if self.appRunner.verifyContents == self.appRunner.P3DVCNever: + # Not allowed to. + return False + url = self.hostUrlPrefix + 'contents.xml' self.notify.info("Redownloading %s" % (url)) @@ -215,7 +223,9 @@ class HostInfo: def hasCurrentContentsFile(self): """ Returns true if a contents.xml file has been successfully read for this host and is still current, false otherwise. """ - if not self.appRunner or self.appRunner.verifyContents == self.appRunner.P3DVCNone: + if not self.appRunner \ + or self.appRunner.verifyContents == self.appRunner.P3DVCNone \ + or self.appRunner.verifyContents == self.appRunner.P3DVCNever: # If we're not asking to verify contents, then # contents.xml files never expires. return self.hasContentsFile @@ -342,14 +352,15 @@ class HostInfo: self.hasContentsFile = True # Now save the contents.xml file into the standard location. - assert self.hostDir - filename = Filename(self.hostDir, 'contents.xml') - filename.makeDir() - if freshDownload: - doc.SaveFile(filename.toOsSpecific()) - else: - if filename != tempFilename: - tempFilename.copyTo(filename) + if self.appRunner.verifyContents != self.appRunner.P3DVCNever: + assert self.hostDir + filename = Filename(self.hostDir, 'contents.xml') + filename.makeDir() + if freshDownload: + doc.SaveFile(filename.toOsSpecific()) + else: + if filename != tempFilename: + tempFilename.copyTo(filename) return True diff --git a/direct/src/p3d/PackageInfo.py b/direct/src/p3d/PackageInfo.py index dc2d2007d6..c4ce7220e1 100644 --- a/direct/src/p3d/PackageInfo.py +++ b/direct/src/p3d/PackageInfo.py @@ -263,42 +263,44 @@ class PackageInfo: # We've already got one. yield self.stepComplete; return - self.http = http + if self.host.appRunner and self.host.appRunner.verifyContents != self.host.appRunner.P3DVCNever: + # We're allowed to download it. + self.http = http - func = lambda step, self = self: self.__downloadFile( - None, self.descFile, - urlbase = self.descFile.filename, - filename = self.descFileBasename) - step = self.InstallStep(func, self.descFile.size, self.downloadFactor, 'downloadDesc') - - for token in step.func(): - if token == self.stepContinue: - yield token - else: - break - - while token == self.restartDownload: - # Try again. func = lambda step, self = self: self.__downloadFile( None, self.descFile, urlbase = self.descFile.filename, filename = self.descFileBasename) step = self.InstallStep(func, self.descFile.size, self.downloadFactor, 'downloadDesc') + for token in step.func(): if token == self.stepContinue: yield token else: break - if token == self.stepFailed: - # Couldn't download the desc file. - yield self.stepFailed; return + while token == self.restartDownload: + # Try again. + func = lambda step, self = self: self.__downloadFile( + None, self.descFile, + urlbase = self.descFile.filename, + filename = self.descFileBasename) + step = self.InstallStep(func, self.descFile.size, self.downloadFactor, 'downloadDesc') + for token in step.func(): + if token == self.stepContinue: + yield token + else: + break - assert token == self.stepComplete + if token == self.stepFailed: + # Couldn't download the desc file. + yield self.stepFailed; return - filename = Filename(self.getPackageDir(), self.descFileBasename) - # Now that we've written the desc file, make it read-only. - os.chmod(filename.toOsSpecific(), 0444) + assert token == self.stepComplete + + filename = Filename(self.getPackageDir(), self.descFileBasename) + # Now that we've written the desc file, make it read-only. + os.chmod(filename.toOsSpecific(), 0444) if not self.__readDescFile(): # Weird, it passed the hash check, but we still can't read @@ -409,6 +411,12 @@ class PackageInfo: pc.start() self.hasPackage = False + + if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever: + # We're not allowed to download anything. + self.installPlans = [] + pc.stop() + return if self.asMirror: # If we're just downloading a mirror archive, we only need @@ -520,6 +528,10 @@ class PackageInfo: """ Returns true if the archive and all extractable files are already correct on disk, false otherwise. """ + if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever: + # Assume that everything is just fine. + return True + # Get a list of all of the files in the directory, so we can # remove files that don't belong. contents = self.__scanDirectoryRecursively(self.getPackageDir()) @@ -604,6 +616,10 @@ class PackageInfo: # We've already got one. yield self.stepComplete; return + if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever: + # We're not allowed to download anything. Assume it's already downloaded. + yield self.stepComplete; return + # We should have an install plan by the time we get here. assert self.installPlans @@ -715,6 +731,10 @@ class PackageInfo: packageDir. Yields one of stepComplete, stepFailed, restartDownload, or stepContinue. """ + if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever: + # We're not allowed to download anything. + yield self.stepFailed; return + self.updated = True if not urlbase: @@ -895,6 +915,10 @@ class PackageInfo: archive. Yields one of stepComplete, stepFailed, restartDownload, or stepContinue. """ + if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever: + # We're not allowed to! + yield self.stepFailed; return + self.updated = True sourcePathname = Filename(self.getPackageDir(), self.compressedArchive.filename) @@ -945,6 +969,10 @@ class PackageInfo: self.hasPackage = True yield self.stepComplete; return + if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever: + # We're not allowed to! + yield self.stepFailed; return + self.updated = True mfPathname = Filename(self.getPackageDir(), self.uncompressedArchive.filename) @@ -1090,6 +1118,10 @@ class PackageInfo: if not hasattr(PandaModules, 'TiXmlDocument'): return + if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever: + # Not allowed to write any files to the package directory. + return + if self.updated: # If we've just installed a new version of the package, # re-measure the actual disk space used. diff --git a/direct/src/p3d/pdeploy.py b/direct/src/p3d/pdeploy.py index 4172544567..99e1de6e53 100644 --- a/direct/src/p3d/pdeploy.py +++ b/direct/src/p3d/pdeploy.py @@ -229,6 +229,8 @@ if deploy_mode == 'standalone': s.build(Filename(outputDir, platform + "/" + shortname), platform) elif deploy_mode == 'installer': + if includeRequires: + tokens["verify_contents"] = "never" i = Installer(shortname, fullname, appFilename, version, tokens = tokens) i.licensename = licensename i.licensefile = licensefile diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index 7e0a965558..2a3d94444b 100755 --- a/direct/src/plugin/load_plugin.cxx +++ b/direct/src/plugin/load_plugin.cxx @@ -138,7 +138,8 @@ 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, ostream &logfile) { + const string &root_dir, const string &host_dir, + ostream &logfile) { if (plugin_loaded) { return true; } @@ -254,7 +255,7 @@ load_plugin(const string &p3d_plugin_filename, verify_contents, platform, log_directory, log_basename, trusted_environment, console_environment, - root_dir, logfile)) { + root_dir, host_dir, logfile)) { unload_dso(); return false; } @@ -277,7 +278,8 @@ 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, ostream &logfile) { + const string &root_dir, const string &host_dir, + ostream &logfile) { // Ensure that all of the function pointers have been found. if (P3D_initialize_ptr == NULL || @@ -369,7 +371,7 @@ init_plugin(const string &contents_filename, const string &host_url, 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())) { + root_dir.c_str(), host_dir.c_str())) { // Oops, failure to initialize. logfile << "Failed to initialize plugin (passed API version " diff --git a/direct/src/plugin/load_plugin.h b/direct/src/plugin/load_plugin.h index ae687a6647..16b7922676 100755 --- a/direct/src/plugin/load_plugin.h +++ b/direct/src/plugin/load_plugin.h @@ -67,13 +67,13 @@ 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, ostream &logfile); + const string &root_dir, const string &host_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, ostream &logfile); + const string &root_dir, const string &host_dir, ostream &logfile); void unload_plugin(); bool is_plugin_loaded(); diff --git a/direct/src/plugin/p3dHost.cxx b/direct/src/plugin/p3dHost.cxx index 9477d96528..c04c9b57a5 100644 --- a/direct/src/plugin/p3dHost.cxx +++ b/direct/src/plugin/p3dHost.cxx @@ -23,12 +23,13 @@ //////////////////////////////////////////////////////////////////// // Function: P3DHost::Constructor // Access: Private -// Description: Use P3DInstanceManager::get_host() to construct a new -// P3DHost. +// Description: Use P3DInstanceManager::get_host() to construct a +// new P3DHost. //////////////////////////////////////////////////////////////////// P3DHost:: -P3DHost(const string &host_url) : - _host_url(host_url) +P3DHost(const string &host_url, const string &host_dir) : + _host_url(host_url), + _host_dir(host_dir) { // Ensure that the download URL ends with a slash. _host_url_prefix = _host_url; @@ -116,7 +117,8 @@ get_alt_host(const string &alt_host) { //////////////////////////////////////////////////////////////////// bool P3DHost:: has_current_contents_file(P3DInstanceManager *inst_mgr) const { - if (inst_mgr->get_verify_contents() == P3D_VC_none) { + if (inst_mgr->get_verify_contents() == P3D_VC_never + || inst_mgr->get_verify_contents() == P3D_VC_none) { // If we're not asking to verify contents, then contents.xml files // never expire. return has_contents_file(); @@ -250,36 +252,41 @@ read_contents_file(const string &contents_filename, bool fresh_download) { } } + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + if (_host_dir.empty()) { determine_host_dir(""); } assert(!_host_dir.empty()); - mkdir_complete(_host_dir, nout); - + string standard_filename = _host_dir + "/contents.xml"; - if (fresh_download) { - if (!save_xml_file(&doc, standard_filename)) { - nout << "Couldn't save to " << standard_filename << "\n"; - } - } else { - if (standardize_filename(standard_filename) != - standardize_filename(contents_filename)) { - if (!copy_file(contents_filename, standard_filename)) { - nout << "Couldn't copy to " << standard_filename << "\n"; + + if (inst_mgr->get_verify_contents() != P3D_VC_never) { + mkdir_complete(_host_dir, nout); + + if (fresh_download) { + if (!save_xml_file(&doc, standard_filename)) { + nout << "Couldn't save to " << standard_filename << "\n"; + } + } else { + if (standardize_filename(standard_filename) != + standardize_filename(contents_filename)) { + if (!copy_file(contents_filename, standard_filename)) { + nout << "Couldn't copy to " << standard_filename << "\n"; + } } } - } - P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); - if (_host_url == inst_mgr->get_host_url()) { - // If this is also the plugin host, then copy the contents.xml - // file into the root Panda directory as well, for the next plugin - // iteration. - string top_filename = inst_mgr->get_root_dir() + "/contents.xml"; - if (standardize_filename(top_filename) != - standardize_filename(standard_filename)) { - if (!copy_file(standard_filename, top_filename)) { - nout << "Couldn't copy to " << top_filename << "\n"; + if (_host_url == inst_mgr->get_host_url()) { + // If this is also the plugin host, then copy the contents.xml + // file into the root Panda directory as well, for the next plugin + // iteration. + string top_filename = inst_mgr->get_root_dir() + "/contents.xml"; + if (standardize_filename(top_filename) != + standardize_filename(standard_filename)) { + if (!copy_file(standard_filename, top_filename)) { + nout << "Couldn't copy to " << top_filename << "\n"; + } } } } @@ -305,7 +312,9 @@ read_xhost(TiXmlElement *xhost) { if (host_dir_basename == NULL) { host_dir_basename = ""; } - determine_host_dir(host_dir_basename); + if (_host_dir.empty()) { + determine_host_dir(host_dir_basename); + } // Get the "download" URL, which is the source from which we // download everything other than the contents.xml file. @@ -610,6 +619,14 @@ uninstall() { nout << "Cannot uninstall " << _descriptive_name << ": host directory not yet known.\n"; return; } + + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + + // Check if we're even allowed to. + if (inst_mgr->get_verify_contents() == P3D_VC_never) { + nout << "Not allowed to uninstall " << _descriptive_name << ".\n"; + return; + } // First, explicitly uninstall each of our packages. Packages::iterator mi; @@ -624,8 +641,6 @@ uninstall() { // Then, uninstall the host itself. nout << "Uninstalling " << _descriptive_name << " from " << _host_dir << "\n"; - - P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); inst_mgr->delete_directory_recursively(_host_dir); inst_mgr->forget_host(this); } diff --git a/direct/src/plugin/p3dHost.h b/direct/src/plugin/p3dHost.h index aef86a13db..7b943fe84d 100644 --- a/direct/src/plugin/p3dHost.h +++ b/direct/src/plugin/p3dHost.h @@ -30,7 +30,7 @@ class P3DPackage; //////////////////////////////////////////////////////////////////// class P3DHost { private: - P3DHost(const string &host_url); + P3DHost(const string &host_url, const string &host_dir = ""); ~P3DHost(); public: diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 950246a932..9747867ece 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -505,10 +505,6 @@ set_p3d_filename(const string &p3d_filename, const int &p3d_offset) { //////////////////////////////////////////////////////////////////// void P3DInstance:: set_wparams(const P3DWindowParams &wparams) { - if (is_failed()) { - return; - } - bool prev_got_wparams = _got_wparams; _got_wparams = true; _wparams = wparams; @@ -531,7 +527,15 @@ set_wparams(const P3DWindowParams &wparams) { } else { make_splash_window(); } - + } + + // It doesn't make much sense to go further than this point + // if the instance is already in the failed state. + if (is_failed()) { + return; + } + + if (_wparams.get_window_type() != P3D_WT_hidden) { #ifdef __APPLE__ // On Mac, we have to communicate the results of the rendering // back via shared memory, instead of directly parenting windows @@ -1534,12 +1538,15 @@ uninstall_packages() { } // Also clean up the start directory, if we have a custom start dir. - string start_dir_suffix = get_start_dir_suffix(); - if (!start_dir_suffix.empty()) { - P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); - string start_dir = inst_mgr->get_root_dir() + "/start" + start_dir_suffix; - nout << "Cleaning up start directory " << start_dir << "\n"; - inst_mgr->delete_directory_recursively(start_dir); + // We won't do this if verify_contents is 'none'. + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + 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; + nout << "Cleaning up start directory " << start_dir << "\n"; + inst_mgr->delete_directory_recursively(start_dir); + } } return true; diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index 3a85434626..bc91ff4787 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -194,7 +194,8 @@ initialize(int api_version, 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) { + bool console_environment, + const string &root_dir, const string &host_dir) { _api_version = api_version; _host_url = host_url; _verify_contents = verify_contents; @@ -236,6 +237,8 @@ initialize(int api_version, const string &contents_filename, } else { _root_dir = root_dir; } + + _host_dir = host_dir; // Allow the caller (e.g. panda3d.exe) to specify a log directory. // Or, allow the developer to compile one in. @@ -641,7 +644,7 @@ get_host(const string &host_url) { return (*pi).second; } - P3DHost *host = new P3DHost(host_url); + P3DHost *host = new P3DHost(host_url, _host_dir); bool inserted = _hosts.insert(Hosts::value_type(host_url, host)).second; assert(inserted); @@ -1384,6 +1387,9 @@ create_runtime_environment() { << ", host_url = " << _host_url << ", verify_contents = " << _verify_contents << "\n"; + if (!_host_dir.empty()) { + nout << "_host_dir = " << _host_dir << "\n"; + } nout << "api_version = " << _api_version << "\n"; // Make the certificate directory. @@ -1458,3 +1464,4 @@ nt_thread_run() { } _notify_ready.release(); } + diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h index 2b2a16a9d6..33163fcc79 100644 --- a/direct/src/plugin/p3dInstanceManager.h +++ b/direct/src/plugin/p3dInstanceManager.h @@ -58,7 +58,8 @@ public: const string &log_basename, bool trusted_environment, bool console_environment, - const string &root_dir = ""); + const string &root_dir = "", + const string &host_dir = ""); inline bool is_initialized() const; inline void reconsider_runtime_environment(); @@ -164,6 +165,7 @@ private: int _api_version; string _host_url; string _root_dir; + string _host_dir; string _certs_dir; P3D_verify_contents _verify_contents; string _platform; diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx index 2fec7a8286..8740df96cd 100755 --- a/direct/src/plugin/p3dPackage.cxx +++ b/direct/src/plugin/p3dPackage.cxx @@ -229,6 +229,12 @@ remove_instance(P3DInstance *inst) { //////////////////////////////////////////////////////////////////// void P3DPackage:: mark_used() { + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + if (inst_mgr->get_verify_contents() == P3D_VC_never) { + // We're not allowed to create any files in the package directory. + return; + } + // Unlike the Python variant of this function, we don't mess around // with updating the disk space or anything. string filename = get_package_dir() + "/usage.xml"; @@ -404,6 +410,12 @@ download_contents_file() { return; } + // Don't download it if we're not allowed to. + if (inst_mgr->get_verify_contents() == P3D_VC_never) { + contents_file_download_finished(false); + return; + } + // Download contents.xml to a temporary filename first, in case // multiple packages are downloading it simultaneously. if (_temp_contents_file != NULL) { @@ -426,17 +438,24 @@ void P3DPackage:: contents_file_download_finished(bool success) { P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); if (!_host->has_current_contents_file(inst_mgr)) { - if (!success || !_host->read_contents_file(_temp_contents_file->get_filename(), true)) { - nout << "Couldn't read " << *_temp_contents_file << "\n"; + if (!success || _temp_contents_file == NULL || + !_host->read_contents_file(_temp_contents_file->get_filename(), true)) { + + if (_temp_contents_file) { + nout << "Couldn't read " << *_temp_contents_file << "\n"; + } // Maybe we can read an already-downloaded contents.xml file. string standard_filename = _host->get_host_dir() + "/contents.xml"; if (_host->get_host_dir().empty() || !_host->read_contents_file(standard_filename, false)) { // Couldn't even read that. Fail. + nout << "Couldn't read " << standard_filename << "\n"; report_done(false); - delete _temp_contents_file; - _temp_contents_file = NULL; + if (_temp_contents_file) { + delete _temp_contents_file; + _temp_contents_file = NULL; + } return; } } @@ -444,8 +463,10 @@ contents_file_download_finished(bool success) { // The file is correctly installed by now; we can remove the // temporary file. - delete _temp_contents_file; - _temp_contents_file = NULL; + if (_temp_contents_file) { + delete _temp_contents_file; + _temp_contents_file = NULL; + } host_got_contents_file(); } @@ -480,6 +501,12 @@ redownload_contents_file(P3DPackage::Download *download) { return; } + // Don't download it if we're not allowed to. + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + if (inst_mgr->get_verify_contents() == P3D_VC_never) { + return; + } + set_saved_download(download); // Download contents.xml to a temporary filename first. @@ -526,8 +553,10 @@ contents_file_redownload_finished(bool success) { } // We no longer need the temporary file. - delete _temp_contents_file; - _temp_contents_file = NULL; + if (_temp_contents_file) { + delete _temp_contents_file; + _temp_contents_file = NULL; + } if (contents_changed) { // OK, the contents.xml has changed; this means we have to restart @@ -600,7 +629,10 @@ host_got_contents_file() { } // Ensure the package directory exists; create it if it does not. - mkdir_complete(_package_dir, nout); + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + if (inst_mgr->get_verify_contents() != P3D_VC_never) { + mkdir_complete(_package_dir, nout); + } download_desc_file(); } @@ -645,7 +677,8 @@ download_desc_file() { local_desc_file.set_filename(_desc_file_basename); _desc_file_pathname = local_desc_file.get_pathname(_package_dir); - if (!local_desc_file.full_verify(_package_dir)) { + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + if (!local_desc_file.full_verify(_package_dir) && inst_mgr->get_verify_contents() != P3D_VC_never) { nout << _desc_file_pathname << " is stale.\n"; } else { @@ -663,6 +696,13 @@ download_desc_file() { } } + // Don't download it if we're not allowed to. + if (inst_mgr->get_verify_contents() == P3D_VC_never) { + nout << "Couldn't read " << _desc_file_pathname << "\n"; + report_done(false); + return; + } + // The desc file is not current. Go download it. start_download(DT_desc_file, _desc_file.get_filename(), _desc_file_pathname, local_desc_file); @@ -680,8 +720,11 @@ desc_file_download_finished(bool success) { return; } - // Now that we've downloaded the desc file, make it read-only. - chmod(_desc_file_pathname.c_str(), 0444); + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + if (inst_mgr->get_verify_contents() != P3D_VC_never) { + // Now that we've downloaded the desc file, make it read-only. + chmod(_desc_file_pathname.c_str(), 0444); + } if (_package_solo) { // No need to load it: the desc file *is* the package. @@ -785,6 +828,13 @@ got_desc_file(TiXmlDocument *doc, bool freshly_downloaded) { xrequires = xrequires->NextSiblingElement("requires"); } + if (inst_mgr->get_verify_contents() == P3D_VC_never) { + // This means we'll just leave it at this + // and assume that we're finished. + report_done(true); + return; + } + // Get a list of all of the files in the directory, so we can remove // files that don't belong. vector contents, dirname_contents; @@ -1208,6 +1258,9 @@ start_download(P3DPackage::DownloadType dtype, const string &urlbase, const string &pathname, const FileSpec &file_spec) { // Only one download should be active at a time assert(_active_download == NULL); + // This can't happen! If verify_contents is set to P3D_VC_never, + // we're not allowed to download anything, so we shouldn't get here. + assert(inst_mgr->get_verify_contents() != P3D_VC_never); // We can't explicitly support partial downloads here, because // Mozilla provides no interface to ask for one. We have to trust diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index 16d8cf3d78..8641a72121 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -38,7 +38,8 @@ P3D_initialize(int api_version, const char *contents_filename, const char *host_url, P3D_verify_contents verify_contents, const char *platform, const char *log_directory, const char *log_basename, bool trusted_environment, - bool console_environment, const char *root_dir) { + bool console_environment, + const char *root_dir, const char *host_dir) { if (api_version < 10 || api_version > P3D_API_VERSION) { // Can't accept an incompatible version. return false; @@ -79,17 +80,21 @@ P3D_initialize(int api_version, const char *contents_filename, if (log_basename == NULL) { log_basename = ""; } - + if (api_version < 12 || root_dir == NULL) { root_dir = ""; } + if (api_version < 16 || host_dir == NULL) { + host_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); + root_dir, host_dir); RELEASE_LOCK(_api_lock); return result; } diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index 7225cba68e..e053e6e21b 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 15 +#define P3D_API_VERSION 16 /************************ GLOBAL FUNCTIONS **************************/ @@ -91,6 +91,7 @@ typedef enum { P3D_VC_none, P3D_VC_normal, P3D_VC_force, + P3D_VC_never, } P3D_verify_contents; /* This function should be called immediately after the core API is @@ -110,8 +111,11 @@ typedef enum { If it is P3D_VC_normal, the server will be contacted whenever the contents.xml has expired. If it is P3D_VC_force, each server will be contacted initially in all cases, and subseqeuntly only whenever - contents.xml has expired for that server. Normally, a web plugin - should set this to P3D_VC_normal. + contents.xml has expired for that server. The opposite of + P3D_VC_force is P3D_VC_never, which forces the plugin never to + contact the server and not to verify the contents at all. This + option should only be used if the host directory is prepopulated. + Normally, a web plugin should set this to P3D_VC_normal. If platform is not NULL or empty, it specifies the current platform string; otherwise, the compiled-in default is used. This should @@ -137,13 +141,16 @@ typedef enum { p3d file will be run without checking its signature. Normally, a browser plugin should set this false. - Finally, console_environment should be set true to indicate that we - are running within a text-based console, and expect to preserve the - current working directory, and also see standard output, or false + Furthermore, console_environment should be set true to indicate that + we are running within a text-based console, and expect to preserve + the current working directory, and also see standard output, or false to indicate that we are running within a GUI environment, and expect none of these. Normally, a browser plugin should set this false. + Finally, root_dir and host_dir can be set to override the default + root and package directories. Normally, you don't need to set them. + 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 @@ -154,7 +161,7 @@ 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 *root_dir, const char *host_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 bdec9beb9c..3b7c4e39c8 100644 --- a/direct/src/plugin_activex/PPInstance.cpp +++ b/direct/src/plugin_activex/PPInstance.cpp @@ -525,7 +525,7 @@ int PPInstance::LoadPlugin( const std::string& dllFilename ) 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)) { + 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 090120c026..b68fd1276c 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -1593,7 +1593,7 @@ do_load_plugin() { 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)) { + _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 66da5975bd..0645acd9b3 100644 --- a/direct/src/plugin_standalone/p3dEmbed.cxx +++ b/direct/src/plugin_standalone/p3dEmbed.cxx @@ -81,6 +81,7 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { string keyword; string value; string root_dir; + string host_dir; while (true) { if (curchr == EOF) { cerr << "Truncated stream\n"; @@ -109,10 +110,24 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { _win_width = atoi(value.c_str()); } else if (keyword == "height") { _win_height = atoi(value.c_str()); + } else if (keyword == "log_basename") { + _log_basename = value; } else if (keyword == "root_dir") { root_dir = value; + } else if (keyword == "host_dir") { + host_dir = value; } else if (keyword == "verify_contents") { - _verify_contents = (P3D_verify_contents)atoi(value.c_str()); + if (value == "never") { + _verify_contents = P3D_VC_never; + } else if (value == "force") { + _verify_contents = P3D_VC_force; + } else if (value == "normal") { + _verify_contents = P3D_VC_normal; + } else if (value == "none") { + _verify_contents = P3D_VC_none; + } else { + _verify_contents = (P3D_verify_contents)atoi(value.c_str()); + } } } curstr = ""; @@ -139,6 +154,13 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { root_dir_f.make_absolute(f.get_dirname()); _root_dir = root_dir_f.to_os_specific(); } + + // Make the host directory absolute + if (!host_dir.empty()) { + Filename host_dir_f(host_dir); + host_dir_f.make_absolute(f.get_dirname()); + _host_dir = host_dir_f.to_os_specific(); + } // Initialize the core API by directly assigning all of the function // pointers. @@ -185,6 +207,7 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { // Calling the executable with --prep just prepares the directory // structure, this is usually invoked in the installer. if (argc == 2 && strcmp(argv[1], "--prep") == 0) { + cerr << "Invoking the prepare step is deprecated, please rebuild the application using a more recent version of pdeploy\n"; _window_type = P3D_WT_hidden; _log_basename = "prep"; P3D_token token; @@ -200,7 +223,7 @@ 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, cerr)) { + _root_dir, _host_dir, cerr)) { cerr << "Unable to launch core API\n"; return 1; } diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index 7dd261f5b0..9d299de0e3 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -802,7 +802,7 @@ 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)) { + _root_dir, "", cerr)) { cerr << "Unable to launch core API in " << pathname << "\n"; return false; } diff --git a/direct/src/plugin_standalone/panda3dBase.h b/direct/src/plugin_standalone/panda3dBase.h index fba5bdd8a9..b71ab22cdc 100755 --- a/direct/src/plugin_standalone/panda3dBase.h +++ b/direct/src/plugin_standalone/panda3dBase.h @@ -73,6 +73,7 @@ protected: protected: string _host_url; string _root_dir; + string _host_dir; string _log_dirname; string _log_basename; string _this_platform;