[CalendarServer-changes] [12874] CalendarServer/trunk/calendarserver/webadmin/principals.py
source_changes at macosforge.org
source_changes at macosforge.org
Mon Mar 10 18:14:57 PDT 2014
Revision: 12874
http://trac.calendarserver.org//changeset/12874
Author: wsanchez at apple.com
Date: 2014-03-10 18:14:56 -0700 (Mon, 10 Mar 2014)
Log Message:
-----------
Add some code for downloading calendar data.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/webadmin/principals.py
Modified: CalendarServer/trunk/calendarserver/webadmin/principals.py
===================================================================
--- CalendarServer/trunk/calendarserver/webadmin/principals.py 2014-03-10 23:37:41 UTC (rev 12873)
+++ CalendarServer/trunk/calendarserver/webadmin/principals.py 2014-03-11 01:14:56 UTC (rev 12874)
@@ -25,9 +25,17 @@
"PrincipalsResource",
]
+from cStringIO import StringIO
+from zipfile import ZipFile
+
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.web.template import tags as html, renderer
+from txweb2.stream import MemoryStream
+from txweb2.resource import Resource
+from txweb2.http import Response
+from txweb2.http_headers import MimeType
+
from .resource import PageElement, TemplateResource
@@ -104,12 +112,13 @@
addSlash = True
- def __init__(self, directory):
+ def __init__(self, directory, store):
TemplateResource.__init__(
self, lambda: PrincipalsPageElement(directory)
)
self._directory = directory
+ self._store = store
def getChild(self, name):
@@ -119,13 +128,13 @@
record = self._directory.recordWithUID(name)
if record:
- return PrincipalEditResource(record)
+ return PrincipalResource(record, self._store)
else:
return None
-class PrincipalEditPageElement(PageElement):
+class PrincipalPageElement(PageElement):
"""
Principal editing page element.
"""
@@ -150,21 +159,127 @@
-class PrincipalEditResource(TemplateResource):
+class PrincipalResource(TemplateResource):
"""
Principal editing resource.
"""
- addSlash = False
+ addSlash = True
- def __init__(self, record):
+ def __init__(self, record, store):
TemplateResource.__init__(
- self, lambda: PrincipalEditPageElement(record)
+ self, lambda: PrincipalPageElement(record)
)
+ self._record = record
+ self._store = store
+ def getChild(self, name):
+ if name == "":
+ return self
+
+ if name == "calendars_combined":
+ return PrincipalCalendarsExportResource(self._record, self._store)
+
+
+
+class PrincipalCalendarsExportResource(Resource):
+ """
+ Resource that vends a principal's calendars as iCalendar text.
+ """
+
+ addSlash = False
+
+
+ def __init__(self, record, store):
+ Resource.__init__(self)
+
+ self._record = record
+ self._store = store
+
+
+ @inlineCallbacks
+ def calendarComponents(self):
+ uid = self._record.uid
+
+ calendarComponents = []
+
+ txn = self._store.newTransaction()
+ try:
+ calendarHome = yield txn.calendarHomeWithUID(uid)
+
+ if calendarHome is None:
+ raise RuntimeError("No calendar home for UID: {}".format(uid))
+
+ for calendar in (yield calendarHome.calendars()):
+ name = calendar.displayName()
+
+ for calendarObject in (yield calendar.calendarObjects()):
+ perUser = yield calendarObject.filteredComponent(uid, True)
+ calendarComponents.add((name, perUser))
+
+ finally:
+ txn.abort()
+
+ returnValue(calendarComponents)
+
+
+ @inlineCallbacks
+ def iCalendarZipArchiveData(self):
+ calendarComponents = yield self.calendarComponents()
+
+ fileHandle = StringIO()
+ try:
+ zipFile = ZipFile(fileHandle, "w", allowZip64=True)
+ try:
+ zipFile.comment = (
+ "Calendars for UID: {}".format(self._record.uid)
+ )
+
+ names = set()
+
+ for name, component in calendarComponents:
+ if name in names:
+ i = 0
+ while True:
+ i += 1
+ nextName = "{} {:d}".format(name, i)
+ if nextName not in names:
+ name = nextName
+ break
+ assert i < len(calendarComponents)
+
+ text = component.getText().encode("utf-8")
+
+ zipFile.writestr(name.encode("utf-8"), text)
+
+ finally:
+ zipFile.close()
+
+ data = fileHandle.getvalue()
+ finally:
+ fileHandle.close()
+
+ returnValue(data)
+
+
+ @inlineCallbacks
+ def render(self, request):
+ response = Response()
+ response.stream = MemoryStream((yield self.iCalendarZipArchiveData()))
+
+ # FIXME: Use content-encoding instead?
+ response.headers.setHeader(
+ b"content-type",
+ MimeType.fromString(b"application/zip")
+ )
+
+ returnValue(response)
+
+
+
def searchTerms(request):
if not hasattr(request, "_search_terms"):
terms = set()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140310/12fb7778/attachment.html>
More information about the calendarserver-changes
mailing list