예제 #1
0
 def _fail(self, value, contextinfo=None, srcexception=None, errcondition=None):
     """Wrapper to raise (and log) DAVError."""
     e = DAVError(value, contextinfo, srcexception, errcondition)
     if self._verbose >= 2:
         print("Raising DAVError %s" % safeReEncode(e.getUserInfo(), sys.stdout.encoding or "ASCII"),
               file=sys.stdout)
     raise e
예제 #2
0
 def _fail(self, value, contextinfo=None, srcexception=None, errcondition=None):
     """Wrapper to raise (and log) DAVError."""
     e = DAVError(value, contextinfo, srcexception, errcondition)
     if self._verbose >= 2:
         _logger.error("Raising DAVError {}".format(
                       safeReEncode(e.getUserInfo(), sys.stdout.encoding)))
     raise e
예제 #3
0
 def getDomainRealm(self, inputURL, environ):
     """Resolve a relative url to the  appropriate realm name."""
     # we don't get the realm here, its already been resolved in
     # request_resolver
     davProvider = environ["wsgidav.provider"]
     if not davProvider:
         if environ["wsgidav.verbose"] >= 2:
             _logger.debug("getDomainRealm({}): '{}'".format(
                 util.safeReEncode(inputURL, sys.stdout.encoding), None))
         return None
     realm = davProvider.sharePath
     if realm == "":
         realm = "/"
     return realm
예제 #4
0
    def getDomainRealm(self, inputURL, environ):
        """Resolve a relative url to the  appropriate realm name."""
        # we don't get the realm here, its already been resolved in
        # request_resolver
        davProvider = environ["wsgidav.provider"]
        if not davProvider:
            if environ["wsgidav.verbose"] >= 2:
                print("getDomainRealm(%s): '%s'"
                      % (safeReEncode(inputURL, sys.stdout.encoding), None), file=sys.stdout)
            return None
        realm = davProvider.sharePath
        if realm == "":
            realm = "/"
#        if environ["wsgidav.verbose"] >= 2:
#            print >>sys.stdout, "getDomainRealm(%s): '%s'" %(inputURL, realm)
        return realm
예제 #5
0
    def __call__(self, environ, start_response):
        """"""
        # srvcfg = environ["wsgidav.config"]
        verbose = self._config.get("verbose", 3)

        method = environ["REQUEST_METHOD"]

        debugBreak = False
        dumpRequest = False
        dumpResponse = False

        if verbose >= 5:
            dumpRequest = dumpResponse = True

        # Process URL commands
        if "dump_storage" in environ.get("QUERY_STRING", ""):
            dav = environ.get("wsgidav.provider")
            if dav.lockManager:
                dav.lockManager._dump()
            if dav.propManager:
                dav.propManager._dump()

        # Turn on max. debugging for selected litmus tests
        litmusTag = environ.get("HTTP_X_LITMUS",
                                environ.get("HTTP_X_LITMUS_SECOND"))
        if litmusTag and verbose >= 3:
            _logger.info("----\nRunning litmus test '{}'...".format(litmusTag))
            for litmusSubstring in self.debug_litmus:
                if litmusSubstring in litmusTag:
                    verbose = 5
                    debugBreak = True
                    dumpRequest = True
                    dumpResponse = True
                    break
            for litmusSubstring in self.break_after_litmus:
                if litmusSubstring in self.passedLitmus and litmusSubstring not in litmusTag:
                    _logger.info(
                        " *** break after litmus {}".format(litmusTag))
                    sys.exit(-1)
                if litmusSubstring in litmusTag:
                    self.passedLitmus[litmusSubstring] = True

        # Turn on max. debugging for selected request methods
        if verbose >= 3 and method in self.debug_methods:
            verbose = 5
            debugBreak = True
            dumpRequest = True
            dumpResponse = True

        # Set debug options to environment
        environ["wsgidav.verbose"] = verbose
        # environ["wsgidav.debug_methods"] = self.debug_methods
        environ["wsgidav.debug_break"] = debugBreak
        environ["wsgidav.dump_request_body"] = dumpRequest
        environ["wsgidav.dump_response_body"] = dumpResponse

        # Dump request headers
        if dumpRequest:
            _logger.info("{} Request ---".format(method))
            # _logger.info("<{}> --- {} Request ---".format(
            #         threading.currentThread().ident, method))
            for k, v in environ.items():
                if k == k.upper():
                    _logger.info("{:<20}: '{}'".format(k,
                                                       safeReEncode(v,
                                                                    "utf8")))
            _logger.info("\n")

        # Intercept start_response
        #
        sub_app_start_response = util.SubAppStartResponse()

        nbytes = 0
        first_yield = True
        app_iter = self._application(environ, sub_app_start_response)

        for v in app_iter:
            # Start response (the first time)
            if first_yield:
                # Success!
                start_response(sub_app_start_response.status,
                               sub_app_start_response.response_headers,
                               sub_app_start_response.exc_info)

            # Dump response headers
            if first_yield and dumpResponse:
                _logger.info("<{}> ---{}  Response({}): ---".format(
                    threading.currentThread().ident, method,
                    sub_app_start_response.status))
                headersdict = dict(sub_app_start_response.response_headers)
                for envitem in headersdict.keys():
                    _logger.info("{}: {}".format(envitem,
                                                 repr(headersdict[envitem])))
                _logger.info("")

            # Check, if response is a binary string, otherwise we probably have
            # calculated a wrong content-length
            assert compat.is_bytes(v), v

            # Dump response body
            drb = environ.get("wsgidav.dump_response_body")
            if compat.is_basestring(drb):
                # Middleware provided a formatted body representation
                _logger.info(drb)
                drb = environ["wsgidav.dump_response_body"] = None
            elif drb is True:
                # Else dump what we get, (except for long GET responses)
                if method == "GET":
                    if first_yield:
                        _logger.info("{}...".format(v[:50]))
                elif len(v) > 0:
                    _logger.info(v)

            nbytes += len(v)
            first_yield = False
            yield v
        if hasattr(app_iter, "close"):
            app_iter.close()

        # Start response (if it hasn't been done yet)
        if first_yield:
            # Success!
            start_response(sub_app_start_response.status,
                           sub_app_start_response.response_headers,
                           sub_app_start_response.exc_info)

        if dumpResponse:
            _logger.info("<{}> --- End of {} Response ({:d} bytes) ---".format(
                threading.currentThread().ident, method, nbytes))
        return
예제 #6
0
        def _start_response_wrapper(status, response_headers, exc_info=None):
            # Postprocess response headers
            headerDict = {}
            for header, value in response_headers:
                if header.lower() in headerDict:
                    util.warn("Duplicate header in response: %s" % header)
                headerDict[header.lower()] = value

            # Check if we should close the connection after this request.
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
            forceCloseConnection = False
            currentContentLength = headerDict.get("content-length")
            statusCode = int(status.split(" ", 1)[0])
            contentLengthRequired = (environ["REQUEST_METHOD"] != "HEAD"
                                     and statusCode >= 200
                                     and not statusCode in (204, 304))
#            print(environ["REQUEST_METHOD"], statusCode, contentLengthRequired)
            if contentLengthRequired and currentContentLength in (None, ""):
                # A typical case: a GET request on a virtual resource, for which
                # the provider doesn't know the length
                util.warn(
                    "Missing required Content-Length header in %s-response: closing connection" %
                    statusCode)
                forceCloseConnection = True
            elif not type(currentContentLength) is str:
                util.warn("Invalid Content-Length header in response (%r): closing connection" %
                          headerDict.get("content-length"))
                forceCloseConnection = True

            # HOTFIX for Vista and Windows 7 (GC issue 13, issue 23)
            # It seems that we must read *all* of the request body, otherwise
            # clients may miss the response.
            # For example Vista MiniRedir didn't understand a 401 response,
            # when trying an anonymous PUT of big files. As a consequence, it
            # doesn't retry with credentials and the file copy fails.
            # (XP is fine however).
            util.readAndDiscardInput(environ)

            # Make sure the socket is not reused, unless we are 100% sure all
            # current input was consumed
            if(util.getContentLength(environ) != 0
               and not environ.get("wsgidav.all_input_read")):
                util.warn(
                    "Input stream not completely consumed: closing connection")
                forceCloseConnection = True

            if forceCloseConnection and headerDict.get("connection") != "close":
                util.warn("Adding 'Connection: close' header")
                response_headers.append(("Connection", "close"))

            # Log request
            if self._verbose >= 1:
                userInfo = environ.get("http_authenticator.username")
                if not userInfo:
                    userInfo = "(anonymous)"
                threadInfo = ""
                if self._verbose >= 1:
                    threadInfo = "<%s> " % threading.currentThread().ident
                extra = []
                if "HTTP_DESTINATION" in environ:
                    extra.append('dest="%s"' % environ.get("HTTP_DESTINATION"))
                if environ.get("CONTENT_LENGTH", "") != "":
                    extra.append("length=%s" % environ.get("CONTENT_LENGTH"))
                if "HTTP_DEPTH" in environ:
                    extra.append("depth=%s" % environ.get("HTTP_DEPTH"))
                if "HTTP_RANGE" in environ:
                    extra.append("range=%s" % environ.get("HTTP_RANGE"))
                if "HTTP_OVERWRITE" in environ:
                    extra.append("overwrite=%s" %
                                 environ.get("HTTP_OVERWRITE"))
                if self._verbose >= 1 and "HTTP_EXPECT" in environ:
                    extra.append('expect="%s"' % environ.get("HTTP_EXPECT"))
                if self._verbose >= 2 and "HTTP_CONNECTION" in environ:
                    extra.append('connection="%s"' %
                                 environ.get("HTTP_CONNECTION"))
                if self._verbose >= 2 and "HTTP_USER_AGENT" in environ:
                    extra.append('agent="%s"' % environ.get("HTTP_USER_AGENT"))
                if self._verbose >= 2 and "HTTP_TRANSFER_ENCODING" in environ:
                    extra.append('transfer-enc=%s' %
                                 environ.get("HTTP_TRANSFER_ENCODING"))
                if self._verbose >= 1:
                    extra.append('elap=%.3fsec' % (time.time() - start_time))
                extra = ", ".join(extra)

#               This is the CherryPy format:
#                127.0.0.1 - - [08/Jul/2009:17:25:23] "GET /loginPrompt?redirect=/renderActionList%3Frelation%3Dpersonal%26key%3D%26filter%3DprivateSchedule&reason=0 HTTP/1.1" 200 1944 "http://127.0.0.1:8002/command?id=CMD_Schedule" "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1) Gecko/20090624 Firefox/3.5"
#                print >>sys.stderr, '%s - %s - [%s] "%s" %s -> %s' % (
                print('%s - %s - [%s] "%s" %s -> %s' % (
                    threadInfo + environ.get("REMOTE_ADDR", ""),
                    userInfo,
                    util.getLogTime(),
                    environ.get("REQUEST_METHOD") + " " +
                    safeReEncode(environ.get("PATH_INFO", ""), sys.stdout.encoding or "ASCII"),
                    extra,
                    status,
                    # response_headers.get(""), # response Content-Length
                    # referer
                ), file=sys.stdout)

            return start_response(status, response_headers, exc_info)