~ubuntu-branches/ubuntu/karmic/calibre/karmic

« back to all changes in this revision

Viewing changes to src/calibre/ebooks/pdb/ztxt/reader.py

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-07-30 12:49:41 UTC
  • mfrom: (1.3.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090730124941-qjdsmri25zt8zocn
Tags: 0.6.3+dfsg-0ubuntu1
* New upstream release. Please see http://calibre.kovidgoyal.net/new_in_6/
  for the list of new features and changes.
* remove_postinstall.patch: Update for new version.
* build_debug.patch: Does not apply any more, disable for now. Might not be
  necessary any more.
* debian/copyright: Fix reference to versionless GPL.
* debian/rules: Drop obsolete dh_desktop call.
* debian/rules: Add workaround for weird Python 2.6 setuptools behaviour of
  putting compiled .so files into src/calibre/plugins/calibre/plugins
  instead of src/calibre/plugins.
* debian/rules: Drop hal fdi moving, new upstream version does not use hal
  any more. Drop hal dependency, too.
* debian/rules: Install udev rules into /lib/udev/rules.d.
* Add debian/calibre.preinst: Remove unmodified
  /etc/udev/rules.d/95-calibre.rules on upgrade.
* debian/control: Bump Python dependencies to 2.6, since upstream needs
  it now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
 
 
3
'''
 
4
Read content from ztxt pdb file.
 
5
'''
 
6
 
 
7
__license__   = 'GPL v3'
 
8
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
 
9
__docformat__ = 'restructuredtext en'
 
10
 
 
11
import os, struct, zlib
 
12
 
 
13
from calibre.ebooks.pdb.formatreader import FormatReader
 
14
from calibre.ebooks.pdb.ztxt import zTXTError
 
15
from calibre.ebooks.txt.processor import txt_to_markdown, opf_writer
 
16
 
 
17
SUPPORTED_VERSION = (1, 40)
 
18
 
 
19
class HeaderRecord(object):
 
20
    '''
 
21
    The first record in the file is always the header record. It holds
 
22
    information related to the location of text, images, and so on
 
23
    in the file. This is used in conjunction with the sections
 
24
    defined in the file header.
 
25
    '''
 
26
 
 
27
    def __init__(self, raw):
 
28
        self.version, = struct.unpack('>H', raw[0:2])
 
29
        self.num_records, = struct.unpack('>H', raw[2:4])
 
30
        self.size, = struct.unpack('>L', raw[4:8])
 
31
        self.record_size, = struct.unpack('>H', raw[8:10])
 
32
        self.flags, = struct.unpack('>B', raw[18:19])
 
33
        
 
34
    
 
35
class Reader(FormatReader):
 
36
    
 
37
    def __init__(self, header, stream, log, encoding=None):
 
38
        self.stream = stream
 
39
        self.log = log
 
40
        self.encoding = encoding
 
41
    
 
42
        self.sections = []
 
43
        for i in range(header.num_sections):
 
44
            self.sections.append(header.section_data(i))
 
45
 
 
46
        self.header_record = HeaderRecord(self.section_data(0))
 
47
        
 
48
        vmajor = (self.header_record.version & 0x0000FF00) >> 8
 
49
        vminor = self.header_record.version & 0x000000FF
 
50
        if vmajor < 1 or (vmajor == 1 and vminor < 40):
 
51
            raise zTXTError('Unsupported ztxt version (%i.%i). Only versions newer than %i.%i are supported.' % (vmajor, vminor, SUPPORTED_VERSION[0], SUPPORTED_VERSION[1]))
 
52
 
 
53
        if (self.header_record.flags & 0x01) == 0:
 
54
            raise zTXTError('Only compression method 1 (random access) is supported')
 
55
 
 
56
        self.log.debug('Foud ztxt version: %i.%i' % (vmajor, vminor))
 
57
 
 
58
        # Initalize the decompressor
 
59
        self.uncompressor = zlib.decompressobj()
 
60
        self.uncompressor.decompress(self.section_data(1))
 
61
 
 
62
    def section_data(self, number):
 
63
        return self.sections[number]
 
64
 
 
65
    def decompress_text(self, number):
 
66
        if number == 1:
 
67
            self.uncompressor = zlib.decompressobj()
 
68
        return self.uncompressor.decompress(self.section_data(number)).decode('cp1252' if self.encoding is None else self.encoding, 'replace')
 
69
 
 
70
    def extract_content(self, output_dir):
 
71
        txt = ''
 
72
        
 
73
        self.log.info('Decompressing text...')
 
74
        for i in range(1, self.header_record.num_records + 1):
 
75
            self.log.debug('\tDecompressing text section %i' % i)
 
76
            txt += self.decompress_text(i)
 
77
 
 
78
        self.log.info('Converting text to OEB...')
 
79
        html = txt_to_markdown(txt)
 
80
        with open(os.path.join(output_dir, 'index.html'), 'wb') as index:
 
81
            index.write(html.encode('utf-8'))
 
82
                        
 
83
        from calibre.ebooks.metadata.meta import get_metadata
 
84
        mi = get_metadata(self.stream, 'pdb')
 
85
        manifest = [('index.html', None)]
 
86
        spine = ['index.html']
 
87
        opf_writer(output_dir, 'metadata.opf', manifest, spine, mi)
 
88
        
 
89
        return os.path.join(output_dir, 'metadata.opf')
 
90