Ejemplo n.º 1
0
    def get_response_page(self):
        """Return a tuple (content-type, response page)."""
        # If it has pre- or post-condition: return as XML response
        if self.err_condition:
            return ("application/xml", compat.to_bytes(self.err_condition.as_string()))

        # Else return as HTML
        status = get_http_status_string(self)
        html = []
        html.append(
            "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' "
            "'http://www.w3.org/TR/html4/strict.dtd'>"
        )
        html.append("<html><head>")
        html.append(
            "  <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>"
        )
        html.append("  <title>{}</title>".format(status))
        html.append("</head><body>")
        html.append("  <h1>{}</h1>".format(status))
        html.append("  <p>{}</p>".format(compat.html_escape(self.get_user_info())))
        html.append("<hr/>")
        html.append(
            "<a href='https://github.com/mar10/wsgidav/'>WsgiDAV/{}</a> - {}".format(
                __version__, compat.html_escape(str(datetime.datetime.now()), "utf-8")
            )
        )
        html.append("</body></html>")
        html = "\n".join(html)
        return ("text/html", compat.to_bytes(html))
    def getResponsePage(self):
        """Return an tuple (content-type, response page)."""
        # If it has pre- or post-condition: return as XML response 
        if self.errcondition:
            return ("application/xml",
                    compat.to_bytes(self.errcondition.as_string()))

        # Else return as HTML 
        status = getHttpStatusString(self)
        html = []
        html.append("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>");
        html.append("<html><head>") 
        html.append("  <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>")
        html.append("  <title>%s</title>" % status) 
        html.append("</head><body>") 
        html.append("  <h1>%s</h1>" % status) 
        html.append("  <p>%s</p>" % compat.html_escape(self.getUserInfo()))         
#        html.append("  <hr>")
#        html.append("  <p>%s</p>" % cgi.escape(str(datetime.datetime.now())))         
#        if self._server_descriptor:
#            respbody.append(self._server_descriptor + "<hr>")
        html.append("<hr/>") 
        html.append("<a href='https://github.com/mar10/wsgidav/'>WsgiDAV/%s</a> - %s" 
                    % (__version__, compat.html_escape(str(datetime.datetime.now()), "utf-8")))
        html.append("</body></html>")
        html = "\n".join(html)
        return ("text/html", compat.to_bytes(html))
Ejemplo n.º 3
0
    def get_response_page(self):
        """Return a tuple (content-type, response page)."""
        # If it has pre- or post-condition: return as XML response
        if self.err_condition:
            return ("application/xml",
                    compat.to_bytes(self.err_condition.as_string()))

        # Else return as HTML
        status = get_http_status_string(self)
        html = []
        html.append("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' "
                    "'http://www.w3.org/TR/html4/strict.dtd'>")
        html.append("<html><head>")
        html.append(
            "  <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>"
        )
        html.append("  <title>{}</title>".format(status))
        html.append("</head><body>")
        html.append("  <h1>{}</h1>".format(status))
        html.append("  <p>{}</p>".format(
            compat.html_escape(self.get_user_info())))
        html.append("<hr/>")
        html.append(
            "<a href='https://github.com/mar10/wsgidav/'>WsgiDAV/{}</a> - {}".
            format(__version__,
                   compat.html_escape(str(datetime.datetime.now()), "utf-8")))
        html.append("</body></html>")
        html = "\n".join(html)
        return ("text/html", compat.to_bytes(html))
Ejemplo n.º 4
0
    def __call__(self, environ, start_response):
        path = environ["PATH_INFO"]

        dav_res = None
        if environ["wsgidav.provider"]:
            dav_res = environ["wsgidav.provider"].get_resource_inst(path, environ)

        if (
            environ["REQUEST_METHOD"] in ("GET", "HEAD")
            and dav_res
            and dav_res.is_collection
        ):

            if util.get_content_length(environ) != 0:
                self._fail(
                    HTTP_MEDIATYPE_NOT_SUPPORTED,
                    "The server does not handle any body content.",
                )

            if environ["REQUEST_METHOD"] == "HEAD":
                return util.send_status_response(
                    environ, start_response, HTTP_OK, is_head=True
                )

            # Support DAV mount (http://www.ietf.org/rfc/rfc4709.txt)
            if self.dir_config.get("davmount") and "davmount" in environ.get(
                "QUERY_STRING", ""
            ):
                collectionUrl = util.make_complete_url(environ)
                collectionUrl = collectionUrl.split("?", 1)[0]
                res = compat.to_bytes(DAVMOUNT_TEMPLATE.format(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.get_rfc1123_time()),
                    ],
                )
                return [res]

            context = self._get_context(environ, dav_res)

            res = self.template.render(**context)
            res = compat.to_bytes(res)
            start_response(
                "200 OK",
                [
                    ("Content-Type", "text/html"),
                    ("Content-Length", str(len(res))),
                    ("Cache-Control", "private"),
                    ("Date", util.get_rfc1123_time()),
                ],
            )
            return [res]

        return self.next_app(environ, start_response)
Ejemplo n.º 5
0
    def __call__(self, environ, start_response):
        path = environ["PATH_INFO"]

        dav_res = None
        if environ["wsgidav.provider"]:
            dav_res = environ["wsgidav.provider"].get_resource_inst(path, environ)

        if (
            environ["REQUEST_METHOD"] in ("GET", "HEAD")
            and dav_res
            and dav_res.is_collection
        ):

            if util.get_content_length(environ) != 0:
                self._fail(
                    HTTP_MEDIATYPE_NOT_SUPPORTED,
                    "The server does not handle any body content.",
                )

            if environ["REQUEST_METHOD"] == "HEAD":
                return util.send_status_response(
                    environ, start_response, HTTP_OK, is_head=True
                )

            # Support DAV mount (http://www.ietf.org/rfc/rfc4709.txt)
            if self.dir_config.get("davmount") and "davmount" in environ.get(
                "QUERY_STRING", ""
            ):
                collectionUrl = util.make_complete_url(environ)
                collectionUrl = collectionUrl.split("?", 1)[0]
                res = compat.to_bytes(DAVMOUNT_TEMPLATE.format(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.get_rfc1123_time()),
                    ],
                )
                return [res]

            context = self._get_context(environ, dav_res)

            res = self.template.render(**context)
            res = compat.to_bytes(res)
            start_response(
                "200 OK",
                [
                    ("Content-Type", "text/html"),
                    ("Content-Length", str(len(res))),
                    ("Cache-Control", "private"),
                    ("Date", util.get_rfc1123_time()),
                ],
            )
            return [res]

        return self.next_app(environ, start_response)
Ejemplo n.º 6
0
    def send_digest_auth_response(self, environ, start_response):
        realm_name = self.domain_controller.get_domain_realm(
            environ["PATH_INFO"], environ)
        random.seed()
        serverkey = hex(random.getrandbits(32))[2:]
        etagkey = calc_hexdigest(environ["PATH_INFO"])
        timekey = str(time.time())
        nonce_source = timekey + calc_hexdigest(timekey + ":" + etagkey + ":" +
                                                serverkey)
        nonce = calc_base64(nonce_source)
        wwwauthheaders = 'Digest realm="{}", nonce="{}", algorithm=MD5, qop="auth"'.format(
            realm_name, nonce)

        _logger.debug("401 Not Authorized for realm '{}' (digest): {}".format(
            realm_name, wwwauthheaders))

        body = compat.to_bytes(self.get_error_message())
        start_response(
            "401 Not Authorized",
            [
                ("WWW-Authenticate", wwwauthheaders),
                ("Content-Type", "text/html"),
                ("Content-Length", str(len(body))),
                ("Date", util.get_rfc1123_time()),
            ],
        )
        return [body]
Ejemplo n.º 7
0
    def send_digest_auth_response(self, environ, start_response):
        realm = self.domain_controller.get_domain_realm(environ["PATH_INFO"], environ)
        random.seed()
        serverkey = hex(random.getrandbits(32))[2:]
        etagkey = calc_hexdigest(environ["PATH_INFO"])
        timekey = str(time.time())
        nonce_source = timekey + calc_hexdigest(
            timekey + ":" + etagkey + ":" + serverkey
        )
        nonce = calc_base64(nonce_source)
        wwwauthheaders = 'Digest realm="{}", nonce="{}", algorithm=MD5, qop="auth"'.format(
            realm, nonce
        )

        _logger.debug(
            "401 Not Authorized for realm '{}' (digest): {}".format(
                realm, wwwauthheaders
            )
        )

        body = compat.to_bytes(self.error_message_401)
        start_response(
            "401 Not Authorized",
            [
                ("WWW-Authenticate", wwwauthheaders),
                ("Content-Type", "text/html"),
                ("Content-Length", str(len(body))),
                ("Date", util.get_rfc1123_time()),
            ],
        )
        return [body]
Ejemplo n.º 8
0
    def wsgiWriteData(self, data):
        if not self.wsgiSentHeaders:
            status, headers = self.wsgiHeaders
            # Need to send header prior to data
            statusCode = status[:status.find(" ")]
            statusMsg = status[status.find(" ") + 1:]
            _logger.debug("wsgiWriteData: send headers '{!r}', {!r}".format(
                status, headers))
            self.send_response(int(statusCode), statusMsg)
            for header, value in headers:
                self.send_header(header, value)
            self.end_headers()
            self.wsgiSentHeaders = 1
        # Send the data
        # assert type(data) is str # If not, Content-Length is propably wrong!
        _logger.debug("wsgiWriteData: write {} bytes: '{!r}'...".format(
            len(data), compat.to_native(data[:50])))
        if compat.is_unicode(
                data):  # If not, Content-Length is propably wrong!
            _logger.info(
                "ext_wsgiutils_server: Got unicode data: {!r}".format(data))
            # data = compat.wsgi_to_bytes(data)
            data = compat.to_bytes(data)

        try:
            self.wfile.write(data)
        except socket.error as e:
            # Suppress stack trace when client aborts connection disgracefully:
            # 10053: Software caused connection abort
            # 10054: Connection reset by peer
            if e.args[0] in (10053, 10054):
                _logger.info("*** Caught socket.error: ", e, file=sys.stderr)
            else:
                raise
Ejemplo n.º 9
0
    def sendDigestAuthResponse(self, environ, start_response):
        realmname = self._domaincontroller.getDomainRealm(
            environ["PATH_INFO"], environ)
        random.seed()
        serverkey = hex(random.getrandbits(32))[2:]
        etagkey = calc_hexdigest(environ["PATH_INFO"])
        timekey = str(time.time())
        nonce_source = timekey + \
            calc_hexdigest(timekey + ":" + etagkey + ":" + serverkey)
        # nonce = to_native(base64.b64encode(compat.to_bytes(nonce_source)))
        nonce = calc_base64(nonce_source)
        wwwauthheaders = ('Digest realm="%s", nonce="%s", algorithm=MD5, qop="auth"'
                          % (realmname, nonce))

        _logger.debug("401 Not Authorized for realm '%s' (digest): %s" %
                      (realmname, wwwauthheaders))

        body = compat.to_bytes(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]
Ejemplo n.º 10
0
    def testGetPut(self):
        """Read and write file contents."""
        app = self.app

        # Prepare file content
        data1 = b"this is a file\nwith two lines"
        data2 = b"this is another file\nwith three lines\nsee?"
        # Big file with 10 MB
        lines = []
        line = "." * (1000 - 6 - len("\n"))
        for i in compat.xrange(10 * 1000):
            lines.append("%04i: %s\n" % (i, line))
        data3 = "".join(lines)
        data3 = compat.to_bytes(data3)

        # Remove old test files
        app.delete("/file1.txt", expect_errors=True)
        app.delete("/file2.txt", expect_errors=True)
        app.delete("/file3.txt", expect_errors=True)

        # Access unmapped resource (expect '404 Not Found')
        app.delete("/file1.txt", status=404)
        app.get("/file1.txt", status=404)

        # PUT a small file (expect '201 Created')
        app.put("/file1.txt", params=data1, status=201)

        res = app.get("/file1.txt", status=200)
        assert res.body == data1, "GET file content different from PUT"

        # PUT overwrites a small file (expect '204 No Content')
        app.put("/file1.txt", params=data2, status=204)

        res = app.get("/file1.txt", status=200)
        assert res.body == data2, "GET file content different from PUT"

        # PUT writes a big file (expect '201 Created')
        app.put("/file2.txt", params=data3, status=201)

        res = app.get("/file2.txt", status=200)
        assert res.body == data3, "GET file content different from PUT"

        # Request must not contain a body (expect '415 Media Type Not
        # Supported')
        app.request(
            "/file1.txt",
            method="GET",
            headers={"Content-Length": compat.to_native(len(data1))},
            body=data1,
            status=415,
        )

        # Delete existing resource (expect '204 No Content')
        app.delete("/file1.txt", status=204)
        # Get deleted resource (expect '404 Not Found')
        app.get("/file1.txt", status=404)

        # PUT a small file (expect '201 Created')
        app.put("/file1.txt", params=data1, status=201)
Ejemplo n.º 11
0
    def testGetPut(self):
        """Read and write file contents."""
        app = self.app

        # Prepare file content
        data1 = b"this is a file\nwith two lines"
        data2 = b"this is another file\nwith three lines\nsee?"
        # Big file with 10 MB
        lines = []
        line = "." * (1000 - 6 - len("\n"))
        for i in compat.xrange(10 * 1000):
            lines.append("%04i: %s\n" % (i, line))
        data3 = "".join(lines)
        data3 = compat.to_bytes(data3)

        # Remove old test files
        app.delete("/file1.txt", expect_errors=True)
        app.delete("/file2.txt", expect_errors=True)
        app.delete("/file3.txt", expect_errors=True)

        # Access unmapped resource (expect '404 Not Found')
        app.delete("/file1.txt", status=404)
        app.get("/file1.txt", status=404)

        # PUT a small file (expect '201 Created')
        app.put("/file1.txt", params=data1, status=201)

        res = app.get("/file1.txt", status=200)
        assert res.body == data1, "GET file content different from PUT"

        # PUT overwrites a small file (expect '204 No Content')
        app.put("/file1.txt", params=data2, status=204)

        res = app.get("/file1.txt", status=200)
        assert res.body == data2, "GET file content different from PUT"

        # PUT writes a big file (expect '201 Created')
        app.put("/file2.txt", params=data3, status=201)

        res = app.get("/file2.txt", status=200)
        assert res.body == data3, "GET file content different from PUT"

        # Request must not contain a body (expect '415 Media Type Not
        # Supported')
        app.request(
            "/file1.txt",
            method="GET",
            headers={"Content-Length": compat.to_native(len(data1))},
            body=data1,
            status=415,
        )

        # Delete existing resource (expect '204 No Content')
        app.delete("/file1.txt", status=204)
        # Get deleted resource (expect '404 Not Found')
        app.get("/file1.txt", status=404)

        # PUT a small file (expect '201 Created')
        app.put("/file1.txt", params=data1, status=201)
Ejemplo n.º 12
0
 def get_content(self):
     fileLinks = [
         "<a href='%s'>%s</a>\n" % (os.path.basename(f), f)
         for f in self.data["resPathList"]
     ]
     dict = self.data.copy()
     dict["fileLinks"] = ", ".join(fileLinks)
     if self.name == ".Info.html":
         html = (
             """\
         <html><head>
         <title>%(title)s</title>
         </head><body>
         <h1>%(title)s</h1>
         <table>
         <tr>
             <td>Description</td>
             <td>%(description)s</td>
         </tr><tr>
             <td>Status</td>
             <td>%(status)s</td>
         </tr><tr>
             <td>Tags</td>
             <td>%(tags)s</td>
         </tr><tr>
             <td>Orga unit</td>
             <td>%(orga)s</td>
         </tr><tr>
             <td>Files</td>
             <td>%(fileLinks)s</td>
         </tr><tr>
             <td>Key</td>
             <td>%(key)s</td>
         </tr>
         </table>
         <p>This is a virtual WsgiDAV resource called '%(title)s'.</p>
         </body></html>"""
             % dict
         )
     elif self.name == ".Info.txt":
         lines = [
             self.data["title"],
             "=" * len(self.data["title"]),
             self.data["description"],
             "",
             "Status: %s" % self.data["status"],
             "Orga:   %8s" % self.data["orga"],
             "Tags:   '%s'" % "', '".join(self.data["tags"]),
             "Key:    %s" % self.data["key"],
         ]
         html = "\n".join(lines)
     elif self.name == ".Description.txt":
         html = self.data["description"]
     else:
         raise DAVError(HTTP_INTERNAL_ERROR, "Invalid artifact '%s'" % self.name)
     return compat.BytesIO(compat.to_bytes(html))
Ejemplo n.º 13
0
 def _consumer():
     # print("_consumer: {}".format(self.target_path))
     with open(self.target_path, "wb") as f:
         s = 0
         # print("_consumer: read()...")
         data = queue.read()
         while data:
             s += len(data)
             # print("_consumer: read(): write")
             f.write(compat.to_bytes(data))
             data = queue.read()
Ejemplo n.º 14
0
 def get_content(self):
     fileLinks = [
         "<a href='%s'>%s</a>\n" % (os.path.basename(f), f)
         for f in self.data["resPathList"]
     ]
     dict = self.data.copy()
     dict["fileLinks"] = ", ".join(fileLinks)
     if self.name == ".Info.html":
         html = ("""\
         <html><head>
         <title>%(title)s</title>
         </head><body>
         <h1>%(title)s</h1>
         <table>
         <tr>
             <td>Description</td>
             <td>%(description)s</td>
         </tr><tr>
             <td>Status</td>
             <td>%(status)s</td>
         </tr><tr>
             <td>Tags</td>
             <td>%(tags)s</td>
         </tr><tr>
             <td>Orga unit</td>
             <td>%(orga)s</td>
         </tr><tr>
             <td>Files</td>
             <td>%(fileLinks)s</td>
         </tr><tr>
             <td>Key</td>
             <td>%(key)s</td>
         </tr>
         </table>
         <p>This is a virtual WsgiDAV resource called '%(title)s'.</p>
         </body></html>""" % dict)
     elif self.name == ".Info.txt":
         lines = [
             self.data["title"],
             "=" * len(self.data["title"]),
             self.data["description"],
             "",
             "Status: %s" % self.data["status"],
             "Orga:   %8s" % self.data["orga"],
             "Tags:   '%s'" % "', '".join(self.data["tags"]),
             "Key:    %s" % self.data["key"],
         ]
         html = "\n".join(lines)
     elif self.name == ".Description.txt":
         html = self.data["description"]
     else:
         raise DAVError(HTTP_INTERNAL_ERROR,
                        "Invalid artifact '%s'" % self.name)
     return compat.BytesIO(compat.to_bytes(html))
Ejemplo n.º 15
0
 def _consumer():
     # print("_consumer: {}".format(self.target_path))
     with open(self.target_path, "wb") as f:
         s = 0
         # print("_consumer: read()...")
         data = queue.read()
         while data:
             s += len(data)
             # print("_consumer: read(): write")
             f.write(compat.to_bytes(data))
             data = queue.read()
Ejemplo n.º 16
0
    def sendNotAuthorizedResponse(self, body, environ, start_response):
        _logger.debug('401 Not Authorized (token)')
        wwwauthheaders = 'Token'

        body = compat.to_bytes(body)
        start_response('401 Not Authorized', [
            ('WWW-Authenticate', wwwauthheaders),
            ('Content-Type', 'text/html'),
            ('Content-Length', str(len(body))),
            ('Date', util.getRfc1123Time()),
        ])
        return [body]
Ejemplo n.º 17
0
    def sendBasicAuthResponse(self, environ, start_response):
        realmname = self._domaincontroller.getDomainRealm(
            environ["PATH_INFO"], environ)
        _logger.debug("401 Not Authorized for realm '{}' (basic)".format(realmname))
        wwwauthheaders = "Basic realm=\"" + realmname + "\""

        body = compat.to_bytes(self.getErrorMessage())
        start_response("401 Not Authorized", [("WWW-Authenticate", wwwauthheaders),
                                              ("Content-Type", "text/html"),
                                              ("Content-Length", str(len(body))),
                                              ("Date", util.getRfc1123Time()),
                                              ])
        return [body]
Ejemplo n.º 18
0
    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 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 = util.makeCompleteUrl(environ)
                collectionUrl = collectionUrl.split("?", 1)[0]
                res = """
                    <dm:mount xmlns:dm="http://purl.org/NET/webdav/mount">
                        <dm:url>{}</dm:url>
                    </dm:mount>""".format(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]

            context = self._get_context(environ, davres)

            res = self.template.render(**context)
            res = compat.to_bytes(res)
            start_response("200 OK", [
                ("Content-Type", "text/html"),
                ("Content-Length", str(len(res))),
                ("Cache-Control", "private"),
                ("Date", util.getRfc1123Time()),
            ])
            return [res]

        return self.next_app(environ, start_response)
Ejemplo n.º 19
0
    def send_basic_auth_response(self, environ, start_response):
        realm = self.domain_controller.get_domain_realm(environ["PATH_INFO"], environ)
        _logger.debug("401 Not Authorized for realm '{}' (basic)".format(realm))
        wwwauthheaders = 'Basic realm="' + realm + '"'

        body = compat.to_bytes(self.error_message_401)
        start_response(
            "401 Not Authorized",
            [
                ("WWW-Authenticate", wwwauthheaders),
                ("Content-Type", "text/html"),
                ("Content-Length", str(len(body))),
                ("Date", util.get_rfc1123_time()),
            ],
        )
        return [body]
Ejemplo n.º 20
0
    def send_basic_auth_response(self, environ, start_response):
        realm = self.domain_controller.get_domain_realm(environ["PATH_INFO"], environ)
        _logger.debug("401 Not Authorized for realm '{}' (basic)".format(realm))
        wwwauthheaders = 'Basic realm="' + realm + '"'

        body = compat.to_bytes(self.error_message_401)
        start_response(
            "401 Not Authorized",
            [
                ("WWW-Authenticate", wwwauthheaders),
                ("Content-Type", "text/html"),
                ("Content-Length", str(len(body))),
                ("Date", util.get_rfc1123_time()),
            ],
        )
        return [body]
Ejemplo n.º 21
0
    def authBasicAuthRequest(self, environ, start_response):
        realmname = self._domaincontroller.getDomainRealm(
            environ["PATH_INFO"], environ)
        authheader = environ["HTTP_AUTHORIZATION"]
        authvalue = ""
        try:
            authvalue = authheader[len("Basic "):].strip()
        except Exception:
            authvalue = ""
        # authvalue = authvalue.strip().decode("base64")
        authvalue = compat.base64_decodebytes(compat.to_bytes(authvalue))
        authvalue = compat.to_native(authvalue)
        username, password = authvalue.split(":", 1)

        if self._domaincontroller.authDomainUser(realmname, username, password, environ):
            environ["http_authenticator.realm"] = realmname
            environ["http_authenticator.username"] = username
            return self._application(environ, start_response)
        return self.sendBasicAuthResponse(environ, start_response)
Ejemplo n.º 22
0
    def handle_basic_auth_request(self, environ, start_response):
        realm = self.domain_controller.get_domain_realm(environ["PATH_INFO"], environ)
        auth_header = environ["HTTP_AUTHORIZATION"]
        auth_value = ""
        try:
            auth_value = auth_header[len("Basic ") :].strip()
        except Exception:
            auth_value = ""

        auth_value = compat.base64_decodebytes(compat.to_bytes(auth_value))
        auth_value = compat.to_native(auth_value)
        user_name, password = auth_value.split(":", 1)

        if self.domain_controller.basic_auth_user(realm, user_name, password, environ):
            environ["wsgidav.auth.realm"] = realm
            environ["wsgidav.auth.user_name"] = user_name
            return self.next_app(environ, start_response)

        _logger.warning(
            "Authentication (basic) failed for user '{}', realm '{}'.".format(
                user_name, realm
            )
        )
        return self.send_basic_auth_response(environ, start_response)
Ejemplo n.º 23
0
    def handle_basic_auth_request(self, environ, start_response):
        realm = self.domain_controller.get_domain_realm(environ["PATH_INFO"], environ)
        auth_header = environ["HTTP_AUTHORIZATION"]
        auth_value = ""
        try:
            auth_value = auth_header[len("Basic ") :].strip()
        except Exception:
            auth_value = ""

        auth_value = compat.base64_decodebytes(compat.to_bytes(auth_value))
        auth_value = compat.to_native(auth_value)
        user_name, password = auth_value.split(":", 1)

        if self.domain_controller.basic_auth_user(realm, user_name, password, environ):
            environ["wsgidav.auth.realm"] = realm
            environ["wsgidav.auth.user_name"] = user_name
            return self.next_app(environ, start_response)

        _logger.warning(
            "Authentication (basic) failed for user '{}', realm '{}'.".format(
                user_name, realm
            )
        )
        return self.send_basic_auth_response(environ, start_response)
Ejemplo n.º 24
0
    def testGetPut(self):
        """Read and write file contents."""
        client = self.client

        # Prepare file content
        data1 = b"this is a file\nwith two lines"
        data2 = b"this is another file\nwith three lines\nsee?"
        # Big file with 10 MB
        lines = []
        line = "." * (1000 - 6 - len("\n"))
        for i in compat.xrange(10 * 1000):
            lines.append("%04i: %s\n" % (i, line))
        data3 = "".join(lines)
        data3 = compat.to_bytes(data3)

        # Cleanup
        client.delete("/test/")
        client.mkcol("/test/")
        client.checkResponse(201)

        # PUT files
        client.put("/test/file1.txt", data1)
        client.checkResponse(201)
        client.put("/test/file2.txt", data2)
        client.checkResponse(201)
        client.put("/test/bigfile.txt", data3)
        client.checkResponse(201)

        body = client.get("/test/file1.txt")
        client.checkResponse(200)
        assert body == data1, "Put/Get produced different bytes"

        # PUT with overwrite must return 204 No Content, instead of 201 Created
        client.put("/test/file2.txt", data2)
        client.checkResponse(204)

        client.mkcol("/test/folder")
        client.checkResponse(201)

        locks = client.set_lock("/test/lock-0",
                                owner="test-bench",
                                locktype="write",
                                lockscope="exclusive",
                                depth="infinity")
        client.checkResponse(201)  # created
        assert len(locks) == 1, "LOCK failed"
        token = locks[0]
        client.refresh_lock("/test/lock-0", token)
        client.checkResponse(200)  # ok
        client.unlock("/test/lock-0", token)
        client.checkResponse(204)  # no content
        client.unlock("/test/lock-0", token)
        # 409 Conflict, because resource was not locked
        # (http://www.webdav.org/specs/rfc4918.html#METHOD_UNLOCK)
        client.checkResponse(409)

        client.proppatch("/test/file1.txt",
                         set_props=[("{testns:}testname", "testval"),
                                    ],
                         remove_props=None)
        client.checkResponse()

        client.copy("/test/file1.txt",
                    "/test/file2.txt",
                    depth='infinity', overwrite=True)
        client.checkResponse()

        client.move("/test/file2.txt",
                    "/test/file2_moved.txt",
                    depth='infinity', overwrite=True)
        client.checkResponse()

        client.propfind("/",
                        properties="allprop",
                        namespace='DAV:',
                        depth=None,
                        headers=None)
        client.checkResponse()
Ejemplo n.º 25
0
    def testGetPut(self):
        """Read and write file contents."""
        client = self.client
        # Prepare file content
        data1 = b"this is a file\nwith two lines"
        data2 = b"this is another file\nwith three lines\nsee?"
        # Big file with 10 MB
        lines = []
        line = "." * (1000 - 6 - len("\n"))
        for i in compat.xrange(10 * 1000):
            lines.append("%04i: %s\n" % (i, line))
        data3 = "".join(lines)
        data3 = compat.to_bytes(data3)

        # Cleanup
        client.delete("/test/")
        client.mkcol("/test/")
        client.check_response(201)

        # PUT files
        client.put("/test/file1.txt", data1)
        client.check_response(201)
        client.put("/test/file2.txt", data2)
        client.check_response(201)
        client.put("/test/bigfile.txt", data3)
        client.check_response(201)

        body = client.get("/test/file1.txt")
        client.check_response(200)
        assert body == data1, "Put/Get produced different bytes"

        # PUT with overwrite must return 204 No Content, instead of 201 Created
        client.put("/test/file2.txt", data2)
        client.check_response(204)

        client.mkcol("/test/folder")
        client.check_response(201)

        # if a LOCK request is sent to an unmapped URL, we must create a
        # lock-null resource and return '201 Created', instead of '404 Not found'
        locks = client.set_lock(
            "/test/lock-0",
            owner="test-bench",
            lock_type="write",
            lock_scope="exclusive",
            depth="infinity",
        )
        client.check_response(201)  # created
        assert len(locks) == 1, "LOCK failed"

        token = locks[0]
        client.refresh_lock("/test/lock-0", token)
        client.check_response(200)  # ok

        client.unlock("/test/lock-0", token)
        client.check_response(204)  # no content

        client.unlock("/test/lock-0", token)
        # 409 Conflict, because resource was not locked
        # (http://www.webdav.org/specs/rfc4918.html#METHOD_UNLOCK)
        client.check_response(409)

        # issue #71: unlock non existing resource
        client.unlock("/test/lock-not-existing", token)
        client.check_response(404)

        client.proppatch(
            "/test/file1.txt",
            set_props=[("{testns:}testname", "testval")],
            remove_props=None,
        )
        client.check_response()

        client.copy(
            "/test/file1.txt", "/test/file2.txt", depth="infinity", overwrite=True
        )
        client.check_response()

        client.move(
            "/test/file2.txt", "/test/file2_moved.txt", depth="infinity", overwrite=True
        )
        client.check_response()

        client.propfind(
            "/", properties="allprop", namespace="DAV:", depth=None, headers=None
        )
        client.check_response()
Ejemplo n.º 26
0
def write_test_file(name, size):
    path = os.path.join(gettempdir(), name)
    with open(path, "wb") as f:
        f.write(compat.to_bytes("*") * size)
    return path
Ejemplo n.º 27
0
def write_test_file(name, size):
    path = os.path.join(gettempdir(), name)
    with open(path, "wb") as f:
        f.write(compat.to_bytes("*") * size)
    return path
Ejemplo n.º 28
0
 def _compute_http_digest_a1(self, realm, user_name, password):
     """Internal helper for derived classes to compute a digest hash (A1 part)."""
     data = user_name + ":" + realm + ":" + password
     A1 = md5(compat.to_bytes(data)).hexdigest()
     return A1
Ejemplo n.º 29
0
def calc_base64(s):
    """Return base64 encoded binarystring."""
    s = compat.to_bytes(s)
    s = base64.encodestring(s).strip()  # return bytestring
    return compat.to_native(s)
Ejemplo n.º 30
0
 def md5h(data):
     return md5(compat.to_bytes(data)).hexdigest()
Ejemplo n.º 31
0
def calc_base64(s):
    """Return base64 encoded binarystring."""
    s = compat.to_bytes(s)
    s = compat.base64_encodebytes(s).strip()  # return bytestring
    return compat.to_native(s)
Ejemplo n.º 32
0
    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 = compat.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>" % " &#8211; ".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)
        body = compat.to_bytes(body)

        start_response("200 OK", [("Content-Type", "text/html"),
                                  ("Content-Length", str(len(body))),
                                  ("Date", util.getRfc1123Time()),
                                  ])
        return [body]
Ejemplo n.º 33
0
def calc_hexdigest(s):
    """Return md5 digest for a string."""
    s = compat.to_bytes(s)
    return md5(s).hexdigest()  # return native string
Ejemplo n.º 34
0
def calc_hexdigest(s):
    """Return md5 digest for a string."""
    s = compat.to_bytes(s)
    return md5(s).hexdigest()  # return native string
Ejemplo n.º 35
0
def _bench_script(opts):
    # print("Scriptes benchmarks")
    # print("_bench_script(), {}...".format(opts))

    from tests import davclient

    server_url = opts.get("external_server") or "http://localhost:8080/"
    client = davclient.DAVClient(server_url)
    client.set_basic_auth("tester", "secret")

    # Prepare file content
    data_1k = b"." * 1000

    # Prepare big file with 10 MB
    lines = []
    line = "." * (1000 - 6 - len("\n"))
    for i in compat.xrange(10 * 1000):
        lines.append("%04i: %s\n" % (i, line))
    data_10m = "".join(lines)
    data_10m = compat.to_bytes(data_10m)

    with Timing("Setup fixture"):
        _setup_fixture(opts, client)

    # PUT files
    with Timing("1000 x PUT 1 kB", 1000, "{:>6.1f} req/sec", 1,
                "{:>7,.3f} MB/sec"):
        for _ in compat.xrange(1000):
            client.put("/test/file1.txt", data_1k)
        client.check_response()

    with Timing("10 x PUT 10 MB", 10, "{:>6.1f} req/sec", 100,
                "{:>7,.3f} MB/sec"):
        for _ in compat.xrange(10):
            client.put("/test/bigfile.txt", data_10m)
        client.check_response()

    with Timing("1000 x GET 1 kB", 1000, "{:>6.1f} req/sec", 1,
                "{:>7,.3f} MB/sec"):
        for _ in compat.xrange(1000):
            body = client.get("/test/file1.txt")
        client.check_response()

    with Timing("10 x GET 10 MB", 10, "{:>6.1f} req/sec", 100,
                "{:>7,.3f} MB/sec"):
        for _ in compat.xrange(10):
            body = client.get("/test/bigfile.txt")  # noqa F841
        client.check_response()

    with Timing("10 x COPY 10 MB", 10, "{:>6.1f} req/sec", 100,
                "{:>7,.3f} MB/sec"):
        for _ in compat.xrange(10):
            client.copy(
                "/test/bigfile.txt",
                "/test/bigfile-copy.txt",
                depth="infinity",
                overwrite=True,
            )
        client.check_response()

    with Timing("100 x MOVE 10 MB", 100, "{:>6.1f} req/sec"):
        name_from = "/test/bigfile-copy.txt"
        for i in compat.xrange(100):
            name_to = "/test/bigfile-copy-{}.txt".format(i)
            client.move(name_from, name_to, depth="infinity", overwrite=True)
            name_from = name_to
        client.check_response()

    with Timing("100 x LOCK/UNLOCK", 200, "{:>6.1f} req/sec"):
        for _ in compat.xrange(100):
            locks = client.set_lock(
                "/test/lock-0",
                owner="test-bench",
                locktype="write",
                lockscope="exclusive",
                depth="infinity",
            )
            token = locks[0]
            client.unlock("/test/lock-0", token)
        client.check_response()

    with Timing("1000 x PROPPATCH", 1000, "{:>6.1f} req/sec"):
        for _ in compat.xrange(1000):
            client.proppatch(
                "/test/file1.txt",
                set_props=[("{testns:}testname", "testval")],
                remove_props=None,
            )
        client.check_response()

    with Timing("500 x PROPFIND", 500, "{:>6.1f} req/sec"):
        for _ in compat.xrange(500):
            client.propfind("/",
                            properties="allprop",
                            namespace="DAV:",
                            depth=None,
                            headers=None)
        client.check_response()
Ejemplo n.º 36
0
 def md5h(self, data):
     return md5(compat.to_bytes(data)).hexdigest()
Ejemplo n.º 37
0
 def _compute_http_digest_a1(self, realm, user_name, password):
     """Internal helper for derived classes to compute a digest hash (A1 part)."""
     data = user_name + ":" + realm + ":" + password
     A1 = md5(compat.to_bytes(data)).hexdigest()
     return A1