def __call__(self, environ, start_response): realmname = self._domaincontroller.getDomainRealm(environ["PATH_INFO"], environ) if not self._domaincontroller.requireAuthentication(realmname, environ): # no authentication needed _logger.debug("No authorization required for realm '%s'" % realmname) environ["http_authenticator.realm"] = realmname environ["http_authenticator.username"] = "" return self._application(environ, start_response) if "HTTP_AUTHORIZATION" in environ: authheader = environ["HTTP_AUTHORIZATION"] authmatch = self._headermethod.search(authheader) authmethod = "None" if authmatch: authmethod = authmatch.group(1).lower() if authmethod == "digest" and self._acceptdigest: return self.authDigestAuthRequest(environ, start_response) elif authmethod == "digest" and self._acceptbasic: return self.sendBasicAuthResponse(environ, start_response) elif authmethod == "basic" and self._acceptbasic: return self.authBasicAuthRequest(environ, start_response) util.log("HTTPAuthenticator: respond with 400 Bad request; Auth-Method: %s" % authmethod) start_response("400 Bad Request", [("Content-Length", "0"), ("Date", util.getRfc1123Time()), ]) return [""] if self._defaultdigest: return self.sendDigestAuthResponse(environ, start_response) return self.sendBasicAuthResponse(environ, start_response)
def __call__(self, environ, start_response): path = environ["PATH_INFO"] davres = None if environ["wsgidav.provider"]: davres = environ["wsgidav.provider"].getResourceInst(path, environ) if environ["REQUEST_METHOD"] in ("GET", "HEAD") and davres and davres.isCollection: # if "mozilla" not in environ.get("HTTP_USER_AGENT").lower(): # # issue 14: Nautilus sends GET on collections # # http://code.google.com/p/wsgidav/issues/detail?id=14 # util.status("Directory browsing disabled for agent '%s'" % environ.get("HTTP_USER_AGENT")) # self._fail(HTTP_NOT_IMPLEMENTED) # return self._application(environ, start_response) if util.getContentLength(environ) != 0: self._fail(HTTP_MEDIATYPE_NOT_SUPPORTED, "The server does not handle any body content.") if environ["REQUEST_METHOD"] == "HEAD": return util.sendStatusResponse(environ, start_response, HTTP_OK) # Support DAV mount (http://www.ietf.org/rfc/rfc4709.txt) dirConfig = environ["wsgidav.config"].get("dir_browser", {}) if dirConfig.get("davmount") and "davmount" in environ.get("QUERY_STRING"): # collectionUrl = davres.getHref() collectionUrl = util.makeCompleteUrl(environ) collectionUrl = collectionUrl.split("?")[0] res = """ <dm:mount xmlns:dm="http://purl.org/NET/webdav/mount"> <dm:url>%s</dm:url> </dm:mount>""" % ( collectionUrl ) # TODO: support <dm:open>%s</dm:open> start_response( "200 OK", [ ("Content-Type", "application/davmount+xml"), ("Content-Length", str(len(res))), ("Cache-Control", "private"), ("Date", util.getRfc1123Time()), ], ) return [res] # Profile calls # if True: # from cProfile import Profile # profile = Profile() # profile.runcall(self._listDirectory, environ, start_response) # # sort: 0:"calls",1:"time", 2: "cumulative" # profile.print_stats(sort=2) return self._listDirectory(davres, environ, start_response) return self._application(environ, start_response)
def __call__(self, environ, start_response): path = environ["PATH_INFO"] davres = None if environ["wsgidav.provider"]: davres = environ["wsgidav.provider"].getResourceInst(path, environ) if environ["REQUEST_METHOD"] in ( "GET", "HEAD") and davres and davres.isCollection: # if "mozilla" not in environ.get("HTTP_USER_AGENT").lower(): # # issue 14: Nautilus sends GET on collections # # http://code.google.com/p/wsgidav/issues/detail?id=14 # util.status("Directory browsing disabled for agent '%s'" % environ.get("HTTP_USER_AGENT")) # self._fail(HTTP_NOT_IMPLEMENTED) # return self._application(environ, start_response) if util.getContentLength(environ) != 0: self._fail(HTTP_MEDIATYPE_NOT_SUPPORTED, "The server does not handle any body content.") if environ["REQUEST_METHOD"] == "HEAD": return util.sendStatusResponse(environ, start_response, HTTP_OK) # Support DAV mount (http://www.ietf.org/rfc/rfc4709.txt) dirConfig = environ["wsgidav.config"].get("dir_browser", {}) if dirConfig.get("davmount") and "davmount" in environ.get( "QUERY_STRING"): # collectionUrl = davres.getHref() collectionUrl = util.makeCompleteUrl(environ) collectionUrl = collectionUrl.split("?")[0] res = """ <dm:mount xmlns:dm="http://purl.org/NET/webdav/mount"> <dm:url>%s</dm:url> </dm:mount>""" % (collectionUrl) # TODO: support <dm:open>%s</dm:open> start_response("200 OK", [ ("Content-Type", "application/davmount+xml"), ("Content-Length", str(len(res))), ("Cache-Control", "private"), ("Date", util.getRfc1123Time()), ]) return [res] # Profile calls # if True: # from cProfile import Profile # profile = Profile() # profile.runcall(self._listDirectory, environ, start_response) # # sort: 0:"calls",1:"time", 2: "cumulative" # profile.print_stats(sort=2) return self._listDirectory(davres, environ, start_response) return self._application(environ, start_response)
def sendBasicAuthResponse(self, environ, start_response): realmname = self._domaincontroller.getDomainRealm(environ["PATH_INFO"] , environ) _logger.debug("401 Not Authorized for realm '%s' (basic)" % realmname) wwwauthheaders = "Basic realm=\"" + realmname + "\"" body = self.getErrorMessage() start_response("401 Not Authorized", [("WWW-Authenticate", wwwauthheaders), ("Content-Type", "text/html"), ("Content-Length", str(len(body))), ("Date", util.getRfc1123Time()), ]) return [ body ]
def __call__(self, environ, start_response): path = environ["PATH_INFO"] # We want to answer OPTIONS(*), even if no handler was registered for # the top-level realm (e.g. required to map drive letters). provider = environ["wsgidav.provider"] # Hotfix for WinXP / Vista: accept '/' for a '*' if environ["REQUEST_METHOD"] == "OPTIONS" and path in ("/", "*"): # Answer HTTP 'OPTIONS' method on server-level. # From RFC 2616: # If the Request-URI is an asterisk ("*"), the OPTIONS request is # intended to apply to the server in general rather than to a specific # resource. Since a server's communication options typically depend on # the resource, the "*" request is only useful as a "ping" or "no-op" # type of method; it does nothing beyond allowing the client to test the # capabilities of the server. For example, this can be used to test a # proxy for HTTP/1.1 compliance (or lack thereof). dav_compliance_level = "1,2" if provider is None or provider.isReadOnly( ) or provider.lockManager is None: dav_compliance_level = "1" headers = [ ("Content-Type", "text/html; charset=UTF-8"), ("Content-Length", "0"), ("DAV", dav_compliance_level), ("Date", util.getRfc1123Time()), ] if environ["wsgidav.config"].get("add_header_MS_Author_Via", False): headers.append(("MS-Author-Via", "DAV")) start_response("200 OK", headers) yield "" return if provider is None: raise DAVError(HTTP_NOT_FOUND, "Could not find resource provider for '%s'" % path) # Let the appropriate resource provider for the realm handle the request app = RequestServer(provider) app_iter = app(environ, start_response) for v in app_iter: yield v if hasattr(app_iter, "close"): app_iter.close() return
def __call__(self, environ, start_response): path = environ["PATH_INFO"] # We want to answer OPTIONS(*), even if no handler was registered for # the top-level realm (e.g. required to map drive letters). provider = environ["wsgidav.provider"] # Hotfix for WinXP / Vista: accept '/' for a '*' if environ["REQUEST_METHOD"] == "OPTIONS" and path in ("/", "*"): # Answer HTTP 'OPTIONS' method on server-level. # From RFC 2616: # If the Request-URI is an asterisk ("*"), the OPTIONS request is # intended to apply to the server in general rather than to a specific # resource. Since a server's communication options typically depend on # the resource, the "*" request is only useful as a "ping" or "no-op" # type of method; it does nothing beyond allowing the client to test the # capabilities of the server. For example, this can be used to test a # proxy for HTTP/1.1 compliance (or lack thereof). dav_compliance_level = "1,2" if provider is None or provider.isReadOnly() or provider.lockManager is None: dav_compliance_level = "1" headers = [("Content-Type", "text/html"), ("Content-Length", "0"), ("DAV", dav_compliance_level), ("Date", util.getRfc1123Time()), ] if environ["wsgidav.config"].get("add_header_MS_Author_Via", False): headers.append( ("MS-Author-Via", "DAV") ) start_response("200 OK", headers) yield "" return if provider is None: raise DAVError(HTTP_NOT_FOUND, "Could not find resource provider for '%s'" % path) # Let the appropriate resource provider for the realm handle the request app = RequestServer(provider) app_iter = app(environ, start_response) for v in app_iter: yield v if hasattr(app_iter, "close"): app_iter.close() return
def __call__(self, environ, start_response): realmname = self._domaincontroller.getDomainRealm( environ["PATH_INFO"], environ) _logger.debug("realm '%s'" % realmname) # _logger.debug("%s" % environ) force_allow = False if HOTFIX_WIN_AcceptAnonymousOptions and environ[ "REQUEST_METHOD"] == "OPTIONS": _logger.warning("No authorization required for OPTIONS method") force_allow = True if force_allow or not self._domaincontroller.requireAuthentication( realmname, environ): # no authentication needed _logger.debug("No authorization required for realm '%s'" % realmname) environ["http_authenticator.realm"] = realmname environ["http_authenticator.username"] = "" return self._application(environ, start_response) if "HTTP_AUTHORIZATION" in environ: authheader = environ["HTTP_AUTHORIZATION"] authmatch = self._headermethod.search(authheader) authmethod = "None" if authmatch: authmethod = authmatch.group(1).lower() if authmethod == "digest" and self._acceptdigest: return self.authDigestAuthRequest(environ, start_response) elif authmethod == "digest" and self._acceptbasic: return self.sendBasicAuthResponse(environ, start_response) elif authmethod == "basic" and self._acceptbasic: return self.authBasicAuthRequest(environ, start_response) util.log( "HTTPAuthenticator: respond with 400 Bad request; Auth-Method: %s" % authmethod) start_response("400 Bad Request", [ ("Content-Length", "0"), ("Date", util.getRfc1123Time()), ]) return [""] if self._defaultdigest: return self.sendDigestAuthResponse(environ, start_response) return self.sendBasicAuthResponse(environ, start_response)
def sendDigestAuthResponse(self, environ, start_response): realmname = self._domaincontroller.getDomainRealm(environ["PATH_INFO"] , environ) random.seed() serverkey = hex(random.getrandbits(32))[2:] etagkey = md5(environ["PATH_INFO"]).hexdigest() timekey = str(time.time()) nonce = base64.b64encode(timekey + md5(timekey + ":" + etagkey + ":" + serverkey).hexdigest()) wwwauthheaders = "Digest realm=\"" + realmname + "\", nonce=\"" + nonce + \ "\", algorithm=\"MD5\", qop=\"auth\"" _logger.debug("401 Not Authorized for realm '%s' (digest): %s" % (realmname, wwwauthheaders)) body = self.getErrorMessage() # start_response("403 Forbidden", [("WWW-Authenticate", wwwauthheaders), start_response("401 Not Authorized", [("WWW-Authenticate", wwwauthheaders), ("Content-Type", "text/html"), ("Content-Length", str(len(body))), ("Date", util.getRfc1123Time()), ]) return [ body ]
def __call__(self, environ, start_response): path = environ["PATH_INFO"] # We want to answer OPTIONS(*), even if no handler was registered for # the top-level realm (e.g. required to map drive letters). # Hotfix for WinXP / Vista: accept '/' for a '*' if environ["REQUEST_METHOD"] == "OPTIONS" and path in ("/", "*"): # Answer HTTP 'OPTIONS' method on server-level. # From RFC 2616: # If the Request-URI is an asterisk ("*"), the OPTIONS request is # intended to apply to the server in general rather than to a specific # resource. Since a server's communication options typically depend on # the resource, the "*" request is only useful as a "ping" or "no-op" # type of method; it does nothing beyond allowing the client to test the # capabilities of the server. For example, this can be used to test a # proxy for HTTP/1.1 compliance (or lack thereof). start_response("200 OK", [("Content-Type", "text/html"), ("Content-Length", "0"), ("DAV", "1,2"), ("Server", "DAV/2"), ("Date", util.getRfc1123Time()), ]) yield "" return provider = environ["wsgidav.provider"] if provider is None: raise DAVError(HTTP_NOT_FOUND, "Could not find resource provider for '%s'" % path) # Let the appropriate resource provider for the realm handle the request app = RequestServer(provider) for v in app(environ, start_response): yield v return
def _listDirectory(self, davres, environ, start_response): """ @see: http://www.webdav.org/specs/rfc4918.html#rfc.section.9.4 """ assert davres.isCollection dirConfig = environ["wsgidav.config"].get("dir_browser", {}) displaypath = urllib.unquote(davres.getHref()) isReadOnly = environ["wsgidav.provider"].isReadOnly() trailer = dirConfig.get("response_trailer") if trailer: trailer = trailer.replace("${version}", "<a href='https://github.com/mar10/wsgidav/'>WsgiDAV/%s</a>" % __version__) trailer = trailer.replace("${time}", util.getRfc1123Time()) else: trailer = ("Seafile WebDAV Server, based on <a href='https://github.com/mar10/wsgidav/'>WsgiDAV/%s</a> - %s" % (__version__, util.getRfc1123Time())) html = [] html.append("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>"); html.append("<html>") html.append("<head>") html.append("<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>") html.append("<meta name='generator' content='WsgiDAV %s'>" % __version__) html.append("<title>WsgiDAV - Index of %s </title>" % displaypath) html.append("<script type='text/javascript'>%s</script>" % PAGE_SCRIPT) html.append("<style type='text/css'>%s</style>" % PAGE_CSS) # Special CSS to enable MS Internet Explorer behaviour if dirConfig.get("ms_mount"): html.append("<style type='text/css'> A {behavior: url(#default#AnchorClick);} </style>") if dirConfig.get("ms_sharepoint_plugin"): html.append("<object id='winFirefoxPlugin' type='application/x-sharepoint' width='0' height='0' style=''visibility: hidden;'></object>") html.append("</head>") html.append("<body onload='onLoad()'>") # Title html.append("<h1>Index of %s</h1>" % displaypath) # Add DAV-Mount link and Web-Folder link links = [] if dirConfig.get("davmount"): links.append("<a title='Open this folder in a WebDAV client.' href='%s?davmount'>Mount</a>" % util.makeCompleteUrl(environ)) if dirConfig.get("ms_mount"): links.append("<a title='Open as Web Folder (requires Microsoft Internet Explorer)' href='' FOLDER='%s'>Open as Web Folder</a>" % util.makeCompleteUrl(environ)) # html.append("<a href='' FOLDER='%ssetup.py'>Open setup.py as WebDAV</a>" % util.makeCompleteUrl(environ)) if links: html.append("<p>%s</p>" % " – ".join(links)) html.append("<hr>") # Listing html.append("<table onclick='return onClickTable(event)'>") html.append("<thead>") html.append("<tr><th>Name</th> <th>Type</th> <th class='right'>Size</th> <th class='right'>Last modified</th> </tr>") html.append("</thead>") html.append("<tbody>") if davres.path in ("", "/"): html.append("<tr><td>Top level share</td> <td></td> <td></td> <td></td> </tr>") else: parentUrl = util.getUriParent(davres.getHref()) html.append("<tr><td><a href='" + parentUrl + "'>Parent Directory</a></td> <td></td> <td></td> <td></td> </tr>") # Ask collection for member info list dirInfoList = davres.getDirectoryInfo() if dirInfoList is None: # No pre-build info: traverse members dirInfoList = [] childList = davres.getDescendants(depth="1", addSelf=False) for res in childList: di = res.getDisplayInfo() href = res.getHref() infoDict = {"href": href, "class": "", "displayName": escapeName(res.getDisplayName()), "lastModified": res.getLastModified(), "isCollection": res.isCollection, "contentLength": res.getContentLength(), "displayType": di.get("type"), "displayTypeComment": di.get("typeComment"), } if not isReadOnly and not res.isCollection: ext = os.path.splitext(href)[1].lstrip(".").lower() officeType = msOfficeExtToTypeMap.get(ext) if officeType: # print "OT", officeType # print "OT", dirConfig if dirConfig.get("ms_sharepoint_plugin"): infoDict["class"] = "msoffice" elif dirConfig.get("ms_sharepoint_urls"): infoDict["href"] = "ms-%s:ofe|u|%s" % (officeType, href) dirInfoList.append(infoDict) # for infoDict in dirInfoList: lastModified = infoDict.get("lastModified") if lastModified is None: infoDict["strModified"] = "" else: infoDict["strModified"] = util.getRfc1123Time(lastModified) infoDict["strSize"] = "-" if not infoDict.get("isCollection"): contentLength = infoDict.get("contentLength") if contentLength is not None: infoDict["strSize"] = util.byteNumberString(contentLength) html.append("""\ <tr><td><a href="%(href)s" class="%(class)s">%(displayName)s</a></td> <td>%(displayType)s</td> <td class='right'>%(strSize)s</td> <td class='right'>%(strModified)s</td></tr>""" % infoDict) html.append("</tbody>") html.append("</table>") html.append("<hr>") if "http_authenticator.username" in environ: if environ.get("http_authenticator.username"): html.append("<p>Authenticated user: '******', realm: '%s'.</p>" % (environ.get("http_authenticator.username"), environ.get("http_authenticator.realm"))) # else: # html.append("<p>Anonymous</p>") if trailer: html.append("<p class='trailer'>%s</p>" % trailer) html.append("</body></html>") body = "\n".join(html) start_response("200 OK", [("Content-Type", "text/html"), ("Content-Length", str(len(body))), ("Date", util.getRfc1123Time()), ]) return [ body ]
def _listDirectory(self, davres, environ, start_response): """ @see: http://www.webdav.org/specs/rfc4918.html#rfc.section.9.4 """ assert davres.isCollection dirConfig = environ["wsgidav.config"].get("dir_browser", {}) displaypath = urllib.unquote(davres.getHref()) trailer = dirConfig.get("response_trailer") if trailer: trailer = trailer.replace( "${version}", "<a href='http://wsgidav.googlecode.com/'>WsgiDAV/%s</a>" % __version__) trailer = trailer.replace("${time}", util.getRfc1123Time()) else: trailer = ( "<a href='http://wsgidav.googlecode.com/'>WsgiDAV/%s</a> - %s" % (__version__, util.getRfc1123Time())) html = [] html.append( "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>" ) html.append("<html>") html.append("<head>") html.append( "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>" ) html.append("<meta name='generator' content='WsgiDAV %s'>" % __version__) html.append("<title>WsgiDAV - Index of %s </title>" % displaypath) html.append("""\ <style type="text/css"> img { border: 0; padding: 0 2px; vertical-align: text-bottom; } th, td { padding: 2px 20px 2px 2px; } th { text-align: left; } th.right { text-align: right; } td { font-family: monospace; vertical-align: bottom; white-space: pre; } td.right { text-align: right; } table { border: 0; } a.symlink { font-style: italic; } p.trailer { font-size: smaller; } </style>""") # Special CSS to enable MS Internet Explorer behaviour if dirConfig.get("msmount"): html.append("""\ <style type="text/css"> A {behavior: url(#default#AnchorClick);} </style>""") html.append("</head><body>") # Title html.append("<h1>Index of %s</h1>" % displaypath) # Add DAV-Mount link and Web-Folder link links = [] if dirConfig.get("davmount"): links.append( "<a title='Open this folder in a WebDAV client.' href='%s?davmount'>Mount</a>" % util.makeCompleteUrl(environ)) if dirConfig.get("msmount"): links.append( "<a title='Open as Web Folder (requires Microsoft Internet Explorer)' href='' FOLDER='%s'>Open as Web Folder</a>" % util.makeCompleteUrl(environ)) # html.append("<a href='' FOLDER='%ssetup.py'>Open setup.py as WebDAV</a>" % util.makeCompleteUrl(environ)) if links: html.append("<p>%s</p>" % " – ".join(links)) html.append("<hr>") # Listing html.append("<table>") html.append("<thead>") html.append( "<tr><th>Name</th> <th>Type</th> <th class='right'>Size</th> <th class='right'>Last modified</th> </tr>" ) html.append("</thead>") html.append("<tbody>") if davres.path in ("", "/"): html.append( "<tr><td>Top level share</td> <td></td> <td></td> <td></td> </tr>" ) else: parentUrl = util.getUriParent(davres.getHref()) html.append( "<tr><td><a href='" + parentUrl + "'>Parent Directory</a></td> <td></td> <td></td> <td></td> </tr>" ) # Ask collection for member info list dirInfoList = davres.getDirectoryInfo() if dirInfoList is None: # No pre-build info: traverse members dirInfoList = [] childList = davres.getDescendants(depth="1", addSelf=False) for res in childList: di = res.getDisplayInfo() infoDict = { "href": res.getHref(), "displayName": res.getDisplayName(), "lastModified": res.getLastModified(), "isCollection": res.isCollection, "contentLength": res.getContentLength(), "displayType": di.get("type"), "displayTypeComment": di.get("typeComment"), } dirInfoList.append(infoDict) # for infoDict in dirInfoList: lastModified = infoDict.get("lastModified") if lastModified is None: infoDict["strModified"] = "" else: infoDict["strModified"] = util.getRfc1123Time(lastModified) infoDict["strSize"] = "-" if not infoDict.get("isCollection"): contentLength = infoDict.get("contentLength") if contentLength is not None: infoDict["strSize"] = util.byteNumberString(contentLength) html.append("""\ <tr><td><a href="%(href)s">%(displayName)s</a></td> <td>%(displayType)s</td> <td class='right'>%(strSize)s</td> <td class='right'>%(strModified)s</td></tr>""" % infoDict) html.append("</tbody>") html.append("</table>") html.append("<hr>") if "http_authenticator.username" in environ: if environ.get("http_authenticator.username"): html.append("<p>Authenticated user: '******', realm: '%s'.</p>" % (environ.get("http_authenticator.username"), environ.get("http_authenticator.realm"))) # else: # html.append("<p>Anonymous</p>") if trailer: html.append("<p class='trailer'>%s</p>" % trailer) # html.append("<p class='trailer'><a href='http://wsgidav.googlecode.com/'>WsgiDAV/%s</a> - %s</p>" # % (__version__, util.getRfc1123Time())) html.append("</body></html>") body = "\n".join(html) start_response("200 OK", [ ("Content-Type", "text/html"), ("Content-Length", str(len(body))), ("Date", util.getRfc1123Time()), ]) return [body]
util.warn("ErrorPrinter: caught Exception") util.warn(traceback.format_exc()) raise except DAVError, e: _logger.debug("caught %s" % e) status = getHttpStatusString(e) # Dump internal errors to console if e.value == HTTP_INTERNAL_ERROR: util.warn(traceback.format_exc()) util.warn("e.srcexception:\n%s" % e.srcexception) elif e.value in (HTTP_NOT_MODIFIED, HTTP_NO_CONTENT): # util.log("ErrorPrinter: forcing empty error response for %s" % e.value) # See paste.lint: these code don't have content start_response(status, [("Content-Length", "0"), ("Date", util.getRfc1123Time()), ]) yield "" return # If exception has pre-/post-condition: return as XML response, # else return as HTML content_type, body = e.getResponsePage() # TODO: provide exc_info=sys.exc_info()? start_response(status, [("Content-Type", content_type), ("Content-Length", str(len(body))), ("Date", util.getRfc1123Time()), ]) yield body return
def _listDirectory(self, davres, environ, start_response): """ @see: http://www.webdav.org/specs/rfc4918.html#rfc.section.9.4 """ assert davres.isCollection dirConfig = environ["wsgidav.config"].get("dir_browser", {}) displaypath = urllib.unquote(davres.getHref()) isReadOnly = environ["wsgidav.provider"].isReadOnly() trailer = dirConfig.get("response_trailer") if trailer: trailer = trailer.replace("${version}", "<a href='https://github.com/mar10/wsgidav/'>WsgiDAV/%s</a>" % __version__) trailer = trailer.replace("${time}", util.getRfc1123Time()) else: trailer = ("<a href='https://github.com/mar10/wsgidav/'>WsgiDAV/%s</a> - %s" % (__version__, util.getRfc1123Time())) html = [] html.append("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>"); html.append("<html>") html.append("<head>") html.append("<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>") html.append("<meta name='generator' content='WsgiDAV %s'>" % __version__) html.append("<title>WsgiDAV - Index of %s </title>" % displaypath) html.append("<script type='text/javascript'>%s</script>" % PAGE_SCRIPT) html.append("<style type='text/css'>%s</style>" % PAGE_CSS) # Special CSS to enable MS Internet Explorer behaviour if dirConfig.get("ms_mount"): html.append("<style type='text/css'> A {behavior: url(#default#AnchorClick);} </style>") if dirConfig.get("ms_sharepoint_plugin"): html.append("<object id='winFirefoxPlugin' type='application/x-sharepoint' width='0' height='0' style=''visibility: hidden;'></object>") html.append("</head>") html.append("<body onload='onLoad()'>") # Title html.append("<h1>Index of %s</h1>" % displaypath) # Add DAV-Mount link and Web-Folder link links = [] if dirConfig.get("davmount"): links.append("<a title='Open this folder in a WebDAV client.' href='%s?davmount'>Mount</a>" % util.makeCompleteUrl(environ)) if dirConfig.get("ms_mount"): links.append("<a title='Open as Web Folder (requires Microsoft Internet Explorer)' href='' FOLDER='%s'>Open as Web Folder</a>" % util.makeCompleteUrl(environ)) # html.append("<a href='' FOLDER='%ssetup.py'>Open setup.py as WebDAV</a>" % util.makeCompleteUrl(environ)) if links: html.append("<p>%s</p>" % " – ".join(links)) html.append("<hr>") # Listing html.append("<table onclick='return onClickTable(event)'>") html.append("<thead>") html.append("<tr><th>Name</th> <th>Type</th> <th class='right'>Size</th> <th class='right'>Last modified</th> </tr>") html.append("</thead>") html.append("<tbody>") if davres.path in ("", "/"): html.append("<tr><td>Top level share</td> <td></td> <td></td> <td></td> </tr>") else: parentUrl = util.getUriParent(davres.getHref()) html.append("<tr><td><a href='" + parentUrl + "'>Parent Directory</a></td> <td></td> <td></td> <td></td> </tr>") # Ask collection for member info list dirInfoList = davres.getDirectoryInfo() if dirInfoList is None: # No pre-build info: traverse members dirInfoList = [] childList = davres.getDescendants(depth="1", addSelf=False) for res in childList: di = res.getDisplayInfo() href = res.getHref() infoDict = {"href": href, "class": "", "displayName": res.getDisplayName(), "lastModified": res.getLastModified(), "isCollection": res.isCollection, "contentLength": res.getContentLength(), "displayType": di.get("type"), "displayTypeComment": di.get("typeComment"), } if not isReadOnly and not res.isCollection: ext = os.path.splitext(href)[1].lstrip(".").lower() officeType = msOfficeExtToTypeMap.get(ext) if officeType: print "OT", officeType print "OT", dirConfig if dirConfig.get("ms_sharepoint_plugin"): infoDict["class"] = "msoffice" elif dirConfig.get("ms_sharepoint_urls"): infoDict["href"] = "ms-%s:ofe|u|%s" % (officeType, href) dirInfoList.append(infoDict) # for infoDict in dirInfoList: lastModified = infoDict.get("lastModified") if lastModified is None: infoDict["strModified"] = "" else: infoDict["strModified"] = util.getRfc1123Time(lastModified) infoDict["strSize"] = "-" if not infoDict.get("isCollection"): contentLength = infoDict.get("contentLength") if contentLength is not None: infoDict["strSize"] = util.byteNumberString(contentLength) html.append("""\ <tr><td><a href="%(href)s" class="%(class)s">%(displayName)s</a></td> <td>%(displayType)s</td> <td class='right'>%(strSize)s</td> <td class='right'>%(strModified)s</td></tr>""" % infoDict) html.append("</tbody>") html.append("</table>") html.append("<hr>") if "http_authenticator.username" in environ: if environ.get("http_authenticator.username"): html.append("<p>Authenticated user: '******', realm: '%s'.</p>" % (environ.get("http_authenticator.username"), environ.get("http_authenticator.realm"))) # else: # html.append("<p>Anonymous</p>") if trailer: html.append("<p class='trailer'>%s</p>" % trailer) html.append("</body></html>") body = "\n".join(html) start_response("200 OK", [("Content-Type", "text/html"), ("Content-Length", str(len(body))), ("Date", util.getRfc1123Time()), ]) return [ body ]
except DAVError, e: _logger.debug("caught %s" % e) status = getHttpStatusString(e) # Dump internal errors to console if e.value == HTTP_INTERNAL_ERROR: print >> sys.stdout, "ErrorPrinter: caught HTTPRequestException(HTTP_INTERNAL_ERROR)" traceback.print_exc(10, environ.get("wsgi.errors") or sys.stdout) print >> sys.stdout, "e.srcexception:\n%s" % e.srcexception elif e.value in (HTTP_NOT_MODIFIED, HTTP_NO_CONTENT): # util.log("ErrorPrinter: forcing empty error response for %s" % e.value) # See paste.lint: these code don't have content start_response(status, [ ("Content-Length", "0"), ("Date", util.getRfc1123Time()), ]) yield "" return # If exception has pre-/post-condition: return as XML response, # else return as HTML content_type, body = e.getResponsePage() # TODO: provide exc_info=sys.exc_info()? start_response(status, [ ("Content-Type", content_type), ("Content-Length", str(len(body))), ("Date", util.getRfc1123Time()), ]) yield body
def _listDirectory(self, davres, environ, start_response): """ @see: http://www.webdav.org/specs/rfc4918.html#rfc.section.9.4 """ assert davres.isCollection dirConfig = environ["wsgidav.config"].get("dir_browser", {}) displaypath = urllib.unquote(davres.getHref()) trailer = dirConfig.get("response_trailer") if trailer: trailer = trailer.replace("${version}", "<a href='http://wsgidav.googlecode.com/'>WsgiDAV/%s</a>" % __version__) trailer = trailer.replace("${time}", util.getRfc1123Time()) else: trailer = ("<a href='http://wsgidav.googlecode.com/'>WsgiDAV/%s</a> - %s" % (__version__, util.getRfc1123Time())) html = [] html.append("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>"); html.append("<html>") html.append("<head>") html.append("<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>") html.append("<meta name='generator' content='WsgiDAV %s'>" % __version__) html.append("<title>WsgiDAV - Index of %s </title>" % displaypath) html.append("""\ <style type="text/css"> img { border: 0; padding: 0 2px; vertical-align: text-bottom; } th, td { padding: 2px 20px 2px 2px; } th { text-align: left; } th.right { text-align: right; } td { font-family: monospace; vertical-align: bottom; white-space: pre; } td.right { text-align: right; } table { border: 0; } a.symlink { font-style: italic; } p.trailer { font-size: smaller; } </style>""") # Special CSS to enable MS Internet Explorer behaviour if dirConfig.get("msmount"): html.append("""\ <style type="text/css"> A {behavior: url(#default#AnchorClick);} </style>""") html.append("</head><body>") # Title html.append("<h1>Index of %s</h1>" % displaypath) # Add DAV-Mount link and Web-Folder link links = [] if dirConfig.get("davmount"): links.append("<a title='Open this folder in a WebDAV client.' href='%s?davmount'>Mount</a>" % util.makeCompleteUrl(environ)) if dirConfig.get("msmount"): links.append("<a title='Open as Web Folder (requires Microsoft Internet Explorer)' href='' FOLDER='%s'>Open as Web Folder</a>" % util.makeCompleteUrl(environ)) # html.append("<a href='' FOLDER='%ssetup.py'>Open setup.py as WebDAV</a>" % util.makeCompleteUrl(environ)) if links: html.append("<p>%s</p>" % " – ".join(links)) html.append("<hr>") # Listing html.append("<table>") html.append("<thead>") html.append("<tr><th>Name</th> <th>Type</th> <th class='right'>Size</th> <th class='right'>Last modified</th> </tr>") html.append("</thead>") html.append("<tbody>") if davres.path in ("", "/"): html.append("<tr><td>Top level share</td> <td></td> <td></td> <td></td> </tr>") else: parentUrl = util.getUriParent(davres.getHref()) html.append("<tr><td><a href='" + parentUrl + "'>Parent Directory</a></td> <td></td> <td></td> <td></td> </tr>") # Ask collection for member info list dirInfoList = davres.getDirectoryInfo() if dirInfoList is None: # No pre-build info: traverse members dirInfoList = [] childList = davres.getDescendants(depth="1", addSelf=False) for res in childList: di = res.getDisplayInfo() infoDict = {"href": res.getHref(), "displayName": res.getDisplayName(), "lastModified": res.getLastModified(), "isCollection": res.isCollection, "contentLength": res.getContentLength(), "displayType": di.get("type"), "displayTypeComment": di.get("typeComment"), } dirInfoList.append(infoDict) # for infoDict in dirInfoList: lastModified = infoDict.get("lastModified") if lastModified is None: infoDict["strModified"] = "" else: infoDict["strModified"] = util.getRfc1123Time(lastModified) infoDict["strSize"] = "-" if not infoDict.get("isCollection"): contentLength = infoDict.get("contentLength") if contentLength is not None: infoDict["strSize"] = util.byteNumberString(contentLength) html.append("""\ <tr><td><a href="%(href)s">%(displayName)s</a></td> <td>%(displayType)s</td> <td class='right'>%(strSize)s</td> <td class='right'>%(strModified)s</td></tr>""" % infoDict) html.append("</tbody>") html.append("</table>") html.append("<hr>") if "http_authenticator.username" in environ: if environ.get("http_authenticator.username"): html.append("<p>Authenticated user: '******', realm: '%s'.</p>" % (environ.get("http_authenticator.username"), environ.get("http_authenticator.realm"))) # else: # html.append("<p>Anonymous</p>") if trailer: html.append("<p class='trailer'>%s</p>" % trailer) # html.append("<p class='trailer'><a href='http://wsgidav.googlecode.com/'>WsgiDAV/%s</a> - %s</p>" # % (__version__, util.getRfc1123Time())) html.append("</body></html>") body = "\n".join(html) start_response("200 OK", [("Content-Type", "text/html"), ("Content-Length", str(len(body))), ("Date", util.getRfc1123Time()), ]) return [ body ]