mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-04-24 14:27:41 +00:00
Validate section names more strictly
This avoids any problems with status files
This commit is contained in:
parent
ddc47c2272
commit
d9e4a5b767
2 changed files with 30 additions and 0 deletions
|
|
@ -11,6 +11,8 @@ from textwrap import dedent
|
||||||
|
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import vdirsyncer.cli as cli
|
import vdirsyncer.cli as cli
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -228,3 +230,17 @@ def test_verbosity(tmpdir):
|
||||||
)
|
)
|
||||||
assert result.exception
|
assert result.exception
|
||||||
assert 'invalid verbosity value' in result.output.lower()
|
assert 'invalid verbosity value' in result.output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_storage_name():
|
||||||
|
f = io.StringIO(dedent(u'''
|
||||||
|
[general]
|
||||||
|
status_path = /tmp/status/
|
||||||
|
|
||||||
|
[storage foo.bar]
|
||||||
|
'''))
|
||||||
|
|
||||||
|
with pytest.raises(cli.CliError) as excinfo:
|
||||||
|
cli.load_config(f)
|
||||||
|
|
||||||
|
assert 'invalid characters' in str(excinfo.value).lower()
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ import errno
|
||||||
import functools
|
import functools
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import string
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
from . import DOCS_HOME, PROJECT_HOME, __version__, log
|
from . import DOCS_HOME, PROJECT_HOME, __version__, log
|
||||||
from .doubleclick import click
|
from .doubleclick import click
|
||||||
|
|
@ -37,6 +39,7 @@ cli_logger = log.get(__name__)
|
||||||
|
|
||||||
GENERAL_ALL = frozenset(['status_path', 'passwordeval'])
|
GENERAL_ALL = frozenset(['status_path', 'passwordeval'])
|
||||||
GENERAL_REQUIRED = frozenset(['status_path'])
|
GENERAL_REQUIRED = frozenset(['status_path'])
|
||||||
|
SECTION_NAME_CHARS = frozenset(chain(string.ascii_letters, string.digits, '_'))
|
||||||
|
|
||||||
|
|
||||||
class CliError(RuntimeError):
|
class CliError(RuntimeError):
|
||||||
|
|
@ -47,6 +50,15 @@ class JobFailed(RuntimeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def validate_section_name(name, section_type):
|
||||||
|
invalid = set(name) - SECTION_NAME_CHARS
|
||||||
|
if invalid:
|
||||||
|
raise CliError('The {}-section {!r} contains invalid characters. Only '
|
||||||
|
'the following characters are allowed for storage and '
|
||||||
|
'pair names:\n{}'.format(section_type, name,
|
||||||
|
SECTION_NAME_CHARS))
|
||||||
|
|
||||||
|
|
||||||
def get_status_name(pair, collection):
|
def get_status_name(pair, collection):
|
||||||
if collection is None:
|
if collection is None:
|
||||||
return pair
|
return pair
|
||||||
|
|
@ -86,10 +98,12 @@ def load_config(f, pair_options=('collections', 'conflict_resolution')):
|
||||||
storages = {}
|
storages = {}
|
||||||
|
|
||||||
def handle_storage(storage_name, options):
|
def handle_storage(storage_name, options):
|
||||||
|
validate_section_name(storage_name, 'storage')
|
||||||
storages.setdefault(storage_name, {}).update(options)
|
storages.setdefault(storage_name, {}).update(options)
|
||||||
storages[storage_name]['instance_name'] = storage_name
|
storages[storage_name]['instance_name'] = storage_name
|
||||||
|
|
||||||
def handle_pair(pair_name, options):
|
def handle_pair(pair_name, options):
|
||||||
|
validate_section_name(pair_name, 'pair')
|
||||||
a, b = options.pop('a'), options.pop('b')
|
a, b = options.pop('a'), options.pop('b')
|
||||||
p, s = split_dict(options, lambda x: x in pair_options)
|
p, s = split_dict(options, lambda x: x in pair_options)
|
||||||
pairs[pair_name] = a, b, p, s
|
pairs[pair_name] = a, b, p, s
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue