Browse Source

great big microsoft nonsense about temporary paths

David Rose 16 years ago
parent
commit
5938d40926

+ 6 - 3
direct/src/p3d/FileSpec.py

@@ -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

+ 1 - 2
direct/src/plugin/find_root_dir.cxx

@@ -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

+ 1 - 1
direct/src/plugin/find_root_dir.h

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

+ 15 - 3
direct/src/plugin/p3dInstanceManager.I

@@ -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 {

+ 92 - 46
direct/src/plugin/p3dInstanceManager.cxx

@@ -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;
+  char buffer_1[MAX_PATH];
+
+  // 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);
+      }
+    }
   }
-  delete[] buffer_1;
 
-  static const size_t buffer_size = 4096;
-  char buffer[buffer_size];
-  if (GetTempPath(buffer_size, buffer) != 0) {
-    _temp_directory = 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

+ 1 - 0
direct/src/plugin/p3dInstanceManager.h

@@ -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;

+ 6 - 1
direct/src/plugin/p3dSession.cxx

@@ -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

+ 10 - 6
direct/src/plugin_activex/PPInstance.cpp

@@ -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

+ 31 - 25
direct/src/plugin_activex/PPLogger.cpp

@@ -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_basename;
-#ifdef P3D_PLUGIN_LOG_BASENAME1
-    log_basename = P3D_PLUGIN_LOG_BASENAME1;
-#endif
-
-    if (!log_basename.empty()) {
-      // Get the log directory.
-      std::string log_directory;
+    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
-      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;
-        }
-      }
+    
+    // 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] != '/') {
-        if (log_directory[log_directory.size() - 1] != '\\')
-          log_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.
+    
+    std::string log_basename;
+#ifdef P3D_PLUGIN_LOG_BASENAME1
+    if (log_basename.empty()) {
+      log_basename = P3D_PLUGIN_LOG_BASENAME1;
+    }
+#endif
 
-      // Construct the full logfile pathname.
+    if (!log_basename.empty()) {
       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

+ 1 - 1
direct/src/plugin_activex/PPLogger.h

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

+ 1 - 1
direct/src/plugin_installer/p3d_installer.nsi

@@ -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"

+ 33 - 28
direct/src/plugin_npapi/startup.cxx

@@ -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_basename;
-#ifdef P3D_PLUGIN_LOG_BASENAME1
-    log_basename = P3D_PLUGIN_LOG_BASENAME1;
-#endif
-
-    if (!log_basename.empty()) {
-      // Get the log directory.
-      string log_directory;
+    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
-      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
-      }
+    
+    // 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] != '/') {
+    // 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] != '\\')
+      if (log_directory[log_directory.size() - 1] != '\\')
+#endif
+        log_directory += "/";
+    }
+    
+    // Construct the logfile pathname.
+    
+    string log_basename;
+#ifdef P3D_PLUGIN_LOG_BASENAME1
+    if (log_basename.empty()) {
+      log_basename = P3D_PLUGIN_LOG_BASENAME1;
+    }
 #endif
-          log_directory += "/";
-      }
 
-      // Construct the full logfile pathname.
+    if (!log_basename.empty()) {
       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;

+ 14 - 3
direct/src/plugin_standalone/panda3d.cxx

@@ -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"

+ 1 - 0
direct/src/plugin_standalone/panda3d.h

@@ -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;