Просмотр исходного кода

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

Conflicts:
	radicale/__init__.py
System User 15 лет назад
Родитель
Сommit
08b145e5ca
7 измененных файлов с 85 добавлено и 49 удалено
  1. 8 1
      NEWS
  2. 1 6
      TODO
  3. 5 4
      config
  4. 43 27
      radicale.py
  5. 24 7
      radicale/__init__.py
  6. 1 2
      radicale/config.py
  7. 3 2
      setup.py

+ 8 - 1
NEWS

@@ -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

+ 1 - 6
TODO

@@ -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
 
 

+ 5 - 4
config

@@ -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
-host =
-# CalDAV server port
-port = 5232
+# CalDAV server hostnames separated by a comma
+# IPv4 syntax: address:port
+# IPv6 syntax: [address]:port
+# 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

+ 43 - 27
radicale.py

@@ -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
-arguments.
+Launch the server according to configuration and command-line options.
 
 
 """
 """
 
 
@@ -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.add_option(
-    "-v", "--version", action="store_true",
-    default=False,
-    help="show version and exit")
+parser = optparse.OptionParser(version=radicale.VERSION)
 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",
-    default=radicale.config.get("server", "host"),
-    help="set server hostname")
-parser.add_option(
-    "-p", "--port", type="int",
-    default=radicale.config.getint("server", "port"),
-    help="set server port")
+    "-H", "--hosts",
+    default=radicale.config.get("server", "hosts"),
+    help="set server hostnames and ports")
 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)
-server.serve_forever()
+
+def exit():
+    """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])

+ 24 - 7
radicale/__init__.py

@@ -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):

+ 1 - 2
radicale/config.py

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

+ 3 - 2
setup.py

@@ -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+
-and Sunbird 0.9+. It is free and open-source software, released under GPL
+MacOS X) and Windows.  It is known to work with Evolution, Lightning, iPhone
+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"])