Commit cf248803 authored by Keith Packard's avatar Keith Packard

Rename to Cadaver

Signed-off-by: 's avatarKeith Packard <keithp@keithp.com>
parent 9d65a019
==========================
Radicale - CalDAV Server
Cadaver - CalDAV Server
==========================
------
......
==========================
Radicale - CalDAV Server
Cadaver - CalDAV Server
==========================
--------
README
--------
The Radicale Project is a free and open-source CalDAV calendar server.
The Cadaver Project is a free and open-source CalDAV calendar server.
For complete documentation, please visit the `Radicale online documentation
<http://www.radicale.org/documentation>`_
For complete documentation, please visit the `Cadaver online documentation
<http://www.cadaver.org/documentation>`_
==========================
Radicale - CalDAV Server
Cadaver - CalDAV Server
==========================
------
......
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# This file is part of Cadaver Server - Calendar Server
# Copyright © 2011 Keith Packard
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
......@@ -17,18 +18,18 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
# along with Cadaver. If not, see <http://www.gnu.org/licenses/>.
# This file is just a script, allow [a-z0-9]* variable names
# pylint: disable-msg=C0103
# ``import radicale`` refers to the ``radicale`` module, not ``radicale.py``
# ``import cadaver`` refers to the ``cadaver`` module, not ``cadaver.py``
# pylint: disable-msg=W0406
"""
Radicale Server entry point.
Cadaver Server entry point.
Launch the Radicale Server according to configuration and command-line
Launch the Cadaver Server according to configuration and command-line
arguments.
"""
......@@ -39,7 +40,7 @@ import os
import sys
import optparse
import radicale
import cadaver
# Get command-line options
parser = optparse.OptionParser()
......@@ -49,56 +50,56 @@ parser.add_option(
help="show version and exit")
parser.add_option(
"-d", "--daemon", action="store_true",
default=radicale.config.getboolean("server", "daemon"),
default=cadaver.config.getboolean("server", "daemon"),
help="launch as daemon")
parser.add_option(
"-f", "--foreground", action="store_false", dest="daemon",
help="launch in foreground (opposite of --daemon)")
parser.add_option(
"-H", "--host",
default=radicale.config.get("server", "host"),
default=cadaver.config.get("server", "host"),
help="set server hostname")
parser.add_option(
"-p", "--port", type="int",
default=radicale.config.getint("server", "port"),
default=cadaver.config.getint("server", "port"),
help="set server port")
parser.add_option(
"-s", "--ssl", action="store_true",
default=radicale.config.getboolean("server", "ssl"),
default=cadaver.config.getboolean("server", "ssl"),
help="use SSL connection")
parser.add_option(
"-S", "--no-ssl", action="store_false", dest="ssl",
help="do not use SSL connection (opposite of --ssl)")
parser.add_option(
"-k", "--key",
default=radicale.config.get("server", "key"),
default=cadaver.config.get("server", "key"),
help="private key file ")
parser.add_option(
"-c", "--certificate",
default=radicale.config.get("server", "certificate"),
default=cadaver.config.get("server", "certificate"),
help="certificate file ")
options = parser.parse_args()[0]
# Update Radicale configuration according to options
# Update Cadaver configuration according to options
for option in parser.option_list:
key = option.dest
if key:
value = getattr(options, key)
radicale.config.set("server", key, value)
cadaver.config.set("server", key, value)
# Print version and exit if the option is given
if options.version:
print(radicale.VERSION)
print(cadaver.VERSION)
sys.exit()
# Fork if Radicale is launched as daemon
# Fork if Cadaver is launched as daemon
if options.daemon:
if os.fork():
sys.exit()
sys.stdout = sys.stderr = open(os.devnull, "w")
# Launch calendar server
server_class = radicale.HTTPSServer if options.ssl else radicale.HTTPServer
server_class = cadaver.HTTPSServer if options.ssl else cadaver.HTTPServer
server = server_class(
(options.host, options.port), radicale.CalendarHTTPHandler)
(options.host, options.port), cadaver.CalendarHTTPHandler)
server.serve_forever()
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# This file is part of Cadaver Server - Calendar Server
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
......@@ -16,10 +16,10 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
# along with Cadaver. If not, see <http://www.gnu.org/licenses/>.
"""
Radicale Server module.
Cadaver Server module.
This module offers 3 useful classes:
......@@ -28,7 +28,7 @@ This module offers 3 useful classes:
managing SSL connections;
- ``CalendarHTTPHandler`` is a CalDAV request handler for HTTP(S) servers.
To use this module, you should take a look at the file ``radicale.py`` that
To use this module, you should take a look at the file ``cadaver.py`` that
should have been included in this package.
"""
......@@ -46,7 +46,7 @@ except ImportError:
import BaseHTTPServer as server
# pylint: enable=F0401
from radicale import acl, config, ical, xmlutils
from cadaver import acl, config, ical, xmlutils
VERSION = "0.5"
......@@ -74,7 +74,7 @@ def _check(request, function):
request.send_response(client.UNAUTHORIZED)
request.send_header(
"WWW-Authenticate",
"Basic realm=\"Radicale Server - Password Required\"")
"Basic realm=\"Cadaver Server - Password Required\"")
request.end_headers()
# pylint: enable=W0212
......@@ -181,7 +181,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler):
content_type = self.headers.get("Content-Type", None)
if content_type and "charset=" in content_type:
charsets.append(content_type.split("charset=")[1].strip())
# Then append default Radicale charset
# Then append default Cadaver charset
charsets.append(self._encoding)
# Then append various fallbacks
charsets.append("utf-8")
......@@ -317,10 +317,12 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler):
def do_REPORT(self):
"""Manage REPORT request."""
xml_request = self.rfile.read(int(self.headers["Content-Length"]))
print ("report %s" % xml_request)
self._answer = xmlutils.report(self.path, xml_request, self._calendar)
self.send_response(client.MULTI_STATUS)
self.send_header("Content-Length", len(self._answer))
self.end_headers()
print ("answer %s" % self._answer)
self.wfile.write(self._answer)
# pylint: enable=C0103
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# This file is part of Cadaver Server - Calendar Server
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
......@@ -16,7 +16,7 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
# along with Cadaver. If not, see <http://www.gnu.org/licenses/>.
"""
Users and rights management.
......@@ -26,10 +26,10 @@ configuration.
"""
from radicale import config
from cadaver import config
def load():
"""Load list of available ACL managers."""
module = __import__("radicale.acl", fromlist=[config.get("acl", "type")])
module = __import__("cadaver.acl", fromlist=[config.get("acl", "type")])
return getattr(module, config.get("acl", "type"))
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# This file is part of Cadaver Server - Calendar Server
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
......@@ -16,7 +16,7 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
# along with Cadaver. If not, see <http://www.gnu.org/licenses/>.
"""
Fake ACL.
......
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# This file is part of Cadaver Server - Calendar Server
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
......@@ -16,7 +16,7 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
# along with Cadaver. If not, see <http://www.gnu.org/licenses/>.
"""
Htpasswd ACL.
......@@ -30,7 +30,7 @@ supported, but md5 is not (see ``htpasswd`` man page to understand why).
import base64
import hashlib
from radicale import config
from cadaver import config
def _plain(hash_value, password):
......
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# This file is part of Cadaver Server - Calendar Server
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
......@@ -16,10 +16,10 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
# along with Cadaver. If not, see <http://www.gnu.org/licenses/>.
"""
Radicale configuration module.
Cadaver configuration module.
Give a configparser-like interface to read and write configuration.
......@@ -51,10 +51,10 @@ INITIAL_CONFIG = {
"acl": {
"type": "fake",
"personal": "False",
"filename": "/etc/radicale/users",
"filename": "/etc/cadaver/users",
"encryption": "crypt"},
"storage": {
"folder": os.path.expanduser("~/.config/radicale/calendars")}}
"folder": os.path.expanduser("~/.config/cadaver/calendars")}}
# Create a ConfigParser and configure it
_CONFIG_PARSER = ConfigParser()
......@@ -64,8 +64,8 @@ for section, values in INITIAL_CONFIG.items():
for key, value in values.items():
_CONFIG_PARSER.set(section, key, value)
_CONFIG_PARSER.read("/etc/radicale/config")
_CONFIG_PARSER.read(os.path.expanduser("~/.config/radicale/config"))
_CONFIG_PARSER.read("/etc/cadaver/config")
_CONFIG_PARSER.read(os.path.expanduser("~/.config/cadaver/config"))
# Wrap config module into ConfigParser instance
sys.modules[__name__] = _CONFIG_PARSER
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# This file is part of Cadaver Server - Calendar Server
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
......@@ -16,10 +16,10 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
# along with Cadaver. If not, see <http://www.gnu.org/licenses/>.
"""
Radicale calendar classes.
Cadaver calendar classes.
Define the main classes of a calendar as seen from the server.
......@@ -28,11 +28,13 @@ Define the main classes of a calendar as seen from the server.
import os
import codecs
import time
import calendar
import hashlib
import glob
import tempfile
import vobject
from radicale import config
from cadaver import config
FOLDER = os.path.expanduser(config.get("storage", "folder"))
......@@ -55,13 +57,37 @@ def serialize(headers=(), items=()):
lines.append("END:VCALENDAR\n")
return "\n".join(lines)
def parse_time(line):
dtstart = line.rsplit(":",1)[1]
print ("dtstart %s " % dtstart)
try:
return time.strptime("%Y%m%dT%H%M%SZ", dtstart)
except ValueError:
try:
return time.strptime("%Y%m%dT%H%M%S", dtstart)
except ValueError:
return 0
class Item(object):
"""Internal iCal item."""
def __init__(self, text, name=None, path=None):
"""Initialize object from ``text`` and different ``kwargs``."""
# print "New item %s = %s\n" % (name, text)
print "New item %s = %s\n" % (name, text)
lines = text.splitlines(True)
newlines=""
for line in lines:
if line.find(":") >= 0:
newlines = newlines + line
text = newlines
# try:
# j = vobject.readOne(text)
# j.prettyPrint()
# except Exception:
# print ("parse error\n")
self.text = text
self._name = name
......@@ -71,37 +97,43 @@ class Item(object):
# An item must have a name, determined in order by:
#
# - the ``name`` parameter
# - the ``X-RADICALE-NAME`` iCal property (for Events and Todos)
# - the ``X-CADAVER-NAME`` iCal property (for Events and Todos)
# - the ``UID`` iCal property (for Events and Todos)
# - the ``TZID`` iCal property (for Timezones)
if not self._name:
for line in self.text.splitlines():
if line.startswith("X-RADICALE-NAME:"):
self._name = line.replace("X-RADICALE-NAME:", "").strip()
if line.startswith("X-CADAVER-NAME:"):
self._name = line.replace("X-CADAVER-NAME:", "").strip()
break
elif line.startswith("TZID:"):
self._name = line.replace("TZID:", "").strip()
break
elif line.startswith("UID:"):
self._name = line.replace("UID:", "").strip()
# Do not break, a ``X-RADICALE-NAME`` can appear next
# Do not break, a ``X-CADAVER-NAME`` can appear next
# self.dtstart = 0
# for line in self.text.splitlines():
# if line.startswith("DTSTART"):
# self.dtstart = parse_time(line)
# print ("dtstart %s -> %d" % (line, self.dtstart))
h = hashlib.sha1(text.encode("utf-8"))
self._etag = h.hexdigest()
if not self._name:
h = hashlib.sha1(text.encode("utf-8"));
self._name = h.hexdigest();
self._name = self._etag
if "\nX-RADICALE-NAME:" in text:
if "\nX-CADAVER-NAME:" in text:
for line in self.text.splitlines():
if line.startswith("X-RADICALE-NAME:"):
if line.startswith("X-CADAVER-NAME:"):
self.text = self.text.replace(
line, "X-RADICALE-NAME:%s" % self._name)
line, "X-CADAVER-NAME:%s" % self._name)
elif "\nUID:" in text:
self.text = self.text.replace(
"\nUID:", "\nX-RADICALE-NAME:%s\nUID:" % self._name)
"\nUID:", "\nX-CADAVER-NAME:%s\nUID:" % self._name)
else:
self.text = self.text.replace(
"\nSUMMARY:", "\nX-RADICALE-NAME:%s\nSUMMARY:" % self._name)
self._etag = hash(self.text)
"\nSUMMARY:", "\nX-CADAVER-NAME:%s\nSUMMARY:" % self._name)
@property
def etag(self):
......@@ -110,7 +142,7 @@ class Item(object):
Etag is mainly used to know if an item has changed.
"""
return '"%s"' % self._etag
return '%s' % self._etag
@property
def name(self):
......@@ -154,14 +186,14 @@ class Calendar(object):
def insert_file(self, path):
try:
# print ("Insert file %s" % path)
print ("Insert file %s" % path)
text = open(path).read()
self.insert_text(text, path)
except IOError:
return
def remove_file(self, path):
# print ("Remove file %s" % path)
print ("Remove file %s" % path)
old_items=[]
for old_item in self.my_items:
if old_item.path == path:
......@@ -171,16 +203,19 @@ class Calendar(object):
self.my_items.remove(old_item)
def scan_file(self, path):
# print ("Rescan file %s" % path)
print ("Rescan file %s" % path)
self.remove_file(path)
self.insert_file(path)
def scan_dir(self):
files = glob.glob(self.pattern)
mtime = os.path.getmtime(self.path)
if mtime == self.mtime:
try:
mtime = os.path.getmtime(self.path)
if mtime == self.mtime:
return
except OSError:
return
self.mtime = mtime
files = glob.glob(self.pattern)
for file in files:
if not file in self.files:
self.insert_file(file)
......@@ -217,7 +252,9 @@ class Calendar(object):
items = []
lines = text.splitlines()
jtext = text.replace("\n ", "")
lines = jtext.splitlines()
in_item = False
for line in lines:
......@@ -360,7 +397,7 @@ class Calendar(object):
def write(self, headers=None, items=None):
#"""Write calendar with given parameters."""
#headers = headers or self.headers or (
# Header("PRODID:-//Radicale//NONSGML Radicale Server//EN"),
# Header("PRODID:-//Cadaver//NONSGML Cadaver Server//EN"),
# Header("VERSION:2.0"))
#items = items if items is not None else self.items
......@@ -375,7 +412,7 @@ class Calendar(object):
@property
def etag(self):
"""Etag from calendar."""
return '"%s"' % hash(self.text)
return '%s' % hash(self.text)
@property
def name(self):
......@@ -388,7 +425,7 @@ class Calendar(object):
self.scan_dir()
headers = []
headers.append(Header("PRODID:-//Radicale//NONSGML Radicale Server//EN"))
headers.append(Header("PRODID:-//Cadaver//NONSGML Cadaver Server//EN"))
headers.append(Header("VERSION:2.0"))
return serialize(headers=headers, items=self.my_items)
......@@ -398,7 +435,7 @@ class Calendar(object):
"""Find headers items in calendar."""
header_lines = []
header_lines.append(Header("PRODID:-//Radicale//NONSGML Radicale Server//EN"))
header_lines.append(Header("PRODID:-//Cadaver//NONSGML Cadaver Server//EN"))
header_lines.append(Header("VERSION:2.0"))
return header_lines
......
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# This file is part of Cadaver Server - Calendar Server
# Copyright © 2008-2011 Guillaume Ayoub
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
......@@ -16,7 +16,7 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
# along with Cadaver. If not, see <http://www.gnu.org/licenses/>.
"""
XML and iCal requests manager.
......@@ -29,7 +29,7 @@ in them for XML requests (all but PUT).
import xml.etree.ElementTree as ET
from radicale import client, config, ical
from cadaver import client, config, ical
NAMESPACES = {
......@@ -49,7 +49,7 @@ def _response(code):
def name_from_path(path):
"""Return Radicale item name from ``path``."""
"""Return Cadaver item name from ``path``."""
path_parts = path.strip("/").split("/")
return path_parts[-1] if len(path_parts) > 2 else None
......
# Config file for Radicale - A simple calendar server
# Config file for Cadaver - A simple calendar server
#
# Place it into /etc/radicale/config (global)
# or ~/.config/radicale/config (user)
# Place it into /etc/cadaver/config (global)
# or ~/.config/cadaver/config (user)
#
# The current values are the default ones
......@@ -32,7 +32,7 @@ type = fake
# Personal calendars only available for logged in users (if needed)
personal = False
# Htpasswd filename (if needed)
filename = /etc/radicale/users
filename = /etc/cadaver/users
# Htpasswd encryption method (if needed)
# Value: plain | sha1 | crypt
encryption = crypt
......@@ -40,6 +40,6 @@ encryption = crypt
[storage]
# Folder for storing local calendars,
# created if not present
folder = ~/.config/radicale/calendars
folder = ~/.config/cadaver/calendars
# vim:ft=cfg
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# This file is part of Radicale Server - Calendar Server
# This file is part of Cadaver Server - Calendar Server
# Copyright © 2009-2011 Guillaume Ayoub
#
# This library is free software: you can redistribute it and/or modify
......@@ -15,24 +15,24 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
# along with Cadaver. If not, see <http://www.gnu.org/licenses/>.
"""
Radicale CalDAV server
Cadaver CalDAV server
======================
The Radicale Project is a CalDAV calendar server. It aims to be a light
The Cadaver Project is a CalDAV calendar server. It aims to be a light
solution, easy to use, easy to install, easy to configure. As a consequence,
it requires few software dependances and is pre-configured to work
out-of-the-box.
The Radicale Project runs on most of the UNIX-like platforms (Linux, BSD,
The Cadaver 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
version 3.
For further information, please visit the `Radicale Website
<http://www.radicale.org/>`_.
For further information, please visit the `Cadaver Website
<http://www.cadaver.org/>`_.
"""
......@@ -40,7 +40,7 @@ import os
from distutils.core import setup
from distutils.command.build_scripts import build_scripts
import radicale
import cadaver
# build_scripts is known to have a lot of public methods
......@@ -49,7 +49,7 @@ class BuildScripts(build_scripts):
"""Build the package."""
def run(self):
"""Run building."""
# These lines remove the .py extension from the radicale executable
# These lines remove the .py extension from the cadaver executable
self.mkpath(self.build_dir)
for script in self.scripts:
root, _ = os.path.splitext(script)
......@@ -57,23 +57,23 @@ class BuildScripts(build_scripts):
# pylint: enable=R0904
# When the version is updated, ``radicale.VERSION`` must be modified.
# When the version is updated, ``cadaver.VERSION`` must be modified.
# A new section in the ``NEWS`` file must be added too.
setup(
name="Radicale",
version=radicale.VERSION,
description="CalDAV Server",
name="Cadaver",
version=cadaver.VERSION,
description="CalDAV and CardDAV Server",
long_description=__doc__,
author="Guillaume Ayoub",
author_email="guillaume.ayoub@kozea.fr",
url="http://www.radicale.org/",
download_url="http://www.radicale.org/src/radicale/Radicale-%s.tar.gz" % \
radicale.VERSION,
author="Keith Packard",
author_email="keithp@keithp.com",
url="http://keithp.com/",
download_url="http://keithp.com/git/cadaver" % \
cadaver.VERSION,
license="GNU GPL v3",
platforms="Any",
packages=["radicale", "radicale.acl"],
provides=["radicale"],
scripts=["radicale.py"],
packages=["cadaver", "cadaver.acl"],
provides=["cadaver"],
scripts=["cadaver.py"],
cmdclass={"build_scripts": BuildScripts},
keywords=["calendar", "CalDAV"],
classifiers=[
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment