Selaa lähdekoodia

uninstall wip, utf-8

David Rose 16 vuotta sitten
vanhempi
sitoutus
1d7fd44214

+ 3 - 3
direct/src/distributed/ConnectionRepository.py

@@ -641,9 +641,9 @@ class ConnectionRepository(
         # Zero-length datagrams might freak out the server.  No point
         # Zero-length datagrams might freak out the server.  No point
         # in sending them, anyway.
         # in sending them, anyway.
         if datagram.getLength() > 0:
         if datagram.getLength() > 0:
-            if self.notify.getDebug():
-                print "ConnectionRepository sending datagram:"
-                datagram.dumpHex(ostream)
+##             if self.notify.getDebug():
+##                 print "ConnectionRepository sending datagram:"
+##                 datagram.dumpHex(ostream)
 
 
             self.sendDatagram(datagram)
             self.sendDatagram(datagram)
 
 

+ 3 - 3
direct/src/distributed/ServerRepository.py

@@ -340,7 +340,7 @@ class ServerRepository:
         if self.notify.getDebug():
         if self.notify.getDebug():
             self.notify.debug(
             self.notify.debug(
                 "ServerRepository received datagram from %s:" % (client.doIdBase))
                 "ServerRepository received datagram from %s:" % (client.doIdBase))
-            datagram.dumpHex(ostream)
+            #datagram.dumpHex(ostream)
 
 
         if not client:
         if not client:
             # This shouldn't be possible.
             # This shouldn't be possible.
@@ -689,7 +689,7 @@ class ServerRepository:
         if self.notify.getDebug():
         if self.notify.getDebug():
             self.notify.debug(
             self.notify.debug(
                 "ServerRepository sending to all in zone %s except %s:" % (zoneId, map(lambda c: c.doIdBase, exceptionList)))
                 "ServerRepository sending to all in zone %s except %s:" % (zoneId, map(lambda c: c.doIdBase, exceptionList)))
-            datagram.dumpHex(ostream)
+            #datagram.dumpHex(ostream)
 
 
         for client in self.zonesToClients.get(zoneId, []):
         for client in self.zonesToClients.get(zoneId, []):
             if client not in exceptionList:
             if client not in exceptionList:
@@ -706,7 +706,7 @@ class ServerRepository:
         if self.notify.getDebug():
         if self.notify.getDebug():
             self.notify.debug(
             self.notify.debug(
                 "ServerRepository sending to all except %s:" % (map(lambda c: c.doIdBase, exceptionList),))
                 "ServerRepository sending to all except %s:" % (map(lambda c: c.doIdBase, exceptionList),))
-            datagram.dumpHex(ostream)
+            #datagram.dumpHex(ostream)
 
 
         for client in self.clientsByConnection.values():
         for client in self.clientsByConnection.values():
             if client not in exceptionList:
             if client not in exceptionList:

+ 21 - 0
direct/src/plugin/p3dInstance.cxx

@@ -1315,6 +1315,27 @@ auth_finished_main_thread() {
   check_p3d_signature();
   check_p3d_signature();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::uninstall
+//       Access: Public
+//  Description: Stops the instance (if it is running) and deletes any
+//               packages referenced by the instance.  This is
+//               normally called by JavaScript, via
+//               P3DMainObject::call_uninstall().
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+uninstall() {
+  if (_session != NULL) {
+    _session->shutdown();
+  }
+
+  Packages::const_iterator pi;
+  for (pi = _packages.begin(); pi != _packages.end(); ++pi) {
+    P3DPackage *package = (*pi);
+    package->uninstall();
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::priv_set_p3d_filename
 //     Function: P3DInstance::priv_set_p3d_filename
 //       Access: Private
 //       Access: Private

+ 2 - 0
direct/src/plugin/p3dInstance.h

@@ -116,6 +116,8 @@ public:
   void auth_finished_sub_thread();
   void auth_finished_sub_thread();
   void auth_finished_main_thread();
   void auth_finished_main_thread();
 
 
+  void uninstall();
+
 private:
 private:
   class ImageDownload : public P3DFileDownload {
   class ImageDownload : public P3DFileDownload {
   public:
   public:

+ 12 - 7
direct/src/plugin/p3dInstanceManager.cxx

@@ -1067,10 +1067,11 @@ scan_directory(const string &dirname, vector<string> &contents) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstanceManager::scan_directory_recursively
 //     Function: P3DInstanceManager::scan_directory_recursively
 //       Access: Public, Static
 //       Access: Public, Static
-//  Description: Fills up the indicated vector with the list of all
-//               files (but not directories) rooted at the indicated
-//               dirname and below.  The filenames generated are
-//               relative to the root of the dirname, with slashes
+//  Description: Fills up filename_contents with the list of all
+//               files (but not directories), and dirname_contents
+//               with the list of all directories, rooted at the
+//               indicated dirname and below.  The filenames generated
+//               are relative to the root of the dirname, with slashes
 //               (not backslashes) as the directory separator
 //               (not backslashes) as the directory separator
 //               character.
 //               character.
 //
 //
@@ -1078,7 +1079,9 @@ scan_directory(const string &dirname, vector<string> &contents) {
 //               dirname wasn't a directory or something like that.
 //               dirname wasn't a directory or something like that.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DInstanceManager::
 bool P3DInstanceManager::
-scan_directory_recursively(const string &dirname, vector<string> &contents,
+scan_directory_recursively(const string &dirname, 
+                           vector<string> &filename_contents,
+                           vector<string> &dirname_contents,
                            const string &prefix) {
                            const string &prefix) {
   vector<string> dir_contents;
   vector<string> dir_contents;
   if (!scan_directory(dirname, dir_contents)) {
   if (!scan_directory(dirname, dir_contents)) {
@@ -1093,14 +1096,16 @@ scan_directory_recursively(const string &dirname, vector<string> &contents,
     // directory, or is it a regular file?
     // directory, or is it a regular file?
     string pathname = dirname + "/" + (*si);
     string pathname = dirname + "/" + (*si);
     string rel_filename = prefix + (*si);
     string rel_filename = prefix + (*si);
-    if (scan_directory_recursively(pathname, contents, rel_filename + "/")) {
+    if (scan_directory_recursively(pathname, filename_contents, 
+                                   dirname_contents, rel_filename + "/")) {
       // It's a directory, and it's just added its results to the
       // It's a directory, and it's just added its results to the
       // contents.
       // contents.
+      dirname_contents.push_back(rel_filename);
 
 
     } else {
     } else {
       // It's not a directory, so assume it's an ordinary file, and
       // It's not a directory, so assume it's an ordinary file, and
       // add it to the contents.
       // add it to the contents.
-      contents.push_back(rel_filename);
+      filename_contents.push_back(rel_filename);
     }
     }
   }
   }
 
 

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

@@ -131,7 +131,9 @@ public:
 
 
   static inline char encode_hexdigit(int c);
   static inline char encode_hexdigit(int c);
   static bool scan_directory(const string &dirname, vector<string> &contents);
   static bool scan_directory(const string &dirname, vector<string> &contents);
-  static bool scan_directory_recursively(const string &dirname, vector<string> &contents,
+  static bool scan_directory_recursively(const string &dirname, 
+                                         vector<string> &filename_contents,
+                                         vector<string> &dirname_contents,
                                          const string &prefix = "");
                                          const string &prefix = "");
   static bool remove_file_from_list(vector<string> &contents, const string &filename);
   static bool remove_file_from_list(vector<string> &contents, const string &filename);
 
 

+ 25 - 0
direct/src/plugin/p3dMainObject.cxx

@@ -191,6 +191,8 @@ has_method(const string &method_name) {
     return true;
     return true;
   } else if (method_name == "read_system_log") {
   } else if (method_name == "read_system_log") {
     return true;
     return true;
+  } else if (method_name == "uninstall") {
+    return true;
   }
   }
 
 
   if (_pyobj == NULL) {
   if (_pyobj == NULL) {
@@ -225,6 +227,8 @@ call(const string &method_name, bool needs_response,
     return call_read_game_log(params, num_params);
     return call_read_game_log(params, num_params);
   } else if (method_name == "read_system_log") {
   } else if (method_name == "read_system_log") {
     return call_read_system_log(params, num_params);
     return call_read_system_log(params, num_params);
+  } else if (method_name == "uninstall") {
+    return call_uninstall(params, num_params);
   }
   }
 
 
   if (_pyobj == NULL) {
   if (_pyobj == NULL) {
@@ -435,3 +439,24 @@ read_log(const string &log_pathname, P3D_object *params[], int num_params) {
 
 
   return result;
   return result;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DMainObject::call_uninstall
+//       Access: Private
+//  Description: Implements the uninstall() plugin method, which
+//               removes all Panda installed files for a particular
+//               host, or referenced by a particular p3d file.
+////////////////////////////////////////////////////////////////////
+P3D_object *P3DMainObject::
+call_uninstall(P3D_object *params[], int num_params) {
+  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+
+  if (_inst != NULL) {
+    nout << "uninstall for " << _inst << "\n";
+    _inst->uninstall();
+    return inst_mgr->new_bool_object(true);
+  }
+
+  nout << "couldn't uninstall; no instance.\n";
+  return inst_mgr->new_bool_object(false);
+}

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

@@ -73,6 +73,7 @@ private:
   P3D_object *call_read_system_log(P3D_object *params[], int num_params);
   P3D_object *call_read_system_log(P3D_object *params[], int num_params);
   P3D_object *read_log(const string &log_pathname, 
   P3D_object *read_log(const string &log_pathname, 
                        P3D_object *params[], int num_params);
                        P3D_object *params[], int num_params);
+  P3D_object *call_uninstall(P3D_object *params[], int num_params);
 
 
 private:
 private:
   P3D_object *_pyobj;
   P3D_object *_pyobj;

+ 81 - 7
direct/src/plugin/p3dPackage.cxx

@@ -206,6 +206,78 @@ remove_instance(P3DInstance *inst) {
   begin_info_download();
   begin_info_download();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DPackage::uninstall
+//       Access: Public
+//  Description: Removes the package directory and all its contents
+//               from the user's hard disk.
+////////////////////////////////////////////////////////////////////
+void P3DPackage::
+uninstall() {
+  if (_package_dir.empty()) {
+    nout << "Cannot uninstall " << _package_name << ": package directory not yet known.\n";
+    return;
+  }
+
+  nout << "Uninstalling package " << _package_name << " from " << _package_dir << "\n";
+
+  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+  vector<string> contents, dirname_contents;
+  inst_mgr->scan_directory_recursively(_package_dir, contents,
+                                       dirname_contents);
+
+  vector<string>::iterator ci;
+  for (ci = contents.begin(); ci != contents.end(); ++ci) {
+    string filename = (*ci);
+    string pathname = _package_dir + "/" + filename;
+
+#ifdef _WIN32
+    // Windows can't delete a file if it's read-only.
+    chmod(pathname.c_str(), 0644);
+#endif
+    int result = unlink(pathname.c_str());
+    if (result == 0) {
+      nout << "  Deleted " << filename << "\n";
+    } else {
+      nout << "  Could not delete " << filename << "\n";
+    }
+  }
+
+  // Now delete all of the directories too.  Go in reverse order so we
+  // remove deeper directories first.
+  vector<string>::reverse_iterator rci;
+  for (rci = dirname_contents.rbegin(); rci != dirname_contents.rend(); ++rci) {
+    string filename = (*rci);
+    string pathname = _package_dir + "/" + filename;
+
+#ifdef _WIN32
+    chmod(pathname.c_str(), 0755);
+#endif
+    int result = rmdir(pathname.c_str());
+    if (result == 0) {
+      nout << "  Removed directory " << filename << "\n";
+    } else {
+      nout << "  Could not remove directory " << filename << "\n";
+    }
+  }
+
+  // Finally, delete the package directory itself.
+  string pathname = _package_dir;
+#ifdef _WIN32
+  chmod(pathname.c_str(), 0755);
+#endif
+  int result = rmdir(pathname.c_str());
+  if (result == 0) {
+    nout << "Removed directory " << _package_dir << "\n";
+  } else {
+    nout << "Could not remove directory " << _package_dir << "\n";
+  }
+
+  _info_ready = false;
+  _ready = false;
+  _failed = false;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DPackage::make_xml
 //     Function: P3DPackage::make_xml
 //       Access: Public
 //       Access: Public
@@ -442,7 +514,7 @@ contents_file_redownload_finished(bool success) {
 //               rest of the download process.
 //               rest of the download process.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DPackage::
 void P3DPackage::
-host_got_contents_file() {
+host_got_contents_file(bool continue_download) {
   if (!_alt_host.empty()) {
   if (!_alt_host.empty()) {
     // If we have an alt host specification, maybe we need to change
     // If we have an alt host specification, maybe we need to change
     // the host now.
     // the host now.
@@ -476,10 +548,12 @@ host_got_contents_file() {
     _package_dir += string("/") + _package_version;
     _package_dir += string("/") + _package_version;
   }
   }
 
 
-  // Ensure the package directory exists; create it if it does not.
-  mkdir_complete(_package_dir, nout);
-
-  download_desc_file();
+  if (continue_download) {
+    // Ensure the package directory exists; create it if it does not.
+    mkdir_complete(_package_dir, nout);
+    
+    download_desc_file();
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -658,8 +732,8 @@ got_desc_file(TiXmlDocument *doc, bool freshly_downloaded) {
 
 
   // Get a list of all of the files in the directory, so we can remove
   // Get a list of all of the files in the directory, so we can remove
   // files that don't belong.
   // files that don't belong.
-  vector<string> contents;
-  inst_mgr->scan_directory_recursively(_package_dir, contents);
+  vector<string> contents, dirname_contents;
+  inst_mgr->scan_directory_recursively(_package_dir, contents, dirname_contents);
 
 
   inst_mgr->remove_file_from_list(contents, _desc_file_basename);
   inst_mgr->remove_file_from_list(contents, _desc_file_basename);
   inst_mgr->remove_file_from_list(contents, _uncompressed_archive.get_filename());
   inst_mgr->remove_file_from_list(contents, _uncompressed_archive.get_filename());

+ 3 - 1
direct/src/plugin/p3dPackage.h

@@ -69,6 +69,8 @@ public:
   void add_instance(P3DInstance *inst);
   void add_instance(P3DInstance *inst);
   void remove_instance(P3DInstance *inst);
   void remove_instance(P3DInstance *inst);
 
 
+  void uninstall();
+
   TiXmlElement *make_xml();
   TiXmlElement *make_xml();
 
 
 private:
 private:
@@ -192,7 +194,7 @@ private:
   void contents_file_download_finished(bool success);
   void contents_file_download_finished(bool success);
   void redownload_contents_file(Download *download);
   void redownload_contents_file(Download *download);
   void contents_file_redownload_finished(bool success);
   void contents_file_redownload_finished(bool success);
-  void host_got_contents_file();
+  void host_got_contents_file(bool continue_download = true);
 
 
   void download_desc_file();
   void download_desc_file();
   void desc_file_download_finished(bool success);
   void desc_file_download_finished(bool success);

+ 19 - 7
direct/src/plugin/p3dPythonRun.cxx

@@ -1531,14 +1531,26 @@ pyobj_to_xml(PyObject *value) {
     }
     }
 
 
   } else if (PyString_Check(value)) {
   } else if (PyString_Check(value)) {
-    // A string value.
+    // A string value.  Insist that it is utf-8 encoded, by decoding
+    // it first using the standard encoding, then re-encoding it.
     xvalue->SetAttribute("type", "string");
     xvalue->SetAttribute("type", "string");
 
 
-    char *buffer;
-    Py_ssize_t length;
-    if (PyString_AsStringAndSize(value, &buffer, &length) != -1) {
-      string str(buffer, length);
-      xvalue->SetAttribute("value", str);
+    PyObject *ustr = PyUnicode_FromEncodedObject(value, NULL, NULL);
+    if (ustr == NULL) {
+      PyErr_Print();
+      return xvalue;
+    } else {
+      PyObject *as_str = PyUnicode_AsUTF8String(ustr);
+      if (as_str != NULL) {
+        char *buffer;
+        Py_ssize_t length;
+        if (PyString_AsStringAndSize(as_str, &buffer, &length) != -1) {
+          string str(buffer, length);
+          xvalue->SetAttribute("value", str);
+        }
+        Py_DECREF(as_str);
+      }
+      Py_DECREF(ustr);
     }
     }
 
 
   } else if (PyTuple_Check(value)) {
   } else if (PyTuple_Check(value)) {
@@ -1685,7 +1697,7 @@ xml_to_pyobj(TiXmlElement *xvalue) {
     // don't get tripped up on embedded null characters.
     // don't get tripped up on embedded null characters.
     const string *value = xvalue->Attribute(string("value"));
     const string *value = xvalue->Attribute(string("value"));
     if (value != NULL) {
     if (value != NULL) {
-      return PyString_FromStringAndSize(value->data(), value->length());
+      return PyUnicode_DecodeUTF8(value->data(), value->length(), NULL);
     }
     }
 
 
   } else if (strcmp(type, "undefined") == 0) {
   } else if (strcmp(type, "undefined") == 0) {

+ 5 - 3
direct/src/plugin/p3d_plugin.h

@@ -470,8 +470,9 @@ P3D_object_get_float_method(P3D_object *object);
    return value is larger than buffer_size, the string has been
    return value is larger than buffer_size, the string has been
    truncated.  If it is equal, there is no null character written to
    truncated.  If it is equal, there is no null character written to
    the buffer (like strncpy).  You may call this method first with
    the buffer (like strncpy).  You may call this method first with
-   buffer = NULL and buffer_size = 0 to return just the required
-   size of the buffer. */
+   buffer = NULL and buffer_size = 0 to return just the required size
+   of the buffer.  Note that P3D_object string data is internally
+   encoded using utf-8, by convention. */
 typedef int
 typedef int
 P3D_object_get_string_method(P3D_object *object, 
 P3D_object_get_string_method(P3D_object *object, 
                              char *buffer, int buffer_size);
                              char *buffer, int buffer_size);
@@ -676,7 +677,8 @@ typedef P3D_object *
 P3D_new_float_object_func(double value);
 P3D_new_float_object_func(double value);
 
 
 /* Returns a new-reference P3D_object of type string.  The supplied
 /* Returns a new-reference P3D_object of type string.  The supplied
-   string is copied into the object and stored internally. */
+   string should be already encoded in utf-8.  It is copied into the
+   object and stored internally. */
 typedef P3D_object *
 typedef P3D_object *
 P3D_new_string_object_func(const char *string, int length);
 P3D_new_string_object_func(const char *string, int length);
 
 

+ 1 - 0
direct/src/showbase/ShowBase.py

@@ -861,6 +861,7 @@ class ShowBase(DirectObject.DirectObject):
 
 
     def sleepCycleTask(self, task):
     def sleepCycleTask(self, task):
         Thread.sleep(self.clientSleep)
         Thread.sleep(self.clientSleep)
+        #time.sleep(self.clientSleep)
         return Task.cont
         return Task.cont
 
 
     def setFrameRateMeter(self, flag):
     def setFrameRateMeter(self, flag):