New upstream version 0.0.6
Jelmer Vernooij
3 years ago
0 | 0 | Metadata-Version: 1.1 |
1 | 1 | Name: xandikos |
2 | Version: 0.0.5 | |
3 | Summary: CalDAV/CardDAV server | |
4 | Home-page: https://www.jelmer.uk/projects/xandikos | |
2 | Version: 0.0.6 | |
3 | Summary: Lightweight CalDAV/CardDAV server | |
4 | Home-page: https://www.xandikos.org/ | |
5 | 5 | Author: Jelmer Vernooij |
6 | 6 | Author-email: jelmer@jelmer.uk |
7 | 7 | License: GNU GPLv3 or later |
6 | 6 | :alt: Windows Build Status |
7 | 7 | |
8 | 8 | |
9 | Xandikos is a CardDAV/CalDAV server that backs onto a Git repository. | |
9 | Xandikos is a lightweight yet complete CardDAV/CalDAV server that backs onto a Git repository. | |
10 | 10 | |
11 | 11 | Xandikos (Ξανδικός or Ξανθικός) takes its name from the name of the March month |
12 | 12 | in the ancient Macedonian calendar, used in Macedon in the first millennium BC. |
30 | 30 | - :RFC:`6638` (CalDAV Scheduling Extensions) - *not implemented* |
31 | 31 | - :RFC:`7809` (CalDAV Time Zone Extensions) - *not implemented* |
32 | 32 | - :RFC:`7529` (WebDAV Quota) - *not implemented* |
33 | - :RFC:`4709` (WebDAV Mount) - *not implemented* | |
33 | - :RFC:`4709` (WebDAV Mount) - `intentionally <https://github.com/jelmer/xandikos/issues/48>`_ *not implemented* | |
34 | 34 | - :RFC:`5546` (iCal iTIP) - *not implemented* |
35 | 35 | - :RFC:`4324` (iCAL CAP) - *not implemented* |
36 | 36 | - :RFC:`7953` (iCal AVAILABILITY) - *not implemented* |
126 | 126 | mkdir -p $HOME/dav |
127 | 127 | uwsgi examples/uwsgi-standalone.ini |
128 | 128 | |
129 | Contributing | |
130 | ============ | |
131 | ||
132 | Contributions to Xandikos are very welcome. If you run into bugs or have | |
133 | feature requests, please file issues `on GitHub | |
134 | <https://github.com/jelmer/xandikos/issues/new>`_. If you're interested in | |
135 | contributing code or documentation, please read `CONTRIBUTING | |
136 | <CONTRIBUTING.rst>`_. Issues that are good for new contributors are tagged | |
137 | `new-contributor <https://github.com/jelmer/xandikos/labels/new-contributor>`_ | |
138 | on GitHub. | |
139 | ||
129 | 140 | Help |
130 | 141 | ==== |
131 | 142 |
0 | Principal | |
1 | ========= | |
2 | ||
3 | Need per principal config: | |
4 | ||
5 | - calendar home sets | |
6 | - addressbook home sets | |
7 | - user address set | |
8 | - infit settings | |
9 | ||
10 | Calendar | |
11 | ======== | |
12 | ||
13 | Need per calendar config: | |
14 | ||
15 | - color | |
16 | - description | |
17 | - inbox URL | |
18 | - outbox URL | |
19 | - max instances | |
20 | - max attendees per instance | |
21 | - calendar timezone | |
22 | ||
23 | Addresssbook | |
24 | ============ | |
25 | ||
26 | Need per addressbook config: | |
27 | ||
28 | - max image size | |
29 | - max resource size | |
30 | - color | |
31 | - description |
288 | 288 | |
289 | 289 | - {DAV:}quote-available-bytes [supported] |
290 | 290 | - {DAV:}quote-used-bytes [supported] |
291 | ||
292 | rfc4709 (WebDAV Mount) | |
293 | ---------------------- | |
294 | ||
295 | This RFC documents a mechanism that allows clients to find the WebDAV mount | |
296 | associated with a specific page. It's unclear to the writer what the value of | |
297 | this is - an alternate resource in the HTML page would also do. | |
298 | ||
299 | As far as I can tell, there is only a single server side implementation and a | |
300 | single client side implementation of this RFC. I don't have access to the | |
301 | client implementation (Xythos Drive) and the server side implementation is in | |
302 | SabreDAV. | |
303 | ||
304 | Experimental support for WebDAV Mount is available in the 'mount' branch, but | |
305 | won't be merged without a good use case. |
0 | Principal | |
1 | ========= | |
2 | ||
3 | Need per principal config: | |
4 | ||
5 | - calendar home sets | |
6 | - addressbook home sets | |
7 | - user address set | |
8 | - infit settings |
21 | 21 | |
22 | 22 | from setuptools import setup |
23 | 23 | |
24 | version = "0.0.5" | |
24 | version = "0.0.6" | |
25 | 25 | |
26 | 26 | setup(name="xandikos", |
27 | description="CalDAV/CardDAV server", | |
27 | description="Lightweight CalDAV/CardDAV server", | |
28 | 28 | version=version, |
29 | 29 | author="Jelmer Vernooij", |
30 | 30 | author_email="jelmer@jelmer.uk", |
31 | 31 | license="GNU GPLv3 or later", |
32 | url="https://www.jelmer.uk/projects/xandikos", | |
32 | url="https://www.xandikos.org/", | |
33 | 33 | install_requires=['icalendar', 'dulwich', 'defusedxml', 'jinja2'], |
34 | 34 | packages=['xandikos', 'xandikos.tests'], |
35 | 35 | package_data={'xandikos': ['templates/*.html']}, |
20 | 20 | |
21 | 21 | """CalDAV/CardDAV server.""" |
22 | 22 | |
23 | __version__ = (0, 0, 5) | |
23 | __version__ = (0, 0, 6) | |
24 | 24 | |
25 | 25 | import defusedxml.ElementTree # noqa: This does some monkey-patching on-load |
29 | 29 | # Feature to advertise to indicate scheduling support. |
30 | 30 | FEATURE = 'calendar-auto-schedule' |
31 | 31 | |
32 | CALENDAR_USER_TYPE_INDIVIDUAL = "INDIVIDUAL" # An individual | |
33 | CALENDAR_USER_TYPE_GROUP = "GROUP" # A group of individuals | |
34 | CALENDAR_USER_TYPE_RESOURCE = "RESOURCE" # A physical resource | |
35 | CALENDAR_USER_TYPE_ROOM = "ROOM" # A room resource | |
36 | CALENDAR_USER_TYPE_UNKNOWN = "UNKNOWN" # Otherwise not known | |
37 | ||
38 | CALENDAR_USER_TYPES = ( | |
39 | CALENDAR_USER_TYPE_INDIVIDUAL, | |
40 | CALENDAR_USER_TYPE_GROUP, | |
41 | CALENDAR_USER_TYPE_RESOURCE, | |
42 | CALENDAR_USER_TYPE_ROOM, | |
43 | CALENDAR_USER_TYPE_UNKNOWN) | |
44 | ||
32 | 45 | |
33 | 46 | class ScheduleInbox(caldav.Calendar): |
34 | 47 | |
39 | 52 | raise NotImplementedError(self.get_schedule_inbox_url) |
40 | 53 | |
41 | 54 | def get_schedule_outbox_url(self): |
42 | raise NotImplementedError(self.get_schedule_inbox_url) | |
55 | raise NotImplementedError(self.get_schedule_outbox_url) | |
43 | 56 | |
44 | 57 | def get_calendar_user_type(self): |
45 | 58 | # Default, per section 2.4.2 |
46 | return "INDIVIDUAL" | |
59 | return CALENDAR_USER_TYPE_INDIVIDUAL | |
47 | 60 | |
48 | 61 | |
49 | 62 | class ScheduleInboxURLProperty(webdav.Property): |
17 | 17 | </ul> |
18 | 18 | |
19 | 19 | <p>For more information about Xandikos, see <a |
20 | href="https://jelmer.uk/projects/xandikos">https://jelmer.uk/projects/xandikos</a> | |
20 | href="https://www.xandikos.org/">https://www.xandikos.org/</a> | |
21 | 21 | or <a href="https://github.com/jelmer/xandikos">https://github.com/jelmer/xandikos</a>. |
22 | 22 | </p> |
23 | 23 | </body> |
5 | 5 | <p>This is a Xandikos WebDAV server.</p> |
6 | 6 | |
7 | 7 | <p>For more information about Xandikos, see <a |
8 | href="https://jelmer.uk/projects/xandikos">https://jelmer.uk/projects/xandikos</a> | |
8 | href="https://www.xandikos.org/">https://www.xandikos.org/</a> | |
9 | 9 | or <a href="https://github.com/jelmer/xandikos">https://github.com/jelmer/xandikos</a>. |
10 | 10 | </p> |
11 | 11 | </body> |
550 | 550 | return render_jinja_page('root.html', accepted_content_languages) |
551 | 551 | |
552 | 552 | def get_body(self): |
553 | raise NotImplementedError(self.get_body) | |
553 | raise KeyError | |
554 | 554 | |
555 | 555 | def get_content_length(self): |
556 | raise NotImplementedError(self.get_content_length) | |
556 | raise KeyError | |
557 | 557 | |
558 | 558 | def get_content_type(self): |
559 | 559 | return 'text/html' |
637 | 637 | |
638 | 638 | def get_calendar_user_type(self): |
639 | 639 | # TODO(jelmer) |
640 | return "INDIVIDUAL" | |
640 | return scheduling.CALENDAR_USER_TYPE_INDIVIDUAL | |
641 | 641 | |
642 | 642 | def get_calendar_proxy_read_for(self): |
643 | 643 | # TODO(jelmer) |
757 | 757 | """A wsgi App that provides a Xandikos web server. |
758 | 758 | """ |
759 | 759 | |
760 | def __init__(self, backend, current_user_principal): | |
760 | def __init__(self, backend, current_user_principal_href): | |
761 | 761 | super(XandikosApp, self).__init__(backend) |
762 | 762 | self.register_properties([ |
763 | 763 | webdav.ResourceTypeProperty(), |
764 | 764 | webdav.CurrentUserPrincipalProperty( |
765 | current_user_principal), | |
765 | current_user_principal_href), | |
766 | 766 | webdav.PrincipalURLProperty(), |
767 | 767 | webdav.DisplayNameProperty(), |
768 | 768 | webdav.GetETagProperty(), |
873 | 873 | |
874 | 874 | |
875 | 875 | def main(argv): |
876 | import optparse | |
876 | import argparse | |
877 | 877 | import sys |
878 | 878 | from xandikos import __version__ |
879 | parser = optparse.OptionParser(version='.'.join(map(str, __version__))) | |
880 | parser.usage = "%prog -d ROOT-DIR [OPTIONS]" | |
881 | ||
882 | access_group = optparse.OptionGroup(parser, "Access Options") | |
883 | access_group.add_option( | |
879 | parser = argparse.ArgumentParser( | |
880 | usage="%(prog)s -d ROOT-DIR [OPTIONS]", | |
881 | prog=argv[0]) | |
882 | ||
883 | parser.add_argument( | |
884 | '--version', | |
885 | action='version', | |
886 | version='%(prog)s ' + '.'.join(map(str, __version__))) | |
887 | ||
888 | access_group = parser.add_argument_group(title="Access Options") | |
889 | access_group.add_argument( | |
884 | 890 | "-l", "--listen_address", dest="listen_address", default="localhost", |
885 | help="Binding IP address. [%default]") | |
886 | access_group.add_option( | |
891 | help="Binding IP address. [%(default)s]") | |
892 | access_group.add_argument( | |
887 | 893 | "-p", "--port", dest="port", type=int, default=8080, |
888 | help="Port to listen on. [%default]") | |
889 | access_group.add_option( | |
894 | help="Port to listen on. [%(default)s]") | |
895 | access_group.add_argument( | |
890 | 896 | "--route-prefix", default="/", help=( |
891 | 897 | "Path to Xandikos. " |
892 | 898 | "(useful when Xandikos is behind a reverse proxy) " |
893 | "[%default]")) | |
894 | parser.add_option_group(access_group) | |
895 | parser.add_option( | |
899 | "[%(default)s]")) | |
900 | parser.add_argument( | |
896 | 901 | "-d", "--directory", dest="directory", default=None, |
897 | 902 | help="Directory to serve from.") |
898 | parser.add_option( | |
903 | parser.add_argument( | |
899 | 904 | "--current-user-principal", default="/user/", |
900 | help="Path to current user principal. [%default]") | |
901 | parser.add_option( | |
905 | help="Path to current user principal. [%(default)s]") | |
906 | parser.add_argument( | |
902 | 907 | "--autocreate", action="store_true", dest="autocreate", |
903 | 908 | help="Automatically create necessary directories.") |
904 | parser.add_option( | |
909 | parser.add_argument( | |
905 | 910 | "--defaults", action="store_true", dest="defaults", |
906 | 911 | help=("Create initial calendar and address book. " |
907 | 912 | "Implies --autocreate.")) |
908 | options, args = parser.parse_args(argv) | |
913 | options = parser.parse_args(argv[1:]) | |
909 | 914 | |
910 | 915 | if options.directory is None: |
911 | 916 | parser.print_usage() |
933 | 938 | 'Run xandikos with --autocreate?', |
934 | 939 | options.current_user_principal) |
935 | 940 | |
941 | current_user_principal_href = posixpath.join( | |
942 | options.route_prefix, | |
943 | options.current_user_principal.lstrip('/')) | |
944 | ||
936 | 945 | app = XandikosApp( |
937 | 946 | backend, |
938 | current_user_principal=options.current_user_principal) | |
947 | current_user_principal_href=current_user_principal_href) | |
939 | 948 | |
940 | 949 | from wsgiref.simple_server import make_server |
941 | 950 | app = WellknownRedirector(app, options.route_prefix) |
496 | 496 | if self.current_user_principal is None: |
497 | 497 | ET.SubElement(el, '{DAV:}unauthenticated') |
498 | 498 | else: |
499 | el.append(create_href(self.current_user_principal, href)) | |
499 | # TODO(jelmer): Ideally this should receive | |
500 | # SCRIPT_NAME and prefix the returned URL with that. | |
501 | el.append(create_href(self.current_user_principal)) | |
500 | 502 | |
501 | 503 | |
502 | 504 | class PrincipalURLProperty(Property): |
21 | 21 | |
22 | 22 | import logging |
23 | 23 | import os |
24 | import urllib.parse | |
24 | 25 | |
25 | 26 | from xandikos.web import XandikosBackend, XandikosApp |
26 | 27 | |
45 | 46 | current_user_principal)) |
46 | 47 | |
47 | 48 | backend._mark_as_principal(current_user_principal) |
48 | app = XandikosApp(backend, current_user_principal) | |
49 | current_user_principal_href = urllib.parse.urljoin( | |
50 | os.environ.get('ROUTE_PREFIX', '/'), current_user_principal.lstrip('/')) | |
51 | app = XandikosApp(backend, current_user_principal_href) |
0 | 0 | Metadata-Version: 1.1 |
1 | 1 | Name: xandikos |
2 | Version: 0.0.5 | |
3 | Summary: CalDAV/CardDAV server | |
4 | Home-page: https://www.jelmer.uk/projects/xandikos | |
2 | Version: 0.0.6 | |
3 | Summary: Lightweight CalDAV/CardDAV server | |
4 | Home-page: https://www.xandikos.org/ | |
5 | 5 | Author: Jelmer Vernooij |
6 | 6 | Author-email: jelmer@jelmer.uk |
7 | 7 | License: GNU GPLv3 or later |
26 | 26 | examples/uwsgi-standalone.ini |
27 | 27 | examples/uwsgi.ini |
28 | 28 | notes/auth.rst |
29 | notes/config.rst | |
29 | 30 | notes/context.rst |
30 | 31 | notes/dav-compliance.rst |
31 | 32 | notes/file-format.rst |
32 | 33 | notes/goals.rst |
33 | 34 | notes/hacking.txt |
34 | 35 | notes/monitoring.rst |
35 | notes/principal.rst | |
36 | 36 | notes/release-process.rst |
37 | 37 | notes/store.rst |
38 | 38 | notes/structure.rst |