mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Content server OPDS: Handle form encoded search queries. Fixes #1841464 [calibre server search by URL with multiple words not working](https://bugs.launchpad.net/calibre/+bug/1841464)
This commit is contained in:
parent
8d96d125e8
commit
f8f464efc0
@ -66,7 +66,7 @@ def parse_request_uri(uri):
|
|||||||
return None, uri, None
|
return None, uri, None
|
||||||
|
|
||||||
|
|
||||||
def parse_uri(uri, parse_query=True):
|
def parse_uri(uri, parse_query=True, unquote_func=unquote):
|
||||||
scheme, authority, path = parse_request_uri(uri)
|
scheme, authority, path = parse_request_uri(uri)
|
||||||
if path is None:
|
if path is None:
|
||||||
raise HTTPSimpleResponse(http_client.BAD_REQUEST, "No path component")
|
raise HTTPSimpleResponse(http_client.BAD_REQUEST, "No path component")
|
||||||
@ -89,7 +89,7 @@ def parse_uri(uri, parse_query=True):
|
|||||||
query = None
|
query = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
path = '%2F'.join(unquote(x).decode('utf-8') for x in quoted_slash.split(path))
|
path = '%2F'.join(unquote_func(x).decode('utf-8') for x in quoted_slash.split(path))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise HTTPSimpleResponse(http_client.BAD_REQUEST, as_unicode(e))
|
raise HTTPSimpleResponse(http_client.BAD_REQUEST, as_unicode(e))
|
||||||
path = tuple(filter(None, (x.replace('%2F', '/') for x in path.split('/'))))
|
path = tuple(filter(None, (x.replace('%2F', '/') for x in path.split('/'))))
|
||||||
@ -212,6 +212,7 @@ class HTTPRequest(Connection):
|
|||||||
self.max_header_line_size = int(1024 * self.opts.max_header_line_size)
|
self.max_header_line_size = int(1024 * self.opts.max_header_line_size)
|
||||||
self.max_request_body_size = int(1024 * 1024 * self.opts.max_request_body_size)
|
self.max_request_body_size = int(1024 * 1024 * self.opts.max_request_body_size)
|
||||||
self.forwarded_for = None
|
self.forwarded_for = None
|
||||||
|
self.request_original_uri = None
|
||||||
|
|
||||||
def read(self, buf, endpos):
|
def read(self, buf, endpos):
|
||||||
size = endpos - buf.tell()
|
size = endpos - buf.tell()
|
||||||
@ -279,6 +280,7 @@ class HTTPRequest(Connection):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
return self.simple_response(http_client.HTTP_VERSION_NOT_SUPPORTED)
|
return self.simple_response(http_client.HTTP_VERSION_NOT_SUPPORTED)
|
||||||
self.response_protocol = protocol_map[min((1, 1), rp)]
|
self.response_protocol = protocol_map[min((1, 1), rp)]
|
||||||
|
self.request_original_uri = uri
|
||||||
try:
|
try:
|
||||||
self.scheme, self.path, self.query = parse_uri(uri)
|
self.scheme, self.path, self.query = parse_uri(uri)
|
||||||
except HTTPSimpleResponse as e:
|
except HTTPSimpleResponse as e:
|
||||||
|
@ -219,15 +219,18 @@ class RequestData(object): # {{{
|
|||||||
username = None
|
username = None
|
||||||
|
|
||||||
def __init__(self, method, path, query, inheaders, request_body_file, outheaders, response_protocol,
|
def __init__(self, method, path, query, inheaders, request_body_file, outheaders, response_protocol,
|
||||||
static_cache, opts, remote_addr, remote_port, is_local_connection, translator_cache, tdir, forwarded_for):
|
static_cache, opts, remote_addr, remote_port, is_local_connection, translator_cache,
|
||||||
|
tdir, forwarded_for, request_original_uri=None):
|
||||||
|
|
||||||
(self.method, self.path, self.query, self.inheaders, self.request_body_file, self.outheaders,
|
(self.method, self.path, self.query, self.inheaders, self.request_body_file, self.outheaders,
|
||||||
self.response_protocol, self.static_cache, self.translator_cache) = (
|
self.response_protocol, self.static_cache, self.translator_cache) = (
|
||||||
method, path, query, inheaders, request_body_file, outheaders,
|
method, path, query, inheaders, request_body_file, outheaders,
|
||||||
response_protocol, static_cache, translator_cache
|
response_protocol, static_cache, translator_cache
|
||||||
)
|
)
|
||||||
|
|
||||||
self.remote_addr, self.remote_port, self.is_local_connection = remote_addr, remote_port, is_local_connection
|
self.remote_addr, self.remote_port, self.is_local_connection = remote_addr, remote_port, is_local_connection
|
||||||
self.forwarded_for = forwarded_for
|
self.forwarded_for = forwarded_for
|
||||||
|
self.request_original_uri = request_original_uri
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
self.status_code = http_client.OK
|
self.status_code = http_client.OK
|
||||||
self.outcookie = Cookie()
|
self.outcookie = Cookie()
|
||||||
@ -444,7 +447,7 @@ class HTTPConnection(HTTPRequest):
|
|||||||
self.method, self.path, self.query, inheaders, request_body_file,
|
self.method, self.path, self.query, inheaders, request_body_file,
|
||||||
outheaders, self.response_protocol, self.static_cache, self.opts,
|
outheaders, self.response_protocol, self.static_cache, self.opts,
|
||||||
self.remote_addr, self.remote_port, self.is_local_connection,
|
self.remote_addr, self.remote_port, self.is_local_connection,
|
||||||
self.translator_cache, self.tdir, self.forwarded_for
|
self.translator_cache, self.tdir, self.forwarded_for, self.request_original_uri
|
||||||
)
|
)
|
||||||
self.queue_job(self.run_request_handler, data)
|
self.queue_job(self.run_request_handler, data)
|
||||||
|
|
||||||
|
@ -26,9 +26,10 @@ from calibre import force_unicode
|
|||||||
|
|
||||||
from calibre.srv.errors import HTTPNotFound, HTTPInternalServerError
|
from calibre.srv.errors import HTTPNotFound, HTTPInternalServerError
|
||||||
from calibre.srv.routes import endpoint
|
from calibre.srv.routes import endpoint
|
||||||
|
from calibre.srv.http_request import parse_uri
|
||||||
from calibre.srv.utils import get_library_data, http_date, Offsets
|
from calibre.srv.utils import get_library_data, http_date, Offsets
|
||||||
from polyglot.builtins import iteritems, unicode_type, filter, as_bytes
|
from polyglot.builtins import iteritems, unicode_type, filter, as_bytes
|
||||||
from polyglot.urllib import urlencode
|
from polyglot.urllib import urlencode, unquote_plus
|
||||||
from polyglot.binary import as_hex_unicode, from_hex_unicode
|
from polyglot.binary import as_hex_unicode, from_hex_unicode
|
||||||
|
|
||||||
|
|
||||||
@ -624,6 +625,11 @@ def opds_search(ctx, rd, query):
|
|||||||
raise HTTPNotFound('Not found')
|
raise HTTPNotFound('Not found')
|
||||||
|
|
||||||
rc = RequestContext(ctx, rd)
|
rc = RequestContext(ctx, rd)
|
||||||
|
if query:
|
||||||
|
path = parse_uri(rd.request_original_uri, parse_query=False, unquote_func=unquote_plus)[1]
|
||||||
|
query = path[-1]
|
||||||
|
if isinstance(query, bytes):
|
||||||
|
query = query.decode('utf-8')
|
||||||
try:
|
try:
|
||||||
ids = rc.search(query)
|
ids = rc.search(query)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -22,6 +22,7 @@ if is_py3:
|
|||||||
if binary:
|
if binary:
|
||||||
ans = ans.encode(encoding, errors)
|
ans = ans.encode(encoding, errors)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
else:
|
else:
|
||||||
from urllib import (getproxies, quote, unquote as uq, quote_plus, url2pathname, # noqa
|
from urllib import (getproxies, quote, unquote as uq, quote_plus, url2pathname, # noqa
|
||||||
urlencode) # noqa
|
urlencode) # noqa
|
||||||
@ -43,3 +44,9 @@ else:
|
|||||||
if not binary:
|
if not binary:
|
||||||
ans = ans.decode(encoding, errors)
|
ans = ans.decode(encoding, errors)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
def unquote_plus(x, encoding='utf-8', errors='replace'):
|
||||||
|
q, repl = (b'+', b' ') if isinstance(x, bytes) else ('+', ' ')
|
||||||
|
x = x.replace(q, repl)
|
||||||
|
return unquote(x, encoding=encoding, errors=errors)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user