Пример #1
0
 def import_sqlite_db(self):
     """
     Import the songs from an EasyWorship 6 SQLite database
     """
     songs_db_path = next(self.import_source.rglob('Songs.db'), None)
     song_words_db_path = next(self.import_source.rglob('SongWords.db'), None)
     invalid_dir_msg = translate('SongsPlugin.EasyWorshipSongImport',
                                 'This does not appear to be a valid Easy Worship 6 database directory.')
     invalid_db_msg = translate('SongsPlugin.EasyWorshipSongImport', 'This is not a valid Easy Worship 6 database.')
     # check to see if needed files are there
     if not (songs_db_path and songs_db_path.is_file()):
         self.log_error(self.import_source, invalid_dir_msg)
         return
     if not (song_words_db_path and song_words_db_path.is_file()):
         self.log_error(self.import_source, invalid_dir_msg)
         return
     # get database handles
     songs_conn = sqlite3.connect(str(songs_db_path))
     words_conn = sqlite3.connect(str(song_words_db_path))
     if songs_conn is None or words_conn is None:
         self.log_error(self.import_source, invalid_db_msg)
         songs_conn.close()
         words_conn.close()
         return
     songs_db = songs_conn.cursor()
     words_db = words_conn.cursor()
     if songs_conn is None or words_conn is None:
         self.log_error(self.import_source, invalid_db_msg)
         songs_conn.close()
         words_conn.close()
         return
     # Take a stab at how text is encoded
     self.encoding = 'cp1252'
     self.encoding = retrieve_windows_encoding(self.encoding)
     if not self.encoding:
         log.debug('No encoding set.')
         return
     # import songs
     songs = songs_db.execute('SELECT rowid,title,author,copyright,vendor_id FROM song;')
     for song in songs:
         song_id = song[0]
         # keep extra copy of title for error message because error check clears it
         self.title = title = song[1]
         self.author = song[2]
         self.copyright = song[3]
         self.ccli_number = song[4]
         words = words_db.execute('SELECT words FROM word WHERE song_id = ?;', (song_id,))
         self.set_song_import_object(self.author, words.fetchone()[0].encode())
         if not self.finish():
             self.log_error(self.import_source,
                            translate('SongsPlugin.EasyWorshipSongImport',
                                      '"{title}" could not be imported. {entry}').
                            format(title=title, entry=self.entry_error_log))
     # close database handles
     songs_conn.close()
     words_conn.close()
     return
Пример #2
0
    def getEncoding(self):
        """
        Detect character encoding of an openlp.org 1.x song database.
        """
        # Connect to the database.
        connection = sqlite.connect(self.importSource.encode(
            sys.getfilesystemencoding()), mode=0444)
        cursor = connection.cursor()

        detector = UniversalDetector()
        # Detect charset by authors.
        cursor.execute(u'SELECT authorname FROM authors')
        authors = cursor.fetchall()
        for author in authors:
            detector.feed(author[0])
            if detector.done:
                detector.close()
                return detector.result[u'encoding']
        # Detect charset by songs.
        cursor.execute(u'SELECT songtitle, copyrightinfo, '
            u'lyrics || \'\' AS lyrics FROM songs')
        songs = cursor.fetchall()
        for index in [0, 1, 2]:
            for song in songs:
                detector.feed(song[index])
                if detector.done:
                    detector.close()
                    return detector.result[u'encoding']
        # Detect charset by songs.
        cursor.execute(u'SELECT name FROM sqlite_master '
            u'WHERE type = \'table\' AND name = \'tracks\'')
        if cursor.fetchall():
            cursor.execute(u'SELECT fulltrackname FROM tracks')
            tracks = cursor.fetchall()
            for track in tracks:
                detector.feed(track[0])
                if detector.done:
                    detector.close()
                    return detector.result[u'encoding']
        detector.close()
        return retrieve_windows_encoding(detector.result[u'encoding'])
Пример #3
0
 def decode(self, data):
     try:
         # Don't question this, it works...
         return data.decode('utf-8').encode('cp1251').decode('cp1251')
     except:
         return data.decode(retrieve_windows_encoding())
Пример #4
0
 def import_ews(self):
     """
     Import the songs from service file
     The full spec of the ews files can be found here:
     https://github.com/meinders/lithium-ews/blob/master/docs/ews%20file%20format.md
     or here: http://wiki.openlp.org/Development:EasyWorship_EWS_Format
     """
     # Open ews file if it exists
     if not os.path.isfile(self.import_source):
         log.debug('Given ews file does not exists.')
         return
     # Make sure there is room for at least a header and one entry
     if os.path.getsize(self.import_source) < 892:
         log.debug('Given ews file is to small to contain valid data.')
         return
     # Take a stab at how text is encoded
     self.encoding = 'cp1252'
     self.encoding = retrieve_windows_encoding(self.encoding)
     if not self.encoding:
         log.debug('No encoding set.')
         return
     self.ews_file = open(self.import_source, 'rb')
     # EWS header, version '1.6'/'  3'/'  5':
     # Offset   Field             Data type    Length    Details
     # --------------------------------------------------------------------------------------------------
     #       0  Filetype           string           38    Specifies the file type and version.
     #                                                   "EasyWorship Schedule File Version  1.6" or
     #                                                   "EasyWorship Schedule File Version    3" or
     #                                                   "EasyWorship Schedule File Version    5"
     # 40/48/56 Entry count        int32le           4    Number of items in the schedule
     # 44/52/60 Entry length       int16le           2    Length of schedule entries: 0x0718 = 1816
     # Get file version
     type, = struct.unpack('<38s', self.ews_file.read(38))
     version = type.decode()[-3:]
     # Set fileposition based on filetype/version
     file_pos = 0
     if version == '  5':
         file_pos = 56
     elif version == '  3':
         file_pos = 48
     elif version == '1.6':
         file_pos = 40
     else:
         log.debug('Given ews file is of unknown version.')
         return
     entry_count = self.get_i32(file_pos)
     entry_length = self.get_i16(file_pos + 4)
     file_pos += 6
     self.import_wizard.progress_bar.setMaximum(entry_count)
     # Loop over songs
     for i in range(entry_count):
         # Load EWS entry metadata:
         # Offset  Field                  Data type    Length    Details
         # ------------------------------------------------------------------------------------------------
         #      0  Title                  cstring          50
         #    307  Author                 cstring          50
         #    358  Copyright              cstring         100
         #    459  Administrator          cstring          50
         #    800  Content pointer        int32le           4    Position of the content for this entry.
         #    820  Content type           int32le           4    0x01 = Song, 0x02 = Scripture, 0x03 = Presentation,
         #                                                       0x04 = Video, 0x05 = Live video, 0x07 = Image,
         #                                                       0x08 = Audio, 0x09 = Web
         #   1410  Song number            cstring          10
         self.set_defaults()
         self.title = self.get_string(file_pos + 0, 50)
         authors = self.get_string(file_pos + 307, 50)
         copyright = self.get_string(file_pos + 358, 100)
         admin = self.get_string(file_pos + 459, 50)
         cont_ptr = self.get_i32(file_pos + 800)
         cont_type = self.get_i32(file_pos + 820)
         self.ccli_number = self.get_string(file_pos + 1410, 10)
         # Only handle content type 1 (songs)
         if cont_type != 1:
             file_pos += entry_length
             continue
         # Load song content
         # Offset  Field              Data type    Length    Details
         # ------------------------------------------------------------------------------------------------
         #      0  Length             int32le           4    Length (L) of content, including the compressed content
         #                                                   and the following fields (14 bytes total).
         #      4  Content            string         L-14    Content compressed with deflate.
         #         Checksum           int32be           4    Alder-32 checksum.
         #         (unknown)                            4    0x51 0x4b 0x03 0x04
         #         Content length     int32le           4    Length of content after decompression
         content_length = self.get_i32(cont_ptr)
         deflated_content = self.get_bytes(cont_ptr + 4, content_length - 10)
         deflated_length = self.get_i32(cont_ptr + 4 + content_length - 6)
         inflated_content = zlib.decompress(deflated_content, 15, deflated_length)
         if copyright:
             self.copyright = copyright
         if admin:
             if copyright:
                 self.copyright += ', '
             self.copyright += translate('SongsPlugin.EasyWorshipSongImport',
                                         'Administered by {admin}').format(admin=admin)
         # Set the SongImport object members.
         self.set_song_import_object(authors, inflated_content)
         if self.stop_import_flag:
             break
         if self.entry_error_log:
             self.log_error(self.import_source,
                            translate('SongsPlugin.EasyWorshipSongImport',
                                      '"{title}" could not be imported. {entry}').format(title=self.title,
                                                                                         entry=self.entry_error_log))
             self.entry_error_log = ''
         elif not self.finish():
             self.log_error(self.import_source)
         # Set file_pos for next entry
         file_pos += entry_length
     self.ews_file.close()
Пример #5
0
 def import_db(self):
     """
     Import the songs from the database
     """
     # Open the DB and MB files if they exist
     import_source_mb = self.import_source.replace('.DB', '.MB').replace('.db', '.mb')
     if not os.path.isfile(self.import_source):
         self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',
                                                      'This file does not exist.'))
         return
     if not os.path.isfile(import_source_mb):
         self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',
                                                      'Could not find the "Songs.MB" file. It must be in the same '
                                                      'folder as the "Songs.DB" file.'))
         return
     db_size = os.path.getsize(self.import_source)
     if db_size < 0x800:
         self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',
                                                      'This file is not a valid EasyWorship database.'))
         return
     db_file = open(self.import_source, 'rb')
     self.memo_file = open(import_source_mb, 'rb')
     # Don't accept files that are clearly not paradox files
     record_size, header_size, block_size, first_block, num_fields = struct.unpack('<hhxb8xh17xh', db_file.read(35))
     if header_size != 0x800 or block_size < 1 or block_size > 4:
         db_file.close()
         self.memo_file.close()
         self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',
                                                      'This file is not a valid EasyWorship database.'))
         return
     # Take a stab at how text is encoded
     self.encoding = 'cp1252'
     db_file.seek(106)
     code_page, = struct.unpack('<h', db_file.read(2))
     if code_page == 852:
         self.encoding = 'cp1250'
     # The following codepage to actual encoding mappings have not been
     # observed, but merely guessed. Actual example files are needed.
     elif code_page == 737:
         self.encoding = 'cp1253'
     elif code_page == 775:
         self.encoding = 'cp1257'
     elif code_page == 855:
         self.encoding = 'cp1251'
     elif code_page == 857:
         self.encoding = 'cp1254'
     elif code_page == 866:
         self.encoding = 'cp1251'
     elif code_page == 869:
         self.encoding = 'cp1253'
     elif code_page == 862:
         self.encoding = 'cp1255'
     elif code_page == 874:
         self.encoding = 'cp874'
     self.encoding = retrieve_windows_encoding(self.encoding)
     if not self.encoding:
         self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',
                                                      'Could not retrieve encoding.'))
         return
     # Read the field description information
     db_file.seek(120)
     field_info = db_file.read(num_fields * 2)
     db_file.seek(4 + (num_fields * 4) + 261, os.SEEK_CUR)
     field_names = db_file.read(header_size - db_file.tell()).split(b'\0', num_fields)
     field_names.pop()
     field_descriptions = []
     for i, field_name in enumerate(field_names):
         field_type, field_size = struct.unpack_from('BB', field_info, i * 2)
         field_descriptions.append(FieldDescEntry(field_name, field_type, field_size))
     self.set_record_struct(field_descriptions)
     # Pick out the field description indexes we will need
     try:
         success = True
         fi_title = self.find_field(b'Title')
         fi_author = self.find_field(b'Author')
         fi_copy = self.find_field(b'Copyright')
         fi_admin = self.find_field(b'Administrator')
         fi_words = self.find_field(b'Words')
         fi_ccli = self.find_field(b'Song Number')
     except IndexError:
         # This is the wrong table
         success = False
     # There does not appear to be a _reliable_ way of getting the number of songs/records, so loop through the file
     # blocks and total the number of records. Store the information in a list so we dont have to do all this again.
     cur_block = first_block
     total_count = 0
     block_list = []
     while cur_block != 0 and success:
         cur_block_pos = header_size + ((cur_block - 1) * 1024 * block_size)
         db_file.seek(cur_block_pos)
         cur_block, rec_count = struct.unpack('<h2xh', db_file.read(6))
         rec_count = (rec_count + record_size) // record_size
         block_list.append((cur_block_pos, rec_count))
         total_count += rec_count
     self.import_wizard.progress_bar.setMaximum(total_count)
     for block in block_list:
         cur_block_pos, rec_count = block
         db_file.seek(cur_block_pos + 6)
         # Loop through each record within the current block
         for i in range(rec_count):
             if self.stop_import_flag:
                 break
             try:
                 raw_record = db_file.read(record_size)
                 self.fields = self.record_structure.unpack(raw_record)
                 self.set_defaults()
                 self.title = self.get_field(fi_title).decode(self.encoding)
                 # Get remaining fields.
                 copy = self.get_field(fi_copy)
                 admin = self.get_field(fi_admin)
                 ccli = self.get_field(fi_ccli)
                 authors = self.get_field(fi_author)
                 words = self.get_field(fi_words)
                 if copy:
                     self.copyright = copy.decode(self.encoding)
                 if admin:
                     if copy:
                         self.copyright += ', '
                     self.copyright += translate('SongsPlugin.EasyWorshipSongImport',
                                                 'Administered by {admin}').format(admin=admin.decode(self.encoding))
                 if ccli:
                     self.ccli_number = ccli.decode(self.encoding)
                 if authors:
                     authors = authors.decode(self.encoding)
                 else:
                     authors = ''
                 # Set the SongImport object members.
                 self.set_song_import_object(authors, words)
                 if self.stop_import_flag:
                     break
                 if self.entry_error_log:
                     self.log_error(self.import_source,
                                    translate('SongsPlugin.EasyWorshipSongImport',
                                              '"{title}" could not be imported. '
                                              '{entry}').format(title=self.title, entry=self.entry_error_log))
                     self.entry_error_log = ''
                 elif not self.finish():
                     self.log_error(self.import_source)
             except Exception as e:
                 self.log_error(self.import_source,
                                translate('SongsPlugin.EasyWorshipSongImport',
                                          '"{title}" could not be imported. {error}').format(title=self.title,
                                                                                             error=e))
     db_file.close()
     self.memo_file.close()
Пример #6
0
 def import_ews(self):
     """
     Import the songs from service file
     The full spec of the ews files can be found here:
     https://github.com/meinders/lithium-ews/blob/master/docs/ews%20file%20format.md
     or here: http://wiki.openlp.org/Development:EasyWorship_EWS_Format
     """
     # Open ews file if it exists
     if not os.path.isfile(self.import_source):
         log.debug('Given ews file does not exists.')
         return
     # Make sure there is room for at least a header and one entry
     if os.path.getsize(self.import_source) < 892:
         log.debug('Given ews file is to small to contain valid data.')
         return
     # Take a stab at how text is encoded
     self.encoding = 'cp1252'
     self.encoding = retrieve_windows_encoding(self.encoding)
     if not self.encoding:
         log.debug('No encoding set.')
         return
     self.ews_file = open(self.import_source, 'rb')
     # EWS header, version '1.6'/'  3'/'  5':
     # Offset   Field             Data type    Length    Details
     # --------------------------------------------------------------------------------------------------
     #       0  Filetype           string           38    Specifies the file type and version.
     #                                                   "EasyWorship Schedule File Version  1.6" or
     #                                                   "EasyWorship Schedule File Version    3" or
     #                                                   "EasyWorship Schedule File Version    5"
     # 40/48/56 Entry count        int32le           4    Number of items in the schedule
     # 44/52/60 Entry length       int16le           2    Length of schedule entries: 0x0718 = 1816
     # Get file version
     type, = struct.unpack('<38s', self.ews_file.read(38))
     version = type.decode()[-3:]
     # Set fileposition based on filetype/version
     file_pos = 0
     if version == '  5':
         file_pos = 56
     elif version == '  3':
         file_pos = 48
     elif version == '1.6':
         file_pos = 40
     else:
         log.debug('Given ews file is of unknown version.')
         return
     entry_count = self.get_i32(file_pos)
     entry_length = self.get_i16(file_pos + 4)
     file_pos += 6
     self.import_wizard.progress_bar.setMaximum(entry_count)
     # Loop over songs
     for i in range(entry_count):
         # Load EWS entry metadata:
         # Offset  Field                  Data type    Length    Details
         # ------------------------------------------------------------------------------------------------
         #      0  Title                  cstring          50
         #    307  Author                 cstring          50
         #    358  Copyright              cstring         100
         #    459  Administrator          cstring          50
         #    800  Content pointer        int32le           4    Position of the content for this entry.
         #    820  Content type           int32le           4    0x01 = Song, 0x02 = Scripture, 0x03 = Presentation,
         #                                                       0x04 = Video, 0x05 = Live video, 0x07 = Image,
         #                                                       0x08 = Audio, 0x09 = Web
         #   1410  Song number            cstring          10
         self.set_defaults()
         self.title = self.get_string(file_pos + 0, 50)
         authors = self.get_string(file_pos + 307, 50)
         copyright = self.get_string(file_pos + 358, 100)
         admin = self.get_string(file_pos + 459, 50)
         cont_ptr = self.get_i32(file_pos + 800)
         cont_type = self.get_i32(file_pos + 820)
         self.ccli_number = self.get_string(file_pos + 1410, 10)
         # Only handle content type 1 (songs)
         if cont_type != 1:
             file_pos += entry_length
             continue
         # Load song content
         # Offset  Field              Data type    Length    Details
         # ------------------------------------------------------------------------------------------------
         #      0  Length             int32le           4    Length (L) of content, including the compressed content
         #                                                   and the following fields (14 bytes total).
         #      4  Content            string         L-14    Content compressed with deflate.
         #         Checksum           int32be           4    Alder-32 checksum.
         #         (unknown)                            4    0x51 0x4b 0x03 0x04
         #         Content length     int32le           4    Length of content after decompression
         content_length = self.get_i32(cont_ptr)
         deflated_content = self.get_bytes(cont_ptr + 4,
                                           content_length - 10)
         deflated_length = self.get_i32(cont_ptr + 4 + content_length - 6)
         inflated_content = zlib.decompress(deflated_content, 15,
                                            deflated_length)
         if copyright:
             self.copyright = copyright
         if admin:
             if copyright:
                 self.copyright += ', '
             self.copyright += translate(
                 'SongsPlugin.EasyWorshipSongImport',
                 'Administered by %s') % admin
         # Set the SongImport object members.
         self.set_song_import_object(authors, inflated_content)
         if self.stop_import_flag:
             break
         if self.entry_error_log:
             self.log_error(
                 self.import_source,
                 translate('SongsPlugin.EasyWorshipSongImport',
                           '"%s" could not be imported. %s') %
                 (self.title, self.entry_error_log))
             self.entry_error_log = ''
         elif not self.finish():
             self.log_error(self.import_source)
         # Set file_pos for next entry
         file_pos += entry_length
     self.ews_file.close()
Пример #7
0
 def import_db(self):
     """
     Import the songs from the database
     """
     # Open the DB and MB files if they exist
     import_source_mb = self.import_source.replace('.DB', '.MB').replace(
         '.db', '.mb')
     if not os.path.isfile(self.import_source):
         self.log_error(
             self.import_source,
             translate('SongsPlugin.EasyWorshipSongImport',
                       'This file does not exist.'))
         return
     if not os.path.isfile(import_source_mb):
         self.log_error(
             self.import_source,
             translate(
                 'SongsPlugin.EasyWorshipSongImport',
                 'Could not find the "Songs.MB" file. It must be in the same '
                 'folder as the "Songs.DB" file.'))
         return
     db_size = os.path.getsize(self.import_source)
     if db_size < 0x800:
         self.log_error(
             self.import_source,
             translate('SongsPlugin.EasyWorshipSongImport',
                       'This file is not a valid EasyWorship database.'))
         return
     db_file = open(self.import_source, 'rb')
     self.memo_file = open(import_source_mb, 'rb')
     # Don't accept files that are clearly not paradox files
     record_size, header_size, block_size, first_block, num_fields = struct.unpack(
         '<hhxb8xh17xh', db_file.read(35))
     if header_size != 0x800 or block_size < 1 or block_size > 4:
         db_file.close()
         self.memo_file.close()
         self.log_error(
             self.import_source,
             translate('SongsPlugin.EasyWorshipSongImport',
                       'This file is not a valid EasyWorship database.'))
         return
     # Take a stab at how text is encoded
     self.encoding = 'cp1252'
     db_file.seek(106)
     code_page, = struct.unpack('<h', db_file.read(2))
     if code_page == 852:
         self.encoding = 'cp1250'
     # The following codepage to actual encoding mappings have not been
     # observed, but merely guessed. Actual example files are needed.
     elif code_page == 737:
         self.encoding = 'cp1253'
     elif code_page == 775:
         self.encoding = 'cp1257'
     elif code_page == 855:
         self.encoding = 'cp1251'
     elif code_page == 857:
         self.encoding = 'cp1254'
     elif code_page == 866:
         self.encoding = 'cp1251'
     elif code_page == 869:
         self.encoding = 'cp1253'
     elif code_page == 862:
         self.encoding = 'cp1255'
     elif code_page == 874:
         self.encoding = 'cp874'
     self.encoding = retrieve_windows_encoding(self.encoding)
     if not self.encoding:
         self.log_error(
             self.import_source,
             translate('SongsPlugin.EasyWorshipSongImport',
                       'Could not retrieve encoding.'))
         return
     # Read the field description information
     db_file.seek(120)
     field_info = db_file.read(num_fields * 2)
     db_file.seek(4 + (num_fields * 4) + 261, os.SEEK_CUR)
     field_names = db_file.read(header_size - db_file.tell()).split(
         b'\0', num_fields)
     field_names.pop()
     field_descriptions = []
     for i, field_name in enumerate(field_names):
         field_type, field_size = struct.unpack_from(
             'BB', field_info, i * 2)
         field_descriptions.append(
             FieldDescEntry(field_name, field_type, field_size))
     self.set_record_struct(field_descriptions)
     # Pick out the field description indexes we will need
     try:
         success = True
         fi_title = self.find_field(b'Title')
         fi_author = self.find_field(b'Author')
         fi_copy = self.find_field(b'Copyright')
         fi_admin = self.find_field(b'Administrator')
         fi_words = self.find_field(b'Words')
         fi_ccli = self.find_field(b'Song Number')
     except IndexError:
         # This is the wrong table
         success = False
     # There does not appear to be a _reliable_ way of getting the number of songs/records, so loop through the file
     # blocks and total the number of records. Store the information in a list so we dont have to do all this again.
     cur_block = first_block
     total_count = 0
     block_list = []
     while cur_block != 0 and success:
         cur_block_pos = header_size + ((cur_block - 1) * 1024 * block_size)
         db_file.seek(cur_block_pos)
         cur_block, rec_count = struct.unpack('<h2xh', db_file.read(6))
         rec_count = (rec_count + record_size) // record_size
         block_list.append((cur_block_pos, rec_count))
         total_count += rec_count
     self.import_wizard.progress_bar.setMaximum(total_count)
     for block in block_list:
         cur_block_pos, rec_count = block
         db_file.seek(cur_block_pos + 6)
         # Loop through each record within the current block
         for i in range(rec_count):
             if self.stop_import_flag:
                 break
             raw_record = db_file.read(record_size)
             self.fields = self.record_structure.unpack(raw_record)
             self.set_defaults()
             self.title = self.get_field(fi_title).decode('unicode-escape')
             # Get remaining fields.
             copy = self.get_field(fi_copy)
             admin = self.get_field(fi_admin)
             ccli = self.get_field(fi_ccli)
             authors = self.get_field(fi_author)
             words = self.get_field(fi_words)
             if copy:
                 self.copyright = copy.decode('unicode-escape')
             if admin:
                 if copy:
                     self.copyright += ', '
                 self.copyright += translate(
                     'SongsPlugin.EasyWorshipSongImport',
                     'Administered by %s') % admin.decode('unicode-escape')
             if ccli:
                 self.ccli_number = ccli.decode('unicode-escape')
             if authors:
                 authors = authors.decode('unicode-escape')
             else:
                 authors = ''
             # Set the SongImport object members.
             self.set_song_import_object(authors, words)
             if self.stop_import_flag:
                 break
             if self.entry_error_log:
                 self.log_error(
                     self.import_source,
                     translate('SongsPlugin.EasyWorshipSongImport',
                               '"%s" could not be imported. %s') %
                     (self.title, self.entry_error_log))
                 self.entry_error_log = ''
             elif not self.finish():
                 self.log_error(self.import_source)
     db_file.close()
     self.memo_file.close()
Пример #8
0
 def doImport(self):
     # Open the DB and MB files if they exist
     import_source_mb = self.import_source.replace('.DB', '.MB')
     if not os.path.isfile(self.import_source) or not os.path.isfile(import_source_mb):
         return
     db_size = os.path.getsize(self.import_source)
     if db_size < 0x800:
         return
     db_file = open(self.import_source, 'rb')
     self.memoFile = open(import_source_mb, 'rb')
     # Don't accept files that are clearly not paradox files
     record_size, header_size, block_size, first_block, num_fields = struct.unpack('<hhxb8xh17xh', db_file.read(35))
     if header_size != 0x800 or block_size < 1 or block_size > 4:
         db_file.close()
         self.memoFile.close()
         return
     # Take a stab at how text is encoded
     self.encoding = 'cp1252'
     db_file.seek(106)
     code_page, = struct.unpack('<h', db_file.read(2))
     if code_page == 852:
         self.encoding = 'cp1250'
     # The following codepage to actual encoding mappings have not been
     # observed, but merely guessed. Actual example files are needed.
     elif code_page == 737:
         self.encoding = 'cp1253'
     elif code_page == 775:
         self.encoding = 'cp1257'
     elif code_page == 855:
         self.encoding = 'cp1251'
     elif code_page == 857:
         self.encoding = 'cp1254'
     elif code_page == 866:
         self.encoding = 'cp1251'
     elif code_page == 869:
         self.encoding = 'cp1253'
     elif code_page == 862:
         self.encoding = 'cp1255'
     elif code_page == 874:
         self.encoding = 'cp874'
     self.encoding = retrieve_windows_encoding(self.encoding)
     if not self.encoding:
         return
     # Read the field description information
     db_file.seek(120)
     field_info = db_file.read(num_fields * 2)
     db_file.seek(4 + (num_fields * 4) + 261, os.SEEK_CUR)
     field_names = db_file.read(header_size - db_file.tell()).split('\0', num_fields)
     field_names.pop()
     field_descs = []
     for i, field_name in enumerate(field_names):
         field_type, field_size = struct.unpack_from('BB', field_info, i * 2)
         field_descs.append(FieldDescEntry(field_name, field_type, field_size))
     self.setRecordStruct(field_descs)
     # Pick out the field description indexes we will need
     try:
         success = True
         fi_title = self.findField('Title')
         fi_author = self.findField('Author')
         fi_copy = self.findField('Copyright')
         fi_admin = self.findField('Administrator')
         fi_words = self.findField('Words')
         fi_ccli = self.findField('Song Number')
     except IndexError:
         # This is the wrong table
         success = False
     # There does not appear to be a _reliable_ way of getting the number of songs/records, so loop through the file
     # blocks and total the number of records. Store the information in a list so we dont have to do all this again.
     cur_block = first_block
     total_count = 0
     block_list = []
     while cur_block != 0 and success:
         cur_block_pos = header_size + ((cur_block - 1) * 1024 * block_size)
         db_file.seek(cur_block_pos)
         cur_block, rec_count = struct.unpack('<h2xh', db_file.read(6))
         rec_count = (rec_count + record_size) / record_size
         block_list.append((cur_block_pos, rec_count))
         total_count += rec_count
     self.import_wizard.progress_bar.setMaximum(total_count)
     for block in block_list:
         cur_block_pos, rec_count = block
         db_file.seek(cur_block_pos + 6)
         # Loop through each record within the current block
         for i in range(rec_count):
             if self.stop_import_flag:
                 break
             raw_record = db_file.read(record_size)
             self.fields = self.recordStruct.unpack(raw_record)
             self.setDefaults()
             self.title = self.getField(fi_title)
             # Get remaining fields.
             copy = self.getField(fi_copy)
             admin = self.getField(fi_admin)
             ccli = self.getField(fi_ccli)
             authors = self.getField(fi_author)
             words = self.getField(fi_words)
             # Set the SongImport object members.
             if copy:
                 self.copyright = copy
             if admin:
                 if copy:
                     self.copyright += ', '
                 self.copyright += translate('SongsPlugin.EasyWorshipSongImport', 'Administered by %s') % admin
             if ccli:
                 self.ccliNumber = ccli
             if authors:
                 # Split up the authors
                 author_list = authors.split('/')
                 if len(author_list) < 2:
                     author_list = authors.split(';')
                 if len(author_list) < 2:
                     author_list = authors.split(',')
                 for author_name in author_list:
                     self.addAuthor(author_name.strip())
             if words:
                 # Format the lyrics
                 result = strip_rtf(words, self.encoding)
                 if result is None:
                     return
                 words, self.encoding = result
                 verse_type = VerseType.tags[VerseType.Verse]
                 for verse in SLIDE_BREAK_REGEX.split(words):
                     verse = verse.strip()
                     if not verse:
                         continue
                     verse_split = verse.split('\n', 1)
                     first_line_is_tag = False
                     # EW tags: verse, chorus, pre-chorus, bridge, tag,
                     # intro, ending, slide
                     for tag in VerseType.tags + ['tag', 'slide']:
                         tag = tag.lower()
                         ew_tag = verse_split[0].strip().lower()
                         if ew_tag.startswith(tag):
                             verse_type = tag[0]
                             if tag == 'tag' or tag == 'slide':
                                 verse_type = VerseType.tags[VerseType.Other]
                             first_line_is_tag = True
                             number_found = False
                             # check if tag is followed by number and/or note
                             if len(ew_tag) > len(tag):
                                 match = NUMBER_REGEX.search(ew_tag)
                                 if match:
                                     number = match.group()
                                     verse_type += number
                                     number_found = True
                                 match = NOTE_REGEX.search(ew_tag)
                                 if match:
                                     self.comments += ew_tag + '\n'
                             if not number_found:
                                 verse_type += '1'
                             break
                     self.addVerse(verse_split[-1].strip() if first_line_is_tag else verse, verse_type)
             if len(self.comments) > 5:
                 self.comments += str(translate('SongsPlugin.EasyWorshipSongImport',
                     '\n[above are Song Tags with notes imported from EasyWorship]'))
             if self.stop_import_flag:
                 break
             if not self.finish():
                 self.logError(self.import_source)
     db_file.close()
     self.memoFile.close()
Пример #9
0
 def decode(self, data):
     try:
         return str(data, chardet.detect(data)['encoding'])
     except:
         return str(data, retrieve_windows_encoding())
Пример #10
0
 def decode(self, blob):
     while True:
         try:
             return blob.decode(self.encoding)
         except Exception as e:
             self.encoding = retrieve_windows_encoding()
Пример #11
0
 def decode(self, data):
     try:
         return str(data, chardet.detect(data)['encoding'])
     except:
         return str(data, retrieve_windows_encoding())
Пример #12
0
 def decode(self, blob):
     while True:
         try:
             return str(blob, self.encoding)
         except:
             self.encoding = retrieve_windows_encoding()
Пример #13
0
 def decode(self, blob):
     while True:
         try:
             return blob.decode(self.encoding)
         except Exception as e:
             self.encoding = retrieve_windows_encoding()
Пример #14
0
 def decode(self, blob):
     while True:
         try:
             return str(blob, self.encoding)
         except:
             self.encoding = retrieve_windows_encoding()