summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCalum Lind <calumlind+deluge@gmail.com>2019-12-13 11:21:51 +0000
committerCalum Lind <calumlind+deluge@gmail.com>2020-04-25 10:49:08 +0100
commit635f6d970dd83de53ccece2837f8eae72dfc832f (patch)
treec55c4c8371d893a21bdedb8d17bbc540dc45a9c4
parent672e3c42a8c8cf0a0298918500cb15ff26839f61 (diff)
downloaddeluge-635f6d970dd83de53ccece2837f8eae72dfc832f.zip
deluge-635f6d970dd83de53ccece2837f8eae72dfc832f.tar.gz
deluge-635f6d970dd83de53ccece2837f8eae72dfc832f.tar.bz2
[Config] Fix loading config with double-quotes in string
If a password or other string contained a double-quote then the config would fail to be loaded on startup and reset. This occurred due to fixing a similar issue with curly braces for #3079 in commit 33e9545cd44 and the checking for double-quotes had unforseen consequences. To resolve both these issues the code to check for json objects in config files was simplified and utilises the json module raw_decode method to ensure the extracted string indexes are json objects.
-rw-r--r--deluge/config.py43
-rw-r--r--deluge/tests/test_config.py28
2 files changed, 43 insertions, 28 deletions
diff --git a/deluge/config.py b/deluge/config.py
index c852996..90944a3 100644
--- a/deluge/config.py
+++ b/deluge/config.py
@@ -74,38 +74,33 @@ def prop(func):
return property(doc=func.__doc__, **func())
-def find_json_objects(s):
- """Find json objects in a string.
+def find_json_objects(text, decoder=json.JSONDecoder()):
+ """Find json objects in text.
Args:
- s (str): the string to find json objects in
+ text (str): The text to find json objects within.
Returns:
list: A list of tuples containing start and end locations of json
- objects in string `s`. e.g. [(start, end), ...]
+ objects in the text. e.g. [(start, end), ...]
+
"""
objects = []
- opens = 0
- start = s.find('{')
- offset = start
-
- if start < 0:
- return []
-
- quoted = False
- for index, c in enumerate(s[offset:]):
- if c == '"':
- quoted = not quoted
- elif quoted:
- continue
- elif c == '{':
- opens += 1
- elif c == '}':
- opens -= 1
- if opens == 0:
- objects.append((start, index + offset + 1))
- start = index + offset + 1
+ offset = 0
+ while True:
+ try:
+ start = text.index('{', offset)
+ except ValueError:
+ break
+
+ try:
+ __, index = decoder.raw_decode(text[start:])
+ except json.decoder.JSONDecodeError:
+ offset = start + 1
+ else:
+ offset = start + index
+ objects.append((start, offset))
return objects
diff --git a/deluge/tests/test_config.py b/deluge/tests/test_config.py
index 270cc5a..0f6df3b 100644
--- a/deluge/tests/test_config.py
+++ b/deluge/tests/test_config.py
@@ -25,6 +25,7 @@ DEFAULTS = {
'float': 0.435,
'bool': True,
'unicode': 'foobar',
+ 'password': 'abc123*\\[!]?/<>#{@}=|"+$%(^)~',
}
@@ -95,6 +96,7 @@ class ConfigTestCase(unittest.TestCase):
self.assertEqual(config['string'], 'foobar')
self.assertEqual(config['float'], 0.435)
+ self.assertEqual(config['password'], 'abc123*\\[!]?/<>#{@}=|"+$%(^)~')
# Test opening a previous 1.2 config file of just a json object
import json
@@ -107,8 +109,8 @@ class ConfigTestCase(unittest.TestCase):
# Test opening a previous 1.2 config file of having the format versions
# as ints
with open(os.path.join(self.config_dir, 'test.conf'), 'wb') as _file:
- _file.write(bytes(1) + b'\n')
- _file.write(bytes(1) + b'\n')
+ _file.write(b'1\n')
+ _file.write(b'1\n')
json.dump(DEFAULTS, getwriter('utf8')(_file), **JSON_FORMAT)
check_config()
@@ -184,9 +186,27 @@ class ConfigTestCase(unittest.TestCase):
}{
"ssl": true,
"enabled": false,
- "port": 8115
+ "port": 8115,
"password": "abc{def"
-}\n"""
+}"""
+
+ from deluge.config import find_json_objects
+
+ objects = find_json_objects(s)
+ self.assertEqual(len(objects), 2)
+
+ def test_find_json_objects_double_quote(self):
+ """Test with string containing double quote"""
+ s = r"""{
+ "file": 1,
+ "format": 1
+}{
+ "ssl": true,
+ "enabled": false,
+ "port": 8115,
+ "password": "abc\"def"
+}
+"""
from deluge.config import find_json_objects