Zip output works with non-internet-archive epubs (thanks Jan Gerber)
[objavi2.git] / booki-twiki-gateway.cgi
blobd6c2a355caaa1dfa129b772c62fe10b4b4502696
1 #!/usr/bin/python
3 # Part of Objavi2, which turns html manuals into books. This emulates
4 # the Booki-epub-Espri interface for old TWiki books.
6 # Copyright (C) 2009 Douglas Bagnall
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License along
19 # with this program; if not, write to the Free Software Foundation, Inc.,
20 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 import os, sys
23 import re, time, traceback
24 from pprint import pformat
26 from objavi.twiki_wrapper import TWikiBook, get_chapter_html, get_book_list
27 from objavi.cgi_utils import parse_args, optionise, shift_file, output_blob_and_exit, log, make_book_name
28 from objavi import config
30 from booki.xhtml_utils import EpubChapter
31 from booki.bookizip import BookiZip
34 def make_booki_package(server, bookid, clean=False, use_cache=False):
35 """Extract all chapters from the specified book, as well as
36 associated images and metadata, and zip it all up for conversion
37 to epub.
39 If clean is True, the chapters will be cleaned up and converted to
40 XHTML 1.1. If cache is true, images that have been fetched on
41 previous runs will be reused.
42 """
43 if clean:
44 bookname = make_book_name(bookid, server, '-clean.zip')
45 else:
46 bookname = make_book_name(bookid, server, '.zip')
48 book = TWikiBook(bookid, server, bookname)
49 zfn = book.filepath(bookname)
50 md = book.get_twiki_metadata()
51 log(pformat(md))
52 bz = BookiZip(zfn, md)
54 all_images = set()
55 for chapter in bz.info['spine']:
56 contents = get_chapter_html(server, bookid, chapter, wrapped=True)
57 c = EpubChapter(server, bookid, chapter, contents,
58 use_cache=use_cache)
59 images = c.localise_links()
60 all_images.update(images)
61 if clean:
62 c.remove_bad_tags()
63 bz.add_to_package(chapter, chapter + '.xhtml', c.as_xhtml())
64 else:
65 bz.add_to_package(chapter, chapter + '.html', c.as_html())
67 # Add images afterwards, to sift out duplicates
68 for image in all_images:
69 imgdata = c.image_cache.read_local_url(image)
70 bz.add_to_package(image, image, imgdata)
72 bz.finish()
73 return bz.filename
76 # ARG_VALIDATORS is a mapping between the expected cgi arguments and
77 # functions to validate their values. (None means no validation).
78 ARG_VALIDATORS = {
79 "book": re.compile(r'^(\w+/?)*\w+$').match, # can be: BlahBlah/Blah_Blah
80 "server": config.SERVER_DEFAULTS.__contains__,
81 "use-cache": None,
82 "clean": None,
83 'mode': ('zip', 'html').__contains__,
84 "all": ['all', 'skip-existing'].__contains__,
87 if __name__ == '__main__':
89 args = parse_args(ARG_VALIDATORS)
90 clean = bool(args.get('clean', False))
91 use_cache = args.get('use-cache')
92 if use_cache is None:
93 use_cache = (os.environ.get('HTTP_HOST') in config.USE_IMG_CACHE_ALWAYS_HOSTS)
95 make_all = args.get('all')
96 if 'server' in args and 'book' in args:
97 zfn = make_booki_package(args['server'], args['book'], clean, use_cache)
98 fn = shift_file(zfn, config.BOOKI_BOOK_DIR)
99 ziplink = '<p><a href="%s">%s zip file.</a></p>' % (fn, args['book'])
101 mode = args.get('mode', 'html')
102 if mode == 'zip':
103 f = open(fn)
104 data = f.read()
105 f.close()
106 output_blob_and_exit(data, 'application/x-booki+zip', args['book'] + '.zip')
108 elif 'server' in args and make_all is not None:
109 links = []
110 for book in get_book_list(args['server']):
111 if make_all == 'skip-existing' and book + '.zip' in os.listdir(config.BOOKI_BOOK_DIR):
112 log("skipping %s" % book)
113 continue
114 try:
115 zfn = make_booki_package(args['server'], book, use_cache=use_cache)
116 fn = shift_file(zfn, config.BOOKI_BOOK_DIR)
117 links.append('<a href="%s">%s</a> ' % (fn, book))
118 except Exception:
119 log('FAILED to make book "%s"' % book)
120 traceback.print_exc()
121 ziplink = ''.join(links)
122 else:
123 ziplink = ''
125 print "Content-type: text/html; charset=utf-8\n"
126 f = open('templates/booki-twiki-gateway.html')
127 template = f.read()
128 f.close()
130 print template % {'ziplink': ziplink,
131 'server-list': optionise(sorted(config.SERVER_DEFAULTS.keys()))}