Bug #882819 - recover v1.x theme file names from XML info

This commit is contained in:
M2j 2011-12-13 00:46:04 +01:00
parent ebcf7a5dd2
commit 0c06569dc5
4 changed files with 80 additions and 85 deletions

View File

@ -41,7 +41,7 @@ class Ui_FileRenameDialog(object):
self.dialogLayout.addWidget(self.fileNameLabel, 0, 0) self.dialogLayout.addWidget(self.fileNameLabel, 0, 0)
self.fileNameEdit = QtGui.QLineEdit(fileRenameDialog) self.fileNameEdit = QtGui.QLineEdit(fileRenameDialog)
self.fileNameEdit.setValidator(QtGui.QRegExpValidator( self.fileNameEdit.setValidator(QtGui.QRegExpValidator(
QtCore.QRegExp(r'[^/\\?*|<>\[\]":<>+%]+'), self)) QtCore.QRegExp(r'[^/\\?*|<>\[\]":+%]+'), self))
self.fileNameEdit.setObjectName(u'fileNameEdit') self.fileNameEdit.setObjectName(u'fileNameEdit')
self.dialogLayout.addWidget(self.fileNameEdit, 0, 1) self.dialogLayout.addWidget(self.fileNameEdit, 0, 1)
self.buttonBox = create_accept_reject_button_box(fileRenameDialog, True) self.buttonBox = create_accept_reject_button_box(fileRenameDialog, True)

View File

@ -43,8 +43,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
context_menu_action, context_menu_separator, find_and_set_in_combo_box context_menu_action, context_menu_separator, find_and_set_in_combo_box
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
from openlp.core.ui.printserviceform import PrintServiceForm from openlp.core.ui.printserviceform import PrintServiceForm
from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ from openlp.core.utils import AppLocation, delete_file, split_filename
split_filename
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder
class ServiceManagerList(QtGui.QTreeWidget): class ServiceManagerList(QtGui.QTreeWidget):
@ -635,8 +634,11 @@ class ServiceManager(QtGui.QWidget):
try: try:
zip = zipfile.ZipFile(fileName) zip = zipfile.ZipFile(fileName)
for zipinfo in zip.infolist(): for zipinfo in zip.infolist():
ucsfile = file_is_unicode(zipinfo.filename) try:
if not ucsfile: ucsfile = zipinfo.filename.decode(u'utf-8')
except UnicodeDecodeError:
log.exception(u'Filename "%s" is not valid UTF-8' %
zipinfo.filename.decode(u'utf-8', u'replace'))
critical_error_message_box( critical_error_message_box(
message=translate('OpenLP.ServiceManager', message=translate('OpenLP.ServiceManager',
'File is not a valid service.\n' 'File is not a valid service.\n'

View File

@ -30,6 +30,7 @@ import zipfile
import shutil import shutil
import logging import logging
import locale import locale
import re
from xml.etree.ElementTree import ElementTree, XML from xml.etree.ElementTree import ElementTree, XML
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
@ -43,8 +44,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
context_menu_action, context_menu_separator context_menu_action, context_menu_separator
from openlp.core.theme import Theme from openlp.core.theme import Theme
from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.ui import FileRenameForm, ThemeForm
from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ from openlp.core.utils import AppLocation, delete_file, get_filesystem_encoding
get_filesystem_encoding
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -147,6 +147,7 @@ class ThemeManager(QtGui.QWidget):
check_directory_exists(self.thumbPath) check_directory_exists(self.thumbPath)
self.themeForm.path = self.path self.themeForm.path = self.path
self.oldBackgroundImage = None self.oldBackgroundImage = None
self.bad_v1_name_chars = re.compile(r'[%+\[\]]')
# Last little bits of setting up # Last little bits of setting up
self.configUpdated() self.configUpdated()
@ -525,46 +526,74 @@ class ThemeManager(QtGui.QWidget):
filexml = None filexml = None
try: try:
zip = zipfile.ZipFile(filename) zip = zipfile.ZipFile(filename)
themename = None xmlfile = filter(lambda name:
for file in zip.namelist(): os.path.splitext(name)[1].lower() == u'.xml', zip.namelist())
ucsfile = file_is_unicode(file) if len(xmlfile) != 1:
if not ucsfile: log.exception(u'Theme contains "%s" XML files' % len(xmlfile))
critical_error_message_box( raise Exception(u'validation')
message=translate('OpenLP.ThemeManager', xml_tree = ElementTree(element=XML(zip.read(xmlfile[0]))).getroot()
'File is not a valid theme.\n' v1_background = xml_tree.find(u'BackgroundType')
'The content encoding is not UTF-8.')) if v1_background is not None:
continue # openlp.org v1.x theme file
osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile)) themename = xml_tree.find(u'Name').text.strip()
theme_dir = None themename = self.bad_v1_name_chars.sub(u'', themename)
if osfile.endswith(os.path.sep): themedir = os.path.join(dir, themename)
theme_dir = os.path.join(dir, osfile) check_directory_exists(themedir)
check_directory_exists(theme_dir) filexml = unicode(zip.read(xmlfile[0]), u'utf-8')
else: filexml = self._migrateVersion122(filexml)
fullpath = os.path.join(dir, osfile) outfile = open(os.path.join(themedir, themename + u'.xml'),
names = osfile.split(os.path.sep) u'w')
if len(names) > 1: outfile.write(filexml.encode(u'utf-8'))
# not preview file outfile.close()
if themename is None: if v1_background.text.strip() == u'2':
themename = names[0] imagename = xml_tree.find(u'BackgroundParameter1').text\
if theme_dir is None: .strip()
theme_dir = os.path.join(dir, names[0]) # image file is in subfolder and has same extension
check_directory_exists(theme_dir) imagefile = filter(lambda name: name.find(r'/') and
if os.path.splitext(ucsfile)[1].lower() in [u'.xml']: os.path.splitext(name)[1].lower() == os.path.splitext(
xml_data = zip.read(file) imagename)[1].lower(), zip.namelist())
xml_data = file_is_unicode(xml_data) if len(imagefile) >= 1:
if not xml_data: outfile = open(os.path.join(themedir, imagename), u'wb')
break outfile.write(zip.read(imagefile[0]))
filexml = self._checkVersionAndConvert(xml_data) outfile.close()
outfile = open(fullpath, u'w') else:
outfile.write(filexml.encode(u'utf-8')) log.exception(u'Theme file does not contain image file '
else: u'"%s"' % imagename.decode(u'utf-8', u'replace'))
outfile = open(fullpath, u'wb') raise Exception(u'validation')
outfile.write(zip.read(file)) else:
except (IOError, NameError, zipfile.BadZipfile): themename = xml_tree.find(u'name').text.strip()
critical_error_message_box( for name in zip.namelist():
translate('OpenLP.ThemeManager', 'Validation Error'), try:
translate('OpenLP.ThemeManager', 'File is not a valid theme.')) uname = unicode(name, u'utf-8')
except UnicodeDecodeError:
log.exception(u'Theme file contains non utf-8 filename'
u' "%s"' % name.decode(u'utf-8', u'replace'))
raise Exception(u'validation')
uname = unicode(QtCore.QDir.toNativeSeparators(uname))
splitname = uname.split(os.path.sep)
if splitname[-1] == u'' or len(splitname) == 1:
# is directory or preview file
continue
fullname = os.path.join(dir, uname)
check_directory_exists(os.path.dirname(fullname))
if os.path.splitext(uname)[1].lower() == u'.xml':
filexml = unicode(zip.read(name), u'utf-8')
outfile = open(fullname, u'w')
outfile.write(filexml.encode(u'utf-8'))
else:
outfile = open(fullname, u'wb')
outfile.write(zip.read(name))
outfile.close()
except (IOError, zipfile.BadZipfile):
log.exception(u'Importing theme from zip failed %s' % filename) log.exception(u'Importing theme from zip failed %s' % filename)
raise Exception(u'validation')
except Exception as info:
if unicode(info) == u'validation':
critical_error_message_box(translate('OpenLP.ThemeManager',
'Validation Error'), translate('OpenLP.ThemeManager',
'File is not a valid theme.'))
else:
raise
finally: finally:
# Close the files, to be able to continue creating the theme. # Close the files, to be able to continue creating the theme.
if zip: if zip:
@ -695,22 +724,6 @@ class ThemeManager(QtGui.QWidget):
image = os.path.join(self.path, theme + u'.png') image = os.path.join(self.path, theme + u'.png')
return image return image
def _checkVersionAndConvert(self, xml_data):
"""
Check if a theme is from OpenLP version 1
``xml_data``
Theme XML to check the version of
"""
log.debug(u'checkVersion1 ')
theme = xml_data.encode(u'ascii', u'xmlcharrefreplace')
tree = ElementTree(element=XML(theme)).getroot()
# look for old version 1 tags
if tree.find(u'BackgroundType') is None:
return xml_data
else:
return self._migrateVersion122(xml_data)
def _createThemeFromXml(self, themeXml, path): def _createThemeFromXml(self, themeXml, path):
""" """
Return a theme object using information parsed from XML Return a theme object using information parsed from XML
@ -775,7 +788,7 @@ class ThemeManager(QtGui.QWidget):
""" """
theme = Theme(xml_data) theme = Theme(xml_data)
newtheme = ThemeXML() newtheme = ThemeXML()
newtheme.theme_name = theme.Name newtheme.theme_name = self.bad_v1_name_chars.sub(u'', theme.Name)
if theme.BackgroundType == 0: if theme.BackgroundType == 0:
newtheme.background_type = \ newtheme.background_type = \
BackgroundType.to_string(BackgroundType.Solid) BackgroundType.to_string(BackgroundType.Solid)

View File

@ -455,26 +455,6 @@ def get_web_page(url, header=None, update_openlp=False):
log.debug(page) log.debug(page)
return page return page
def file_is_unicode(filename):
"""
Checks if a file is valid unicode and returns the unicode decoded file or
None.
``filename``
File to check is valid unicode.
"""
if not filename:
return None
ucsfile = None
try:
ucsfile = filename.decode(u'utf-8')
except UnicodeDecodeError:
log.exception(u'Filename "%s" is not valid UTF-8' %
filename.decode(u'utf-8', u'replace'))
if not ucsfile:
return None
return ucsfile
def get_uno_command(): def get_uno_command():
""" """
Returns the UNO command to launch an openoffice.org instance. Returns the UNO command to launch an openoffice.org instance.
@ -507,5 +487,5 @@ from actions import ActionList
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', __all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
u'ActionList', u'get_web_page', u'file_is_unicode', u'get_uno_command', u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance',
u'get_uno_instance', u'delete_file', u'clean_filename'] u'delete_file', u'clean_filename']