great big microsoft nonsense about temporary paths

This commit is contained in:
David Rose 2009-09-29 01:53:10 +00:00
parent 46ec3f1d00
commit 5938d40926
14 changed files with 216 additions and 123 deletions

View File

@ -164,9 +164,12 @@ class FileSpec:
def __updateTimestamp(self, pathname, st):
# On Windows, we have to change the file to read-write before
# we can successfully update its timestamp.
os.chmod(pathname.toOsSpecific(), 0755)
os.utime(pathname.toOsSpecific(), (st.st_atime, self.timestamp))
os.chmod(pathname.toOsSpecific(), 0555)
try:
os.chmod(pathname.toOsSpecific(), 0755)
os.utime(pathname.toOsSpecific(), (st.st_atime, self.timestamp))
os.chmod(pathname.toOsSpecific(), 0555)
except OSError:
pass
def checkHash(self, packageDir, pathname, st):
""" Returns true if the file has the expected md5 hash, false

View File

@ -114,7 +114,7 @@ wstr_to_string(string &result, const LPWSTR wstr) {
// on the user's machine.
////////////////////////////////////////////////////////////////////
string
find_root_dir(ostream &logfile) {
find_root_dir() {
#ifdef _WIN32
// First, use IEIsProtectedModeProcess() to determine if we are
// running in IE's "protected mode" under Vista.
@ -130,7 +130,6 @@ find_root_dir(ostream &logfile) {
HRESULT hr = (*func)(&result);
if (hr == S_OK) {
is_protected = (result != 0);
logfile << "IEIsProtectedModeProcess indicates: " << is_protected << "\n";
}
// Any other return value means some error, especially
// E_NOTIMPL, which means we're not running under Vista. In

View File

@ -19,6 +19,6 @@
#include <iostream>
using namespace std;
string find_root_dir(ostream &logfile);
string find_root_dir();
#endif

View File

@ -75,14 +75,26 @@ get_platform() const {
return _platform;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::get_temp_directory
// Access: Public
// Description: Returns the pathname of the directory into which
// temporary files should be written. This filename
// will end with a slash, so that full pathnames may be
// made by concatenting directly with this string.
////////////////////////////////////////////////////////////////////
inline const string &P3DInstanceManager::
get_temp_directory() const {
return _temp_directory;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::get_log_directory
// Access: Public
// Description: Returns the pathname of the directory into which all
// log files should be written. This filename will end
// with a slash or backslash, as appropriate, so that
// logfile pathnames may be made by concatenting
// directly with this string.
// with a slash, so that full pathnames may be made by
// concatenting directly with this string.
////////////////////////////////////////////////////////////////////
inline const string &P3DInstanceManager::
get_log_directory() const {

View File

@ -180,28 +180,109 @@ initialize(const string &contents_filename, const string &download_url,
_platform = DTOOL_PLATFORM;
}
_root_dir = find_root_dir();
// Allow the caller (e.g. panda3d.exe) to specify a log directory.
_log_directory = log_directory;
// Or, allow the developer to compile one in.
#ifdef P3D_PLUGIN_LOG_DIRECTORY
if (_log_directory.empty()) {
_log_directory = P3D_PLUGIN_LOG_DIRECTORY;
}
#endif
// Failing that, we write logfiles to Panda3D/log.
if (_log_directory.empty()) {
_log_directory = _root_dir + "/log";
}
mkdir_complete(_log_directory, cerr);
// Ensure that the log directory ends with a slash.
if (!_log_directory.empty() && _log_directory[_log_directory.size() - 1] != '/') {
#ifdef _WIN32
if (_log_directory[_log_directory.size() - 1] != '\\')
#endif
_log_directory += "/";
}
// Construct the logfile pathname.
_log_basename = log_basename;
#ifdef P3D_PLUGIN_LOG_BASENAME2
if (_log_basename.empty()) {
_log_basename = P3D_PLUGIN_LOG_BASENAME2;
}
#endif
if (!_log_basename.empty()) {
_log_pathname = _log_directory;
_log_pathname += _log_basename;
_log_pathname += ".log";
logfile.clear();
logfile.open(_log_pathname.c_str(), ios::out | ios::trunc);
if (logfile) {
logfile.setf(ios::unitbuf);
nout_stream = &logfile;
}
}
// Determine the temporary directory.
#ifdef _WIN32
size_t needs_size_1 = GetTempPath(0, NULL);
char *buffer_1 = new char[needs_size_1];
if (GetTempPath(needs_size_1, buffer_1) != 0) {
_temp_directory = buffer_1;
}
delete[] buffer_1;
char buffer_1[MAX_PATH];
static const size_t buffer_size = 4096;
char buffer[buffer_size];
if (GetTempPath(buffer_size, buffer) != 0) {
_temp_directory = buffer;
// Figuring out the correct path for temporary files is a real mess
// on Windows. We should be able to use GetTempPath(), but that
// relies on $TMP or $TEMP being defined, and it appears that
// Mozilla clears these environment variables for the plugin, which
// forces GetTempPath() into $USERPROFILE instead. This is really
// an inappropriate place for temporary files, so, GetTempPath()
// isn't a great choice.
// We could use SHGetSpecialFolderPath() instead to get us the path
// to "Temporary Internet Files", which is acceptable. The trouble
// is, if we happen to be running in "Protected Mode" on Vista, this
// folder isn't actually writable by us! On Vista, we're supposed
// to use IEGetWriteableFolderPath() instead, but *this* function
// doesn't exist on XP and below. Good Lord.
// We could go through a bunch of LoadLibrary() calls to try to find
// the right path, like we do in find_root_dir(), but I'm just tired
// of doing all that nonsense. We'll use a two-stage trick instead.
// We'll check for $TEMP or $TMP being defined specifically, and if
// they are, we'll use GetTempPath(); otherwise, we'll fall back to
// SHGetSpecialFolderPath().
if (getenv("TEMP") != NULL || getenv("TMP") != NULL) {
if (GetTempPath(MAX_PATH, buffer_1) != 0) {
_temp_directory = buffer_1;
}
}
if (_temp_directory.empty()) {
if (SHGetSpecialFolderPath(NULL, buffer_1, CSIDL_INTERNET_CACHE, true)) {
_temp_directory = buffer_1;
// That just *might* return a non-writable folder, if we're in
// Protected Mode. We'll test this with GetTempFileName().
char temp_buffer[MAX_PATH];
if (!GetTempFileName(_temp_directory.c_str(), "p3d", 0, temp_buffer)) {
nout << "GetTempFileName failed on " << _temp_directory
<< ", switching to GetTempPath\n";
_temp_directory.clear();
} else {
DeleteFile(temp_buffer);
}
}
}
// If both of the above failed, we'll fall back to GetTempPath()
// once again as a last resort, which is supposed to return
// *something* that works, even if $TEMP and $TMP are undefined.
if (_temp_directory.empty()) {
if (GetTempPath(MAX_PATH, buffer_1) != 0) {
_temp_directory = buffer_1;
}
}
// Also insist that the temp directory is fully specified.
size_t needs_size_2 = GetFullPathName(_temp_directory.c_str(), 0, NULL, NULL);
char *buffer_2 = new char[needs_size_2];
@ -217,18 +298,6 @@ initialize(const string &contents_filename, const string &download_url,
_temp_directory = "/tmp/";
#endif // _WIN32
// If the log directory is still empty, use the temp directory.
if (_log_directory.empty()) {
_log_directory = _temp_directory;
}
_log_basename = log_basename;
#ifdef P3D_PLUGIN_LOG_BASENAME2
if (_log_basename.empty()) {
_log_basename = P3D_PLUGIN_LOG_BASENAME2;
}
#endif
// Ensure that the temp directory ends with a slash.
if (!_temp_directory.empty() && _temp_directory[_temp_directory.size() - 1] != '/') {
#ifdef _WIN32
@ -237,31 +306,8 @@ initialize(const string &contents_filename, const string &download_url,
_temp_directory += "/";
}
// Ensure that the log directory ends with a slash.
if (!_log_directory.empty() && _log_directory[_log_directory.size() - 1] != '/') {
#ifdef _WIN32
if (_log_directory[_log_directory.size() - 1] != '\\')
#endif
_log_directory += "/";
}
// Construct the logfile pathname.
if (!_log_basename.empty()) {
_log_pathname = _log_directory;
_log_pathname += _log_basename;
_log_pathname += ".log";
logfile.clear();
logfile.open(_log_pathname.c_str(), ios::out | ios::trunc);
if (logfile) {
logfile.setf(ios::unitbuf);
nout_stream = &logfile;
}
}
_root_dir = find_root_dir(nout);
nout << "_root_dir = " << _root_dir
<< ", _temp_directory = " << _temp_directory
<< ", platform = " << _platform
<< ", contents_filename = " << contents_filename
<< ", download_url = " << download_url

View File

@ -63,6 +63,7 @@ public:
inline const string &get_root_dir() const;
inline const string &get_platform() const;
inline const string &get_temp_directory() const;
inline const string &get_log_directory() const;
inline const string &get_log_pathname() const;
inline bool get_trusted_environment() const;

View File

@ -769,7 +769,7 @@ start_p3dpython(P3DInstance *inst) {
// These are the enviroment variables we forward from the current
// environment, if they are set.
const char *keep[] = {
"TMP", "TEMP", "HOME", "USER",
"HOME", "USER",
#ifdef _WIN32
"SYSTEMROOT", "USERPROFILE", "COMSPEC",
#endif
@ -795,6 +795,7 @@ start_p3dpython(P3DInstance *inst) {
const char *dont_keep[] = {
"PATH", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH",
"PYTHONPATH", "PYTHONHOME", "PRC_PATH", "PANDA_PRC_PATH",
"TEMP",
NULL
};
@ -862,6 +863,10 @@ start_p3dpython(P3DInstance *inst) {
_env += "PANDA_PRC_PATH=";
_env += prc_path;
_env += '\0';
_env += "TEMP=";
_env += inst_mgr->get_temp_directory();
_env += '\0';
// Define each package's root directory in an environment variable
// named after the package, for the convenience of the packages in

View File

@ -71,10 +71,12 @@ void P3D_NofificationSync(P3D_instance *instance)
PPInstance::PPInstance( CP3DActiveXCtrl& parentCtrl ) :
m_parentCtrl( parentCtrl ), m_p3dInstance( NULL ), m_p3dObject( NULL ), m_handleRequestOnUIThread( true ), m_isInit( false )
{
// Open the logfile first.
m_logger.Open( );
// We need the root dir first.
m_rootDir = find_root_dir( );
// Then open the logfile.
m_logger.Open( m_rootDir );
m_rootDir = find_root_dir( nout );
m_pluginLoaded = false;
}
@ -177,10 +179,12 @@ int PPInstance::DownloadP3DComponents( std::string& p3dDllFilename )
// file. We get a unique temporary filename each time; this is a
// small file and it's very important that we get the most current
// version, not an old cached version.
TCHAR tempFolderName[ MAX_PATH ];
::GetTempPath( MAX_PATH, tempFolderName );
TCHAR tempFileName[ MAX_PATH ];
::GetTempFileName( tempFolderName, "p3d", 0, tempFileName );
if (!::GetTempFileName( m_rootDir.c_str(), "p3d", 0, tempFileName )) {
nout << "GetTempFileName failed (folder is " << m_rootDir << ")\n";
return 1;
}
std::string localContentsFileName( tempFileName );
// We'll also get the final installation path of the contents.xml

View File

@ -89,45 +89,51 @@ int PPLogger::CreateNewFile(const std::string& dirname, const std::string& filen
return error;
}
void PPLogger::Open( )
void PPLogger::Open( const std::string &rootDir )
{
if (!m_isOpen) {
// Note that this logfile name may not be specified at runtime. It
// must be compiled in if it is specified at all.
std::string log_directory;
// Allow the developer to compile in the log directory.
#ifdef P3D_PLUGIN_LOG_DIRECTORY
if (log_directory.empty()) {
log_directory = P3D_PLUGIN_LOG_DIRECTORY;
}
#endif
// Failing that, we write logfiles to Panda3D/log.
if (log_directory.empty()) {
log_directory = rootDir + "/log";
}
mkdir_complete(log_directory, cerr);
// Ensure that the log directory ends with a slash.
if (!log_directory.empty() && log_directory[log_directory.size() - 1] != '/') {
#ifdef _WIN32
if (log_directory[log_directory.size() - 1] != '\\')
#endif
log_directory += "/";
}
// Construct the logfile pathname.
std::string log_basename;
#ifdef P3D_PLUGIN_LOG_BASENAME1
log_basename = P3D_PLUGIN_LOG_BASENAME1;
if (log_basename.empty()) {
log_basename = P3D_PLUGIN_LOG_BASENAME1;
}
#endif
if (!log_basename.empty()) {
// Get the log directory.
std::string log_directory;
#ifdef P3D_PLUGIN_LOG_DIRECTORY
log_directory = P3D_PLUGIN_LOG_DIRECTORY;
#endif
if (log_directory.empty()) {
static const size_t buffer_size = MAX_PATH;
char buffer[buffer_size];
if (GetTempPath(buffer_size, buffer) != 0) {
log_directory = buffer;
}
}
// Ensure that the log directory ends with a slash.
if (!log_directory.empty() && log_directory[log_directory.size() - 1] != '/') {
if (log_directory[log_directory.size() - 1] != '\\')
log_directory += "/";
}
// Construct the full logfile pathname.
std::string log_pathname = log_directory;
log_pathname += log_basename;
log_pathname += ".log";
m_logfile.clear();
m_logfile.open(log_pathname.c_str());
m_logfile.setf(std::ios::unitbuf);
m_logfile.open(log_pathname.c_str(), ios::out | ios::trunc);
m_logfile.setf(ios::unitbuf);
}
// If we didn't have a logfile name compiled in, we throw away log

View File

@ -26,7 +26,7 @@ public:
PPLogger( );
virtual ~PPLogger( );
void Open( );
void Open( const std::string &rootDir );
static std::ofstream& Log( ) { return m_logfile; }
protected:

View File

@ -219,7 +219,7 @@ Mozilla-Uninstall-End:
# contents are installed. Too bad we can't do this for every system
# user, not just the current user.
RmDir /r "$LOCALAPPDATA\Low\${APP_INTERNAL_NAME}"
RmDir /r "$LOCALAPPDATALow\${APP_INTERNAL_NAME}"
RmDir /r "$LOCALAPPDATA\${APP_INTERNAL_NAME}"
Delete "$INSTDIR\uninst.exe"

View File

@ -18,6 +18,7 @@
#include "ppBrowserObject.h"
#ifdef _WIN32
#include <shlobj.h>
#include <malloc.h>
#endif
@ -28,51 +29,54 @@ string global_root_dir;
NPNetscapeFuncs *browser;
// open_logfile() also assigns global_root_dir.
static bool logfile_is_open = false;
static void
open_logfile() {
if (!logfile_is_open) {
global_root_dir = find_root_dir();
// Note that this logfile name may not be specified at runtime. It
// must be compiled in if it is specified at all.
string log_directory;
// Allow the developer to compile in the log directory.
#ifdef P3D_PLUGIN_LOG_DIRECTORY
if (log_directory.empty()) {
log_directory = P3D_PLUGIN_LOG_DIRECTORY;
}
#endif
// Failing that, we write logfiles to Panda3D/log.
if (log_directory.empty()) {
log_directory = global_root_dir + "/log";
}
mkdir_complete(log_directory, cerr);
// Ensure that the log directory ends with a slash.
if (!log_directory.empty() && log_directory[log_directory.size() - 1] != '/') {
#ifdef _WIN32
if (log_directory[log_directory.size() - 1] != '\\')
#endif
log_directory += "/";
}
// Construct the logfile pathname.
string log_basename;
#ifdef P3D_PLUGIN_LOG_BASENAME1
log_basename = P3D_PLUGIN_LOG_BASENAME1;
if (log_basename.empty()) {
log_basename = P3D_PLUGIN_LOG_BASENAME1;
}
#endif
if (!log_basename.empty()) {
// Get the log directory.
string log_directory;
#ifdef P3D_PLUGIN_LOG_DIRECTORY
log_directory = P3D_PLUGIN_LOG_DIRECTORY;
#endif
if (log_directory.empty()) {
#ifdef _WIN32
static const size_t buffer_size = MAX_PATH;
char buffer[buffer_size];
if (GetTempPath(buffer_size, buffer) != 0) {
log_directory = buffer;
}
#else
log_directory = "/tmp/";
#endif // _WIN32
}
// Ensure that the log directory ends with a slash.
if (!log_directory.empty() && log_directory[log_directory.size() - 1] != '/') {
#ifdef _WIN32
if (log_directory[log_directory.size() - 1] != '\\')
#endif
log_directory += "/";
}
// Construct the full logfile pathname.
string log_pathname = log_directory;
log_pathname += log_basename;
log_pathname += ".log";
logfile.clear();
logfile.open(log_pathname.c_str());
logfile.open(log_pathname.c_str(), ios::out | ios::trunc);
logfile.setf(ios::unitbuf);
}
@ -146,9 +150,9 @@ NP_Initialize(NPNetscapeFuncs *browserFuncs,
// save away browser functions
browser = browserFuncs;
// open_logfile() also assigns global_root_dir.
open_logfile();
nout << "initializing\n";
global_root_dir = find_root_dir(nout);
nout << "browserFuncs = " << browserFuncs << "\n";
@ -173,6 +177,7 @@ NP_Initialize(NPNetscapeFuncs *browserFuncs,
////////////////////////////////////////////////////////////////////
NPError OSCALL
NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) {
// open_logfile() also assigns global_root_dir.
open_logfile();
nout << "NP_GetEntryPoints, pluginFuncs = " << pluginFuncs << "\n";
pluginFuncs->version = 11;

View File

@ -49,8 +49,9 @@ static const double wait_cycle = 0.2;
////////////////////////////////////////////////////////////////////
Panda3D::
Panda3D() {
_root_dir = find_root_dir(nout);
_root_dir = find_root_dir();
_reporting_download = false;
_enable_security = false;
}
////////////////////////////////////////////////////////////////////
@ -67,7 +68,7 @@ run(int argc, char *argv[]) {
// We prefix a "+" sign to tell gnu getopt not to parse options
// following the first not-option parameter. (These will be passed
// into the sub-process.)
const char *optstr = "+mu:M:p:fw:t:s:o:l:ih";
const char *optstr = "+mu:M:Sp:fw:t:s:o:l:ih";
bool allow_multiple = false;
string download_url = PANDA_PACKAGE_HOST_URL;
@ -95,6 +96,10 @@ run(int argc, char *argv[]) {
super_mirror_url = optarg;
break;
case 'S':
_enable_security = true;
break;
case 'p':
this_platform = optarg;
break;
@ -542,9 +547,11 @@ get_core_api(const Filename &contents_filename, const string &download_url,
}
#endif // P3D_PLUGIN_P3D_PLUGIN
bool trusted_environment = !_enable_security;
if (!load_plugin(pathname, contents_filename.to_os_specific(),
download_url, verify_contents, this_platform, _log_dirname,
_log_basename, true, cerr)) {
_log_basename, trusted_environment, cerr)) {
cerr << "Unable to launch core API in " << pathname << "\n" << flush;
return false;
}
@ -855,6 +862,10 @@ usage() {
<< " Python files within the p3d file, for rapid iteration on the Python\n"
<< " code.\n\n"
<< " -S\n"
<< " Runs the application with security enabled, as if it were embedded in\n"
<< " a web page.\n\n"
<< " -u url\n"
<< " Specify the URL of the Panda3D download server. This is the host\n"

View File

@ -81,6 +81,7 @@ private:
string _log_basename;
FileSpec _core_api_dll;
bool _reporting_download;
bool _enable_security;
typedef pset<P3D_instance *> Instances;
Instances _instances;