[Bf-extensions-cvs] [010e9556] master: Rigify: improve robustness with bad feature set packages.

Alexander Gavrilov noreply at git.blender.org
Fri May 3 19:26:04 CEST 2019


Commit: 010e955654483c4e5de63d399bd15c5ec4def2d2
Author: Alexander Gavrilov
Date:   Fri May 3 20:23:05 2019 +0300
Branches: master
https://developer.blender.org/rBA010e955654483c4e5de63d399bd15c5ec4def2d2

Rigify: improve robustness with bad feature set packages.

Verify the basic expected directory structure inside the ZIP
archive before installing it, and catch exceptions when loading
the already installed packages.

===================================================================

M	rigify/feature_sets.py
M	rigify/metarig_menu.py
M	rigify/rig_lists.py

===================================================================

diff --git a/rigify/feature_sets.py b/rigify/feature_sets.py
index 9ee6821a..64f40ba9 100644
--- a/rigify/feature_sets.py
+++ b/rigify/feature_sets.py
@@ -19,6 +19,7 @@
 import bpy
 from bpy.props import StringProperty
 import os
+import re
 from zipfile import ZipFile
 from shutil import rmtree
 
@@ -34,6 +35,29 @@ def feature_set_items(scene, context):
 
     return items
 
+def verify_feature_set_archive(zipfile):
+    """Verify that the zip file contains one root directory, and some required files."""
+    dirname = None
+    init_found = False
+    data_found = False
+
+    for name in zipfile.namelist():
+        parts = re.split(r'[/\\]', name)
+
+        if dirname is None:
+            dirname = parts[0]
+        elif dirname != parts[0]:
+            dirname = None
+            break
+
+        if len(parts) == 2 and parts[1] == '__init__.py':
+            init_found = True
+
+        if len(parts) > 2 and parts[1] in {'rigs', 'metarigs'} and parts[-1] == '__init__.py':
+            data_found = True
+
+    return dirname, init_found, data_found
+
 class DATA_OT_rigify_add_feature_set(bpy.types.Operator):
     bl_idname = "wm.rigify_add_feature_set"
     bl_label = "Add External Feature Set"
@@ -57,6 +81,20 @@ class DATA_OT_rigify_add_feature_set(bpy.types.Operator):
         rigify_config_path = os.path.join(bpy.utils.script_path_user(), 'rigify')
         os.makedirs(rigify_config_path, exist_ok=True)
         with ZipFile(bpy.path.abspath(self.filepath), 'r') as zip_archive:
+            base_dirname, init_found, data_found = verify_feature_set_archive(zip_archive)
+
+            if not base_dirname:
+                self.report({'ERROR'}, "The feature set archive must contain one base directory.")
+                return {'CANCELLED'}
+
+            if not re.fullmatch(r'[a-zA-Z_][a-zA-Z_0-9-]*', base_dirname):
+                self.report({'ERROR'}, "The feature set archive has invalid characters in the base directory name: '%s'." % (base_dirname))
+                return {'CANCELLED'}
+
+            if not init_found or not data_found:
+                self.report({'ERROR'}, "The feature set archive has no rigs or metarigs, or is missing __init__.py.")
+                return {'CANCELLED'}
+
             zip_archive.extractall(rigify_config_path)
 
         addon_prefs.machin = bpy.props.EnumProperty(items=(('a',)*3, ('b',)*3, ('c',)*3),)
diff --git a/rigify/metarig_menu.py b/rigify/metarig_menu.py
index 18d8e550..2c8adac7 100644
--- a/rigify/metarig_menu.py
+++ b/rigify/metarig_menu.py
@@ -19,6 +19,8 @@
 # <pep8 compliant>
 
 import os
+import traceback
+
 from string import capwords
 
 import bpy
@@ -44,7 +46,11 @@ def get_metarigs(base_path, path, depth=0):
 
     metarigs = {}
 
-    files = os.listdir(os.path.join(base_path, path))
+    try:
+        files = os.listdir(os.path.join(base_path, path))
+    except FileNotFoundError:
+        files = []
+
     files.sort()
 
     for f in files:
@@ -216,9 +222,19 @@ def get_external_metarigs(feature_sets_path):
 
     for feature_set in os.listdir(feature_sets_path):
         if feature_set:
-            utils.get_resource(os.path.join(feature_set, '__init__'), base_path=feature_sets_path)
-
-            metarigs['external'].update(get_metarigs(feature_sets_path, os.path.join(feature_set, utils.METARIG_DIR)))
+            try:
+                try:
+                    utils.get_resource(os.path.join(feature_set, '__init__'), feature_sets_path)
+                except FileNotFoundError:
+                    print("Rigify Error: Could not load feature set '%s': __init__.py not found.\n" % (feature_set))
+                    continue
+
+                metarigs['external'].update(get_metarigs(feature_sets_path, os.path.join(feature_set, utils.METARIG_DIR)))
+            except Exception:
+                print("Rigify Error: Could not load feature set '%s' metarigs: exception occurred.\n" % (feature_set))
+                traceback.print_exc()
+                print("")
+                continue
 
     metarig_ops.clear()
     armature_submenus.clear()
diff --git a/rigify/rig_lists.py b/rigify/rig_lists.py
index c1846b99..fac88f1a 100644
--- a/rigify/rig_lists.py
+++ b/rigify/rig_lists.py
@@ -17,6 +17,7 @@
 #======================= END GPL LICENSE BLOCK ========================
 
 import os
+import traceback
 
 from . import utils
 
@@ -33,7 +34,11 @@ def get_rigs(base_path, path, feature_set='rigify'):
     rigs = {}
     impl_rigs = {}
 
-    files = os.listdir(os.path.join(base_path, path))
+    try:
+        files = os.listdir(os.path.join(base_path, path))
+    except FileNotFoundError:
+        files = []
+
     files.sort()
 
     for f in files:
@@ -84,7 +89,19 @@ def get_external_rigs(feature_sets_path):
     # Get external rigs
     for feature_set in os.listdir(feature_sets_path):
         if feature_set:
-            utils.get_resource(os.path.join(feature_set, '__init__'), feature_sets_path)
-            external_rigs, external_impl_rigs = get_rigs(feature_sets_path, os.path.join(feature_set, utils.RIG_DIR), feature_set)
+            try:
+                try:
+                    utils.get_resource(os.path.join(feature_set, '__init__'), feature_sets_path)
+                except FileNotFoundError:
+                    print("Rigify Error: Could not load feature set '%s': __init__.py not found.\n" % (feature_set))
+                    continue
+
+                external_rigs, external_impl_rigs = get_rigs(feature_sets_path, os.path.join(feature_set, utils.RIG_DIR), feature_set)
+            except Exception:
+                print("Rigify Error: Could not load feature set '%s' rigs: exception occurred.\n" % (feature_set))
+                traceback.print_exc()
+                print("")
+                continue
+
             rigs.update(external_rigs)
             implementation_rigs.update(external_impl_rigs)



More information about the Bf-extensions-cvs mailing list