__init__.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # -*- coding: utf-8; indent-tabs-mode: nil; -*-
  2. #
  3. # This file is part of Radicale Server - Calendar Server
  4. # Copyright © 2008-2009 Guillaume Ayoub
  5. # Copyright © 2008 Nicolas Kandel
  6. # Copyright © 2008 Pascal Halter
  7. #
  8. # This library is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation, either version 3 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This library is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with Radicale. If not, see <http://www.gnu.org/licenses/>.
  20. # TODO: Manage errors (see xmlutils)
  21. # TODO: Forget twisted?
  22. from twisted.web.resource import Resource
  23. from twisted.web import http
  24. import posixpath
  25. import config
  26. import support
  27. import acl
  28. import xmlutils
  29. import calendar
  30. _users = acl.users()
  31. _calendars = support.calendars()
  32. class CalendarResource(Resource):
  33. """Twisted resource for requests at calendar depth (/user/calendar)."""
  34. # Tell twisted this is a leaf for requests
  35. isLeaf = True
  36. def __init__(self, user, cal):
  37. """Initialize by creating a calendar object.
  38. The calendar object corresponds to the stocked calendar named
  39. ``user``/``cal``.
  40. """
  41. Resource.__init__(self)
  42. self.calendar = calendar.Calendar(user, cal)
  43. def render_DELETE(self, request):
  44. """Manage DELETE ``request``."""
  45. obj = request.getHeader("if-match")
  46. answer = xmlutils.delete(obj, self.calendar, str(request.URLPath()))
  47. request.setResponseCode(http.NO_CONTENT)
  48. return answer
  49. def render_OPTIONS(self, request):
  50. """Manage OPTIONS ``request``."""
  51. request.setHeader("Allow", "DELETE, OPTIONS, PROPFIND, PUT, REPORT")
  52. request.setHeader("DAV", "1, calendar-access")
  53. request.setResponseCode(http.OK)
  54. return ""
  55. def render_PROPFIND(self, request):
  56. """Manage PROPFIND ``request``."""
  57. xml_request = request.content.read()
  58. answer = xmlutils.propfind(xml_request, self.calendar, str(request.URLPath()))
  59. request.setResponseCode(http.MULTI_STATUS)
  60. return answer
  61. def render_PUT(self, request):
  62. """Manage PUT ``request``."""
  63. # TODO: Improve charset detection
  64. contentType = request.getHeader("content-type")
  65. if contentType and "charset=" in contentType:
  66. charset = contentType.split("charset=")[1].strip()
  67. else:
  68. charset = config.get("encoding", "request")
  69. ical_request = request.content.read().decode(charset)
  70. obj = request.getHeader("if-match")
  71. xmlutils.put(ical_request, self.calendar, str(request.URLPath()), obj)
  72. request.setResponseCode(http.CREATED)
  73. return ""
  74. def render_REPORT(self, request):
  75. """Manage REPORT ``request``."""
  76. xml_request = request.content.read()
  77. answer = xmlutils.report(xml_request, self.calendar, str(request.URLPath()))
  78. request.setResponseCode(http.MULTI_STATUS)
  79. return answer
  80. class UserResource(Resource):
  81. """Twisted resource for requests at user depth (/user)."""
  82. def __init__(self, user):
  83. """Initialize by connecting requests to ``user`` calendars resources."""
  84. Resource.__init__(self)
  85. for cal in _calendars:
  86. if cal.startswith("%s%s"%(user, posixpath.sep)):
  87. cal_name = cal.split(posixpath.sep)[1]
  88. self.putChild(cal_name, CalendarResource(user, cal))
  89. def getChild(self, cal, request):
  90. """Get calendar resource if ``cal`` exists."""
  91. if cal in _calendars:
  92. return Resource.getChild(self, cal, request)
  93. else:
  94. return self
  95. class HttpResource(Resource):
  96. """Twisted resource for requests at root depth (/)."""
  97. def __init__(self):
  98. """Initialize by connecting requests to the users resources."""
  99. Resource.__init__(self)
  100. for user in _users:
  101. self.putChild(user, UserResource(user))
  102. def getChild(self, user, request):
  103. """Get user resource if ``user`` exists."""
  104. if user in _users:
  105. return Resource.getChild(self, user, request)
  106. else:
  107. return self