mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
Lots of changes to the plugin and pdeploy to make packaged games run without needing write access or internet access
This commit is contained in:
parent
57f10c8a37
commit
60973fdb7b
@ -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:
|
||||
|
@ -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('</plist>\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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 "
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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<string> 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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ protected:
|
||||
protected:
|
||||
string _host_url;
|
||||
string _root_dir;
|
||||
string _host_dir;
|
||||
string _log_dirname;
|
||||
string _log_basename;
|
||||
string _this_platform;
|
||||
|
Loading…
x
Reference in New Issue
Block a user