pdb/eReader metadata writer

This commit is contained in:
John Schember 2009-05-16 12:14:32 -04:00
parent c52966ffa4
commit d16b8274c6
5 changed files with 84 additions and 17 deletions

View File

@ -297,6 +297,17 @@ class PDFMetadataWriter(MetadataWriterPlugin):
from calibre.ebooks.metadata.pdf import set_metadata from calibre.ebooks.metadata.pdf import set_metadata
set_metadata(stream, mi) set_metadata(stream, mi)
class PDBMetadataWriter(MetadataWriterPlugin):
name = 'Set PDB metadata'
file_types = set(['pdb'])
description = _('Set metadata from %s files') % 'PDB'
author = 'John Schember'
def set_metadata(self, stream, mi, type):
from calibre.ebooks.metadata.pdb import set_metadata
set_metadata(stream, mi)
from calibre.ebooks.epub.input import EPUBInput from calibre.ebooks.epub.input import EPUBInput
from calibre.ebooks.mobi.input import MOBIInput from calibre.ebooks.mobi.input import MOBIInput

View File

@ -10,8 +10,8 @@ __docformat__ = 'restructuredtext en'
import re import re
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation, authors_to_string
from calibre.ebooks.pdb.header import PdbHeaderReader from calibre.ebooks.pdb.header import PdbHeaderReader, PdbHeaderBuilder
from calibre.ebooks.pdb.ereader.reader import HeaderRecord from calibre.ebooks.pdb.ereader.reader import HeaderRecord
def get_metadata(stream, extract_cover=True): def get_metadata(stream, extract_cover=True):
@ -24,8 +24,8 @@ def get_metadata(stream, extract_cover=True):
pheader = PdbHeaderReader(stream) pheader = PdbHeaderReader(stream)
hr = HeaderRecord(pheader.section_data(0)) hr = HeaderRecord(pheader.section_data(0))
if hr.version in (2, 10): if hr.version in (2, 10) and hr.has_metadata == 1:
try: try:
mdata = pheader.section_data(hr.metadata_offset) mdata = pheader.section_data(hr.metadata_offset)
mdata = mdata.split('\x00') mdata = mdata.split('\x00')
@ -41,3 +41,42 @@ def get_metadata(stream, extract_cover=True):
return mi return mi
def set_metadata(stream, mi):
pheader = PdbHeaderReader(stream)
sections = [pheader.section_data(x) for x in range(0, pheader.section_count())]
hr = HeaderRecord(sections[0])
if hr.version not in (2, 10):
return
# Create a metadata record for the file if one does not alreay exist
if not hr.has_metadata:
sections += ['', 'MeTaInFo\x00']
last_data = len(sections) - 1
for i in range(0, 132, 2):
val, = struct.unpack('>H', sections[0][i:i+2])
if val >= hr.last_data_offset:
sections[0][i:i+2] = struct.pack('>H', last_data)
sections[0][24:26] = struct.pack('>H', 1) # Set has metadata
sections[0][44:46] = struct.pack('>H', last_data - 1) # Set location of metadata
sections[0][52:54] = struct.pack('>H', last_data) # Ensure last data offset is updated
# Merge the metadata into the file
file_mi = get_metadata(stream, False)
file_mi.smart_update(mi)
sections[hr.metadata_offset] = '%s\x00%s\x00%s\x00%s\x00%s\x00' % \
(file_mi.title, authors_to_string(file_mi.authors), '', file_mi.publisher, file_mi.isbn)
# Rebuild the PDB wrapper because the offsets have changed due to the
# new metadata.
pheader_builder = PdbHeaderBuilder(pheader.ident, pheader.title)
stream.seek(0)
stream.truncate(0)
pheader_builder.build_header([len(x) for x in sections], stream)
# Write the data back to the file
for item in sections:
stream.write(item)

View File

@ -12,11 +12,18 @@ import re
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.pdb.header import PdbHeaderReader from calibre.ebooks.pdb.header import PdbHeaderReader
from calibre.ebooks.metadata.ereader import get_metadata as eReader from calibre.ebooks.metadata.ereader import get_metadata as get_eReader
MREADER = { MREADER = {
'PNPdPPrs' : eReader, 'PNPdPPrs' : get_eReader,
'PNRdPPrs' : eReader, 'PNRdPPrs' : get_eReader,
}
from calibre.ebooks.metadata.ereader import set_metadata as set_eReader
MWRITER = {
'PNPdPPrs' : set_eReader,
'PNRdPPrs' : set_eReader,
} }
def get_metadata(stream, extract_cover=True): def get_metadata(stream, extract_cover=True):
@ -34,3 +41,16 @@ def get_metadata(stream, extract_cover=True):
return MetadataReader(stream, extract_cover) return MetadataReader(stream, extract_cover)
def set_metadata(stream, mi):
stream.seek(0)
pheader = PdbHeaderReader(stream)
MetadataWriter = MWRITER.get(pheader.ident, None)
if MetadataWriter:
MetadataWriter(stream, mi)
stream.seek(0)
stream.write(re.sub('[^-A-Za-z0-9]+', '_', mi.title).ljust(32, '\x00')[:32])

View File

@ -12,7 +12,6 @@ import os, re, struct, zlib
from calibre import CurrentDir from calibre import CurrentDir
from calibre.ebooks import DRMError from calibre.ebooks import DRMError
from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.pdb.formatreader import FormatReader from calibre.ebooks.pdb.formatreader import FormatReader
from calibre.ebooks.pdb.ereader import EreaderError from calibre.ebooks.pdb.ereader import EreaderError
from calibre.ebooks.pml.pmlconverter import pml_to_html, \ from calibre.ebooks.pml.pmlconverter import pml_to_html, \
@ -31,6 +30,7 @@ class HeaderRecord(object):
def __init__(self, raw): def __init__(self, raw):
self.version, = struct.unpack('>H', raw[0:2]) self.version, = struct.unpack('>H', raw[0:2])
self.non_text_offset, = struct.unpack('>H', raw[12:14]) self.non_text_offset, = struct.unpack('>H', raw[12:14])
self.has_metadata, = struct.unpack('>H', raw[24:26])
self.footnote_rec, = struct.unpack('>H', raw[28:30]) self.footnote_rec, = struct.unpack('>H', raw[28:30])
self.sidebar_rec, = struct.unpack('>H', raw[30:32]) self.sidebar_rec, = struct.unpack('>H', raw[30:32])
self.bookmark_offset, = struct.unpack('>H', raw[32:34]) self.bookmark_offset, = struct.unpack('>H', raw[32:34])
@ -62,6 +62,9 @@ class Reader(FormatReader):
else: else:
raise EreaderError('Unknown book version %i.' % self.header_record.version) raise EreaderError('Unknown book version %i.' % self.header_record.version)
from calibre.ebooks.metadata.pdb import get_metadata
self.mi = get_metadata(stream, False)
def section_data(self, number): def section_data(self, number):
return self.sections[number] return self.sections[number]
@ -144,10 +147,8 @@ class Reader(FormatReader):
return opf_path return opf_path
def create_opf(self, output_dir, images): def create_opf(self, output_dir, images):
mi = MetaInformation(None, None)
with CurrentDir(output_dir): with CurrentDir(output_dir):
opf = OPFCreator(output_dir, mi) opf = OPFCreator(output_dir, self.mi)
manifest = [('index.html', None)] manifest = [('index.html', None)]

View File

@ -18,11 +18,7 @@ from calibre.ebooks.pdb.header import PdbHeaderBuilder
from calibre.ebooks.pdb.ereader import image_name from calibre.ebooks.pdb.ereader import image_name
from calibre.ebooks.pml.pmlconverter import html_to_pml from calibre.ebooks.pml.pmlconverter import html_to_pml
# We are using the older identity because we do not user newer features IDENTITY = 'PNRdPPrs'
# (sidebar, footnotes). This will ensure compatibility with older readers.
# If newer features are used (anything supported by dropbook but not by makebook
# change the identity to the newer PNRdPPrs.
IDENTITY = 'PNPdPPrs'
# This is an arbitrary number that is small enough to work. The actual maximum # This is an arbitrary number that is small enough to work. The actual maximum
# record size is unknown. # record size is unknown.