Merge branch 'master' of git://gitorious.org/radicale/radicale

Conflicts:
	radicale/__init__.py
This commit is contained in:
System User 2011-04-07 16:30:46 +02:00
commit 08b145e5ca
7 changed files with 85 additions and 49 deletions

9
NEWS
View File

@ -6,10 +6,17 @@
NEWS NEWS
------ ------
0.5 - *Not released yet* 0.6 - *Not released yet*
======================== ========================
* IPv6 support
0.5 - Historical Artifacts
==========================
* Calendar depth * Calendar depth
* iPhone support
* MacOS and Windows support * MacOS and Windows support
* HEAD requests management * HEAD requests management
* htpasswd user from calendar path * htpasswd user from calendar path

7
TODO
View File

@ -6,17 +6,12 @@
TODO TODO
------ ------
0.5
===
* iCal and iPhone support
0.6 0.6
=== ===
* [IN PROGRESS] Group calendars * [IN PROGRESS] Group calendars
* [IN PROGRESS] LDAP and databases auth support * [IN PROGRESS] LDAP and databases auth support
* [IN PROGRESS] Smart, verbose and configurable logs
* CalDAV rights * CalDAV rights
* Read-only access for foreign users * Read-only access for foreign users

9
config
View File

@ -6,10 +6,11 @@
# The current values are the default ones # The current values are the default ones
[server] [server]
# CalDAV server hostname, empty for all hostnames # CalDAV server hostnames separated by a comma
host = # IPv4 syntax: address:port
# CalDAV server port # IPv6 syntax: [address]:port
port = 5232 # IPv6 adresses are configured to only allow IPv6 connections
hosts = 0.0.0.0:5232
# Daemon flag # Daemon flag
daemon = False daemon = False
# SSL flag, enable HTTPS protocol # SSL flag, enable HTTPS protocol

View File

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# This file is part of Radicale Server - Calendar Server # This file is part of Radicale Server - Calendar Server
@ -26,10 +26,9 @@
# pylint: disable-msg=W0406 # pylint: disable-msg=W0406
""" """
Radicale Server entry point. Radicale CalDAV Server.
Launch the Radicale Server according to configuration and command-line Launch the server according to configuration and command-line options.
arguments.
""" """
@ -38,15 +37,13 @@ arguments.
import os import os
import sys import sys
import optparse import optparse
import signal
import threading
import radicale import radicale
# Get command-line options # Get command-line options
parser = optparse.OptionParser() parser = optparse.OptionParser(version=radicale.VERSION)
parser.add_option(
"-v", "--version", action="store_true",
default=False,
help="show version and exit")
parser.add_option( parser.add_option(
"-d", "--daemon", action="store_true", "-d", "--daemon", action="store_true",
default=radicale.config.getboolean("server", "daemon"), default=radicale.config.getboolean("server", "daemon"),
@ -55,13 +52,9 @@ parser.add_option(
"-f", "--foreground", action="store_false", dest="daemon", "-f", "--foreground", action="store_false", dest="daemon",
help="launch in foreground (opposite of --daemon)") help="launch in foreground (opposite of --daemon)")
parser.add_option( parser.add_option(
"-H", "--host", "-H", "--hosts",
default=radicale.config.get("server", "host"), default=radicale.config.get("server", "hosts"),
help="set server hostname") help="set server hostnames and ports")
parser.add_option(
"-p", "--port", type="int",
default=radicale.config.getint("server", "port"),
help="set server port")
parser.add_option( parser.add_option(
"-s", "--ssl", action="store_true", "-s", "--ssl", action="store_true",
default=radicale.config.getboolean("server", "ssl"), default=radicale.config.getboolean("server", "ssl"),
@ -72,11 +65,11 @@ parser.add_option(
parser.add_option( parser.add_option(
"-k", "--key", "-k", "--key",
default=radicale.config.get("server", "key"), default=radicale.config.get("server", "key"),
help="private key file ") help="set private key file")
parser.add_option( parser.add_option(
"-c", "--certificate", "-c", "--certificate",
default=radicale.config.get("server", "certificate"), default=radicale.config.get("server", "certificate"),
help="certificate file ") help="set certificate file")
options = parser.parse_args()[0] options = parser.parse_args()[0]
# Update Radicale configuration according to options # Update Radicale configuration according to options
@ -86,19 +79,42 @@ for option in parser.option_list:
value = getattr(options, key) value = getattr(options, key)
radicale.config.set("server", key, value) radicale.config.set("server", key, value)
# Print version and exit if the option is given
if options.version:
print(radicale.VERSION)
sys.exit()
# Fork if Radicale is launched as daemon # Fork if Radicale is launched as daemon
if options.daemon: if options.daemon:
if os.fork(): if os.fork():
sys.exit() sys.exit()
sys.stdout = sys.stderr = open(os.devnull, "w") sys.stdout = sys.stderr = open(os.devnull, "w")
# Launch calendar server # Launch calendar servers
servers = []
server_class = radicale.HTTPSServer if options.ssl else radicale.HTTPServer server_class = radicale.HTTPSServer if options.ssl else radicale.HTTPServer
server = server_class(
(options.host, options.port), radicale.CalendarHTTPHandler) def exit():
server.serve_forever() """Cleanly shutdown servers."""
while servers:
servers.pop().shutdown()
def serve_forever(server):
"""Serve a server forever with no traceback on keyboard interrupts."""
try:
server.serve_forever()
except KeyboardInterrupt:
# No unwanted traceback
pass
finally:
exit()
# Clean exit on SIGTERM
signal.signal(signal.SIGTERM, lambda *_: exit())
for host in options.hosts.split(','):
address, port = host.strip().rsplit(':', 1)
address, port = address.strip('[] '), int(port)
servers.append(server_class((address, port), radicale.CalendarHTTPHandler))
for server in servers[:-1]:
# More servers to come, launch a new thread
threading.Thread(target=serve_forever, args=(server,)).start()
# Last server, no more thread
serve_forever(servers[-1])

View File

@ -88,10 +88,25 @@ class HTTPServer(server.HTTPServer):
# Maybe a Pylint bug, ``__init__`` calls ``server.HTTPServer.__init__`` # Maybe a Pylint bug, ``__init__`` calls ``server.HTTPServer.__init__``
# pylint: disable=W0231 # pylint: disable=W0231
def __init__(self, address, handler): def __init__(self, address, handler, bind_and_activate=True):
"""Create server.""" """Create server."""
log.log(10, "Create HTTP server.") log.log(10, "Create HTTP server.")
server.HTTPServer.__init__(self, address, handler) ipv6 = ":" in address[0]
if ipv6:
self.address_family = socket.AF_INET6
# Do not bind and activate, as we might change socketopts
server.HTTPServer.__init__(self, address, handler, False)
if ipv6:
# Only allow IPv6 connections to the IPv6 socket
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
if bind_and_activate:
self.server_bind()
self.server_activate()
self.acl = acl.load() self.acl = acl.load()
# pylint: enable=W0231 # pylint: enable=W0231
@ -100,7 +115,7 @@ class HTTPSServer(HTTPServer):
"""HTTPS server.""" """HTTPS server."""
PROTOCOL = "https" PROTOCOL = "https"
def __init__(self, address, handler): def __init__(self, address, handler, bind_and_activate=True):
"""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.") 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
@ -108,15 +123,17 @@ class HTTPSServer(HTTPServer):
import ssl import ssl
# pylint: enable=F0401 # pylint: enable=F0401
HTTPServer.__init__(self, address, handler) HTTPServer.__init__(self, address, handler, False)
self.socket = ssl.wrap_socket( self.socket = ssl.wrap_socket(
socket.socket(self.address_family, self.socket_type), self.socket,
server_side=True, server_side=True,
certfile=config.get("server", "certificate"), certfile=config.get("server", "certificate"),
keyfile=config.get("server", "key"), keyfile=config.get("server", "key"),
ssl_version=ssl.PROTOCOL_SSLv23) ssl_version=ssl.PROTOCOL_SSLv23)
self.server_bind()
self.server_activate() if bind_and_activate:
self.server_bind()
self.server_activate()
class CalendarHTTPHandler(server.BaseHTTPRequestHandler): class CalendarHTTPHandler(server.BaseHTTPRequestHandler):

View File

@ -39,8 +39,7 @@ except ImportError:
# Default configuration # Default configuration
INITIAL_CONFIG = { INITIAL_CONFIG = {
"server": { "server": {
"host": "", "hosts": "0.0.0.0:5232",
"port": "5232",
"daemon": "False", "daemon": "False",
"ssl": "False", "ssl": "False",
"certificate": "/etc/apache2/ssl/server.crt", "certificate": "/etc/apache2/ssl/server.crt",

View File

@ -27,8 +27,8 @@ it requires few software dependances and is pre-configured to work
out-of-the-box. out-of-the-box.
The Radicale Project runs on most of the UNIX-like platforms (Linux, BSD, The Radicale Project runs on most of the UNIX-like platforms (Linux, BSD,
MacOS X) and Windows. It is known to work with Evolution 2.30+, Lightning 0.9+ MacOS X) and Windows. It is known to work with Evolution, Lightning, iPhone
and Sunbird 0.9+. It is free and open-source software, released under GPL and Android clients. It is free and open-source software, released under GPL
version 3. version 3.
For further information, please visit the `Radicale Website For further information, please visit the `Radicale Website
@ -91,4 +91,5 @@ setup(
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.0", "Programming Language :: Python :: 3.0",
"Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.1",
"Programming Language :: Python :: 3.2",
"Topic :: Office/Business :: Groupware"]) "Topic :: Office/Business :: Groupware"])