Пример #1
0
    def post(self, query):
        i = self.institution
        logging.debug('posting data to %s' % i.url)
        logging.debug('---- request ----')
        logging.debug(query)
        garbage, path = splittype(i.url)
        host, selector = splithost(path)
        h = HTTPSConnection(host, timeout=60)
        # Discover requires a particular ordering of headers, so send the
        # request step by step.
        h.putrequest('POST',
                     selector,
                     skip_host=True,
                     skip_accept_encoding=True)
        h.putheader('Content-Type', 'application/x-ofx')
        h.putheader('Host', host)
        h.putheader('Content-Length', len(query))
        h.putheader('Connection', 'Keep-Alive')
        if self.accept:
            h.putheader('Accept', self.accept)
        if self.user_agent:
            h.putheader('User-Agent', self.user_agent)
        h.endheaders(query.encode())
        res = h.getresponse()
        response = res.read().decode('ascii', 'ignore')
        logging.debug('---- response ----')
        logging.debug(res.__dict__)
        logging.debug(response)
        res.close()

        return response
Пример #2
0
def make_http_request(url, data=None, files=None, certificate=None):
    # type: (str, Optional[Envelope], Optional[Attachments], str) -> Tuple[int, bytes]
    if data is None:
        data = {}

    if files is None:
        files = {}

    schema, netloc, url, params, query, fragments = urlparse(url)
    logger.debug("Sending POST request to {0}".format(url))
    body, boundary = encode_multipart_formdata(data, files)

    if certificate:
        ssl_context = ssl.create_default_context(cafile=certificate)
    else:
        ssl_context = ssl._create_default_https_context()

    connection = HTTPSConnection(netloc, context=ssl_context)
    connection.connect()

    connection.putrequest("POST", url)
    connection.putheader("Content-Type",
                         "multipart/form-data; boundary={0}".format(boundary))
    connection.putheader("Content-Length", str(len(body)))
    connection.endheaders()

    connection.send(body)

    r = connection.getresponse()

    return r.status, r.read()
Пример #3
0
    def _do_post(self, query, extra_headers=[]):
        """
        Do a POST to the Institution.

        :param query: Body content to POST (OFX Query)
        :type query: str
        :param extra_headers: Extra headers to send with the request, as a list
          of (Name, Value) header 2-tuples.
        :type extra_headers: list
        :return: 2-tuple of (HTTPResponse, str response body)
        :rtype: tuple
        """
        i = self.institution
        logging.debug('posting data to %s' % i.url)
        garbage, path = splittype(i.url)
        host, selector = splithost(path)
        try:
            h = HTTPSConnection(host, timeout=60)
            h.connect()
        except ssl.SSLError as ex:
            if (ex.reason == "UNSUPPORTED_PROTOCOL"):
                h = HTTPSConnection(host,
                                    timeout=60,
                                    context=ssl.SSLContext(ssl.PROTOCOL_TLSv1))
                h.connect()
            else:
                raise
        # Discover requires a particular ordering of headers, so send the
        # request step by step.
        h.putrequest('POST',
                     selector,
                     skip_host=True,
                     skip_accept_encoding=True)
        headers = [('Content-Type', 'application/x-ofx'), ('Host', host),
                   ('Content-Length', len(query)),
                   ('Connection', 'Keep-Alive')]
        if self.accept:
            headers.append(('Accept', self.accept))
        if self.user_agent:
            headers.append(('User-Agent', self.user_agent))
        for ehname, ehval in extra_headers:
            headers.append((ehname, ehval))
        logging.debug('---- request headers ----')
        for hname, hval in headers:
            logging.debug('%s: %s', hname, hval)
            h.putheader(hname, hval)
        logging.debug('---- request body (query) ----')
        logging.debug(query)
        h.endheaders(query.encode())
        res = h.getresponse()
        response = res.read().decode('ascii', 'ignore')
        logging.debug('---- response ----')
        logging.debug(res.__dict__)
        logging.debug('Headers: %s', res.getheaders())
        logging.debug(response)
        res.close()
        return res, response
Пример #4
0
    def doheadrequest(self, timeout=TIMEOUT):
        """
        Sends a HEAD request to the database node. The header returned by the database node contains some
        information on statistics. This information is stored in the headers object of the request instance.
        """

        self.headers = {}

        url = self.baseurl + self.querypath
        urlobj = urlsplit(url)

        if urlobj.scheme == 'https':
            if self.verifyhttps:
                conn = HTTPSConnection(urlobj.netloc, timeout=timeout)
            else:
                conn = HTTPSConnection(
                    urlobj.netloc,
                    timeout=timeout,
                    context=ssl._create_unverified_context())
        else:
            conn = HTTPConnection(urlobj.netloc, timeout=timeout)
        conn.putrequest("HEAD", urlobj.path + "?" + urlobj.query)
        conn.endheaders()

        try:
            res = conn.getresponse()
        except socket.timeout as e:
            self.status = 408
            self.reason = "Socket timeout"
            raise TimeOutError

        self.status = res.status
        self.reason = res.reason

        if res.status == 200:
            headers = res.getheaders()
        elif res.status == 204:
            headers = [("vamdc-count-species", 0), ("vamdc-count-states", 0),
                       ("vamdc-truncated", 0), ("vamdc-count-molecules", 0),
                       ("vamdc-count-sources", 0), ("vamdc-approx-size", 0),
                       ("vamdc-count-radiative", 0), ("vamdc-count-atoms", 0)]
        elif res.status == 408:
            print("TIMEOUT")
            headers = [("vamdc-count-species", 0), ("vamdc-count-states", 0),
                       ("vamdc-truncated", 0), ("vamdc-count-molecules", 0),
                       ("vamdc-count-sources", 0), ("vamdc-approx-size", 0),
                       ("vamdc-count-radiative", 0), ("vamdc-count-atoms", 0)]
        else:
            print("STATUS: %d" % res.status)
            headers = [("vamdc-count-species", 0), ("vamdc-count-states", 0),
                       ("vamdc-truncated", 0), ("vamdc-count-molecules", 0),
                       ("vamdc-count-sources", 0), ("vamdc-approx-size", 0),
                       ("vamdc-count-radiative", 0), ("vamdc-count-atoms", 0)]

        for key, value in headers:
            self.headers[key] = value
Пример #5
0
    def _do_post(self, query, extra_headers=[]):
        """
        Do a POST to the Institution.

        :param query: Body content to POST (OFX Query)
        :type query: str
        :param extra_headers: Extra headers to send with the request, as a list
          of (Name, Value) header 2-tuples.
        :type extra_headers: list
        :return: 2-tuple of (HTTPResponse, str response body)
        :rtype: tuple
        """
        i = self.institution
        logging.debug('posting data to %s' % i.url)
        garbage, path = splittype(i.url)
        host, selector = splithost(path)
        try:
            h = HTTPSConnection(host, timeout=60)
            h.connect()
        except ssl.SSLError as ex:
            if (ex.reason == "UNSUPPORTED_PROTOCOL"):
                h = HTTPSConnection(host, timeout=60, context=ssl.SSLContext(ssl.PROTOCOL_TLSv1))
                h.connect()
            else:
                raise
        # Discover requires a particular ordering of headers, so send the
        # request step by step.
        h.putrequest('POST', selector, skip_host=True,
                     skip_accept_encoding=True)
        headers = [
            ('Content-Type', 'application/x-ofx'),
            ('Host', host),
            ('Content-Length', len(query)),
            ('Connection', 'Keep-Alive')
        ]
        if self.accept:
            headers.append(('Accept', self.accept))
        if self.user_agent:
            headers.append(('User-Agent', self.user_agent))
        for ehname, ehval in extra_headers:
            headers.append((ehname, ehval))
        logging.debug('---- request headers ----')
        for hname, hval in headers:
            logging.debug('%s: %s', hname, hval)
            h.putheader(hname, hval)
        logging.debug('---- request body (query) ----')
        logging.debug(query)
        h.endheaders(query.encode())
        res = h.getresponse()
        response = res.read().decode('ascii', 'ignore')
        logging.debug('---- response ----')
        logging.debug(res.__dict__)
        logging.debug('Headers: %s', res.getheaders())
        logging.debug(response)
        res.close()
        return res, response
Пример #6
0
    def fetch_file(self, server, path):
        "Fetch file using httplib module."

        print("downloading https://%s%s" % (server, path))

        req = HTTPSConnection(server)
        req.putrequest('GET', path)
        req.putheader('Host', server)
        req.putheader('Accept', 'text/svg')
        req.endheaders()
        r1 = req.getresponse()
        data = r1.read().decode('utf-8')
        req.close()

        return data
Пример #7
0
    def fetchFile(self, server, path):
        "Fetch file using httplib module."
    
        print("downloading http://%s%s" % (server, path))
            
        req = HTTPSConnection(server)
        req.putrequest('GET', path)
        req.putheader('Host', server)
        req.putheader('Accept', 'text/svg')
        req.endheaders()
        r1 = req.getresponse()
        data = r1.read().decode('utf-8')
        req.close()

        return data
Пример #8
0
    def dorequest(self, timeout=TIMEOUT, HttpMethod="POST", parsexsams=True):
        """
        Sends the request to the database node and returns a result.Result instance. The
        request uses 'POST' requests by default. If the request fails or if stated in the parameter 'HttpMethod',
        'GET' requests will be performed. 
        The returned result will be parsed by default and the model defined in 'specmodel' will be populated by default 
        (parseexams = True).
        """
        self.xml = None
        #self.get_xml(self.Source.Requesturl)
        url = self.baseurl + self.querypath
        urlobj = urlsplit(url)

        if urlobj.scheme == 'https':
            if self.verifyhttps:
                conn = HTTPSConnection(urlobj.netloc, timeout=timeout)
            else:
                conn = HTTPSConnection(
                    urlobj.netloc,
                    timeout=timeout,
                    context=ssl._create_unverified_context())
        else:
            conn = HTTPConnection(urlobj.netloc, timeout=timeout)
        conn.putrequest(HttpMethod, urlobj.path + "?" + urlobj.query)
        conn.endheaders()

        try:
            res = conn.getresponse()
        except socket.timeout:
            # error handling has to be included
            self.status = 408
            self.reason = "Socket timeout"
            raise TimeOutError

        self.status = res.status
        self.reason = res.reason

        if not parsexsams:
            if res.status == 200:
                result = r.Result()
                result.Content = res.read()
            elif res.status == 400 and HttpMethod == 'POST':
                # Try to use http-method: GET
                result = self.dorequest(HttpMethod='GET',
                                        parsexsams=parsexsams)
            else:
                result = None
        else:
            if res.status == 200:
                self.xml = res.read()

                result = r.Result()
                result.Xml = self.xml
                result.populate_model()
            elif res.status == 400 and HttpMethod == 'POST':
                # Try to use http-method: GET
                result = self.dorequest(HttpMethod='GET',
                                        parsexsams=parsexsams)
            else:
                result = None

        return result
Пример #9
0
class HessianProxy(object):

    def __init__(self, service_uri, credentials=None, key_file=None, cert_file=None, timeout=10, buffer_size=65535, error_factory=lambda x: x, overload=False):
        self._headers = list()
        self._headers.append(('User-Agent', 'mustaine/' + __version__,))
        self._headers.append(('Content-Type', 'application/x-hessian',))

        if sys.version_info < (2,6):
            warn('HessianProxy timeout not enforceable before Python 2.6', RuntimeWarning, stacklevel=2)
            timeout = {}
        else:
            timeout = {'timeout': timeout}

        self._uri = urlparse(service_uri)
        if self._uri.scheme == 'http':
            self._client = HTTPConnection(self._uri.hostname,
                                          self._uri.port or 80,
                                          strict=True,
                                          **timeout)
        elif self._uri.scheme == 'https':
            self._client = HTTPSConnection(self._uri.hostname,
                                           self._uri.port or 443,
                                           key_file=key_file,
                                           cert_file=cert_file,
                                           strict=True,
                                           **timeout)
        else:
            raise NotImplementedError("HessianProxy only supports http:// and https:// URIs")

        # autofill credentials if they were passed via url instead of kwargs
        if (self._uri.username and self._uri.password) and not credentials:
            credentials = (self._uri.username, self._uri.password)

        if credentials:
            auth = 'Basic ' + base64.b64encode(':'.join(credentials))
            self._headers.append(('Authorization', auth))

        self._buffer_size = buffer_size
        self._error_factory = error_factory
        self._overload = overload
        self._parser = Parser()

    class __RemoteMethod(object):
        # dark magic for autoloading methods
        def __init__(self, caller, method):
            self.__caller = caller
            self.__method = method
        def __call__(self, *args):
            return self.__caller(self.__method, args)

    def __getattr__(self, method):
        return self.__RemoteMethod(self, method)

    def __repr__(self):
        return "<mustaine.client.HessianProxy(\"%s\")>" % (self._uri.geturl(),)

    def __str__(self):
        return self.__repr__()

    def __call__(self, method, args):
        try:
            self._client.putrequest('POST', self._uri.path)
            for header in self._headers:
                self._client.putheader(*header)

            request = encode_object(Call(method, args, overload=self._overload))
            self._client.putheader("Content-Length", str(len(request)))
            self._client.endheaders()
            self._client.send(str(request))

            response = self._client.getresponse()
            if response.status != 200:
                raise ProtocolError(self._uri.geturl(), response.status, response.reason)

            length = response.getheader('Content-Length', -1)
            if length == '0':
                raise ProtocolError(self._uri.geturl(), 'FATAL:', 'Server sent zero-length response')

            reply = self._parser.parse_stream(BufferedReader(response, buffer_size=self._buffer_size))
            self._client.close()

            if isinstance(reply.value, Fault):
                raise self._error_factory(reply.value)
            else:
                return reply.value
        except:
            self._client.close()
            raise
Пример #10
0
class HessianProxy(object):
    def __init__(
        self,
        service_uri,
        credentials=None,
        key_file=None,
        cert_file=None,
        timeout=10,
        buffer_size=65535,
        error_factory=lambda x: x,
        overload=False,
    ):
        self._headers = list()
        self._headers.append(("User-Agent", "mustaine/" + __version__))
        self._headers.append(("Content-Type", "application/x-hessian"))

        if sys.version_info < (2, 6):
            warn("HessianProxy timeout not enforceable before Python 2.6", RuntimeWarning, stacklevel=2)
            timeout = {}
        else:
            timeout = {"timeout": timeout}

        self._uri = urlparse(service_uri)
        if self._uri.scheme == "http":
            self._client = HTTPConnection(self._uri.hostname, self._uri.port or 80, strict=True, **timeout)
        elif self._uri.scheme == "https":
            self._client = HTTPSConnection(
                self._uri.hostname,
                self._uri.port or 443,
                key_file=key_file,
                cert_file=cert_file,
                strict=True,
                **timeout
            )
        else:
            raise NotImplementedError("HessianProxy only supports http:// and https:// URIs")

        # autofill credentials if they were passed via url instead of kwargs
        if (self._uri.username and self._uri.password) and not credentials:
            credentials = (self._uri.username, self._uri.password)

        if credentials:
            auth = "Basic " + base64.b64encode(":".join(credentials))
            self._headers.append(("Authorization", auth))

        self._buffer_size = buffer_size
        self._error_factory = error_factory
        self._overload = overload
        self._parser = Parser()

    class __RemoteMethod(object):
        # dark magic for autoloading methods
        def __init__(self, caller, method):
            self.__caller = caller
            self.__method = method

        def __call__(self, *args):
            return self.__caller(self.__method, args)

    def __getattr__(self, method):
        return self.__RemoteMethod(self, method)

    def __repr__(self):
        return '<mustaine.client.HessianProxy("%s")>' % (self._uri.geturl(),)

    def __str__(self):
        return self.__repr__()

    def __call__(self, method, args):
        try:
            self._client.putrequest("POST", self._uri.path)
            for header in self._headers:
                self._client.putheader(*header)

            request = encode_object(Call(method, args, overload=self._overload))
            self._client.putheader("Content-Length", str(len(request)).encode("utf8"))
            self._client.endheaders()
            self._client.send(request)

            response = self._client.getresponse()
            if response.status != 200:
                raise ProtocolError(self._uri.geturl(), response.status, response.reason)

            length = response.getheader("Content-Length", -1)
            if length == "0":
                raise ProtocolError(self._uri.geturl(), "FATAL:", "Server sent zero-length response")

            reply = self._parser.parse_stream(BufferedReader(response, buffer_size=self._buffer_size))
            self._client.close()

            if isinstance(reply.value, Fault):
                raise self._error_factory(reply.value)
            else:
                return reply.value
        except:
            self._client.close()
            raise
class ClamAVFileUploadHandler(FileUploadHandler):
    chunk_size = CHUNK_SIZE
    skip_av_check = False

    def new_file(self, *args, **kwargs):
        super().new_file(*args, **kwargs)
        extension = pathlib.Path(self.file_name).suffix

        if extension in CLAM_AV_IGNORE_EXTENSIONS:
            self.skip_av_check = True
            return

        if CLAM_USE_HTTP:
            self.av_conn = HTTPConnection(host=CLAM_AV_DOMAIN, )
        else:
            self.av_conn = HTTPSConnection(  # noqa S309
                host=CLAM_AV_DOMAIN,
                port=443,
            )

        credentials = b64encode(
            bytes(
                f"{CLAM_AV_USERNAME}:{CLAM_AV_PASSWORD}",
                encoding="utf8",
            )).decode("ascii")

        try:
            self.av_conn.connect()
            self.av_conn.putrequest("POST", CLAM_PATH)
            self.av_conn.putheader("Content-Type", self.content_type)
            self.av_conn.putheader("Authorization", f"Basic {credentials}")
            self.av_conn.putheader("Transfer-encoding", "chunked")
            self.av_conn.endheaders()
        except Exception as ex:
            logger.error("Error connecting to ClamAV service", exc_info=True)
            raise AntiVirusServiceErrorException(ex)

    def receive_data_chunk(self, raw_data, start):
        if not self.skip_av_check:
            self.av_conn.send(hex(len(raw_data))[2:].encode("utf-8"))
            self.av_conn.send(b"\r\n")
            self.av_conn.send(raw_data)
            self.av_conn.send(b"\r\n")

        return raw_data

    def file_complete(self, file_size):
        if self.skip_av_check:
            return None

        self.av_conn.send(b"0\r\n\r\n")

        resp = self.av_conn.getresponse()
        response_content = resp.read()

        scanned_file = ScannedFile()

        if resp.status != 200:
            scanned_file.av_passed = False
            scanned_file.av_reason = "Non 200 response from AV server"
            scanned_file.save()

            raise AntiVirusServiceErrorException(
                f"Non 200 response from anti virus service, content: {response_content}"
            )
        else:
            json_response = json.loads(response_content)

            if "malware" not in json_response:
                scanned_file.av_passed = False
                scanned_file.av_reason = "Malformed response from AV server"
                scanned_file.save()

                raise MalformedAntiVirusResponseException()

            if json_response["malware"]:
                scanned_file.av_passed = False
                scanned_file.av_reason = json_response["reason"]
                scanned_file.save()
                logger.error(f"Malware found in user uploaded file "
                             f"'{self.file_name}', exiting upload process")
            else:
                scanned_file.av_passed = True
                scanned_file.save()

            # We are using 'content_type_extra' as the a means of making
            # the results available to following file handlers

            #  TODO - put in a PR to Django project to allow file_complete
            # to return objects and not break out of file handler loop
            if not hasattr(self.content_type_extra, "clam_av_results"):
                self.content_type_extra["clam_av_results"] = []

            self.content_type_extra["clam_av_results"].append({
                "file_name":
                self.file_name,
                "av_passed":
                scanned_file.av_passed,
                "scanned_at":
                scanned_file.scanned_at,
            })

            return None
Пример #12
0
def upload_document(path,
                    progress_tracker=None,
                    file_id=0,
                    post_url='/upload_file3'):
    """

    :param path:
    :param progress_tracker:
    :param file_id: 0 if uploading a new document, not 0 if repplacing an existing document.
    :param post_url:
    :return:
    """

    mr = None
    if progress_tracker:
        mr = Wrap(progress_tracker)
    else:
        mr = MultiRead()

    mr.add_field('file_id',
                 str(file_id))  # 0 == It's a new document, > 0 == overwrite

    # We store the filename here 'cos the one encoded in the file part
    # must be ASCII (IETF, RFC 2183, section 2.3 : Current [RFC 2045] grammar
    # restricts parameter values (and hence Content-Disposition filenames)
    # to US-ASCII. We recognize the great desirability of allowing
    # arbitrary character sets in filenames, but it is beyond the
    # scope of this document to define the necessary mechanisms.

    mr.add_field('encoding_safe_filename', os.path.split(path)[-1])
    mr.add_file_part(path)
    mr.close_parts()

    host, port = extract_host_port(
        configuration.get("DownloadSite", "base_url"))
    mainlog.debug(
        u"Upload to {}:{}{} (determined from DownloadSite/base_url : {})".
        format(host, port, post_url,
               configuration.get("DownloadSite", "base_url")))

    if configuration.get("DownloadSite", "base_url").startswith('https'):
        h = HTTPSConnection(host, port)
    else:
        h = HTTPConnection(host, port)

    h.putrequest('POST', post_url)

    h.putheader('content-type', mr.content_type())
    h.putheader('content-length', str(mr.total_size()))
    h.putheader('x-filesize', str(mr.total_size()))
    h.endheaders()

    mr.open()
    h.send(mr)
    mr.close()

    server_response = h.getresponse()
    if server_response.status == OK:
        server_response.getheaders(
        )  # Skip headers (is this really necessary ?)
        t = server_response.read()
        file_id = int(t)
        mainlog.debug("Successfully uploaded {} bytes".format(mr.total_size()))
        h.close()
        return file_id
    else:
        raise Exception(
            "Unable to upload, server response status was {}".format(
                server_response.status))