home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_953 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  10.5 KB  |  333 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. __license__ = 'GPL v3'
  6. __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
  7. import os
  8. import re
  9. import posixpath
  10. import shutil
  11. from cStringIO import StringIO
  12. from contextlib import closing
  13. from calibre.utils.zipfile import ZipFile, BadZipfile, safe_replace
  14. from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup
  15. from calibre.ebooks.metadata import MetaInformation
  16. from calibre.ebooks.metadata.opf2 import OPF
  17. from calibre.ptempfile import TemporaryDirectory, PersistentTemporaryFile
  18. from calibre import CurrentDir
  19.  
  20. class EPubException(Exception):
  21.     pass
  22.  
  23.  
  24. class OCFException(EPubException):
  25.     pass
  26.  
  27.  
  28. class ContainerException(OCFException):
  29.     pass
  30.  
  31.  
  32. class Container(dict):
  33.     
  34.     def __init__(self, stream = None):
  35.         if not stream:
  36.             return None
  37.         soup = BeautifulStoneSoup(stream.read())
  38.         container = soup.find(name = re.compile('container$', re.I))
  39.         if not container:
  40.             raise OCFException('<container> element missing')
  41.         container
  42.         if container.get('version', None) != '1.0':
  43.             raise EPubException('unsupported version of OCF')
  44.         container.get('version', None) != '1.0'
  45.         rootfiles = container.find(re.compile('rootfiles$', re.I))
  46.         if not rootfiles:
  47.             raise EPubException('<rootfiles/> element missing')
  48.         rootfiles
  49.         for rootfile in rootfiles.findAll(re.compile('rootfile$', re.I)):
  50.             
  51.             try:
  52.                 self[rootfile['media-type']] = rootfile['full-path']
  53.             continue
  54.             except KeyError:
  55.                 stream
  56.                 stream
  57.                 raise EPubException('<rootfile/> element malformed')
  58.                 continue
  59.             
  60.  
  61.         
  62.  
  63.  
  64.  
  65. class OCF(object):
  66.     MIMETYPE = 'application/epub+zip'
  67.     CONTAINER_PATH = 'META-INF/container.xml'
  68.     ENCRYPTION_PATH = 'META-INF/encryption.xml'
  69.     
  70.     def __init__(self):
  71.         raise NotImplementedError('Abstract base class')
  72.  
  73.  
  74.  
  75. class Encryption(object):
  76.     OBFUSCATION_ALGORITHMS = frozenset([
  77.         'http://ns.adobe.com/pdf/enc#RC',
  78.         'http://www.idpf.org/2008/embedding'])
  79.     
  80.     def __init__(self, raw):
  81.         etree = etree
  82.         import lxml
  83.         self.root = None if raw else None
  84.         self.entries = { }
  85.         if self.root is not None:
  86.             for em in self.root.xpath('descendant::*[contains(name(), "EncryptionMethod")]'):
  87.                 algorithm = em.get('Algorithm', '')
  88.                 cr = em.getparent().xpath('descendant::*[contains(name(), "CipherReference")]')
  89.                 if cr:
  90.                     uri = cr[0].get('URI', '')
  91.                     if uri and algorithm:
  92.                         self.entries[uri] = algorithm
  93.                     
  94.                 algorithm
  95.             
  96.         
  97.  
  98.     
  99.     def is_encrypted(self, uri):
  100.         algo = self.entries.get(uri, None)
  101.         if algo is not None:
  102.             pass
  103.         return algo not in self.OBFUSCATION_ALGORITHMS
  104.  
  105.  
  106.  
  107. class OCFReader(OCF):
  108.     
  109.     def __init__(self):
  110.         
  111.         try:
  112.             mimetype = self.open('mimetype').read().rstrip()
  113.             if mimetype != OCF.MIMETYPE:
  114.                 print 'WARNING: Invalid mimetype declaration', mimetype
  115.         except:
  116.             print "WARNING: Epub doesn't contain a mimetype declaration"
  117.  
  118.         
  119.         try:
  120.             
  121.             try:
  122.                 f = _[1]
  123.                 self.container = Container(f)
  124.             finally:
  125.                 pass
  126.  
  127.         except KeyError:
  128.             raise EPubException('missing OCF container.xml file')
  129.  
  130.         self.opf_path = self.container[OPF.MIMETYPE]
  131.         
  132.         try:
  133.             
  134.             try:
  135.                 f = _[2]
  136.                 self.opf = OPF(f, self.root, populate_spine = False)
  137.             finally:
  138.                 pass
  139.  
  140.         except KeyError:
  141.             raise EPubException('missing OPF package file')
  142.  
  143.         
  144.         try:
  145.             
  146.             try:
  147.                 f = _[3]
  148.                 self.encryption_meta = Encryption(f.read())
  149.             finally:
  150.                 pass
  151.  
  152.         except:
  153.             self.encryption_meta = Encryption(None)
  154.  
  155.  
  156.  
  157.  
  158. class OCFZipReader(OCFReader):
  159.     
  160.     def __init__(self, stream, mode = 'r', root = None):
  161.         
  162.         try:
  163.             self.archive = ZipFile(stream, mode = mode)
  164.         except BadZipfile:
  165.             raise EPubException('not a ZIP .epub OCF container')
  166.  
  167.         self.root = root
  168.         if self.root is None:
  169.             self.root = os.getcwdu()
  170.             if hasattr(stream, 'name'):
  171.                 self.root = os.path.abspath(os.path.dirname(stream.name))
  172.             
  173.         
  174.         super(OCFZipReader, self).__init__()
  175.  
  176.     
  177.     def open(self, name, mode = 'r'):
  178.         return StringIO(self.archive.read(name))
  179.  
  180.  
  181.  
  182. class OCFDirReader(OCFReader):
  183.     
  184.     def __init__(self, path):
  185.         self.root = path
  186.         super(OCFDirReader, self).__init__()
  187.  
  188.     
  189.     def open(self, path, *args, **kwargs):
  190.         return open(os.path.join(self.root, path), *args, **kwargs)
  191.  
  192.  
  193.  
  194. def get_cover(opf, opf_path, stream, reader = None):
  195.     render_html_svg_workaround = render_html_svg_workaround
  196.     import calibre.ebooks
  197.     default_log = default_log
  198.     import calibre.utils.logging
  199.     raster_cover = opf.raster_cover
  200.     stream.seek(0)
  201.     zf = ZipFile(stream)
  202.     if raster_cover:
  203.         base = posixpath.dirname(opf_path)
  204.         cpath = posixpath.normpath(posixpath.join(base, raster_cover))
  205.         if reader is not None and reader.encryption_meta.is_encrypted(cpath):
  206.             return None
  207.         
  208.         try:
  209.             member = zf.getinfo(cpath)
  210.         except:
  211.             reader.encryption_meta.is_encrypted(cpath)
  212.  
  213.         f = zf.open(member)
  214.         data = f.read()
  215.         f.close()
  216.         zf.close()
  217.         return data
  218.     raster_cover
  219.     cpage = opf.first_spine_item()
  220.     if not cpage:
  221.         return None
  222.     if reader is not None and reader.encryption_meta.is_encrypted(cpage):
  223.         return None
  224.     
  225.     try:
  226.         tdir = _[1]
  227.         CurrentDir(tdir).__enter__()
  228.         
  229.         try:
  230.             zf.extractall()
  231.             opf_path = opf_path.replace('/', os.sep)
  232.             cpage = os.path.join(tdir, os.path.dirname(opf_path), cpage)
  233.             if not os.path.exists(cpage):
  234.                 return None
  235.             return render_html_svg_workaround(cpage, default_log)
  236.         finally:
  237.             pass
  238.  
  239.     finally:
  240.         pass
  241.  
  242.  
  243.  
  244. def get_metadata(stream, extract_cover = True):
  245.     stream.seek(0)
  246.     reader = OCFZipReader(stream)
  247.     mi = MetaInformation(reader.opf)
  248.     if extract_cover:
  249.         
  250.         try:
  251.             cdata = get_cover(reader.opf, reader.opf_path, stream, reader = reader)
  252.             if cdata is not None:
  253.                 mi.cover_data = ('jpg', cdata)
  254.         import traceback
  255.         traceback.print_exc()
  256.  
  257.     
  258.     return mi
  259.  
  260.  
  261. def get_quick_metadata(stream):
  262.     return get_metadata(stream, False)
  263.  
  264.  
  265. def set_metadata(stream, mi, apply_null = False, update_timestamp = False):
  266.     stream.seek(0)
  267.     reader = OCFZipReader(stream, root = os.getcwdu())
  268.     raster_cover = reader.opf.raster_cover
  269.     mi = MetaInformation(mi)
  270.     new_cdata = None
  271.     replacements = { }
  272.     
  273.     try:
  274.         new_cdata = mi.cover_data[1]
  275.         if not new_cdata:
  276.             raise Exception('no cover')
  277.         new_cdata
  278.     except:
  279.         
  280.         try:
  281.             new_cdata = open(mi.cover, 'rb').read()
  282.         import traceback
  283.         traceback.print_exc()
  284.  
  285.  
  286.     if new_cdata and raster_cover:
  287.         
  288.         try:
  289.             cpath = posixpath.join(posixpath.dirname(reader.opf_path), raster_cover)
  290.             if not reader.encryption_meta.is_encrypted(cpath):
  291.                 pass
  292.             cover_replacable = os.path.splitext(cpath)[1].lower() in ('.png', '.jpg', '.jpeg')
  293.             if cover_replacable:
  294.                 save_cover_data_to = save_cover_data_to
  295.                 identify = identify
  296.                 import calibre.utils.magick.draw
  297.                 new_cover = PersistentTemporaryFile(suffix = os.path.splitext(cpath)[1])
  298.                 resize_to = None
  299.                 if False:
  300.                     shutil.copyfileobj(reader.open(cpath), new_cover)
  301.                     new_cover.close()
  302.                     (width, height, fmt) = identify(new_cover.name)
  303.                     resize_to = (width, height)
  304.                 else:
  305.                     new_cover.close()
  306.                 save_cover_data_to(new_cdata, new_cover.name, resize_to = resize_to)
  307.                 replacements[cpath] = open(new_cover.name, 'rb')
  308.         import traceback
  309.         traceback.print_exc()
  310.  
  311.     
  312.     for x in ('guide', 'toc', 'manifest', 'spine'):
  313.         setattr(mi, x, None)
  314.     
  315.     reader.opf.smart_update(mi)
  316.     if apply_null:
  317.         if not getattr(mi, 'series', None):
  318.             reader.opf.series = None
  319.         
  320.         if not getattr(mi, 'tags', []):
  321.             reader.opf.tags = []
  322.         
  323.         if not getattr(mi, 'isbn', None):
  324.             reader.opf.isbn = None
  325.         
  326.     
  327.     if update_timestamp and mi.timestamp is not None:
  328.         reader.opf.timestamp = mi.timestamp
  329.     
  330.     newopf = StringIO(reader.opf.render())
  331.     safe_replace(stream, reader.container[OPF.MIMETYPE], newopf, extra_replacements = replacements)
  332.  
  333.