def getProperty(self, respath, propertyname, propertyns):
     if propertyns == 'DAV:':
         isfile = os.path.isfile(respath)
         if propertyname == 'creationdate':
             statresults = os.stat(respath)
             return httpdatehelper.getstrftime(statresults[stat.ST_CTIME])
         elif propertyname == 'getcontenttype':
             return self.getContentType(respath)
         elif propertyname == 'resourcetype':
             if os.path.isdir(respath):
                 return '<D:collection />'
             else:
                 return ''
         elif propertyname == 'getlastmodified':
             statresults = os.stat(respath)
             return httpdatehelper.getstrftime(statresults[stat.ST_MTIME])
         elif propertyname == 'getcontentlength':
             if isfile:
                 statresults = os.stat(respath)
                 return str(statresults[stat.ST_SIZE])
             raise HTTPRequestException(
                 processrequesterrorhandler.HTTP_NOT_FOUND)
         elif propertyname == 'getetag':
             return self.getEntityTag(respath)
     raise HTTPRequestException(processrequesterrorhandler.HTTP_NOT_FOUND)
示例#2
0
    def __call__(self, environ, start_response):
        self._srvcfg = environ['pyfileserver.config']

        requestmethod = environ['REQUEST_METHOD']
        requestpath = urllib.unquote(environ['PATH_INFO'])

        if requestmethod == 'TRACE':
            return self.doTRACE(environ, start_response)

        if requestpath == '*' and requestmethod == 'OPTIONS':
            return self.doOPTIONS(environ, start_response)

        if requestpath == '/' and requestmethod == 'OPTIONS':  #hotfix for WinXP
            return self.doOPTIONS(environ, start_response)

        if 'config_mapping' not in environ['pyfileserver.config']:
            if requestmethod == 'GET':
                self.printConfigErrorMessage()
            else:
                raise HTTPRequestException(
                    processrequesterrorhandler.HTTP_NOT_FOUND)

        (mappedrealm, mappedpath, displaypath,
         resourceAL) = self.resolveRealmURI(environ['pyfileserver.config'],
                                            requestpath)

        if mappedrealm is None:
            raise HTTPRequestException(
                processrequesterrorhandler.HTTP_NOT_FOUND)

        environ['pyfileserver.mappedrealm'] = mappedrealm
        environ['pyfileserver.mappedpath'] = mappedpath
        environ['pyfileserver.mappedURI'] = displaypath
        environ['pyfileserver.resourceAL'] = resourceAL

        if 'HTTP_DESTINATION' in environ:
            desturl = websupportfuncs.getRelativeURL(
                environ['HTTP_DESTINATION'], environ)
            desturl = urllib.unquote(desturl)
            (destrealm, destpath, destdisplaypath,
             destresourceAL) = self.resolveRealmURI(
                 environ['pyfileserver.config'], desturl)

            if destrealm is None:
                raise HTTPRequestException(
                    processrequesterrorhandler.HTTP_BAD_REQUEST)

            environ['pyfileserver.destrealm'] = destrealm
            environ['pyfileserver.destpath'] = destpath
            environ['pyfileserver.destURI'] = destdisplaypath
            environ['pyfileserver.destresourceAL'] = destresourceAL

        if requestmethod == 'OPTIONS':
            return self.doOPTIONSSpec(environ, start_response)

        return self._application(environ, start_response)
示例#3
0
def evaluateHTTPConditionals(resourceAL, respath, lastmodified, entitytag, environ, isnewfile=False):
    ## Conditions

    # An HTTP/1.1 origin server, upon receiving a conditional request that includes both a Last-Modified date
    # (e.g., in an If-Modified-Since or If-Unmodified-Since header field) and one or more entity tags (e.g., 
    # in an If-Match, If-None-Match, or If-Range header field) as cache validators, MUST NOT return a response 
    # status of 304 (Not Modified) unless doing so is consistent with all of the conditional header fields in 
    # the request.

    if 'HTTP_IF_MATCH' in environ and resourceAL.supportEntityTag(respath):
        if isnewfile:
            raise HTTPRequestException(processrequesterrorhandler.HTTP_PRECONDITION_FAILED)
        else:
            ifmatchlist = environ['HTTP_IF_MATCH'].split(",")
            for ifmatchtag in ifmatchlist:
                ifmatchtag = ifmatchtag.strip(" \"\t")
                if ifmatchtag == entitytag or ifmatchtag == '*':
                    break   
                raise HTTPRequestException(processrequesterrorhandler.HTTP_PRECONDITION_FAILED)

    # If-None-Match 
    # If none of the entity tags match, then the server MAY perform the requested method as if the 
    # If-None-Match header field did not exist, but MUST also ignore any If-Modified-Since header field
    # (s) in the request. That is, if no entity tags match, then the server MUST NOT return a 304 (Not Modified) 
    # response.
    ignoreifmodifiedsince = False         
    if 'HTTP_IF_NONE_MATCH' in environ and resourceAL.supportEntityTag(respath):         
        if isnewfile:
            ignoreifmodifiedsince = True
        else:
            ifmatchlist = environ['HTTP_IF_NONE_MATCH'].split(",")
            for ifmatchtag in ifmatchlist:
                ifmatchtag = ifmatchtag.strip(" \"\t")
                if ifmatchtag == entitytag or ifmatchtag == '*':
                    raise HTTPRequestException(processrequesterrorhandler.HTTP_PRECONDITION_FAILED)
            ignoreifmodifiedsince = True

    if not isnewfile and 'HTTP_IF_UNMODIFIED_SINCE' in environ and resourceAL.supportLastModified(respath):
        ifunmodtime = httpdatehelper.getsecstime(environ['HTTP_IF_UNMODIFIED_SINCE'])
        if ifunmodtime:
            if ifunmodtime <= lastmodified:
                raise HTTPRequestException(processrequesterrorhandler.HTTP_PRECONDITION_FAILED)

    if not isnewfile and 'HTTP_IF_MODIFIED_SINCE' in environ and not ignoreifmodifiedsince and resourceAL.supportLastModified(respath):
        ifmodtime = httpdatehelper.getsecstime(environ['HTTP_IF_MODIFIED_SINCE'])
        if ifmodtime:
            if ifmodtime > lastmodified:
                raise HTTPRequestException(processrequesterrorhandler.HTTP_NOT_MODIFIED)
 def doOPTIONSSpec(self, environ, start_response):
     mappedpath = environ['pyfileserver.mappedpath']
     if os.path.isdir(mappedpath):
         start_response('200 OK', [
             ('Content-Type', 'text/html'), ('Content-Length', '0'),
             ('Allow',
              'OPTIONS HEAD GET DELETE PROPFIND PROPPATCH COPY MOVE LOCK UNLOCK'
              ), ('DAV', '1,2'), ('Server', 'DAV/2'),
             ('Date', httpdatehelper.getstrftime())
         ])
     elif os.path.isfile(mappedpath):
         start_response('200 OK', [
             ('Content-Type', 'text/html'), ('Content-Length', '0'),
             ('Allow',
              'OPTIONS HEAD GET PUT DELETE PROPFIND PROPPATCH COPY MOVE LOCK UNLOCK'
              ), ('DAV', '1,2'), ('Allow-Ranges', 'bytes'),
             ('Date', httpdatehelper.getstrftime())
         ])
     elif os.path.isdir(os.path.dirname(mappedpath)):
         start_response('200 OK', [('Content-Type', 'text/html'),
                                   ('Content-Length', '0'),
                                   ('Allow', 'OPTIONS PUT MKCOL'),
                                   ('DAV', '1,2'),
                                   ('Date', httpdatehelper.getstrftime())])
     else:
         raise HTTPRequestException(
             processrequesterrorhandler.HTTP_NOT_FOUND)
     # @@: I'd say that return [''] is generally better, as you don't set up an unnecessary
     # generator context
     yield ''
     return
示例#5
0
    def doOPTIONSSpec(self, environ, start_response):
        resourceAL = environ['pyfileserver.resourceAL']

        headers = []
        if resourceAL.isCollection(environ['pyfileserver.mappedpath']):
            headers.append((
                'Allow',
                'OPTIONS HEAD GET DELETE PROPFIND PROPPATCH COPY MOVE LOCK UNLOCK'
            ))
        elif resourceAL.isResource(environ['pyfileserver.mappedpath']):
            headers.append((
                'Allow',
                'OPTIONS HEAD GET PUT DELETE PROPFIND PROPPATCH COPY MOVE LOCK UNLOCK'
            ))
            if resourceAL.supportRanges():
                headers.append(('Allow-Ranges', 'bytes'))
        elif resourceAL.isCollection(
                resourceAL.getContainingCollection(
                    environ['pyfileserver.mappedpath'])):
            headers.append(('Allow', 'OPTIONS PUT MKCOL'))
        else:
            raise HTTPRequestException(
                processrequesterrorhandler.HTTP_NOT_FOUND)
        headers.append(('Content-Type', 'text/html'))
        headers.append(('Content-Length', '0'))
        headers.append(('DAV', '1,2'))
        headers.append(('Server', 'DAV/2'))
        headers.append(('Date', httpdatehelper.getstrftime()))
        start_response('200 OK', headers)
        return ['']
def getProperty(pm, lm, resourceAL, mappedpath, displaypath, propns, propname):
    if propns is None:
        propns = ''

    # live properties
    if resourceAL.isPropertySupported(mappedpath, propname, propns):
        return resourceAL.getProperty(mappedpath, propname, propns)

    # reserved properties
    if propns == 'DAV:':
        reservedprops = [
            'creationdate', 'displayname', 'getcontenttype', 'resourcetype',
            'getlastmodified', 'getcontentlength', 'getetag',
            'getcontentlanguage', 'source', 'lockdiscovery', 'supportedlock'
        ]
        if propname == 'displayname':
            return displaypath
        elif propname == 'lockdiscovery':
            lockinfo = ''
            activelocklist = locklibrary.getTokenListForUrl(lm, displaypath)
            for activelocktoken in activelocklist:
                lockinfo = lockinfo + '<D:activelock>\n'
                lockinfo = lockinfo + '<D:locktype><' + locklibrary.getLockProperty(
                    lm, activelocktoken, 'LOCKTYPE') + '/></D:locktype>\n'
                lockinfo = lockinfo + '<D:lockscope><' + locklibrary.getLockProperty(
                    lm, activelocktoken, 'LOCKSCOPE') + '/></D:lockscope>\n'
                lockinfo = lockinfo + '<D:depth>' + locklibrary.getLockProperty(
                    lm, activelocktoken, 'LOCKDEPTH') + '</D:depth>\n'
                lockinfo = lockinfo + '<D:owner>' + locklibrary.getLockProperty(
                    lm, activelocktoken, 'LOCKOWNER') + '</D:owner>\n'
                lockinfo = lockinfo + '<D:timeout>' + locklibrary.getLockProperty(
                    lm, activelocktoken, 'LOCKTIME') + '</D:timeout>\n'
                lockinfo = lockinfo + '<D:locktoken><D:href>' + activelocktoken + '</D:href></D:locktoken>\n'
                lockinfo = lockinfo + '</D:activelock>\n'
            return lockinfo
        elif propname == 'supportedlock':
            return '<D:lockentry xmlns:D=\"DAV:\" >\n<D:lockscope><D:exclusive/></D:lockscope>\n<D:locktype><D:write/></D:locktype>\n</D:lockentry>\n<D:lockentry xmlns:D=\"DAV:\" >\n<D:lockscope><D:shared/></D:lockscope>\n<D:locktype><D:write/></D:locktype>\n</D:lockentry>'
        elif propname in reservedprops:
            raise HTTPRequestException(
                processrequesterrorhandler.HTTP_NOT_FOUND)

    # dead properties
    propvalue = pm.getProperty(displaypath, propname, propns)
    if propvalue is None:
        raise HTTPRequestException(processrequesterrorhandler.HTTP_NOT_FOUND)
    else:
        return propvalue
def writeProperty(pm,
                  resourceAL,
                  mappedpath,
                  displaypath,
                  propns,
                  propname,
                  propupdatemethod,
                  propvalue,
                  reallydoit=True):

    if propns is None:
        propns = ''

    # live properties
    if resourceAL.isPropertySupported(mappedpath, propname, propns):
        if reallydoit:
            if propupdatemethod == 'set':
                resourceAL.writeProperty(mappedpath, propname, propns,
                                         propvalue)
            elif propupdatemethod == 'remove':
                resourceAL.removeProperty(mappedpath, propname, propns)
        return

    # raise exception for those reserved DAV: properties not supported by live properties
    reservedprops = [
        'creationdate', 'displayname', 'getcontenttype', 'resourcetype',
        'getlastmodified', 'getcontentlength', 'getetag', 'getcontentlanguage',
        'source', 'lockdiscovery', 'supportedlock'
    ]
    if propns == 'DAV:':
        if propname in reservedprops:
            raise HTTPRequestException(
                processrequesterrorhandler.HTTP_CONFLICT)

    # rest of the items go to dead properties library
    if reallydoit:
        if propupdatemethod == 'set':
            pm.writeProperty(displaypath, propname, propns, propvalue)
        elif propupdatemethod == 'remove':
            pm.removeProperty(displaypath, propname, propns)
    return
 def doTRACE(self, environ, start_response):
     raise HTTPRequestException(
         processrequesterrorhandler.HTTP_NOT_IMPLEMENTED)
 def removeProperty(self, respath, propertyname, propertyns):
     raise HTTPRequestException(processrequesterrorhandler.HTTP_CONFLICT)
 def writeProperty(self, respath, propertyname, propertyns, propertyvalue):
     raise HTTPRequestException(processrequesterrorhandler.HTTP_CONFLICT)
 def copyResource(self, respath, destrespath):
     raise HTTPRequestException(processrequesterrorhandler.HTTP_FORBIDDEN)
 def openResourceForWrite(self, respath, contenttype=None):
     raise HTTPRequestException(processrequesterrorhandler.HTTP_FORBIDDEN)
 def deleteCollection(self, respath):
     raise HTTPRequestException(processrequesterrorhandler.HTTP_FORBIDDEN)