Fix T54477: Broken utf8 strings in old .blend files

Back in the days (2.4x and before), it was rather easy to get some
invalid utf-8 strings in Blender. This is totally breaking modern code,
so this commit adds a simple 'check & fix strings' operator, available
from the main File menu.
This commit is contained in:
Bastien Montagne 2018-04-03 15:50:49 +02:00
parent 601835cd31
commit 96f565b380
Notes: blender-bot 2023-02-14 06:04:16 +01:00
Referenced by issue #54477, .blend file can't be exported
2 changed files with 55 additions and 0 deletions

View File

@ -249,7 +249,61 @@ class WM_OT_previews_batch_clear(Operator):
return {'FINISHED'}
class WM_OT_blend_strings_utf8_validate(Operator):
"""Check and fix all strings in current .blend file to be valid UTF-8 Unicode (needed for some old, 2.4x area files)"""
bl_idname = "wm.blend_strings_utf8_validate"
bl_label = "Validate .blend strings"
bl_options = {'REGISTER'}
def validate_strings(self, item, done_items):
if item is None:
return False
if item in done_items:
return False
done_items.add(item)
if getattr(item, 'library', None) is not None:
return False # No point in checking library data, we cannot fix it anyway...
changed = False
for prop in item.bl_rna.properties:
if prop.identifier in {'bl_rna', 'rna_type'}:
continue # Or we'd recurse 'till Hell freezes.
if prop.is_readonly:
continue
if prop.type == 'STRING':
val_bytes = item.path_resolve(prop.identifier, False).as_bytes()
val_utf8 = val_bytes.decode('utf-8', 'replace')
val_bytes_valid = val_utf8.encode('utf-8')
if val_bytes_valid != val_bytes:
print("found bad utf8 encoded string %r, fixing to %r (%r)..."
"" % (val_bytes, val_bytes_valid, val_utf8))
setattr(item, prop.identifier, val_utf8)
changed = True
elif prop.type == 'POINTER':
it = getattr(item, prop.identifier)
changed |= self.validate_strings(it, done_items)
elif prop.type == 'COLLECTION':
for it in getattr(item, prop.identifier):
changed |= self.validate_strings(it, done_items)
return changed
def execute(self, context):
changed = False
done_items = set()
for prop in bpy.data.bl_rna.properties:
if prop.type == 'COLLECTION':
for it in getattr(bpy.data, prop.identifier):
changed |= self.validate_strings(it, done_items)
if changed:
self.report({'WARNING'},
"Some strings were fixed, don't forget to save the .blend file to keep those changes")
return {'FINISHED'}
classes = (
WM_OT_previews_batch_clear,
WM_OT_previews_batch_generate,
WM_OT_blend_strings_utf8_validate,
)

View File

@ -154,6 +154,7 @@ class INFO_MT_file(Menu):
layout.separator()
layout.menu("INFO_MT_file_external_data", icon='EXTERNAL_DATA')
layout.operator("wm.blend_strings_utf8_validate", icon='FILE_BLEND')
layout.separator()