mirror of
https://github.com/kovidgoyal/calibre.git
synced 2026-05-30 18:45:20 -04:00
Use rooted paths for served local files
This commit is contained in:
@@ -44,7 +44,7 @@ from calibre.gui2.viewer import link_prefix_for_location_links, performance_moni
|
||||
from calibre.gui2.viewer.config import get_session_pref, load_viewer_profiles, save_viewer_profile, viewer_config_dir, vprefs
|
||||
from calibre.gui2.viewer.tts import TTS
|
||||
from calibre.srv.code import get_translations_data
|
||||
from calibre.utils.filenames import make_long_path_useable
|
||||
from calibre.utils.filenames import make_long_path_useable, path_from_root
|
||||
from calibre.utils.localization import _, localize_user_manual_link
|
||||
from calibre.utils.resources import get_path as P
|
||||
from calibre.utils.serialize import json_loads
|
||||
@@ -74,9 +74,10 @@ def get_path_for_name(name):
|
||||
bdir = getattr(set_book_path, 'path', None)
|
||||
if bdir is None:
|
||||
return
|
||||
path = os.path.abspath(os.path.join(bdir, name))
|
||||
if path.startswith(bdir):
|
||||
return path
|
||||
try:
|
||||
return path_from_root(bdir, name)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
def get_data(name):
|
||||
@@ -103,12 +104,12 @@ def background_image(encoded_fname=''):
|
||||
return mt, data
|
||||
except FileNotFoundError:
|
||||
return 'image/jpeg', b''
|
||||
fname = bytes.fromhex(encoded_fname).decode()
|
||||
base = os.path.abspath(os.path.join(viewer_config_dir, 'background-images')) + os.sep
|
||||
img_path = os.path.abspath(os.path.join(base, fname))
|
||||
try:
|
||||
fname = bytes.fromhex(encoded_fname).decode('utf-8')
|
||||
img_path = path_from_root(os.path.abspath(os.path.join(viewer_config_dir, 'background-images')), fname, reject_colon=True)
|
||||
except (ValueError, UnicodeDecodeError):
|
||||
return 'image/jpeg', b''
|
||||
mt = guess_type(fname)[0] or 'image/jpeg'
|
||||
if not img_path.startswith(base):
|
||||
return mt, b''
|
||||
try:
|
||||
with open(make_long_path_useable(img_path), 'rb') as f:
|
||||
return mt, f.read()
|
||||
@@ -123,8 +124,12 @@ def get_mathjax_dir():
|
||||
|
||||
def handle_mathjax_request(rq, name):
|
||||
mathjax_dir = get_mathjax_dir()
|
||||
path = os.path.abspath(os.path.join(mathjax_dir, '..', name))
|
||||
if path.startswith(mathjax_dir):
|
||||
mathjax_name = name.partition('/')[2]
|
||||
try:
|
||||
path = path_from_root(mathjax_dir, mathjax_name)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
mt = guess_type(name)
|
||||
try:
|
||||
with open(path, 'rb') as f:
|
||||
@@ -136,9 +141,9 @@ def handle_mathjax_request(rq, name):
|
||||
if name.endswith('/startup.js'):
|
||||
raw = P('pdf-mathjax-loader.js', data=True, allow_user_override=False) + raw
|
||||
send_reply(rq, mt, raw)
|
||||
else:
|
||||
prints(f'Failed to get mathjax file: {name} outside mathjax directory', file=sys.stderr)
|
||||
rq.fail(QWebEngineUrlRequestJob.Error.RequestFailed)
|
||||
return
|
||||
prints(f'Failed to get mathjax file: {name} outside mathjax directory', file=sys.stderr)
|
||||
rq.fail(QWebEngineUrlRequestJob.Error.RequestFailed)
|
||||
|
||||
|
||||
class UrlSchemeHandler(QWebEngineUrlSchemeHandler):
|
||||
|
||||
@@ -20,7 +20,7 @@ from calibre.srv.metadata import book_as_json
|
||||
from calibre.srv.render_book import RENDER_VERSION
|
||||
from calibre.srv.routes import endpoint, json
|
||||
from calibre.srv.utils import get_db, get_library_data
|
||||
from calibre.utils.filenames import rmtree
|
||||
from calibre.utils.filenames import path_from_root, rmtree
|
||||
from calibre.utils.localization import _
|
||||
from calibre.utils.resources import get_path as P
|
||||
from calibre.utils.serialize import json_dumps
|
||||
@@ -187,9 +187,10 @@ def book_file(ctx, rd, book_id, fmt, size, mtime, name):
|
||||
if not ctx.has_id(rd, db, book_id):
|
||||
raise BookNotFound(book_id, db)
|
||||
bhash = book_hash(db.library_id, book_id, fmt, size, mtime)
|
||||
base = abspath(os.path.join(books_cache_dir(), 'f'))
|
||||
mpath = abspath(os.path.join(base, bhash, name))
|
||||
if not mpath.startswith(base):
|
||||
base = abspath(os.path.join(books_cache_dir(), 'f', bhash))
|
||||
try:
|
||||
mpath = path_from_root(base, name)
|
||||
except ValueError:
|
||||
raise HTTPNotFound(f'No book file with hash: {bhash} and name: {name}')
|
||||
try:
|
||||
return rd.filesystem_file_with_custom_etag(open(mpath, 'rb'), bhash, name)
|
||||
|
||||
+13
-14
@@ -31,7 +31,7 @@ from calibre.srv.routes import endpoint, json
|
||||
from calibre.srv.utils import get_db, get_use_roman, http_date
|
||||
from calibre.utils.config_base import tweaks
|
||||
from calibre.utils.date import timestampfromdt
|
||||
from calibre.utils.filenames import ascii_filename, atomic_rename, make_long_path_useable
|
||||
from calibre.utils.filenames import ascii_filename, atomic_rename, make_long_path_useable, path_from_root
|
||||
from calibre.utils.img import image_from_data, scale_image
|
||||
from calibre.utils.localization import _
|
||||
from calibre.utils.resources import get_image_path as I
|
||||
@@ -236,11 +236,10 @@ def static(ctx, rd, what):
|
||||
if not what:
|
||||
raise HTTPNotFound()
|
||||
base = P('content-server', allow_user_override=False)
|
||||
path = os.path.abspath(os.path.join(base, *what.split('/')))
|
||||
if not path.startswith(base) or ':' in what:
|
||||
try:
|
||||
path = path_from_root(base, what, reject_colon=True)
|
||||
except ValueError:
|
||||
raise HTTPNotFound('Naughty, naughty!')
|
||||
path = os.path.relpath(path, base).replace(os.sep, '/')
|
||||
path = P('content-server/' + path)
|
||||
try:
|
||||
return share_open(path, 'rb')
|
||||
except OSError:
|
||||
@@ -269,16 +268,16 @@ def icon(ctx, rd, which):
|
||||
raise HTTPNotFound()
|
||||
if which.startswith('_'):
|
||||
base = os.path.join(config_dir, 'tb_icons')
|
||||
path = os.path.abspath(os.path.join(base, *which[1:].split('/')))
|
||||
if not path.startswith(base) or ':' in which:
|
||||
try:
|
||||
path = path_from_root(base, which[1:], reject_colon=True)
|
||||
except ValueError:
|
||||
raise HTTPNotFound('Naughty, naughty!')
|
||||
else:
|
||||
base = P('images', allow_user_override=False)
|
||||
path = os.path.abspath(os.path.join(base, *which.split('/')))
|
||||
if not path.startswith(base) or ':' in which:
|
||||
try:
|
||||
path = path_from_root(base, which, reject_colon=True)
|
||||
except ValueError:
|
||||
raise HTTPNotFound('Naughty, naughty!')
|
||||
path = os.path.relpath(path, base).replace(os.sep, '/')
|
||||
path = P('images/' + path)
|
||||
if sz == 'full':
|
||||
try:
|
||||
return share_open(path, 'rb')
|
||||
@@ -309,9 +308,9 @@ def icon(ctx, rd, which):
|
||||
@endpoint('/reader-background/{encoded_fname}', android_workaround=True)
|
||||
def reader_background(ctx, rd, encoded_fname):
|
||||
base = os.path.abspath(os.path.normpath(os.path.join(config_dir, 'viewer', 'background-images')))
|
||||
fname = bytes.fromhex(encoded_fname)
|
||||
q = os.path.abspath(os.path.normpath(os.path.join(base, fname)))
|
||||
if not q.startswith(base):
|
||||
try:
|
||||
q = path_from_root(base, bytes.fromhex(encoded_fname).decode('utf-8'), reject_colon=True)
|
||||
except (ValueError, UnicodeDecodeError):
|
||||
raise HTTPNotFound(f'Reader background {encoded_fname} not found')
|
||||
try:
|
||||
return share_open(make_long_path_useable(q), 'rb')
|
||||
|
||||
Reference in New Issue
Block a user