Browse Source

Merge branch 'release/1.10.x'

rdb 3 years ago
parent
commit
7a55c723ba

+ 71 - 0
dtool/src/prc/encryptStreamBuf.cxx

@@ -23,6 +23,32 @@
 #include <openssl/rand.h>
 #include <openssl/evp.h>
 
+#if OPENSSL_VERSION_MAJOR >= 3
+#include <openssl/provider.h>
+
+/**
+ * Tries to load the legacy provider in OpenSSL.  Returns true if the provider
+ * was just loaded, false if it was already loaded or couldn't be loaded.
+ */
+static bool load_legacy_provider() {
+  static bool tried = false;
+  if (!tried) {
+    tried = true;
+    if (OSSL_PROVIDER_try_load(nullptr, "legacy", 1) != nullptr) {
+      if (prc_cat.is_debug()) {
+        prc_cat.debug()
+          << "Loaded legacy OpenSSL provider.\n";
+      }
+      return true;
+    } else {
+      prc_cat.warning()
+        << "Failed to load legacy OpenSSL provider.\n";
+    }
+  }
+  return false;
+}
+#endif  // OPENSSL_VERSION_MAJOR
+
 // The iteration count is scaled by this factor for writing to the stream.
 static const int iteration_count_factor = 1000;
 
@@ -122,7 +148,31 @@ open_read(std::istream *source, bool owns_source, const std::string &password) {
   int key_length = sr.get_uint16();
   int count = sr.get_uint16();
 
+#if OPENSSL_VERSION_MAJOR >= 3
+  // First, convert the cipher's nid to its full name.
+  const char *cipher_name = OBJ_nid2ln(nid);
+
+  const EVP_CIPHER *cipher = nullptr;
+  if (cipher_name != nullptr) {
+    // Now, fetch the cipher known by this name.
+    cipher = EVP_CIPHER_fetch(nullptr, cipher_name, nullptr);
+
+    if (cipher == nullptr && EVP_get_cipherbynid(nid) != nullptr) {
+      if (load_legacy_provider()) {
+        cipher = EVP_CIPHER_fetch(nullptr, cipher_name, nullptr);
+      }
+
+      if (cipher == nullptr) {
+        prc_cat.error()
+          << "No implementation available for encryption algorithm in stream: "
+          << cipher_name << "\n";
+        return;
+      }
+    }
+  }
+#else
   const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);
+#endif
 
   if (cipher == nullptr) {
     prc_cat.error()
@@ -220,8 +270,29 @@ open_write(std::ostream *dest, bool owns_dest, const std::string &password) {
   _dest = dest;
   _owns_dest = owns_dest;
 
+#if OPENSSL_VERSION_MAJOR >= 3
+  // This checks that there is actually an implementation available.
+  const EVP_CIPHER *cipher =
+    EVP_CIPHER_fetch(nullptr, _algorithm.c_str(), nullptr);
+
+  if (cipher == nullptr &&
+      EVP_get_cipherbyname(_algorithm.c_str()) != nullptr) {
+    // The cipher does exist, though, do we need to load the legacy provider?
+    if (load_legacy_provider()) {
+      cipher = EVP_CIPHER_fetch(nullptr, _algorithm.c_str(), nullptr);
+    }
+
+    if (cipher == nullptr) {
+      prc_cat.error()
+        << "No implementation available for encryption algorithm: "
+        << _algorithm << "\n";
+      return;
+    }
+  }
+#else
   const EVP_CIPHER *cipher =
     EVP_get_cipherbyname(_algorithm.c_str());
+#endif
 
   if (cipher == nullptr) {
     prc_cat.error()

+ 18 - 5
panda/src/pgraph/nodePath.cxx

@@ -3208,13 +3208,14 @@ get_texture(TextureStage *stage) const {
  * Recursively searches the scene graph for references to the given texture,
  * and replaces them with the new texture.
  *
+ * As of Panda3D 1.10.13, new_tex may be null to remove the texture.
+ *
  * @since 1.10.4
  */
 void NodePath::
 replace_texture(Texture *tex, Texture *new_tex) {
   nassertv_always(!is_empty());
   nassertv(tex != nullptr);
-  nassertv(new_tex != nullptr);
 
   r_replace_texture(node(), tex, new_tex);
 }
@@ -4250,15 +4251,19 @@ get_material() const {
  * Recursively searches the scene graph for references to the given material,
  * and replaces them with the new material.
  *
+ * As of Panda3D 1.10.13, new_mat may be null to remove the material.
+ *
  * @since 1.10.0
  */
 void NodePath::
 replace_material(Material *mat, Material *new_mat) {
   nassertv_always(!is_empty());
   nassertv(mat != nullptr);
-  nassertv(new_mat != nullptr);
 
-  CPT(RenderAttrib) new_attrib = MaterialAttrib::make(new_mat);
+  CPT(RenderAttrib) new_attrib;
+  if (new_mat != nullptr) {
+    new_attrib = MaterialAttrib::make(new_mat);
+  }
   r_replace_material(node(), mat, (const MaterialAttrib *)new_attrib.p());
 }
 
@@ -6878,7 +6883,11 @@ r_replace_material(PandaNode *node, Material *mat,
     const MaterialAttrib *ma;
     if (node_state->get_attrib(ma)) {
       if (mat == ma->get_material()) {
-        node->set_state(node_state->set_attrib(new_attrib));
+        if (new_attrib != nullptr) {
+          node->set_state(node_state->set_attrib(new_attrib));
+        } else {
+          node->set_state(node_state->remove_attrib(MaterialAttrib::get_class_slot()));
+        }
       }
     }
   }
@@ -6897,7 +6906,11 @@ r_replace_material(PandaNode *node, Material *mat,
       if (geom_state->get_attrib(ma)) {
         if (mat == ma->get_material()) {
           // Replace it
-          gnode->set_geom_state(i, geom_state->set_attrib(new_attrib));
+          if (new_attrib != nullptr) {
+            gnode->set_geom_state(i, geom_state->set_attrib(new_attrib));
+          } else {
+            gnode->set_geom_state(i, geom_state->remove_attrib(MaterialAttrib::get_class_slot()));
+          }
         }
       }
     }

+ 6 - 0
panda/src/pgraph/nodePath.h

@@ -619,6 +619,9 @@ PUBLISHED:
   Texture *get_texture() const;
   Texture *get_texture(TextureStage *stage) const;
   void replace_texture(Texture *tex, Texture *new_tex);
+#ifdef CPPPARSER  // Let interrogate know this also accepts None
+  void replace_texture(Texture *tex, std::nullptr_t new_tex);
+#endif
   const SamplerState &get_texture_sampler() const;
   const SamplerState &get_texture_sampler(TextureStage *stage) const;
 
@@ -771,6 +774,9 @@ PUBLISHED:
   bool has_material() const;
   PT(Material) get_material() const;
   void replace_material(Material *mat, Material *new_mat);
+#ifdef CPPPARSER  // Let interrogate know this also accepts None
+  void replace_material(Material *mat, std::nullptr_t new_mat);
+#endif
 
   void set_fog(Fog *fog, int priority = 0);
   void set_fog_off(int priority = 0);

+ 1 - 1
panda/src/pgraph/renderEffects.I

@@ -26,7 +26,7 @@ Effect(const RenderEffect *effect) :
  * file.  At this point, the effect pointer is unknown.
  */
 INLINE RenderEffects::Effect::
-Effect() {
+Effect() : _type(TypeHandle::none()) {
 }
 
 /**

+ 10 - 1
panda/src/pgraph/textureAttrib.cxx

@@ -253,12 +253,15 @@ unify_texture_stages(TextureStage *stage) const {
  * Returns a new TextureAttrib, just like this one, but with all references to
  * the given texture replaced with the new texture.
  *
+ * As of Panda3D 1.10.13, new_tex may be null to remove the texture.
+ *
  * @since 1.10.4
  */
 CPT(RenderAttrib) TextureAttrib::
 replace_texture(Texture *tex, Texture *new_tex) const {
   TextureAttrib *attrib = nullptr;
 
+  size_t j = 0;
   for (size_t i = 0; i < _on_stages.size(); ++i) {
     const StageNode &sn = _on_stages[i];
     if (sn._texture == tex) {
@@ -266,8 +269,14 @@ replace_texture(Texture *tex, Texture *new_tex) const {
         attrib = new TextureAttrib(*this);
       }
 
-      attrib->_on_stages[i]._texture = new_tex;
+      if (new_tex != nullptr) {
+        attrib->_on_stages[j]._texture = new_tex;
+      } else {
+        attrib->_on_stages.erase(attrib->_on_stages.begin() + j);
+        continue;
+      }
     }
+    ++j;
   }
 
   if (attrib != nullptr) {

+ 3 - 0
panda/src/pgraph/textureAttrib.h

@@ -90,6 +90,9 @@ PUBLISHED:
   CPT(RenderAttrib) remove_off_stage(TextureStage *stage) const;
   CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const;
   CPT(RenderAttrib) replace_texture(Texture *tex, Texture *new_tex) const;
+#ifdef CPPPARSER  // Let interrogate know this also accepts None
+  CPT(RenderAttrib) replace_texture(Texture *tex, std::nullptr_t new_tex) const;
+#endif
 
 public:
   CPT(TextureAttrib) filter_to_max(int max_texture_stages) const;

+ 10 - 5
tests/express/test_encrypt.py

@@ -3,12 +3,17 @@ from panda3d import core
 
 def test_encrypt_string():
     # Test encrypt and then decrypt cycle
-    enc = core.encrypt_string('abcdefg', '12345')
-    assert len(enc) > 0
+    for algorithm in ('', 'bf-cbc', 'aes-256-cbc'):
+        enc = core.encrypt_string('abcdefg', '12345', algorithm)
+        assert len(enc) > 0
 
-    dec = core.decrypt_string(enc, '12345')
-    assert dec == 'abcdefg'
+        dec = core.decrypt_string(enc, '12345')
+        assert dec == 'abcdefg'
 
-    # Test pre-encrypted string
+    # Test pre-encrypted bf-cbc string
     enc = b'[\x00\x10\x00d\x00\xb5\x7f\xc44Y\xb7\xd9\x15\xe3\xbd\xcf\xb3yK\xfb\xf6'
     assert 'test' == core.decrypt_string(enc, '98765')
+
+    # Test pre-encrypted aes-256-cbc string
+    enc = b'\xab\x01 \x00d\x00\xf1WP\xb0\x96h\xf8\xc5\xf4\x8d\x0b>q0\xf15\x185\xf8+\x1b\xe4\xae8\x88\xf2\x91\x15\xb8\x8fh\x88'
+    assert 'test' == core.decrypt_string(enc, '98765')

+ 21 - 0
tests/pgraph/test_nodepath.py

@@ -291,3 +291,24 @@ def test_nodepath_replace_texture():
     path1.replace_texture(tex1, tex2)
     assert not path1.has_texture()
     assert path2.get_texture() == tex2
+
+
+def test_nodepath_replace_texture_none():
+    from panda3d.core import NodePath, Texture
+
+    tex1 = Texture("tex1")
+
+    path1 = NodePath("node1")
+    assert path1.get_texture() is None
+    path1.set_texture(tex1)
+    assert path1.get_texture() == tex1
+    path1.replace_texture(tex1, None)
+    assert path1.get_texture() is None
+
+    path1 = NodePath("node1")
+    path2 = path1.attach_new_node("node2")
+    assert path2.get_texture() is None
+    path2.set_texture(tex1)
+    assert path2.get_texture() == tex1
+    path1.replace_texture(tex1, None)
+    assert path2.get_texture() is None