Logging
This commit is contained in:
		
							
								
								
									
										6
									
								
								config
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								config
									
									
									
									
									
								
							| @@ -42,4 +42,10 @@ encryption = crypt | |||||||
| # created if not present | # created if not present | ||||||
| folder = ~/.config/radicale/calendars | folder = ~/.config/radicale/calendars | ||||||
|  |  | ||||||
|  | [Logging] | ||||||
|  | # Logging filename | ||||||
|  | logfile = ~/.config/radicale/radicale.log | ||||||
|  | # Log facility 10: DEBUG, 20: INFO, 30 WARNING, 40 ERROR, 50 CRITICAL | ||||||
|  | facility = 50 | ||||||
|  |  | ||||||
| # vim:ft=cfg | # vim:ft=cfg | ||||||
|   | |||||||
| @@ -46,13 +46,14 @@ except ImportError: | |||||||
|     import BaseHTTPServer as server |     import BaseHTTPServer as server | ||||||
| # pylint: enable=F0401 | # pylint: enable=F0401 | ||||||
|  |  | ||||||
| from radicale import acl, config, ical, xmlutils | from radicale import acl, config, ical, xmlutils, log | ||||||
|  |  | ||||||
|  |  | ||||||
| VERSION = "git" | VERSION = "git" | ||||||
|  |  | ||||||
| def _check(request, function): | def _check(request, function): | ||||||
|     """Check if user has sufficient rights for performing ``request``.""" |     """Check if user has sufficient rights for performing ``request``.""" | ||||||
|  |     log.log(10, "Check if user has sufficient rights for performing ``request``.") | ||||||
|     # ``_check`` decorator can access ``request`` protected functions |     # ``_check`` decorator can access ``request`` protected functions | ||||||
|     # pylint: disable=W0212 |     # pylint: disable=W0212 | ||||||
|     authorization = request.headers.get("Authorization", None) |     authorization = request.headers.get("Authorization", None) | ||||||
| @@ -64,8 +65,10 @@ def _check(request, function): | |||||||
|         user = password = None |         user = password = None | ||||||
|  |  | ||||||
|     if request.server.acl.has_right(request._calendar.owner, user, password): |     if request.server.acl.has_right(request._calendar.owner, user, password): | ||||||
|  |         log.log(20, "Sufficient rights for performing ``request``.") | ||||||
|         function(request) |         function(request) | ||||||
|     else: |     else: | ||||||
|  |         log.log(40, "No sufficient rights for performing ``request``.") | ||||||
|         request.send_response(client.UNAUTHORIZED) |         request.send_response(client.UNAUTHORIZED) | ||||||
|         request.send_header( |         request.send_header( | ||||||
|             "WWW-Authenticate", |             "WWW-Authenticate", | ||||||
| @@ -82,6 +85,7 @@ class HTTPServer(server.HTTPServer): | |||||||
|     # pylint: disable=W0231 |     # pylint: disable=W0231 | ||||||
|     def __init__(self, address, handler): |     def __init__(self, address, handler): | ||||||
|         """Create server.""" |         """Create server.""" | ||||||
|  |         log.log(10, "Create HTTP server.") | ||||||
|         server.HTTPServer.__init__(self, address, handler) |         server.HTTPServer.__init__(self, address, handler) | ||||||
|         self.acl = acl.load() |         self.acl = acl.load() | ||||||
|     # pylint: enable=W0231 |     # pylint: enable=W0231 | ||||||
| @@ -92,6 +96,7 @@ class HTTPSServer(HTTPServer): | |||||||
|     PROTOCOL = "https" |     PROTOCOL = "https" | ||||||
|     def __init__(self, address, handler): |     def __init__(self, address, handler): | ||||||
|         """Create server by wrapping HTTP socket in an SSL socket.""" |         """Create server by wrapping HTTP socket in an SSL socket.""" | ||||||
|  |         log.log(10, "Create server by wrapping HTTP socket in an SSL socket.") | ||||||
|         # Fails with Python 2.5, import if needed |         # Fails with Python 2.5, import if needed | ||||||
|         # pylint: disable=F0401 |         # pylint: disable=F0401 | ||||||
|         import ssl |         import ssl | ||||||
| @@ -110,6 +115,7 @@ class HTTPSServer(HTTPServer): | |||||||
|  |  | ||||||
| class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | ||||||
|     """HTTP requests handler for calendars.""" |     """HTTP requests handler for calendars.""" | ||||||
|  |     log.log(10, "HTTP requests handler for calendars.") | ||||||
|     _encoding = config.get("encoding", "request") |     _encoding = config.get("encoding", "request") | ||||||
|  |  | ||||||
|     # Decorator checking rights before performing request |     # Decorator checking rights before performing request | ||||||
| @@ -118,6 +124,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | |||||||
|     @property |     @property | ||||||
|     def _calendar(self): |     def _calendar(self): | ||||||
|         """The ``ical.Calendar`` object corresponding to the given path.""" |         """The ``ical.Calendar`` object corresponding to the given path.""" | ||||||
|  |         log.log(10, "The ``ical.Calendar`` object corresponding to the given path.") | ||||||
|         # ``self.path`` must be something like a posix path |         # ``self.path`` must be something like a posix path | ||||||
|         # ``normpath`` should clean malformed and malicious request paths |         # ``normpath`` should clean malformed and malicious request paths | ||||||
|         attributes = posixpath.normpath(self.path.strip("/")).split("/") |         attributes = posixpath.normpath(self.path.strip("/")).split("/") | ||||||
| @@ -127,6 +134,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | |||||||
|  |  | ||||||
|     def _decode(self, text): |     def _decode(self, text): | ||||||
|         """Try to decode text according to various parameters.""" |         """Try to decode text according to various parameters.""" | ||||||
|  |         log.log(10, "Try to decode text according to various parameters.") | ||||||
|         # List of charsets to try |         # List of charsets to try | ||||||
|         charsets = [] |         charsets = [] | ||||||
|  |  | ||||||
| @@ -153,12 +161,14 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | |||||||
|  |  | ||||||
|     def do_GET(self): |     def do_GET(self): | ||||||
|         """Manage GET request.""" |         """Manage GET request.""" | ||||||
|  |         log.log(10, "Manage GET request.") | ||||||
|         self.do_HEAD() |         self.do_HEAD() | ||||||
|         self.wfile.write(self._answer) |         self.wfile.write(self._answer) | ||||||
|  |  | ||||||
|     @check_rights |     @check_rights | ||||||
|     def do_HEAD(self): |     def do_HEAD(self): | ||||||
|         """Manage HEAD request.""" |         """Manage HEAD request.""" | ||||||
|  |         log.log(10, "Manage HEAD request.") | ||||||
|         item_name = xmlutils.name_from_path(self.path) |         item_name = xmlutils.name_from_path(self.path) | ||||||
|         if item_name: |         if item_name: | ||||||
|             # Get calendar item |             # Get calendar item | ||||||
| @@ -188,6 +198,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | |||||||
|     @check_rights |     @check_rights | ||||||
|     def do_DELETE(self): |     def do_DELETE(self): | ||||||
|         """Manage DELETE request.""" |         """Manage DELETE request.""" | ||||||
|  |         log.log(10, "Manage DELETE request.") | ||||||
|         item = self._calendar.get_item(xmlutils.name_from_path(self.path)) |         item = self._calendar.get_item(xmlutils.name_from_path(self.path)) | ||||||
|         if item and self.headers.get("If-Match", item.etag) == item.etag: |         if item and self.headers.get("If-Match", item.etag) == item.etag: | ||||||
|             # No ETag precondition or precondition verified, delete item |             # No ETag precondition or precondition verified, delete item | ||||||
| @@ -203,6 +214,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | |||||||
|  |  | ||||||
|     def do_OPTIONS(self): |     def do_OPTIONS(self): | ||||||
|         """Manage OPTIONS request.""" |         """Manage OPTIONS request.""" | ||||||
|  |         log.log(10, "Manage OPTIONS request.") | ||||||
|         self.send_response(client.OK) |         self.send_response(client.OK) | ||||||
|         self.send_header( |         self.send_header( | ||||||
|             "Allow", "DELETE, HEAD, GET, OPTIONS, PROPFIND, PUT, REPORT") |             "Allow", "DELETE, HEAD, GET, OPTIONS, PROPFIND, PUT, REPORT") | ||||||
| @@ -211,6 +223,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | |||||||
|  |  | ||||||
|     def do_PROPFIND(self): |     def do_PROPFIND(self): | ||||||
|         """Manage PROPFIND request.""" |         """Manage PROPFIND request.""" | ||||||
|  |         log.log(10, "Manage PROPFIND request.") | ||||||
|         xml_request = self.rfile.read(int(self.headers["Content-Length"])) |         xml_request = self.rfile.read(int(self.headers["Content-Length"])) | ||||||
|         self._answer = xmlutils.propfind( |         self._answer = xmlutils.propfind( | ||||||
|             self.path, xml_request, self._calendar, |             self.path, xml_request, self._calendar, | ||||||
| @@ -226,6 +239,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | |||||||
|     @check_rights |     @check_rights | ||||||
|     def do_PUT(self): |     def do_PUT(self): | ||||||
|         """Manage PUT request.""" |         """Manage PUT request.""" | ||||||
|  |         log.log(10, "Manage PUT request.") | ||||||
|         item_name = xmlutils.name_from_path(self.path) |         item_name = xmlutils.name_from_path(self.path) | ||||||
|         item = self._calendar.get_item(item_name) |         item = self._calendar.get_item(item_name) | ||||||
|         if (not item and not self.headers.get("If-Match")) or \ |         if (not item and not self.headers.get("If-Match")) or \ | ||||||
| @@ -249,6 +263,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | |||||||
|     @check_rights |     @check_rights | ||||||
|     def do_REPORT(self): |     def do_REPORT(self): | ||||||
|         """Manage REPORT request.""" |         """Manage REPORT request.""" | ||||||
|  |         log.log(10, "Manage REPORT request.") | ||||||
|         xml_request = self.rfile.read(int(self.headers["Content-Length"])) |         xml_request = self.rfile.read(int(self.headers["Content-Length"])) | ||||||
|         self._answer = xmlutils.report(self.path, xml_request, self._calendar) |         self._answer = xmlutils.report(self.path, xml_request, self._calendar) | ||||||
|  |  | ||||||
| @@ -257,4 +272,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): | |||||||
|         self.end_headers() |         self.end_headers() | ||||||
|         self.wfile.write(self._answer) |         self.wfile.write(self._answer) | ||||||
|  |  | ||||||
|  |     def log_message(self, format, *args): | ||||||
|  | 		log.log(10, format % (args)) | ||||||
|  |  | ||||||
|     # pylint: enable=C0103 |     # pylint: enable=C0103 | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
|  |  | ||||||
| import sys, ldap | import sys, ldap | ||||||
|  |  | ||||||
| from radicale import config | from radicale import config, log | ||||||
|  |  | ||||||
| def has_right(owner, user, password): | def has_right(owner, user, password): | ||||||
| 	if user == None: | 	if user == None: | ||||||
| @@ -12,11 +12,15 @@ def has_right(owner, user, password): | |||||||
| 	if owner != user: | 	if owner != user: | ||||||
| 		return False | 		return False | ||||||
| 	try: | 	try: | ||||||
|  | 		log.log(10, "Open LDAP server connexion") | ||||||
| 		l=ldap.open(LDAPSERVER, 389) | 		l=ldap.open(LDAPSERVER, 389) | ||||||
| 		cn="%s%s,%s" % (LDAPPREPEND, user, LDAPAPPEND) | 		cn="%s%s,%s" % (LDAPPREPEND, user, LDAPAPPEND) | ||||||
|  | 		log.log(10, "LDAP bind with dn: %s" %(cn)) | ||||||
| 		l.simple_bind_s(cn, password); | 		l.simple_bind_s(cn, password); | ||||||
|  | 		log.log(20, "LDAP bind Ok") | ||||||
| 		return True | 		return True | ||||||
| 	except: | 	except: | ||||||
|  | 		log.log(40, "LDAP bind error") | ||||||
| 		return False | 		return False | ||||||
|  |  | ||||||
| LDAPSERVER = config.get("authLdap", "LDAPServer") | LDAPSERVER = config.get("authLdap", "LDAPServer") | ||||||
|   | |||||||
| @@ -56,7 +56,10 @@ INITIAL_CONFIG = { | |||||||
|         "filename": "/etc/radicale/users", |         "filename": "/etc/radicale/users", | ||||||
|         "encryption": "crypt"}, |         "encryption": "crypt"}, | ||||||
|     "storage": { |     "storage": { | ||||||
|         "folder": os.path.expanduser("~/.config/radicale/calendars")}} |         "folder": os.path.expanduser("~/.config/radicale/calendars")}, | ||||||
|  |     "logging": { | ||||||
|  | 		"logfile": os.path.expanduser("~/.config/radicale/radicale.log"), | ||||||
|  | 		"facility": 10}} | ||||||
|  |  | ||||||
| # Create a ConfigParser and configure it | # Create a ConfigParser and configure it | ||||||
| _CONFIG_PARSER = ConfigParser() | _CONFIG_PARSER = ConfigParser() | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								radicale/log.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								radicale/log.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | import logging, sys | ||||||
|  | from radicale import config | ||||||
|  |  | ||||||
|  | class log: | ||||||
|  | 	def __init__(self): | ||||||
|  | 		self.logger=logging.getLogger("radicale") | ||||||
|  | 		self.logger.setLevel(config.get("logging", "facility")) | ||||||
|  | 		 | ||||||
|  | 		handler=logging.FileHandler(config.get("logging", "logfile")) | ||||||
|  | 		 | ||||||
|  | 		formatter = logging.Formatter('%(name)s %(asctime)s %(levelname)s %(message)s') | ||||||
|  | 		handler.setFormatter(formatter) | ||||||
|  |  | ||||||
|  | 		self.logger.addHandler(handler) | ||||||
|  | 	def log(self, level, msg): | ||||||
|  | 		self.logger.log(level, msg) | ||||||
|  |  | ||||||
|  | _LOGGING = log() | ||||||
|  |  | ||||||
|  | sys.modules[__name__] = _LOGGING | ||||||
| @@ -31,7 +31,7 @@ in them for XML requests (all but PUT). | |||||||
|  |  | ||||||
| import xml.etree.ElementTree as ET | import xml.etree.ElementTree as ET | ||||||
|  |  | ||||||
| from radicale import client, config, ical | from radicale import client, config, ical, log | ||||||
|  |  | ||||||
|  |  | ||||||
| NAMESPACES = { | NAMESPACES = { | ||||||
| @@ -47,11 +47,13 @@ def _tag(short_name, local): | |||||||
|  |  | ||||||
| def _response(code): | def _response(code): | ||||||
|     """Return full W3C names from HTTP status codes.""" |     """Return full W3C names from HTTP status codes.""" | ||||||
|  |     log.log(10, "Return full W3C names from HTTP status codes.") | ||||||
|     return "HTTP/1.1 %i %s" % (code, client.responses[code]) |     return "HTTP/1.1 %i %s" % (code, client.responses[code]) | ||||||
|  |  | ||||||
|  |  | ||||||
| def name_from_path(path): | def name_from_path(path): | ||||||
|     """Return Radicale item name from ``path``.""" |     """Return Radicale item name from ``path``.""" | ||||||
|  |     log.log(10, "Return Radicale item name from ``path``.") | ||||||
|     return path.split("/")[-1] |     return path.split("/")[-1] | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -62,6 +64,7 @@ def delete(path, calendar): | |||||||
|  |  | ||||||
|     """ |     """ | ||||||
|     # Reading request |     # Reading request | ||||||
|  |     log.log(10, "Read and answer DELETE requests.") | ||||||
|     calendar.remove(name_from_path(path)) |     calendar.remove(name_from_path(path)) | ||||||
|  |  | ||||||
|     # Writing answer |     # Writing answer | ||||||
| @@ -87,8 +90,9 @@ def propfind(path, xml_request, calendar, depth, request): | |||||||
|  |  | ||||||
|     """ |     """ | ||||||
|     # Reading request |     # Reading request | ||||||
|  |     log.log(10, "Read and answer PROPFIND requests.") | ||||||
|     root = ET.fromstring(xml_request) |     root = ET.fromstring(xml_request) | ||||||
|  |      | ||||||
|     prop_element = root.find(_tag("D", "prop")) |     prop_element = root.find(_tag("D", "prop")) | ||||||
|     prop_list = prop_element.getchildren() |     prop_list = prop_element.getchildren() | ||||||
|     props = [prop.tag for prop in prop_list] |     props = [prop.tag for prop in prop_list] | ||||||
| @@ -164,6 +168,7 @@ def propfind(path, xml_request, calendar, depth, request): | |||||||
|  |  | ||||||
| def put(path, ical_request, calendar): | def put(path, ical_request, calendar): | ||||||
|     """Read PUT requests.""" |     """Read PUT requests.""" | ||||||
|  |     log.log(10, "Read PUT requests.") | ||||||
|     name = name_from_path(path) |     name = name_from_path(path) | ||||||
|     if name in (item.name for item in calendar.items): |     if name in (item.name for item in calendar.items): | ||||||
|         # PUT is modifying an existing item |         # PUT is modifying an existing item | ||||||
| @@ -180,6 +185,7 @@ def report(path, xml_request, calendar): | |||||||
|  |  | ||||||
|     """ |     """ | ||||||
|     # Reading request |     # Reading request | ||||||
|  |     log.log(10, "Read and answer REPORT requests.") | ||||||
|     root = ET.fromstring(xml_request) |     root = ET.fromstring(xml_request) | ||||||
|  |  | ||||||
|     prop_element = root.find(_tag("D", "prop")) |     prop_element = root.find(_tag("D", "prop")) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Corentin Le Bail
					Corentin Le Bail