This commit is contained in:
Phill Ridout 2015-02-13 20:41:54 +00:00
commit 3e697dc213
14 changed files with 118 additions and 22 deletions

View File

@ -190,31 +190,32 @@ def verify_ip_address(addr):
return True if verify_ipv4(addr) else verify_ipv6(addr)
def md5_hash(salt, data):
def md5_hash(salt, data=None):
"""
Returns the hashed output of md5sum on salt,data
using Python3 hashlib
:param salt: Initial salt
:param data: Data to hash
:param data: OPTIONAL Data to hash
:returns: str
"""
log.debug('md5_hash(salt="%s")' % salt)
hash_obj = hashlib.new('md5')
hash_obj.update(salt.encode('ascii'))
hash_obj.update(data.encode('ascii'))
hash_obj.update(salt)
if data:
hash_obj.update(data)
hash_value = hash_obj.hexdigest()
log.debug('md5_hash() returning "%s"' % hash_value)
return hash_value
def qmd5_hash(salt, data):
def qmd5_hash(salt, data=None):
"""
Returns the hashed output of MD5Sum on salt, data
using PyQt4.QCryptographicHash.
:param salt: Initial salt
:param data: Data to hash
:param data: OPTIONAL Data to hash
:returns: str
"""
log.debug('qmd5_hash(salt="%s"' % salt)
@ -223,7 +224,7 @@ def qmd5_hash(salt, data):
hash_obj.addData(data)
hash_value = hash_obj.result().toHex()
log.debug('qmd5_hash() returning "%s"' % hash_value)
return decode(hash_value.data(), 'ascii')
return hash_value.data()
def clean_button_text(button_text):

View File

@ -343,7 +343,7 @@ class PJLink1(QTcpSocket):
# Authenticated login with salt
log.debug('(%s) Setting hash with salt="%s"' % (self.ip, data_check[2]))
log.debug('(%s) pin="%s"' % (self.ip, self.pin))
salt = qmd5_hash(salt=data_check[2], data=self.pin)
salt = qmd5_hash(salt=data_check[2].endcode('ascii'), data=self.pin.encode('ascii'))
else:
salt = None
# We're connected at this point, so go ahead and do regular I/O

View File

@ -268,9 +268,11 @@ class FirstTimeForm(QtGui.QWizard, UiFirstTimeWizard, RegistryProperties):
self.web = 'http://openlp.org/files/frw/'
self.cancel_button.clicked.connect(self.on_cancel_button_clicked)
self.no_internet_finish_button.clicked.connect(self.on_no_internet_finish_button_clicked)
self.no_internet_cancel_button.clicked.connect(self.on_no_internet_cancel_button_clicked)
self.currentIdChanged.connect(self.on_current_id_changed)
Registry().register_function('config_screen_changed', self.update_screen_list_combo)
self.no_internet_finish_button.setVisible(False)
self.no_internet_cancel_button.setVisible(False)
# Check if this is a re-run of the wizard.
self.has_run_wizard = Settings().value('core/has run wizard')
check_directory_exists(os.path.join(gettempdir(), 'openlp'))
@ -327,6 +329,10 @@ class FirstTimeForm(QtGui.QWizard, UiFirstTimeWizard, RegistryProperties):
self.next_button.setVisible(False)
self.cancel_button.setVisible(False)
self.no_internet_finish_button.setVisible(True)
if self.has_run_wizard:
self.no_internet_cancel_button.setVisible(False)
else:
self.no_internet_cancel_button.setVisible(True)
elif page_id == FirstTimePage.Plugins:
self.back_button.setVisible(False)
elif page_id == FirstTimePage.Progress:
@ -372,6 +378,13 @@ class FirstTimeForm(QtGui.QWizard, UiFirstTimeWizard, RegistryProperties):
Settings().setValue('core/has run wizard', True)
self.close()
def on_no_internet_cancel_button_clicked(self):
"""
Process the triggering of the "Cancel" button on the No Internet page.
"""
self.was_cancelled = True
self.close()
def url_get_file(self, url, f_path):
""""
Download a file given a URL. The file is retrieved in chunks, giving the ability to cancel the download at any

View File

@ -59,7 +59,8 @@ class UiFirstTimeWizard(object):
first_time_wizard.resize(550, 386)
first_time_wizard.setModal(True)
first_time_wizard.setOptions(QtGui.QWizard.IndependentPages | QtGui.QWizard.NoBackButtonOnStartPage |
QtGui.QWizard.NoBackButtonOnLastPage | QtGui.QWizard.HaveCustomButton1)
QtGui.QWizard.NoBackButtonOnLastPage | QtGui.QWizard.HaveCustomButton1 |
QtGui.QWizard.HaveCustomButton2)
if is_macosx():
first_time_wizard.setPixmap(QtGui.QWizard.BackgroundPixmap,
QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
@ -69,6 +70,7 @@ class UiFirstTimeWizard(object):
self.finish_button = self.button(QtGui.QWizard.FinishButton)
self.no_internet_finish_button = self.button(QtGui.QWizard.CustomButton1)
self.cancel_button = self.button(QtGui.QWizard.CancelButton)
self.no_internet_cancel_button = self.button(QtGui.QWizard.CustomButton2)
self.next_button = self.button(QtGui.QWizard.NextButton)
self.back_button = self.button(QtGui.QWizard.BackButton)
add_welcome_page(first_time_wizard, ':/wizards/wizard_firsttime.bmp')
@ -271,3 +273,4 @@ class UiFirstTimeWizard(object):
'and OpenLP is configured.'))
self.progress_label.setText(translate('OpenLP.FirstTimeWizard', 'Starting configuration process...'))
first_time_wizard.setButtonText(QtGui.QWizard.CustomButton1, translate('OpenLP.FirstTimeWizard', 'Finish'))
first_time_wizard.setButtonText(QtGui.QWizard.CustomButton2, translate('OpenLP.FirstTimeWizard', 'Cancel'))

View File

@ -371,7 +371,7 @@ def parse_reference(reference, bible, language_selection, book_ref_id=False):
from_chapter = from_verse
from_verse = None
if to_chapter:
if to_chapter < from_chapter:
if from_chapter and to_chapter < from_chapter:
continue
else:
chapter = to_chapter
@ -387,7 +387,7 @@ def parse_reference(reference, bible, language_selection, book_ref_id=False):
from_verse = 1
if not to_verse:
to_verse = -1
if to_chapter > from_chapter:
if to_chapter and to_chapter > from_chapter:
ref_list.append((book_ref_id, from_chapter, from_verse, -1))
for i in range(from_chapter + 1, to_chapter):
ref_list.append((book_ref_id, i, 1, -1))

View File

@ -225,10 +225,10 @@ class PresentationMediaItem(MediaManagerItem):
self.clean_up_thumbnails(filepath)
self.main_window.increment_progress_bar()
self.main_window.finished_progress_bar()
self.application.set_busy_cursor()
for row in row_list:
self.list_view.takeItem(row)
Settings().setValue(self.settings_section + '/presentations files', self.get_file_list())
self.application.set_normal_cursor()
def clean_up_thumbnails(self, filepath):
"""

View File

@ -134,7 +134,7 @@ class PresentationDocument(object):
"""
# TODO: If statment can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
if Settings().value('presentations/thumbnail_scheme') == 'md5':
folder = md5_hash('', self.file_path)
folder = md5_hash(self.file_path)
else:
folder = self.get_file_name()
return os.path.join(self.controller.thumbnail_folder, folder)
@ -145,7 +145,7 @@ class PresentationDocument(object):
"""
# TODO: If statment can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
if Settings().value('presentations/thumbnail_scheme') == 'md5':
folder = md5_hash('', self.file_path)
folder = md5_hash(self.file_path)
else:
folder = folder = self.get_file_name()
return os.path.join(self.controller.temp_folder, folder)

View File

@ -25,7 +25,9 @@ Presentationmanager song files into the current database.
"""
import os
from lxml import objectify
import re
import chardet
from lxml import objectify, etree
from openlp.core.ui.wizard import WizardStrings
from .songimport import SongImport
@ -42,7 +44,18 @@ class PresentationManagerImport(SongImport):
if self.stop_import_flag:
return
self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
root = objectify.parse(open(file_path, 'rb')).getroot()
try:
tree = etree.parse(file_path, parser=etree.XMLParser(recover=True))
except etree.XMLSyntaxError:
# Try to detect encoding and use it
file = open(file_path, mode='rb')
encoding = chardet.detect(file.read())['encoding']
file.close()
# Open file with detected encoding and remove encoding declaration
text = open(file_path, mode='r', encoding=encoding).read()
text = re.sub('.+\?>\n', '', text)
tree = etree.fromstring(text, parser=etree.XMLParser(recover=True))
root = objectify.fromstring(etree.tostring(tree))
self.process_song(root)
def process_song(self, root):

View File

@ -83,6 +83,7 @@
<file>openlp-logo-64x64.png</file>
<file>openlp-logo-128x128.png</file>
<file>openlp-logo-256x256.png</file>
<file>openlp-logo.svg</file>
</qresource>
<qresource prefix="graphics">
<file>exception.png</file>

View File

@ -23,6 +23,8 @@
Package to test the openlp.core.ui.projector.networkutils package.
"""
import os
from unittest import TestCase
from openlp.core.common import verify_ip_address, md5_hash, qmd5_hash
@ -30,6 +32,8 @@ from openlp.core.common import verify_ip_address, md5_hash, qmd5_hash
salt = '498e4a67'
pin = 'JBMIAProjectorLink'
test_hash = '5d8409bc1c3fa39749434aa3a5c38682'
test_non_ascii_string = '이것은 한국어 시험 문자열'
test_non_ascii_hash = 'fc00c7912976f6e9c19099b514ced201'
ip4_loopback = '127.0.0.1'
ip4_local = '192.168.1.1'
@ -120,7 +124,7 @@ class testProjectorUtilities(TestCase):
Test MD5 hash from salt+data pass (python)
"""
# WHEN: Given a known salt+data
hash_ = md5_hash(salt=salt, data=pin)
hash_ = md5_hash(salt=salt.encode('ascii'), data=pin.encode('ascii'))
# THEN: Validate return has is same
self.assertEquals(hash_, test_hash, 'MD5 should have returned a good hash')
@ -130,7 +134,7 @@ class testProjectorUtilities(TestCase):
Test MD5 hash from salt+data fail (python)
"""
# WHEN: Given a different salt+hash
hash_ = md5_hash(salt=pin, data=salt)
hash_ = md5_hash(salt=pin.encode('ascii'), data=salt.encode('ascii'))
# THEN: return data is different
self.assertNotEquals(hash_, test_hash, 'MD5 should have returned a bad hash')
@ -140,17 +144,37 @@ class testProjectorUtilities(TestCase):
Test MD5 hash from salt+data pass (Qt)
"""
# WHEN: Given a known salt+data
hash_ = qmd5_hash(salt=salt, data=pin)
hash_ = qmd5_hash(salt=salt.encode('ascii'), data=pin.encode('ascii'))
# THEN: Validate return has is same
self.assertEquals(hash_, test_hash, 'Qt-MD5 should have returned a good hash')
self.assertEquals(hash_.decode('ascii'), test_hash, 'Qt-MD5 should have returned a good hash')
def test_qmd5_hash_bad(self):
"""
Test MD5 hash from salt+hash fail (Qt)
"""
# WHEN: Given a different salt+hash
hash_ = qmd5_hash(salt=pin, data=salt)
hash_ = qmd5_hash(salt=pin.encode('ascii'), data=salt.encode('ascii'))
# THEN: return data is different
self.assertNotEquals(hash_, test_hash, 'Qt-MD5 should have returned a bad hash')
self.assertNotEquals(hash_.decode('ascii'), test_hash, 'Qt-MD5 should have returned a bad hash')
def test_md5_non_ascii_string(self):
"""
Test MD5 hash with non-ascii string - bug 1417809
"""
# WHEN: Non-ascii string is hashed
hash_ = md5_hash(salt=test_non_ascii_string.encode('utf-8'), data=None)
# THEN: Valid MD5 hash should be returned
self.assertEqual(hash_, test_non_ascii_hash, 'MD5 should have returned a valid hash')
def test_qmd5_non_ascii_string(self):
"""
Test MD5 hash with non-ascii string - bug 1417809
"""
# WHEN: Non-ascii string is hashed
hash_ = md5_hash(salt=test_non_ascii_string.encode('utf-8'), data=None)
# THEN: Valid MD5 hash should be returned
self.assertEqual(hash_, test_non_ascii_hash, 'Qt-MD5 should have returned a valid hash')

View File

@ -46,3 +46,5 @@ class TestPresentationManagerFileImport(SongImportTestHelper):
self.load_external_result_data(os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.json')))
self.file_import([os.path.join(TEST_PATH, 'Agnus Dei.sng')],
self.load_external_result_data(os.path.join(TEST_PATH, 'Agnus Dei.json')))
self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.sng')],
self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))

View File

@ -109,3 +109,13 @@ class TestBibleManager(TestCase, TestMixin):
results = parse_reference('Raoul 1', self.manager.db_cache['tests'], MagicMock())
# THEN a verse array should be returned
self.assertEqual(False, results, "The bible Search should return False")
def parse_reference_five_test(self):
"""
Test the parse_reference method with 1 Timothy 1:3-end
"""
# GIVEN given a bible in the bible manager
# WHEN asking to parse the bible reference
results = parse_reference('1 Timothy 1:3-end', self.manager.db_cache['tests'], MagicMock(), 54)
# THEN a verse array should be returned
self.assertEqual([(54, 1, 3, -1)], results, "The bible verses should matches the expected results")

View File

@ -0,0 +1,29 @@
{
"title": "Amazing Grace",
"authors": [
"John Newton"
],
"verse_order_list": ["v1", "v2", "v3", "v4", "v5"],
"verses": [
[
"Amazing grace! How sweet the sound!\nThat saved a wretch like me!\nI once was lost, but now am found;\nWas blind, but now I see.",
"v1"
],
[
"'Twas grace that taught my heart to fear,\nAnd grace my fears relieved.\nHow precious did that grace appear,\nThe hour I first believed.",
"v2"
],
[
"The Lord has promised good to me,\nHis Word my hope secures.\nHe will my shield and portion be\nAs long as life endures.",
"v3"
],
[
"Thro' many dangers, toils and snares\nI have already come.\n'Tis grace that brought me safe thus far,\nAnd grace will lead me home.",
"v4"
],
[
"When we've been there ten thousand years,\nBright shining as the sun,\nWe've no less days to sing God's praise,\nThan when we first begun.",
"v5"
]
]
}