new option for checking path/user value
This commit is contained in:
@@ -1617,6 +1617,33 @@ Strict preconditions check on PUT in case item already exists [RFC6352#9.2](http
|
||||
|
||||
Default: `False`
|
||||
|
||||
##### validate_user_value
|
||||
|
||||
_(>= 3.7.2)_
|
||||
|
||||
Validate user value content
|
||||
|
||||
Available types are:
|
||||
* `none`
|
||||
* `minimal` (control and some special chars)
|
||||
* `unicodeletter` (unicode letters)
|
||||
* `strict` (reduced ASCII set)
|
||||
|
||||
Default: `minimum`
|
||||
|
||||
##### validate_path_type
|
||||
|
||||
_(>= 3.7.2)_
|
||||
|
||||
Validate path value content
|
||||
|
||||
* `none`
|
||||
* `minimal` (control and some special chars)
|
||||
* `unicodeletter` (unicode letters)
|
||||
* `strict` (reduced ASCII set)
|
||||
|
||||
Default: `minimum`
|
||||
|
||||
##### hook
|
||||
|
||||
Command that is run after changes to storage. See the
|
||||
|
||||
8
config
8
config
@@ -58,6 +58,14 @@
|
||||
# script name to strip from URI if called by reverse proxy
|
||||
#script_name = (default taken from HTTP_X_SCRIPT_NAME or SCRIPT_NAME)
|
||||
|
||||
# validate user type
|
||||
# Value: none|minimal|unicodeletter|strict
|
||||
#validate_user_type = minimal
|
||||
|
||||
# validate path value
|
||||
# Value: none|minimal|unicodeletter|strict
|
||||
#validate_path_type = minimal
|
||||
|
||||
|
||||
[encoding]
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
|
||||
_profiling_per_request: bool = False
|
||||
_profiling_per_request_method: bool = False
|
||||
_limit_content: int
|
||||
_validate_user_value: str
|
||||
_validate_path_value: str
|
||||
profiler_per_request_method: dict[str, cProfile.Profile] = {}
|
||||
profiler_per_request_method_counter: dict[str, int] = {}
|
||||
profiler_per_request_method_starttime: datetime.datetime
|
||||
@@ -158,6 +160,11 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
|
||||
self._extra_headers[key] = configuration.get("headers", key)
|
||||
self._strict_preconditions = configuration.get("storage", "strict_preconditions")
|
||||
logger.info("strict preconditions check: %s", self._strict_preconditions)
|
||||
# Format checks
|
||||
self._validate_user_value = configuration.get("server", "validate_user_value")
|
||||
self._validate_path_value = configuration.get("server", "validate_path_value")
|
||||
logger.info("validate user value: %r", self._validate_user_value)
|
||||
logger.info("validate path value: %r", self._validate_path_value)
|
||||
# Profiling options
|
||||
self._profiling = configuration.get("logging", "profiling")
|
||||
self._profiling_per_request_min_duration = configuration.get("logging", "profiling_per_request_min_duration")
|
||||
|
||||
@@ -44,6 +44,8 @@ class ApplicationBase:
|
||||
_permit_delete_collection: bool
|
||||
_permit_overwrite_collection: bool
|
||||
_strict_preconditions: bool
|
||||
_validate_user_value: str
|
||||
_validate_path_format: str
|
||||
_hook: hook.BaseHook
|
||||
|
||||
def __init__(self, configuration: config.Configuration) -> None:
|
||||
@@ -58,6 +60,8 @@ class ApplicationBase:
|
||||
self._response_content_on_debug = configuration.get("logging", "response_content_on_debug")
|
||||
self._request_content_on_debug = configuration.get("logging", "request_content_on_debug")
|
||||
self._limit_content = configuration.get("logging", "limit_content")
|
||||
self._validate_user_value = configuration.get("server", "validate_user_value")
|
||||
self._validate_path_value = configuration.get("server", "validate_path_value")
|
||||
self._hook = hook.load(configuration)
|
||||
|
||||
def _read_xml_request_body(self, environ: types.WSGIEnviron
|
||||
|
||||
@@ -48,6 +48,8 @@ DEFAULT_CONFIG_PATH: str = os.pathsep.join([
|
||||
|
||||
PROFILING: Sequence[str] = ("per_request", "per_request_method", "none")
|
||||
|
||||
VALIDATE_TYPES: Sequence[str] = ("none", "minimal", "unicodeletter", "strict")
|
||||
|
||||
|
||||
def positive_int(value: Any) -> int:
|
||||
value = int(value)
|
||||
@@ -84,6 +86,12 @@ def logging_level(value: Any) -> str:
|
||||
return value
|
||||
|
||||
|
||||
def validate_types(value: Any) -> str:
|
||||
if value not in VALIDATE_TYPES:
|
||||
raise ValueError("unsupported validation type: %r" % value)
|
||||
return value
|
||||
|
||||
|
||||
def profiling(value: Any) -> str:
|
||||
if value not in PROFILING:
|
||||
raise ValueError("unsupported profiling: %r" % value)
|
||||
@@ -221,6 +229,14 @@ DEFAULT_CONFIG_SCHEMA: types.CONFIG_SCHEMA = OrderedDict([
|
||||
"value": "",
|
||||
"help": "script name to strip from URI if called by reverse proxy (default taken from HTTP_X_SCRIPT_NAME or SCRIPT_NAME)",
|
||||
"type": str}),
|
||||
("validate_user_value", {
|
||||
"value": "minimal",
|
||||
"help": "validate user value (" + "|".join(VALIDATE_TYPES) + ")",
|
||||
"type": validate_types}),
|
||||
("validate_path_value", {
|
||||
"value": "minimal",
|
||||
"help": "validate path value (" + "|".join(VALIDATE_TYPES) + ")",
|
||||
"type": validate_types}),
|
||||
("_internal_server", {
|
||||
"value": "False",
|
||||
"help": "the internal server is used",
|
||||
|
||||
@@ -29,6 +29,7 @@ from urllib.parse import parse_qs
|
||||
|
||||
from radicale import (config, httputils, pathutils, rights, storage, types,
|
||||
utils)
|
||||
from radicale.app.base import ApplicationBase
|
||||
from radicale.log import logger
|
||||
|
||||
INTERNAL_TYPES: Sequence[str] = ("csv", "files", "none")
|
||||
@@ -135,7 +136,7 @@ def load(configuration: "config.Configuration") -> "BaseSharing":
|
||||
return utils.load_plugin(INTERNAL_TYPES, "sharing", "Sharing", BaseSharing, configuration)
|
||||
|
||||
|
||||
class BaseSharing:
|
||||
class BaseSharing(ApplicationBase):
|
||||
|
||||
_storage: storage.BaseStorage
|
||||
_rights: rights.BaseRights
|
||||
@@ -157,6 +158,8 @@ class BaseSharing:
|
||||
self._rights = rights.load(configuration)
|
||||
self._storage = storage.load(configuration)
|
||||
self._auth_delay = configuration.get("auth", "delay")
|
||||
self._validate_user_value = configuration.get("server", "validate_user_value")
|
||||
self._validate_path_value = configuration.get("server", "validate_path_value")
|
||||
# Sharing
|
||||
self.sharing_collection_by_map = configuration.get("sharing", "collection_by_map")
|
||||
self.sharing_collection_by_token = configuration.get("sharing", "collection_by_token")
|
||||
|
||||
Reference in New Issue
Block a user