[CalendarServer-changes] [5481] CalendarServer/trunk/twistedcaldav/method
source_changes at macosforge.org
source_changes at macosforge.org
Thu Apr 15 13:58:42 PDT 2010
Revision: 5481
http://trac.macosforge.org/projects/calendarserver/changeset/5481
Author: cdaboo at apple.com
Date: 2010-04-15 13:58:40 -0700 (Thu, 15 Apr 2010)
Log Message:
-----------
CardDAV specific clean-up.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/method/put.py
CalendarServer/trunk/twistedcaldav/method/put_addressbook_common.py
CalendarServer/trunk/twistedcaldav/method/report_addressbook_multiget.py
CalendarServer/trunk/twistedcaldav/method/report_addressbook_query.py
Modified: CalendarServer/trunk/twistedcaldav/method/put.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/put.py 2010-04-15 19:05:29 UTC (rev 5480)
+++ CalendarServer/trunk/twistedcaldav/method/put.py 2010-04-15 20:58:40 UTC (rev 5481)
@@ -93,11 +93,14 @@
# Read the vcard component from the stream
try:
vcarddata = (yield allDataFromStream(request.stream))
+ if not hasattr(request, "extendedLogItems"):
+ request.extendedLogItems = {}
+ request.extendedLogItems["cl"] = str(len(vcarddata)) if vcarddata else "0"
# We must have some data at this point
if vcarddata is None:
# Use correct DAV:error response
- raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, "valid-address-data")))
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, "valid-address-data"), description="No vcard data"))
storer = StoreAddressObjectResource(
request = request,
Modified: CalendarServer/trunk/twistedcaldav/method/put_addressbook_common.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/put_addressbook_common.py 2010-04-15 19:05:29 UTC (rev 5480)
+++ CalendarServer/trunk/twistedcaldav/method/put_addressbook_common.py 2010-04-15 20:58:40 UTC (rev 5481)
@@ -20,17 +20,17 @@
__all__ = ["StoreAddressObjectResource"]
+import os
import types
from twisted.internet import reactor
from twisted.internet.defer import Deferred, inlineCallbacks, succeed
-from twisted.internet.defer import maybeDeferred, returnValue
+from twisted.internet.defer import returnValue
from twisted.python import failure
from twext.python.filepath import CachingFilePath as FilePath
from twext.web2 import responsecode
from twext.web2.dav import davxml
from twext.web2.dav.element.base import dav_namespace
-from twext.web2.dav.element.base import PCDATAElement
from twext.web2.dav.fileop import delete
from twext.web2.dav.http import ErrorResponse
from twext.web2.dav.resource import TwistedGETContentMD5
@@ -38,16 +38,13 @@
from twext.web2.dav.util import joinURL, parentForURL
from twext.web2.http import HTTPError
from twext.web2.http import StatusResponse
-from twext.web2.iweb import IResponse
from twext.web2.stream import MemoryStream
from twistedcaldav.config import config
-from twistedcaldav.caldavxml import NumberOfRecurrencesWithinLimits
from twistedcaldav.carddavxml import NoUIDConflict, carddav_namespace
from twistedcaldav.fileops import copyToWithXAttrs
from twistedcaldav.fileops import putWithXAttrs
from twistedcaldav.fileops import copyWithXAttrs
-from twistedcaldav.instance import TooManyInstancesError
from twistedcaldav.vcard import Component
from twistedcaldav.vcardindex import ReservationError
from twext.python.log import Logger
@@ -268,7 +265,7 @@
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, "valid-address-data")))
# Valid vcard data for CalDAV check
- result, message = self.validCardDAVDataCheck()
+ result, message = self.validAddressDataCheck()
if not result:
log.err(message)
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, "valid-addressbook-object-resource")))
@@ -323,7 +320,7 @@
return result, message
- def validCardDAVDataCheck(self):
+ def validAddressDataCheck(self):
"""
Check that the vcard data is valid vCard.
@return: tuple: (True/False if the vcard data is valid,
@@ -343,22 +340,6 @@
return result, message
- def validCalDAVDataCheck(self):
- """
- Check that the vcard data is valid as a CalDAV vcard object resource.
- @return: tuple: (True/False if the vcard data is valid,
- log message string).
- """
- result = True
- message = ""
- try:
- self.vcard.validateForCardDAV()
- except ValueError, e:
- result = False
- message = "Calendar data does not conform to CalDAV requirements: %s" % (e,)
-
- return result, message
-
def validSizeCheck(self):
"""
Make sure that the content-type of the source resource is text/vcard.
@@ -451,11 +432,15 @@
so rename the original file in case we need to rollback.
"""
+ def _createRollbackPath(path):
+ parent, child = os.path.split(path)
+ child = "." + child + ".rollback"
+ return os.path.join(parent, child)
+
self.rollback = StoreAddressObjectResource.RollbackState(self)
self.overwrite = self.destination.exists()
if self.overwrite:
- self.rollback.destination_copy = FilePath(self.destination.fp.path)
- self.rollback.destination_copy.path += ".rollback"
+ self.rollback.destination_copy = FilePath(_createRollbackPath(self.destination.fp.path))
copyToWithXAttrs(self.destination.fp, self.rollback.destination_copy)
log.debug("Rollback: backing up destination %s to %s" % (self.destination.fp.path, self.rollback.destination_copy.path))
else:
@@ -463,8 +448,7 @@
log.debug("Rollback: will create new destination %s" % (self.destination.fp.path,))
if self.deletesource:
- self.rollback.source_copy = FilePath(self.source.fp.path)
- self.rollback.source_copy.path += ".rollback"
+ self.rollback.source_copy = FilePath(_createRollbackPath(self.source.fp.path))
copyToWithXAttrs(self.source.fp, self.rollback.source_copy)
log.debug("Rollback: backing up source %s to %s" % (self.source.fp.path, self.rollback.source_copy.path))
@@ -472,27 +456,19 @@
def doStore(self):
# Do put or copy based on whether source exists
if self.source is not None:
- response = maybeDeferred(copyWithXAttrs, self.source.fp, self.destination.fp, self.destination_uri)
+ response = (yield copyWithXAttrs(self.source.fp, self.destination.fp, self.destination_uri))
else:
if self.vcarddata is None:
self.vcarddata = str(self.vcard)
md5 = MD5StreamWrapper(MemoryStream(self.vcarddata))
- response = maybeDeferred(putWithXAttrs, md5, self.destination.fp)
- response = (yield response)
-
- # Update the MD5 value on the resource
- if self.source is not None:
- # Copy MD5 value from source to destination
- if self.source.hasDeadProperty(TwistedGETContentMD5):
- md5 = self.source.readDeadProperty(TwistedGETContentMD5)
- self.destination.writeDeadProperty(md5)
- else:
+ response = (yield putWithXAttrs(md5, self.destination.fp))
+
# Finish MD5 calculation and write dead property
md5.close()
md5 = md5.getMD5()
self.destination.writeDeadProperty(TwistedGETContentMD5.fromString(md5))
- returnValue(IResponse(response))
+ returnValue(response)
@inlineCallbacks
def doSourceDelete(self):
@@ -542,17 +518,8 @@
"""
# Add or update the index for this resource.
- try:
- self.source_index.addResource(self.source.fp.basename(), self.vcard, self.newrevision)
- except TooManyInstancesError, ex:
- raise HTTPError(ErrorResponse(
- responsecode.FORBIDDEN,
- NumberOfRecurrencesWithinLimits(PCDATAElement(str(ex.max_allowed)))
- ))
+ self.source_index.addResource(self.source.fp.basename(), self.vcard, self.newrevision)
- self.source.writeDeadProperty(davxml.GETContentType.fromString("text/vcard"))
- return None
-
def doDestinationIndex(self, vcardtoindex):
"""
Do destination resource indexing, replacing any index previous stored.
@@ -569,8 +536,9 @@
self.destination_index.addResource(self.destination.fp.basename(), vcardtoindex, self.newrevision)
log.debug("Destination indexed %s" % (self.destination.fp.path,))
except (ValueError, TypeError), ex:
- log.err("Cannot index vcard resource: %s" % (ex,))
- raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, "valid-address-data")))
+ msg = "Cannot index vcard resource: %s" % (ex,)
+ log.err(msg)
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, "valid-address-data"), description=msg))
self.destination.writeDeadProperty(davxml.GETContentType.fromString("text/vcard"))
return None
Modified: CalendarServer/trunk/twistedcaldav/method/report_addressbook_multiget.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/report_addressbook_multiget.py 2010-04-15 19:05:29 UTC (rev 5480)
+++ CalendarServer/trunk/twistedcaldav/method/report_addressbook_multiget.py 2010-04-15 20:58:40 UTC (rev 5481)
@@ -20,7 +20,6 @@
__all__ = ["report_urn_ietf_params_xml_ns_carddav_addressbook_multiget"]
-import time
from urllib import unquote
from twisted.internet.defer import inlineCallbacks, returnValue
@@ -41,6 +40,7 @@
log = Logger()
+max_number_of_addressbook_multigets = 5000
@inlineCallbacks
def report_urn_ietf_params_xml_ns_carddav_addressbook_multiget(self, request, multiget):
@@ -49,8 +49,6 @@
(CardDAV, section 8.7)
"""
- startTime = time.time()
-
# Verify root element
if multiget.qname() != (carddav_namespace, "addressbook-multiget"):
raise ValueError("{CardDAV:}addressbook-multiget expected as root element, not %s." % (multiget.sname(),))
@@ -67,6 +65,15 @@
propertyreq = multiget.property
resources = multiget.resources
+ if not hasattr(request, "extendedLogItems"):
+ request.extendedLogItems = {}
+ request.extendedLogItems["rcount"] = len(resources)
+
+ # Check size of results is within limit
+ if len(resources) > max_number_of_addressbook_multigets:
+ log.err("Too many results in multiget report: %d" % len(resources))
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, davxml.NumberOfMatchesWithinLimits()))
+
if propertyreq.qname() == ("DAV:", "allprop"):
propertiesForResource = report_common.allPropertiesForResource
@@ -227,11 +234,23 @@
# Get properties for all valid readable resources
for resource, href in ok_resources:
- yield report_common.responseForHrefAB(request, responses, davxml.HRef.fromString(href), resource, propertiesForResource, propertyreq)
-
- # Indicate error for all valid non-readable resources
- for ignore_resource, href in bad_resources: #@UnusedVariable
- responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
+ try:
+ yield report_common.responseForHrefAB(request, responses, davxml.HRef.fromString(href), resource, propertiesForResource, propertyreq)
+ except ValueError:
+ log.err("Invalid address resource during multiget: %s" % (href,))
+ responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
+ except IOError:
+ # This can happen because of a race-condition between the
+ # time we determine which resources exist and the deletion
+ # of one of these resources in another request. In this
+ # case, return a 404 for the now missing resource rather
+ # than raise an error for the entire report.
+ log.err("Missing calendar resource during multiget: %s" % (href,))
+ responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.NOT_FOUND)))
+
+ # Indicate error for all valid non-readable resources
+ for ignore_resource, href in bad_resources: #@UnusedVariable
+ responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
finally:
if directoryAddressBookLock:
@@ -309,10 +328,4 @@
yield report_common.responseForHrefAB(request, responses, href, child, propertiesForResource, propertyreq)
- retValue = MultiStatusResponse(responses)
-
- elaspedTime = time.time() - startTime
- self.log_info("Timing: CARDDAV:addressbook-multiget Report total: %.1f ms" % (elaspedTime*1000,))
-
- returnValue(retValue)
-
+ returnValue(MultiStatusResponse(responses))
Modified: CalendarServer/trunk/twistedcaldav/method/report_addressbook_query.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/report_addressbook_query.py 2010-04-15 19:05:29 UTC (rev 5480)
+++ CalendarServer/trunk/twistedcaldav/method/report_addressbook_query.py 2010-04-15 20:58:40 UTC (rev 5481)
@@ -21,7 +21,6 @@
__all__ = ["report_urn_ietf_params_xml_ns_carddav_addressbook_query"]
import urllib
-import time
from twisted.internet.defer import succeed, inlineCallbacks, returnValue, maybeDeferred
@@ -40,16 +39,12 @@
log = Logger()
-
@inlineCallbacks
def report_urn_ietf_params_xml_ns_carddav_addressbook_query(self, request, addressbook_query):
"""
Generate an addressbook-query REPORT.
(CardDAV, section 8.6)
"""
- startTime = time.time()
- #print("Timing: report_urn_ietf_params_xml_ns_carddav_addressbook_query.starttime=%f" % startTime)
-
# Verify root element
if addressbook_query.qname() != (carddav_namespace, "addressbook-query"):
raise ValueError("{CardDAV:}addressbook-query expected as root element, not %s." % (addressbook_query.sname(),))
@@ -161,8 +156,6 @@
directoryAddressBookLock = None
try:
- #self.maxDSQueryRecords and len(queryResults) >= self.maxDSQueryRecords
-
if addrresource.isDirectoryBackedAddressBookCollection() and addrresource.directory.cacheQuery:
directory = addrresource.directory
@@ -290,10 +283,9 @@
#davxml.ResponseDescription("Results limited by %s at %d" % resultsWereLimited),
davxml.ResponseDescription("Results limited to %d items" % e.maxLimit()),
))
-
- retValue = MultiStatusResponse(responses)
- elaspedTime = time.time() - startTime
- self.log_info("Timing: CARDDAV:addressbook-query Report total: %.1f ms" % (elaspedTime*1000,))
+ if not hasattr(request, "extendedLogItems"):
+ request.extendedLogItems = {}
+ request.extendedLogItems["responses"] = len(responses)
- returnValue(retValue)
+ returnValue(MultiStatusResponse(responses))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100415/d6555d3a/attachment-0001.html>
More information about the calendarserver-changes
mailing list