diff --git a/radicale.py b/radicale.py index 7802576..8ac9bdb 100755 --- a/radicale.py +++ b/radicale.py @@ -81,10 +81,10 @@ for option in parser.option_list: if key: section = "logging" if key == "debug" else "server" value = getattr(options, key) - radicale.config.set(section, key, value) + radicale.config.set(section, key, str(value)) # Start logging -radicale.log.start(options.debug) +radicale.log.start() # Fork if Radicale is launched as daemon if options.daemon: diff --git a/radicale/__init__.py b/radicale/__init__.py index e446b6c..fcf6265 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -190,7 +190,11 @@ class Application(object): # Set content length if answer: - log.LOGGER.debug("Response content:\n%s" % answer) + # decoding the answer for logging purposes on Python 3 + log_answer = answer + if not isinstance(log_answer, str): + log_answer = log_answer.decode(config.get("encoding", "request")) + log.LOGGER.debug("Response content:\n%s" % log_answer) headers["Content-Length"] = "%i" % len(answer) # Start response diff --git a/radicale/acl/htpasswd.py b/radicale/acl/htpasswd.py index 70197d1..d6600ee 100644 --- a/radicale/acl/htpasswd.py +++ b/radicale/acl/htpasswd.py @@ -65,5 +65,5 @@ def has_right(owner, user, password): if line.strip(): login, hash_value = line.strip().split(":") if login == user and (not PERSONAL or user == owner): - return locals()["_%s" % ENCRYPTION](hash_value, password) + return globals()["_%s" % ENCRYPTION](hash_value, password) return False diff --git a/radicale/log.py b/radicale/log.py index 3d36f9f..19ec046 100644 --- a/radicale/log.py +++ b/radicale/log.py @@ -35,10 +35,8 @@ from radicale import config LOGGER = logging.getLogger() FILENAME = os.path.expanduser(config.get("logging", "config")) -def start(debug=False): +def start(): """Start the logging according to the configuration.""" - if debug: - LOGGER.setLevel(logging.DEBUG) if os.path.exists(FILENAME): # Configuration taken from file @@ -48,3 +46,8 @@ def start(debug=False): handler = logging.StreamHandler(sys.stdout) handler.setFormatter(logging.Formatter("%(message)s")) LOGGER.addHandler(handler) + + if config.getboolean("logging", "debug"): + LOGGER.setLevel(logging.DEBUG) + for handler in LOGGER.handlers: + handler.setLevel(logging.DEBUG) diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index e582dc0..2806a32 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -38,6 +38,26 @@ NAMESPACES = { "CS": "http://calendarserver.org/ns/"} +for short, url in NAMESPACES.items(): + ET._namespace_map[url] = short + + +def _et_indent(elem, level=0): + i = "\n" + level * " " + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for elem in elem: + _et_indent(elem, level+1) + if not elem.tail or not elem.tail.strip(): + elem.tail = i + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = i + + def _tag(short_name, local): """Get XML Clark notation {uri(``short_name``)}``local``.""" return "{%s}%s" % (NAMESPACES[short_name], local) @@ -77,6 +97,9 @@ def delete(path, calendar): status.text = _response(200) response.append(status) + if config.getboolean("logging", "debug"): + _et_indent(multistatus) + return ET.tostring(multistatus, config.get("encoding", "request")) @@ -90,9 +113,8 @@ def propfind(path, xml_request, calendar, depth): root = ET.fromstring(xml_request) prop_element = root.find(_tag("D", "prop")) - prop_list = prop_element.getchildren() - props = [prop.tag for prop in prop_list] - + props = [prop.tag for prop in prop_element] + # Writing answer multistatus = ET.Element(_tag("D", "multistatus")) @@ -179,6 +201,9 @@ def propfind(path, xml_request, calendar, depth): status.text = _response(200) propstat.append(status) + if config.getboolean("logging", "debug"): + _et_indent(multistatus) + return ET.tostring(multistatus, config.get("encoding", "request")) @@ -194,10 +219,9 @@ def proppatch(path, xml_request, calendar): for action in ("set", "remove"): action_element = root.find(_tag("D", action)) - if action_element: + if action_element is not None: prop_element = action_element.find(_tag("D", "prop")) - prop_list = prop_element.getchildren() - props.extend(prop.tag for prop in prop_list) + props.extend(prop.tag for prop in prop_element) # Writing answer multistatus = ET.Element(_tag("D", "multistatus")) @@ -223,6 +247,9 @@ def proppatch(path, xml_request, calendar): status.text = _response(200) propstat.append(status) + if config.getboolean("logging", "debug"): + _et_indent(multistatus) + return ET.tostring(multistatus, config.get("encoding", "request")) @@ -247,8 +274,7 @@ def report(path, xml_request, calendar): root = ET.fromstring(xml_request) prop_element = root.find(_tag("D", "prop")) - prop_list = prop_element.getchildren() - props = [prop.tag for prop in prop_list] + props = [prop.tag for prop in prop_element] if calendar: if root.tag == _tag("C", "calendar-multiget"): @@ -303,4 +329,7 @@ def report(path, xml_request, calendar): status.text = _response(200) propstat.append(status) + if config.getboolean("logging", "debug"): + _et_indent(multistatus) + return ET.tostring(multistatus, config.get("encoding", "request"))