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)
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)
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
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)