[CalendarServer-changes] [14645] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Apr 1 14:31:16 PDT 2015


Revision: 14645
          http://trac.calendarserver.org//changeset/14645
Author:   cdaboo at apple.com
Date:     2015-04-01 14:31:16 -0700 (Wed, 01 Apr 2015)
Log Message:
-----------
Proper trailing slash handling with unauth'd requests.

Modified Paths:
--------------
    CalendarServer/trunk/requirements-dev.txt
    CalendarServer/trunk/twistedcaldav/directory/calendar.py
    CalendarServer/trunk/twistedcaldav/directory/common.py
    CalendarServer/trunk/twistedcaldav/directory/principal.py
    CalendarServer/trunk/twistedcaldav/resource.py
    CalendarServer/trunk/txweb2/dav/resource.py

Modified: CalendarServer/trunk/requirements-dev.txt
===================================================================
--- CalendarServer/trunk/requirements-dev.txt	2015-04-01 21:27:23 UTC (rev 14644)
+++ CalendarServer/trunk/requirements-dev.txt	2015-04-01 21:31:16 UTC (rev 14645)
@@ -8,4 +8,4 @@
 q
 tl.eggdeps
 --editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVClientLibrary/trunk@13420#egg=CalDAVClientLibrary
---editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVTester/trunk@14535#egg=CalDAVTester
+--editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVTester/trunk@14644#egg=CalDAVTester

Modified: CalendarServer/trunk/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/calendar.py	2015-04-01 21:27:23 UTC (rev 14644)
+++ CalendarServer/trunk/twistedcaldav/directory/calendar.py	2015-04-01 21:31:16 UTC (rev 14645)
@@ -27,25 +27,28 @@
 ]
 
 from twext.python.log import Logger
+
 from txweb2 import responsecode
+from txweb2.auth.wrapper import UnauthorizedResponse
+from txweb2.dav.http import ErrorResponse
 from txweb2.dav.util import joinURL
-from txweb2.http import HTTPError, JSONResponse
+from txweb2.http import HTTPError, RedirectResponse, JSONResponse
 from txweb2.http_headers import ETag, MimeType
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue
 
+from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.config import config
 from twistedcaldav.directory.common import uidsResourceName, \
     CommonUIDProvisioningResource, CommonHomeTypeProvisioningResource
-
-from txdav.who.wiki import getWikiACL
 from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource, \
     DAVResourceWithChildrenMixin
 from twistedcaldav.resource import CalendarHomeResource
 
+from txdav.who.wiki import getWikiACL
+
 from uuid import uuid4
-from txweb2.dav.http import ErrorResponse
-from twistedcaldav.caldavxml import caldav_namespace
+import urllib
 
 
 log = Logger()
@@ -81,7 +84,32 @@
         return MimeType("httpd", "unix-directory")
 
 
+    @inlineCallbacks
+    def handleMissingTrailingSlash(self, request):
+        try:
+            _ignore_authnUser, authzUser = yield self.authenticate(request)
+        except Exception:
+            authzUser = None
 
+        # Turn 301 into 401
+        if authzUser is None:
+            response = (yield UnauthorizedResponse.makeResponse(
+                request.credentialFactories,
+                request.remoteAddr
+            ))
+            returnValue(response)
+        else:
+            response = RedirectResponse(
+                request.unparseURL(
+                    path=urllib.quote(
+                        urllib.unquote(request.path),
+                        safe=':/') + '/'
+                )
+            )
+            returnValue(response)
+
+
+
 class DirectoryCalendarHomeProvisioningResource (DirectoryCalendarProvisioningResource):
     """
     Resource which provisions calendar home collections as needed.
@@ -325,6 +353,7 @@
                 "The action parameter in the request-URI is not valid",
             ))
 
+
     def _ok(self, status, description, result=None):
         if result is None:
             result = {}

Modified: CalendarServer/trunk/twistedcaldav/directory/common.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/common.py	2015-04-01 21:27:23 UTC (rev 14644)
+++ CalendarServer/trunk/twistedcaldav/directory/common.py	2015-04-01 21:31:16 UTC (rev 14645)
@@ -90,19 +90,20 @@
 
     @inlineCallbacks
     def locateChild(self, request, segments):
-
         name = segments[0]
         if name == "":
             returnValue((self, ()))
 
         record = yield self.directory.recordWithUID(name)
-        if record:
-            child = yield self.homeResourceForRecord(record, request)
-            returnValue((child, segments[1:]))
-        else:
-            returnValue((None, ()))
+        if record is None:
+            returnValue(
+                (NotFoundResource(principalCollections=self.parent.principalCollections()), [])
+            )
 
+        child = yield self.homeResourceForRecord(record, request)
+        returnValue((child, segments[1:]))
 
+
     def listChildren(self):
         # Not a listable collection
         raise HTTPError(responsecode.FORBIDDEN)

Modified: CalendarServer/trunk/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/principal.py	2015-04-01 21:27:23 UTC (rev 14644)
+++ CalendarServer/trunk/twistedcaldav/directory/principal.py	2015-04-01 21:31:16 UTC (rev 14645)
@@ -60,9 +60,10 @@
 from txweb2 import responsecode
 from txweb2.auth.digest import DigestedCredentials
 from txweb2.auth.tls import TLSCredentials
+from txweb2.auth.wrapper import UnauthorizedResponse
 from txweb2.dav.noneprops import NonePropertyStore
 from txweb2.dav.util import joinURL
-from txweb2.http import HTTPError
+from txweb2.http import HTTPError, RedirectResponse
 
 try:
     from twistedcaldav.authkerb import NegotiateCredentials
@@ -907,6 +908,31 @@
         return True
 
 
+    @inlineCallbacks
+    def handleMissingTrailingSlash(self, request):
+        try:
+            _ignore_authnUser, authzUser = yield self.authenticate(request)
+        except Exception:
+            authzUser = None
+
+        # Turn 301 into 401
+        if authzUser is None:
+            response = (yield UnauthorizedResponse.makeResponse(
+                request.credentialFactories,
+                request.remoteAddr
+            ))
+            returnValue(response)
+        else:
+            response = RedirectResponse(
+                request.unparseURL(
+                    path=quote(
+                        unquote(request.path),
+                        safe=':/') + '/'
+                )
+            )
+            returnValue(response)
+
+
     def displayName(self):
         return self.record.displayName
 

Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py	2015-04-01 21:27:23 UTC (rev 14644)
+++ CalendarServer/trunk/twistedcaldav/resource.py	2015-04-01 21:31:16 UTC (rev 14645)
@@ -47,6 +47,7 @@
 from txdav.xml.element import dav_namespace
 
 from txweb2 import responsecode, http, http_headers
+from txweb2.auth.wrapper import UnauthorizedResponse
 from txweb2.dav.auth import AuthenticationWrapper as SuperAuthenticationWrapper
 from txweb2.dav.idav import IDAVPrincipalCollectionResource
 from txweb2.dav.resource import AccessDeniedError, DAVPrincipalCollectionResource, \
@@ -347,6 +348,31 @@
         returnValue(response)
 
 
+    @inlineCallbacks
+    def handleMissingTrailingSlash(self, request):
+        try:
+            _ignore_authnUser, authzUser = yield self.authenticate(request)
+        except Exception:
+            authzUser = None
+
+        # Turn 301 into 401
+        if authzUser is None:
+            response = (yield UnauthorizedResponse.makeResponse(
+                request.credentialFactories,
+                request.remoteAddr
+            ))
+            returnValue(response)
+        else:
+            response = RedirectResponse(
+                request.unparseURL(
+                    path=urllib.quote(
+                        urllib.unquote(request.path),
+                        safe=':/') + '/'
+                )
+            )
+            returnValue(response)
+
+
     # Begin transitional new-store resource interface:
 
     def copyDeadPropertiesTo(self, other):
@@ -1720,6 +1746,31 @@
         return True
 
 
+    @inlineCallbacks
+    def handleMissingTrailingSlash(self, request):
+        try:
+            _ignore_authnUser, authzUser = yield self.authenticate(request)
+        except Exception:
+            authzUser = None
+
+        # Turn 301 into 401
+        if authzUser is None:
+            response = (yield UnauthorizedResponse.makeResponse(
+                request.credentialFactories,
+                request.remoteAddr
+            ))
+            returnValue(response)
+        else:
+            response = RedirectResponse(
+                request.unparseURL(
+                    path=urllib.quote(
+                        urllib.unquote(request.path),
+                        safe=':/') + '/'
+                )
+            )
+            returnValue(response)
+
+
     def calendarsEnabled(self):
         return config.EnableCalDAV
 

Modified: CalendarServer/trunk/txweb2/dav/resource.py
===================================================================
--- CalendarServer/trunk/txweb2/dav/resource.py	2015-04-01 21:27:23 UTC (rev 14644)
+++ CalendarServer/trunk/txweb2/dav/resource.py	2015-04-01 21:31:16 UTC (rev 14645)
@@ -2354,13 +2354,7 @@
         # If this is a collection and the URI doesn't end in "/", redirect.
         #
         if self.isCollection() and request.path[-1:] != "/":
-            return RedirectResponse(
-                request.unparseURL(
-                    path=urllib.quote(
-                        urllib.unquote(request.path),
-                        safe=':/') + '/'
-                )
-            )
+            return self.handleMissingTrailingSlash(request)
 
         def setHeaders(response):
             response = IResponse(response)
@@ -2390,7 +2384,17 @@
         return d.addCallbacks(setHeaders, onError)
 
 
+    def handleMissingTrailingSlash(self, request):
+        return RedirectResponse(
+            request.unparseURL(
+                path=urllib.quote(
+                    urllib.unquote(request.path),
+                    safe=':/') + '/'
+            )
+        )
 
+
+
 class DAVLeafResource (DAVResource, LeafResource):
     """
     DAV resource with no children.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20150401/c5abf7ad/attachment-0001.html>


More information about the calendarserver-changes mailing list