Merge remote branch 'radicale/master'

This commit is contained in:
System User 2011-02-14 10:07:05 +01:00
commit 1f1d051656
9 changed files with 79 additions and 68 deletions

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# Copyright © 2008-2010 Guillaume Ayoub
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
#
@ -28,7 +28,7 @@
"""
Radicale Server entry point.
Launch the Radicale Serve according to configuration and command-line
Launch the Radicale Server according to configuration and command-line
arguments.
"""

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# Copyright © 2008-2010 Guillaume Ayoub
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
#
@ -55,6 +55,11 @@ def _check(request, function):
"""Check if user has sufficient rights for performing ``request``."""
# ``_check`` decorator can access ``request`` protected functions
# pylint: disable=W0212
# If we have no calendar, don't check rights
if not request._calendar:
return function(request)
authorization = request.headers.get("Authorization", None)
if authorization:
challenge = authorization.lstrip("Basic").strip().encode("ascii")
@ -90,6 +95,7 @@ class HTTPServer(server.HTTPServer):
class HTTPSServer(HTTPServer):
"""HTTPS server."""
PROTOCOL = "https"
def __init__(self, address, handler):
"""Create server by wrapping HTTP socket in an SSL socket."""
# Fails with Python 2.5, import if needed
@ -203,11 +209,18 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler):
# No item or ETag precondition not verified, do not delete item
self.send_response(client.PRECONDITION_FAILED)
@check_rights
def do_MKCALENDAR(self):
"""Manage MKCALENDAR request."""
self.send_response(client.CREATED)
self.end_headers()
def do_OPTIONS(self):
"""Manage OPTIONS request."""
self.send_response(client.OK)
self.send_header(
"Allow", "DELETE, HEAD, GET, OPTIONS, PROPFIND, PUT, REPORT")
"Allow", "DELETE, HEAD, GET, MKCALENDAR, "
"OPTIONS, PROPFIND, PUT, REPORT")
self.send_header("DAV", "1, calendar-access")
self.end_headers()
@ -216,7 +229,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler):
xml_request = self.rfile.read(int(self.headers["Content-Length"]))
self._answer = xmlutils.propfind(
self.path, xml_request, self._calendar,
self.headers.get("depth", "infinity"), self)
self.headers.get("depth", "infinity"))
self.send_response(client.MULTI_STATUS)
self.send_header("DAV", "1, calendar-access")

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# Copyright © 2008-2010 Guillaume Ayoub
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
#

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# Copyright © 2008-2010 Guillaume Ayoub
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
#

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# Copyright © 2008-2010 Guillaume Ayoub
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
#
@ -49,7 +49,7 @@ def _sha1(hash_value, password):
"""Check if ``hash_value`` and ``password`` match using sha1 method."""
hash_value = hash_value.replace("{SHA}", "").encode("ascii")
password = password.encode(config.get("encoding", "stock"))
sha1 = hashlib.sha1()
sha1 = hashlib.sha1() # pylint: disable=E1101
sha1.update(password)
return sha1.digest() == base64.b64decode(hash_value)

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# Copyright © 2008-2010 Guillaume Ayoub
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
#
@ -25,8 +25,6 @@ Give a configparser-like interface to read and write configuration.
"""
# TODO: Use abstract filenames for other platforms
import os
import sys
# Manage Python2/3 different modules

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# Copyright © 2008-2010 Guillaume Ayoub
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
#
@ -135,7 +135,6 @@ class Calendar(object):
def __init__(self, path):
"""Initialize the calendar with ``cal`` and ``user`` parameters."""
# TODO: Use properties from the calendar configuration
self.encoding = "utf-8"
self.owner = path.split("/")[0]
self.path = os.path.join(FOLDER, path.replace("/", os.path.sep))

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# Copyright © 2008-2010 Guillaume Ayoub
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
#
@ -79,7 +79,7 @@ def delete(path, calendar):
return ET.tostring(multistatus, config.get("encoding", "request"))
def propfind(path, xml_request, calendar, depth, request):
def propfind(path, xml_request, calendar, depth):
"""Read and answer PROPFIND requests.
Read rfc4918-9.1 for info.
@ -95,14 +95,15 @@ def propfind(path, xml_request, calendar, depth, request):
# Writing answer
multistatus = ET.Element(_tag("D", "multistatus"))
if calendar:
if depth == "0":
items = [calendar]
elif depth == "1":
items = [calendar] + calendar.events + calendar.todos
else:
# depth is infinity or not specified
# depth is 1, infinity or not specified
# we limit ourselves to depth == 1
items = [calendar] + calendar.events + calendar.todos
else:
items = []
for item in items:
is_calendar = isinstance(item, ical.Calendar)
@ -111,7 +112,7 @@ def propfind(path, xml_request, calendar, depth, request):
multistatus.append(response)
href = ET.Element(_tag("D", "href"))
href.text = path if is_calendar else "%s/%s" % (path, item.name)
href.text = path if is_calendar else path + item.name
response.append(href)
propstat = ET.Element(_tag("D", "propstat"))
@ -122,42 +123,44 @@ def propfind(path, xml_request, calendar, depth, request):
for tag in props:
element = ET.Element(tag)
if tag == _tag("D", "resourcetype"):
if is_calendar:
if tag == _tag("D", "resourcetype") and is_calendar:
tag = ET.Element(_tag("C", "calendar"))
element.append(tag)
tag = ET.Element(_tag("D", "collection"))
element.append(tag)
else:
tag = ET.Element(_tag("C", "comp"))
tag.set("name", element.tag)
element.append(tag)
elif tag == _tag("D", "owner"):
element.text = calendar.owner
elif tag == _tag("D", "getcontenttype"):
element.text = "text/calendar"
elif tag == _tag("CS", "getctag") and is_calendar:
element.text = item.etag
elif tag == _tag("D", "getetag"):
element.text = item.etag
elif tag == _tag("D", "displayname"):
elif tag == _tag("D", "displayname") and is_calendar:
element.text = calendar.name
elif tag == _tag("D", "supported-report-set"):
supported_report = ET.Element(_tag("D", "supported-report"))
report_set = ET.Element(_tag("D", "report"))
report_set.append(ET.Element(_tag("C", "calendar-multiget")))
supported_report.append(report_set)
element.append(supported_report)
elif tag == _tag("D", "principal-URL"):
# TODO: use a real principal URL, read rfc3744-4.2 for info
element.text = "%s://%s%s" % (
request.server.PROTOCOL, request.headers["Host"],
request.path)
elif tag == _tag("C", "calendar-home-set"):
tag = ET.Element(_tag("D", "href"))
tag.text = "%s://%s%s" % (
request.server.PROTOCOL, request.headers["Host"],
request.path)
tag.text = path
element.append(tag)
elif tag in (
_tag("D", "principal-collection-set"),
_tag("C", "calendar-user-address-set"),
_tag("C", "calendar-home-set")):
tag = ET.Element(_tag("D", "href"))
tag.text = path
element.append(tag)
elif tag == _tag("C", "supported-calendar-component-set"):
comp = ET.Element(_tag("C", "comp"))
comp.set("name", "VTODO") # pylint: disable=W0511
element.append(comp)
comp = ET.Element(_tag("C", "comp"))
comp.set("name", "VEVENT")
element.append(comp)
elif tag == _tag("D", "current-user-privilege-set"):
privilege = ET.Element(_tag("D", "privilege"))
privilege.append(ET.Element(_tag("D", "all")))
element.append(privilege)
prop.append(element)
status = ET.Element(_tag("D", "status"))
@ -191,12 +194,15 @@ def report(path, xml_request, calendar):
prop_list = prop_element.getchildren()
props = [prop.tag for prop in prop_list]
if calendar:
if root.tag == _tag("C", "calendar-multiget"):
# Read rfc4791-7.9 for info
hreferences = set((href_element.text for href_element
in root.findall(_tag("D", "href"))))
else:
hreferences = (path,)
else:
hreferences = ()
# Writing answer
multistatus = ET.Element(_tag("D", "multistatus"))
@ -227,17 +233,12 @@ def report(path, xml_request, calendar):
prop = ET.Element(_tag("D", "prop"))
propstat.append(prop)
if _tag("D", "getetag") in props:
element = ET.Element(_tag("D", "getetag"))
for tag in props:
element = ET.Element(tag)
if tag == _tag("D", "getetag"):
element.text = item.etag
prop.append(element)
if _tag("C", "calendar-data") in props:
element = ET.Element(_tag("C", "calendar-data"))
if isinstance(item, ical.Event):
element.text = ical.serialize(
calendar.headers, calendar.timezones + [item])
elif isinstance(item, ical.Todo):
elif tag == _tag("C", "calendar-data"):
if isinstance(item, (ical.Event, ical.Todo)):
element.text = ical.serialize(
calendar.headers, calendar.timezones + [item])
prop.append(element)

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# Copyright © 2009-2010 Guillaume Ayoub
# Copyright © 2009-2011 Guillaume Ayoub
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by