home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_863 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  9.8 KB  |  251 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>, and Alex Bramley <a.bramley at gmail.com>.'
  7. import os
  8. import re
  9. from mimetypes import guess_type as guess_mimetype
  10. from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString
  11. from calibre.constants import iswindows, filesystem_encoding
  12. from calibre.utils.chm.chm import CHMFile
  13. from calibre.utils.chm.chmlib import CHM_RESOLVE_SUCCESS, CHM_ENUMERATE_NORMAL, chm_enumerate
  14. from calibre.utils.config import OptionParser
  15. from calibre.ebooks.metadata.toc import TOC
  16. from calibre.ebooks.chardet import xml_to_unicode
  17.  
  18. def match_string(s1, s2_already_lowered):
  19.     if s1 is not None and s2_already_lowered is not None:
  20.         if s1.lower() == s2_already_lowered:
  21.             return True
  22.     
  23.     return False
  24.  
  25.  
  26. def check_all_prev_empty(tag):
  27.     if tag is None:
  28.         return True
  29.     if tag.__class__ == NavigableString and not check_empty(tag):
  30.         return False
  31.     return check_all_prev_empty(tag.previousSibling)
  32.  
  33.  
  34. def check_empty(s, rex = re.compile('\\S')):
  35.     return rex.search(s) is None
  36.  
  37.  
  38. def option_parser():
  39.     parser = OptionParser(usage = _('%prog [options] mybook.chm'))
  40.     parser.add_option('--output-dir', '-d', default = '.', help = _('Output directory. Defaults to current directory'), dest = 'output')
  41.     parser.add_option('--verbose', default = False, action = 'store_true', dest = 'verbose')
  42.     parser.add_option('-t', '--title', action = 'store', type = 'string', dest = 'title', help = _('Set the book title'))
  43.     parser.add_option('--title-sort', action = 'store', type = 'string', default = None, dest = 'title_sort', help = _('Set sort key for the title'))
  44.     parser.add_option('-a', '--author', action = 'store', type = 'string', dest = 'author', help = _('Set the author'))
  45.     parser.add_option('--author-sort', action = 'store', type = 'string', default = None, dest = 'author_sort', help = _('Set sort key for the author'))
  46.     parser.add_option('-c', '--category', action = 'store', type = 'string', dest = 'category', help = _('The category this book belongs to. E.g.: History'))
  47.     parser.add_option('--thumbnail', action = 'store', type = 'string', dest = 'thumbnail', help = _("Path to a graphic that will be set as this files' thumbnail"))
  48.     parser.add_option('--comment', action = 'store', type = 'string', dest = 'freetext', help = _('Path to a txt file containing a comment.'))
  49.     parser.add_option('--get-thumbnail', action = 'store_true', dest = 'get_thumbnail', default = False, help = _('Extract thumbnail from LRF file'))
  50.     parser.add_option('--publisher', default = None, help = _('Set the publisher'))
  51.     parser.add_option('--classification', default = None, help = _('Set the book classification'))
  52.     parser.add_option('--creator', default = None, help = _('Set the book creator'))
  53.     parser.add_option('--producer', default = None, help = _('Set the book producer'))
  54.     parser.add_option('--get-cover', action = 'store_true', default = False, help = _('Extract cover from LRF file. Note that the LRF format has no defined cover, so we use some heuristics to guess the cover.'))
  55.     parser.add_option('--bookid', action = 'store', type = 'string', default = None, dest = 'book_id', help = _('Set book ID'))
  56.     parser.add_option('--font-delta', action = 'store', type = 'int', default = 0, dest = 'font_delta', help = _('Set font delta'))
  57.     return parser
  58.  
  59.  
  60. class CHMError(Exception):
  61.     pass
  62.  
  63.  
  64. class CHMReader(CHMFile):
  65.     
  66.     def __init__(self, input, log):
  67.         CHMFile.__init__(self)
  68.         if isinstance(input, unicode):
  69.             input = input.encode(filesystem_encoding)
  70.         
  71.         if not self.LoadCHM(input):
  72.             raise CHMError("Unable to open CHM file '%s'" % (input,))
  73.         self.LoadCHM(input)
  74.         self.log = log
  75.         self._sourcechm = input
  76.         self._contents = None
  77.         self._playorder = 0
  78.         self._metadata = False
  79.         self._extracted = False
  80.         (self.root, ext) = os.path.splitext(self.topics.lstrip('/'))
  81.         self.hhc_path = self.root + '.hhc'
  82.  
  83.     
  84.     def _parse_toc(self, ul, basedir = os.getcwdu()):
  85.         toc = TOC(play_order = self._playorder, base_path = basedir, text = '')
  86.         self._playorder += 1
  87.         for li in ul('li', recursive = False):
  88.             href = li.object('param', {
  89.                 'name': 'Local' })[0]['value']
  90.             if href.count('#'):
  91.                 (href, frag) = href.split('#')
  92.             else:
  93.                 frag = None
  94.             name = self._deentity(li.object('param', {
  95.                 'name': 'Name' })[0]['value'])
  96.             toc.add_item(href, frag, name, play_order = self._playorder)
  97.             self._playorder += 1
  98.             if li.ul:
  99.                 child = self._parse_toc(li.ul)
  100.                 child.parent = toc
  101.                 toc.append(child)
  102.                 continue
  103.             self
  104.         
  105.         return toc
  106.  
  107.     
  108.     def GetFile(self, path):
  109.         if path[0] != '/':
  110.             path = '/' + path
  111.         
  112.         (res, ui) = self.ResolveObject(path)
  113.         if res != CHM_RESOLVE_SUCCESS:
  114.             raise CHMError("Unable to locate '%s' within CHM file '%s'" % (path, self.filename))
  115.         res != CHM_RESOLVE_SUCCESS
  116.         (size, data) = self.RetrieveObject(ui)
  117.         if size == 0:
  118.             raise CHMError("'%s' is zero bytes in length!" % (path,))
  119.         size == 0
  120.         return data
  121.  
  122.     
  123.     def ExtractFiles(self, output_dir = os.getcwdu()):
  124.         for path in self.Contents():
  125.             lpath = os.path.join(output_dir, path)
  126.             self._ensure_dir(lpath)
  127.             data = self.GetFile(path)
  128.             if lpath.find(';') != -1:
  129.                 lpath = lpath.split(';')[0]
  130.             
  131.             
  132.             try:
  133.                 
  134.                 try:
  135.                     f = _[1]
  136.                     f.write(data)
  137.                 finally:
  138.                     pass
  139.  
  140.             continue
  141.             if iswindows and len(lpath) > 250:
  142.                 self.log.warn('%r filename too long, skipping' % path)
  143.                 continue
  144.             
  145.  
  146.             raise 
  147.         
  148.         self._extracted = True
  149.         files = os.listdir(output_dir)
  150.         if self.hhc_path not in files:
  151.             for f in files:
  152.                 if f.lower() == self.hhc_path.lower():
  153.                     self.hhc_path = f
  154.                     break
  155.                     continue
  156.             
  157.         
  158.         if self.hhc_path not in files and files:
  159.             self.hhc_path = files[0]
  160.         
  161.  
  162.     
  163.     def _reformat(self, data):
  164.         
  165.         try:
  166.             data = xml_to_unicode(data, strip_encoding_pats = True)[0]
  167.             soup = BeautifulSoup(data)
  168.         except ValueError:
  169.             self.log.exception('Unable to parse html for cleaning, leaving it')
  170.             return data
  171.  
  172.         [ s.extract() for s in soup('script') ]
  173.         t = soup('table')
  174.         if t:
  175.             if t[-1].nextSibling is None or t[-1].nextSibling.nextSibling is None:
  176.                 
  177.                 try:
  178.                     alt = t[-1].img['alt'].lower()
  179.                     if alt.find('prev') != -1 and alt.find('next') != -1 or alt.find('team') != -1:
  180.                         t[-1].extract()
  181.  
  182.             
  183.         
  184.         br = soup('br')
  185.         if br:
  186.             if check_all_prev_empty(br[0].previousSibling):
  187.                 br[0].extract()
  188.             
  189.         
  190.         for img in soup('img'):
  191.             
  192.             try:
  193.                 while img['src'].startswith('../'):
  194.                     img['src'] = img['src'][3:]
  195.                 img['src'] = img['src'].split(';')[0]
  196.             continue
  197.             except KeyError:
  198.                 continue
  199.             
  200.  
  201.         
  202.         
  203.         try:
  204.             tables = soup.body.findAll('table', recursive = False)
  205.             if tables and len(tables) == 1:
  206.                 trs = tables[0].findAll('tr', recursive = False)
  207.                 if trs and len(trs) == 1:
  208.                     tds = trs[0].findAll('td', recursive = False)
  209.                     if tds and len(tds) == 1:
  210.                         tdContents = tds[0].contents
  211.                         tableIdx = soup.body.contents.index(tables[0])
  212.                         tables[0].extract()
  213.                         while tdContents:
  214.                             soup.body.insert(tableIdx, tdContents.pop())
  215.                             continue
  216.                             None<EXCEPTION MATCH>KeyError
  217.                     
  218.                 
  219.         except:
  220.             None<EXCEPTION MATCH>KeyError
  221.  
  222.         return str(soup)
  223.  
  224.     
  225.     def Contents(self):
  226.         if self._contents is not None:
  227.             return self._contents
  228.         paths = []
  229.         
  230.         def get_paths(chm, ui, ctx):
  231.             if ui.path[-1] != '/':
  232.                 paths.append(ui.path.lstrip('/'))
  233.             
  234.  
  235.         chm_enumerate(self.file, CHM_ENUMERATE_NORMAL, get_paths, None)
  236.         self._contents = paths
  237.         return self._contents
  238.  
  239.     
  240.     def _ensure_dir(self, path):
  241.         dir = os.path.dirname(path)
  242.         if not os.path.isdir(dir):
  243.             os.makedirs(dir)
  244.         
  245.  
  246.     
  247.     def extract_content(self, output_dir = os.getcwdu()):
  248.         self.ExtractFiles(output_dir = output_dir)
  249.  
  250.  
  251.