[CalendarServer-changes] [8051] CalendarServer/trunk/txdav/caldav/datastore
source_changes at macosforge.org
source_changes at macosforge.org
Tue Sep 6 14:19:52 PDT 2011
Revision: 8051
http://trac.macosforge.org/projects/calendarserver/changeset/8051
Author: cdaboo at apple.com
Date: 2011-09-06 14:19:52 -0700 (Tue, 06 Sep 2011)
Log Message:
-----------
Fix migration error when attachments are missing a content-type.
Modified Paths:
--------------
CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py
CalendarServer/trunk/txdav/caldav/datastore/util.py
Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py 2011-09-06 19:37:25 UTC (rev 8050)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py 2011-09-06 21:19:52 UTC (rev 8051)
@@ -18,11 +18,16 @@
Tests for txdav.caldav.datastore.util.
"""
+from twext.web2.http_headers import MimeType
+
from twisted.internet.defer import inlineCallbacks
+
from twistedcaldav.ical import Component
from twistedcaldav.test.util import TestCase
-from txdav.caldav.datastore.util import dropboxIDFromCalendarObject
+from txdav.caldav.datastore.util import dropboxIDFromCalendarObject,\
+ StorageTransportBase
+
class DropboxIDTests(TestCase):
"""
Test dropbox ID extraction from calendar data.
@@ -270,3 +275,29 @@
(yield dropboxIDFromCalendarObject(resource)),
"%s.dropbox" % (result,),
)
+
+class StorageTransportTests(TestCase):
+
+ def test_MissingContentType(self):
+
+ test_files = (
+ ("plain.txt", MimeType.fromString("text/plain"),),
+ ("word.doc", MimeType.fromString("application/msword"),),
+ ("markup.xml", MimeType.fromString("application/xml"),),
+ ("octet", MimeType.fromString("application/octet-stream"),),
+ ("bogus.bog", MimeType.fromString("application/octet-stream"),),
+ )
+
+ class FakeAttachment(object):
+
+ def __init__(self, name):
+ self._name = name
+
+ def name(self):
+ return self._name
+
+ for filename, result in test_files:
+ item = StorageTransportBase(FakeAttachment(filename), None)
+ self.assertEquals(item._contentType, result)
+ item = StorageTransportBase(FakeAttachment(filename), result)
+ self.assertEquals(item._contentType, result)
Modified: CalendarServer/trunk/txdav/caldav/datastore/util.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/util.py 2011-09-06 19:37:25 UTC (rev 8050)
+++ CalendarServer/trunk/txdav/caldav/datastore/util.py 2011-09-06 21:19:52 UTC (rev 8051)
@@ -19,20 +19,24 @@
Utility logic common to multiple backend implementations.
"""
+from twext.python.log import Logger
+from twext.python.vcomponent import InvalidICalendarDataError
+from twext.python.vcomponent import VComponent
+from twext.web2 import http_headers
+
from twisted.internet.defer import inlineCallbacks, Deferred, returnValue
from twisted.internet.protocol import Protocol
-from twext.python.vcomponent import InvalidICalendarDataError
-from twext.python.vcomponent import VComponent
+from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
+from twistedcaldav.datafilters.privateevents import PrivateEventFilter
-from txdav.common.icommondatastore import InvalidObjectResourceError, \
- NoSuchObjectResourceError, InternalDataStoreError
+from txdav.caldav.icalendarstore import IAttachmentStorageTransport
+from txdav.common.icommondatastore import InvalidObjectResourceError, NoSuchObjectResourceError, InternalDataStoreError
-from twistedcaldav.datafilters.privateevents import PrivateEventFilter
-from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
from zope.interface.declarations import implements
-from txdav.caldav.icalendarstore import IAttachmentStorageTransport
-from twext.python.log import Logger
+
+import os
+
log = Logger()
def validateCalendarComponent(calendarObject, calendar, component, inserting):
@@ -189,6 +193,52 @@
returnValue((ok_count, bad_count,))
+
+# MIME helpers - mostly copied from twext.web2.static
+
+def loadMimeTypes(mimetype_locations=['/etc/mime.types']):
+ """
+ Multiple file locations containing mime-types can be passed as a list.
+ The files will be sourced in that order, overriding mime-types from the
+ files sourced beforehand, but only if a new entry explicitly overrides
+ the current entry.
+ """
+ import mimetypes
+ # Grab Python's built-in mimetypes dictionary.
+ contentTypes = mimetypes.types_map #@UndefinedVariable
+ # Update Python's semi-erroneous dictionary with a few of the
+ # usual suspects.
+ contentTypes.update(
+ {
+ '.conf': 'text/plain',
+ '.diff': 'text/plain',
+ '.exe': 'application/x-executable',
+ '.flac': 'audio/x-flac',
+ '.java': 'text/plain',
+ '.ogg': 'application/ogg',
+ '.oz': 'text/x-oz',
+ '.swf': 'application/x-shockwave-flash',
+ '.tgz': 'application/x-gtar',
+ '.wml': 'text/vnd.wap.wml',
+ '.xul': 'application/vnd.mozilla.xul+xml',
+ '.py': 'text/plain',
+ '.patch': 'text/plain',
+ }
+ )
+ # Users can override these mime-types by loading them out configuration
+ # files (this defaults to ['/etc/mime.types']).
+ for location in mimetype_locations:
+ if os.path.exists(location):
+ contentTypes.update(mimetypes.read_mime_types(location))
+
+ return contentTypes
+
+def getType(filename, types, defaultType="application/octet-stream"):
+ _ignore_p, ext = os.path.splitext(filename)
+ ext = ext.lower()
+ return types.get(ext, defaultType)
+
+
class _AttachmentMigrationProto(Protocol, object):
def __init__(self, storeTransport):
self.storeTransport = storeTransport
@@ -277,9 +327,9 @@
calendar = self.calendar()
isOwner = asAdmin or (calendar._owned and
calendar.ownerCalendarHome().uid() == accessUID)
- for filter in [PrivateEventFilter(self.accessMode, isOwner),
+ for data_filter in [PrivateEventFilter(self.accessMode, isOwner),
PerUserDataFilter(accessUID)]:
- component = filter.filter(component)
+ component = data_filter.filter(component)
returnValue(component)
@@ -313,7 +363,6 @@
return '<Storing Attachment: %r%s>' % (self.attachment.name(), host)
-
class StorageTransportBase(object):
"""
Base logic shared between file- and sql-based L{IAttachmentStorageTransport}
@@ -322,6 +371,8 @@
implements(IAttachmentStorageTransport)
+ contentTypes = loadMimeTypes()
+
def __init__(self, attachment, contentType):
"""
Create a storage transport with a reference to an L{IAttachment} and a
@@ -329,6 +380,10 @@
"""
self._attachment = attachment
self._contentType = contentType
+
+ # Make sure we have some kind of contrent-type
+ if self._contentType is None:
+ self._contentType = http_headers.MimeType.fromString(getType(self._attachment.name(), self.contentTypes))
def getPeer(self):
@@ -341,5 +396,3 @@
def writeSequence(self, seq):
return self.write(''.join(seq))
-
-
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110906/1adeb351/attachment.html>
More information about the calendarserver-changes
mailing list