openmedialibrary/oml/item/handlers.py

129 lines
4.5 KiB
Python
Raw Normal View History

2014-05-20 00:50:41 +02:00
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
2014-09-03 00:32:44 +02:00
2014-05-20 00:50:41 +02:00
2014-08-12 10:16:57 +02:00
from datetime import datetime
import mimetypes
2014-05-20 00:50:41 +02:00
import os
2014-10-31 12:48:20 +01:00
from urllib.request import quote
2014-05-20 00:50:41 +02:00
import zipfile
2014-09-03 00:32:44 +02:00
from .models import Item
2014-08-09 18:33:59 +02:00
import db
2014-08-12 10:16:57 +02:00
import settings
import tornado.web
2014-05-20 00:50:41 +02:00
class OMLHandler(tornado.web.RequestHandler):
2014-08-09 18:33:59 +02:00
def initialize(self):
pass
2014-05-20 00:50:41 +02:00
class EpubHandler(OMLHandler):
def get(self, id, filename):
2014-08-09 18:33:59 +02:00
with db.session():
2014-05-20 00:50:41 +02:00
item = Item.get(id)
path = item.get_path()
if not item or item.info['extension'] != 'epub' or not path:
self.set_status(404)
self.write('')
else:
z = zipfile.ZipFile(path)
if filename == '':
self.write('<br>\n'.join([f.filename for f in z.filelist]))
elif filename not in [f.filename for f in z.filelist]:
self.set_status(404)
self.write('')
else:
content_type = {
'xpgt': 'application/vnd.adobe-page-template+xml'
}.get(filename.split('.')[0], mimetypes.guess_type(filename)[0]) or 'text/plain'
self.set_header('Content-Type', content_type)
self.write(z.read(filename))
2014-10-31 12:48:20 +01:00
def serve_static(handler, path, mimetype, include_body=True, disposition=None):
2014-05-20 00:50:41 +02:00
handler.set_header('Content-Type', mimetype)
2015-02-22 16:38:06 +05:30
size = os.stat(path).st_size
handler.set_header('Accept-Ranges', 'bytes')
2014-10-31 12:48:20 +01:00
if disposition:
handler.set_header('Content-Disposition', "attachment; filename*=UTF-8''%s" % quote(disposition.encode('utf-8')))
2014-05-25 22:32:00 +02:00
if include_body:
2015-02-22 16:38:06 +05:30
if 'Range' in handler.request.headers:
handler.set_status(206)
r = handler.request.headers.get('Range').split('=')[-1].split('-')
start = int(r[0])
end = int(r[1]) if r[1] else size
2015-02-22 17:38:58 +05:30
length = end - start + 1
2015-02-22 16:38:06 +05:30
handler.set_header('Content-Length', str(length))
2015-02-22 17:38:58 +05:30
handler.set_header('Content-Range', 'bytes %s-%s/%s' % (start, end, size))
2015-02-22 16:38:06 +05:30
with open(path, 'rb') as fd:
fd.seek(start)
handler.write(fd.read(length))
else:
handler.set_header('Content-Length', str(size))
with open(path, 'rb') as fd:
handler.write(fd.read())
else:
handler.set_header('Content-Length', str(size))
2014-05-20 00:50:41 +02:00
return
class FileHandler(OMLHandler):
2014-12-13 21:01:54 +01:00
def initialize(self, attachment=False):
self._attachment = attachment
2014-05-25 22:32:00 +02:00
def head(self, id):
self.get(id, include_body=False)
def get(self, id, include_body=True):
2014-08-09 18:33:59 +02:00
with db.session():
2014-05-20 00:50:41 +02:00
item = Item.get(id)
2014-05-25 22:32:00 +02:00
path = item.get_path() if item else None
if not item or not path:
2014-05-20 00:50:41 +02:00
self.set_status(404)
return
mimetype = {
2015-03-14 13:05:15 +05:30
'cbr': 'application/x-cbr',
'cbz': 'application/x-cbz',
2014-05-20 00:50:41 +02:00
'epub': 'application/epub+zip',
'pdf': 'application/pdf',
2014-05-22 01:06:08 +02:00
'txt': 'text/plain',
2014-05-20 00:50:41 +02:00
}.get(path.split('.')[-1], None)
if mimetype == 'text/plain':
try:
open(path, 'rb').read().decode('utf-8')
mimetype = 'text/plain; charset=utf-8'
except:
mimetype = 'text/plain; charset=latin-1'
2014-12-13 21:01:54 +01:00
if self._attachment:
disposition = os.path.basename(path)
else:
disposition = None
return serve_static(self, path, mimetype, include_body, disposition=disposition)
2014-05-20 00:50:41 +02:00
class ReaderHandler(OMLHandler):
def get(self, id):
2014-08-09 18:33:59 +02:00
with db.session():
2014-05-20 00:50:41 +02:00
item = Item.get(id)
if not item:
self.set_status(404)
return
2015-03-14 13:05:15 +05:30
if item.info['extension'] in ('cbr', 'cbz'):
html = 'html/cbr.html'
elif item.info['extension'] == 'epub':
2014-05-20 00:50:41 +02:00
html = 'html/epub.html'
elif item.info['extension'] == 'pdf':
html = 'html/pdf.html'
elif item.info['extension'] == 'txt':
html = 'html/txt.html'
else:
self.set_status(404)
return
item.accessed = datetime.utcnow()
item.timesaccessed = (item.timesaccessed or 0) + 1
item.update_sort()
2014-05-20 00:50:41 +02:00
item.save()
return serve_static(self, os.path.join(settings.static_path, html), 'text/html')