recover v1.x theme file names from XML info

bzr-revno: 1846
This commit is contained in:
Meinert Jordan 2011-12-20 20:23:36 +00:00 committed by Tim Bentley
commit d94816d481
4 changed files with 86 additions and 83 deletions

View File

@ -41,7 +41,7 @@ class Ui_FileRenameDialog(object):
self.dialogLayout.addWidget(self.fileNameLabel, 0, 0)
self.fileNameEdit = QtGui.QLineEdit(fileRenameDialog)
self.fileNameEdit.setValidator(QtGui.QRegExpValidator(
QtCore.QRegExp(r'[^/\\?*|<>\[\]":<>+%]+'), self))
QtCore.QRegExp(r'[^/\\?*|<>\[\]":+%]+'), self))
self.fileNameEdit.setObjectName(u'fileNameEdit')
self.dialogLayout.addWidget(self.fileNameEdit, 0, 1)
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
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
from openlp.core.ui.printserviceform import PrintServiceForm
from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \
split_filename
from openlp.core.utils import AppLocation, delete_file, split_filename
from openlp.core.utils.actions import ActionList, CategoryOrder
class ServiceManagerList(QtGui.QTreeWidget):
@ -636,8 +635,11 @@ class ServiceManager(QtGui.QWidget):
try:
zip = zipfile.ZipFile(fileName)
for zipinfo in zip.infolist():
ucsfile = file_is_unicode(zipinfo.filename)
if not ucsfile:
try:
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(
message=translate('OpenLP.ServiceManager',
'File is not a valid service.\n'

View File

@ -30,6 +30,7 @@ import zipfile
import shutil
import logging
import locale
import re
from xml.etree.ElementTree import ElementTree, XML
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
from openlp.core.theme import Theme
from openlp.core.ui import FileRenameForm, ThemeForm
from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \
get_filesystem_encoding
from openlp.core.utils import AppLocation, delete_file, get_filesystem_encoding
log = logging.getLogger(__name__)
@ -147,6 +147,7 @@ class ThemeManager(QtGui.QWidget):
check_directory_exists(self.thumbPath)
self.themeForm.path = self.path
self.oldBackgroundImage = None
self.bad_v1_name_chars = re.compile(r'[%+\[\]]')
# Last little bits of setting up
self.configUpdated()
@ -524,44 +525,50 @@ class ThemeManager(QtGui.QWidget):
filexml = None
try:
zip = zipfile.ZipFile(filename)
themename = None
for file in zip.namelist():
# Handle UTF-8 files
ucsfile = file_is_unicode(file)
if not ucsfile:
# Handle native Unicode files from Windows
ucsfile = file
osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile))
theme_dir = None
if osfile.endswith(os.path.sep):
theme_dir = os.path.join(dir, osfile)
check_directory_exists(theme_dir)
xmlfile = filter(lambda name:
os.path.splitext(name)[1].lower() == u'.xml', zip.namelist())
if len(xmlfile) != 1:
log.exception(u'Theme contains "%s" XML files' % len(xmlfile))
raise Exception(u'validation')
xml_tree = ElementTree(element=XML(zip.read(xmlfile[0]))).getroot()
v1_background = xml_tree.find(u'BackgroundType')
if v1_background is not None:
(themename, filexml, outfile) = self.unzipVersion122(dir, zip,
xmlfile[0], xml_tree, v1_background, outfile)
else:
fullpath = os.path.join(dir, osfile)
names = osfile.split(os.path.sep)
if len(names) > 1:
# not preview file
if themename is None:
themename = names[0]
if theme_dir is None:
theme_dir = os.path.join(dir, names[0])
check_directory_exists(theme_dir)
if os.path.splitext(ucsfile)[1].lower() in [u'.xml']:
xml_data = zip.read(file)
xml_data = file_is_unicode(xml_data)
if not xml_data:
break
filexml = self._checkVersionAndConvert(xml_data)
outfile = open(fullpath, u'w')
themename = xml_tree.find(u'name').text.strip()
for name in zip.namelist():
try:
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(fullpath, u'wb')
outfile.write(zip.read(file))
except (IOError, NameError, zipfile.BadZipfile):
critical_error_message_box(
translate('OpenLP.ThemeManager', 'Validation Error'),
translate('OpenLP.ThemeManager', 'File is not a valid theme.'))
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)
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:
# Close the files, to be able to continue creating the theme.
if zip:
@ -582,6 +589,36 @@ class ThemeManager(QtGui.QWidget):
log.exception(u'Theme file does not contain XML data %s' %
filename)
def unzipVersion122(self, dir, zip, xmlfile, xml_tree, background, outfile):
"""
Unzip openlp.org 1.2x theme file and upgrade the theme xml. When calling
this method, please keep in mind, that some parameters are redundant.
"""
themename = xml_tree.find(u'Name').text.strip()
themename = self.bad_v1_name_chars.sub(u'', themename)
themedir = os.path.join(dir, themename)
check_directory_exists(themedir)
filexml = unicode(zip.read(xmlfile), u'utf-8')
filexml = self._migrateVersion122(filexml)
outfile = open(os.path.join(themedir, themename + u'.xml'), u'w')
outfile.write(filexml.encode(u'utf-8'))
outfile.close()
if background.text.strip() == u'2':
imagename = xml_tree.find(u'BackgroundParameter1').text.strip()
# image file has same extension and is in subfolder
imagefile = filter(lambda name: os.path.splitext(name)[1].lower()
== os.path.splitext(imagename)[1].lower() and name.find(r'/'),
zip.namelist())
if len(imagefile) >= 1:
outfile = open(os.path.join(themedir, imagename), u'wb')
outfile.write(zip.read(imagefile[0]))
outfile.close()
else:
log.exception(u'Theme file does not contain image file "%s"' %
imagename.decode(u'utf-8', u'replace'))
raise Exception(u'validation')
return (themename, filexml, outfile)
def checkIfThemeExists(self, themeName):
"""
Check if theme already exists and displays error message
@ -692,22 +729,6 @@ class ThemeManager(QtGui.QWidget):
image = os.path.join(self.path, theme + u'.png')
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):
"""
Return a theme object using information parsed from XML
@ -772,7 +793,7 @@ class ThemeManager(QtGui.QWidget):
"""
theme = Theme(xml_data)
newtheme = ThemeXML()
newtheme.theme_name = theme.Name
newtheme.theme_name = self.bad_v1_name_chars.sub(u'', theme.Name)
if theme.BackgroundType == 0:
newtheme.background_type = \
BackgroundType.to_string(BackgroundType.Solid)

View File

@ -455,26 +455,6 @@ def get_web_page(url, header=None, update_openlp=False):
log.debug(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():
"""
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',
u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
u'ActionList', u'get_web_page', u'file_is_unicode', u'get_uno_command',
u'get_uno_instance', u'delete_file', u'clean_filename']
u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance',
u'delete_file', u'clean_filename']