Merge remote-tracking branch 'upstream/master'
Conflicts: radicale/__init__.py radicale/acl/courier.py
This commit is contained in:
commit
55a13d4c39
17
.project
Normal file
17
.project
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Radicale</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.python.pydev.PyDevBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.python.pydev.pythonNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
10
.pydevproject
Normal file
10
.pydevproject
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?>
|
||||
|
||||
<pydev_project>
|
||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||
<path>/Radicale</path>
|
||||
</pydev_pathproperty>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
</pydev_project>
|
4
.settings/org.eclipse.core.resources.prefs
Normal file
4
.settings/org.eclipse.core.resources.prefs
Normal file
@ -0,0 +1,4 @@
|
||||
#Sat Aug 04 10:58:22 CEST 2012
|
||||
eclipse.preferences.version=1
|
||||
encoding//radicale/__init__.py=utf-8
|
||||
encoding//radicale/__main__.py=utf-8
|
12
NEWS.rst
12
NEWS.rst
@ -3,6 +3,18 @@
|
||||
======
|
||||
|
||||
|
||||
0.7.1 - Waterfalls
|
||||
==================
|
||||
|
||||
* Many address books fixes
|
||||
* New IMAP ACL (by Daniel Aleksandersen)
|
||||
* PAM ACL fixed (by Daniel Aleksandersen)
|
||||
* Courier ACL fixed (by Benjamin Frank)
|
||||
* Always set display name to collections (by Oskari Timperi)
|
||||
* Various DELETE responses fixed
|
||||
|
||||
|
||||
|
||||
0.7 - Eternal Sunshine
|
||||
======================
|
||||
|
||||
|
@ -172,7 +172,7 @@ class Application(object):
|
||||
def __call__(self, environ, start_response):
|
||||
"""Manage a request."""
|
||||
log.LOGGER.info("%s request at %s received" % (
|
||||
environ["REQUEST_METHOD"], environ["PATH_INFO"]))
|
||||
environ["REQUEST_METHOD"], environ["PATH_INFO"]))
|
||||
headers = pprint.pformat(self.headers_log(environ))
|
||||
log.LOGGER.debug("Request headers:\n%s" % headers)
|
||||
|
||||
@ -216,20 +216,29 @@ class Application(object):
|
||||
|
||||
if access.is_authenticated(user, password):
|
||||
|
||||
collections = []
|
||||
for collection in items:
|
||||
log.LOGGER.debug("Testing %s" % (collection.name))
|
||||
if not isinstance(collection, ical.Collection):
|
||||
log.LOGGER.info("not a collection: " + collection.name)
|
||||
last_collection_allowed = None
|
||||
allowed_items = []
|
||||
for item in items:
|
||||
log.LOGGER.debug("Testing %s" % (item.name))
|
||||
if not isinstance(item, ical.Collection):
|
||||
# item is not a colleciton, it's the child of the last
|
||||
# collection we've met in the loop. Only add this item if
|
||||
# this last collection was allowed. log.LOGGER.info("not a collection: " + collection.name)
|
||||
# collections.append(collection)
|
||||
elif access.may_read(user, collection) or access.may_write(user, collection):
|
||||
log.LOGGER.info("Has access to " + collection.name)
|
||||
collections.append(collection)
|
||||
if last_collection_allowed:
|
||||
allowed_items.append(item)
|
||||
else:
|
||||
if access.may_read(user, item) or access.may_write(user, item):
|
||||
log.LOGGER.info(user + "has access to " + item.name)
|
||||
last_collection_allowed = True
|
||||
allowed_items.append(item)
|
||||
else:
|
||||
last_collection_allowed = False
|
||||
|
||||
if collections:
|
||||
if allowed_items:
|
||||
# Collections found
|
||||
status, headers, answer = function(
|
||||
environ, collections, content, user)
|
||||
environ, allowed_items, content, user)
|
||||
else:
|
||||
# Good user and no collections found, redirect user to home
|
||||
location = "/%s/" % str(quote(user))
|
||||
@ -241,7 +250,7 @@ class Application(object):
|
||||
else:
|
||||
# Send answer anyway since else we're getting into a redirect loop
|
||||
status, headers, answer = function(
|
||||
environ, collections, content, user)
|
||||
environ, allowed_items, content, user)
|
||||
|
||||
else:
|
||||
|
||||
@ -499,7 +508,7 @@ class Application(object):
|
||||
# Evolution bug workaround
|
||||
etag = environ.get("HTTP_IF_MATCH", "").replace("\\", "")
|
||||
if (not item and not etag) or (
|
||||
item and ((etag or item.etag) == item.etag)):
|
||||
item and ((etag or item.etag) == item.etag)):
|
||||
# PUT allowed in 3 cases
|
||||
# Case 1: No item and no ETag precondition: Add new item
|
||||
# Case 2: Item and ETag precondition verified: Modify item
|
||||
|
@ -91,6 +91,8 @@ def run():
|
||||
|
||||
# Fork if Radicale is launched as daemon
|
||||
if options.daemon:
|
||||
if options.pid and os.path.exists(options.pid):
|
||||
raise OSError("PID file exists: %s" % options.pid)
|
||||
pid = os.fork()
|
||||
if pid:
|
||||
try:
|
||||
|
@ -33,7 +33,7 @@ def is_authenticated(user, password):
|
||||
"""Check if ``user``/``password`` couple is valid."""
|
||||
|
||||
line = "%s\nlogin\n%s\n%s" % (sys.argv[0], user, password)
|
||||
line = "%i\n%s" % (len(line), line)
|
||||
line = "AUTH %i\n%s" % (len(line), line)
|
||||
try:
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
sock.connect(COURIER_SOCKET)
|
||||
@ -48,7 +48,13 @@ def is_authenticated(user, password):
|
||||
|
||||
log.LOGGER.debug("Got Courier socket response: %r" % data)
|
||||
|
||||
if repr(data) == "FAIL":
|
||||
return False
|
||||
# Address, HOME, GID, and either UID or USERNAME are mandatory in resposne
|
||||
# see http://www.courier-mta.org/authlib/README_authlib.html#authpipeproto
|
||||
for line in data.split():
|
||||
if 'GID' in line:
|
||||
return True
|
||||
|
||||
return True
|
||||
# default is reject
|
||||
# this alleviates the problem of a possibly empty reply from authlib
|
||||
# see http://www.courier-mta.org/authlib/README_authlib.html#authpipeproto
|
||||
return False
|
||||
|
@ -270,8 +270,8 @@ def _propfind_response(path, item, props, user):
|
||||
element.append(privilege)
|
||||
elif tag == _tag("D", "supported-report-set"):
|
||||
for report_name in (
|
||||
"principal-property-search", "sync-collection"
|
||||
"expand-property", "principal-search-property-set"):
|
||||
"principal-property-search", "sync-collection"
|
||||
"expand-property", "principal-search-property-set"):
|
||||
supported = ET.Element(_tag("D", "supported-report"))
|
||||
report_tag = ET.Element(_tag("D", "report"))
|
||||
report_tag.text = report_name
|
||||
@ -422,9 +422,8 @@ def report(path, xml_request, collection):
|
||||
props = [prop.tag for prop in prop_element]
|
||||
|
||||
if collection:
|
||||
if root.tag in (
|
||||
_tag("C", "calendar-multiget"),
|
||||
_tag("CR", "addressbook-multiget")):
|
||||
if root.tag in (_tag("C", "calendar-multiget"),
|
||||
_tag("CR", "addressbook-multiget")):
|
||||
# Read rfc4791-7.9 for info
|
||||
hreferences = set(
|
||||
href_element.text for href_element
|
||||
@ -472,8 +471,8 @@ def report(path, xml_request, collection):
|
||||
element = ET.Element(tag)
|
||||
if tag == _tag("D", "getetag"):
|
||||
element.text = item.etag
|
||||
elif tag in (
|
||||
_tag("C", "calendar-data"), _tag("CR", "address-data")):
|
||||
elif tag in (_tag("C", "calendar-data"),
|
||||
_tag("CR", "address-data")):
|
||||
if isinstance(item, ical.Component):
|
||||
element.text = ical.serialize(
|
||||
collection_tag, collection_headers,
|
||||
|
Loading…
Reference in New Issue
Block a user