Exemplo n.º 1
0
def _join_attachment(ns_soap_env, href_id, envelope, payload, prefix=True):
    """Places the data from an attachment back into a SOAP message, replacing
    its xop:Include element or href.

    Returns a tuple of length 2 with the new message and the number of
    replacements made

    :param  id:       content-id or content-location of attachment
    :param  prefix:   Set this to true if id is content-id or false if it is
                      content-location.  It prefixes a "cid:" to the href value.
    :param  envelope: soap envelope string to be operated on
    :param  payload:  attachment data
    """

    # grab the XML element of the message in the SOAP body
    soaptree = etree.fromstring(envelope)
    soapbody = soaptree.find("{%s}Body" % ns_soap_env)

    if soapbody is None:
        raise ValidationError(None, "SOAP Body tag not found")

    message = None
    for child in list(soapbody):
        if child.tag != "{%s}Fault" % ns_soap_env:
            message = child
            break

    idprefix = ''

    if prefix:
        idprefix = "cid:"
    href_id = "%s%s" % (idprefix, href_id,)

    num = 0
    xpath = ".//xop:Include[@href=\"{}\"]".format(href_id)

    for num, node in enumerate(message.xpath(xpath, namespaces=XPATH_NSDICT)):
        parent = node.getparent()
        parent.remove(node)
        parent.text = payload

    return etree.tostring(soaptree), num
Exemplo n.º 2
0
    def from_string(cls, s):
        match = cls._SEGMENT_RE.match(s)
        if match is None:
            raise ValidationError(s)
        start_incl, start_str, end_str, end_incl = match.groups()

        print()
        print(start_incl, start_str, end_str, end_incl)

        start_incl = (start_incl == '[')
        start = InProtocolBase().from_unicode(cls._type_info['start'],
                                              start_str)
        end = InProtocolBase().from_unicode(cls._type_info['start'], end_str)
        end_incl = (end_incl == ']')

        print(start_incl, start, end, end_incl)

        return cls(start_inclusive=start_incl,
                   start=start,
                   end=end,
                   end_inclusive=end_incl)
Exemplo n.º 3
0
        def process(value):
            if value is not None:
                if value.data is not None:
                    value.path = uuid1().hex
                    fp = join(self.store, value.path)
                    if not abspath(fp).startswith(self.store):
                        raise ValidationError(
                            value.path, "Path %r contains "
                            "relative path operators (e.g. '..')")

                    with open(fp, 'wb') as file:
                        for d in value.data:
                            file.write(d)

                elif value.handle is not None:
                    value.path = uuid1().hex
                    fp = join(self.store, value.path)
                    if not abspath(fp).startswith(self.store):
                        raise ValidationError(
                            value.path, "Path %r contains "
                            "relative path operators (e.g. '..')")

                    if isinstance(value.handle, (StringIO, BytesIO)):
                        with open(fp, 'wb') as out_file:
                            out_file.write(value.handle.getvalue())
                    else:
                        with closing(
                                mmap(value.handle.fileno(),
                                     0,
                                     access=ACCESS_READ)) as data:
                            with open(fp, 'wb') as out_file:
                                out_file.write(data)

                elif value.path is not None:
                    in_file_path = value.path

                    if not isfile(in_file_path):
                        logger.error("File path in %r not found" % value)

                    if dirname(abspath(in_file_path)) != self.store:
                        dest = join(self.store, uuid1().get_hex())

                        if value.move:
                            shutil.move(in_file_path, dest)
                            logger.debug("move '%s' => '%s'", in_file_path,
                                         dest)

                        else:
                            shutil.copy(in_file_path, dest)
                            logger.debug("copy '%s' => '%s'", in_file_path,
                                         dest)

                        value.path = basename(dest)
                        value.abspath = dest

                else:
                    raise ValueError("Invalid file object passed in. All of "
                                     ".data, .handle and .path are None.")

                value.store = self.store
                value.abspath = join(self.store, value.path)

                return self.get_object_as_json(
                    value,
                    self.cls,
                    ignore_wrappers=self.ignore_wrappers,
                    complex_as=self.complex_as,
                )
Exemplo n.º 4
0
def collapse_swa(ctx, content_type, ns_soap_env):
    """
    Translates an SwA multipart/related message into an application/soap+xml
    message.

    Returns the 'appication/soap+xml' version of the given HTTP body.

    References:
    SwA     http://www.w3.org/TR/SOAP-attachments
    XOP     http://www.w3.org/TR/xop10/
    MTOM    http://www.w3.org/TR/soap12-mtom/
            http://www.w3.org/Submission/soap11mtom10/

    :param  content_type: value of the Content-Type header field, parsed by
                          cgi.parse_header() function
    :param  ctx:          request context
    """

    envelope = ctx.in_string
    # convert multipart messages back to pure SOAP
    mime_type, content_data = content_type
    if not six.PY2:
        assert isinstance(mime_type, six.text_type)

    if u'multipart/related' not in mime_type:
        return envelope

    charset = content_data.get('charset', None)
    if charset is None:
        charset = 'ascii'

    boundary = content_data.get('boundary', None)
    if boundary is None:
        raise ValidationError(None, u"Missing 'boundary' value from "
                                                         u"Content-Type header")

    envelope = list(envelope)

    # What an ugly hack...
    request = MIMEMultipart('related', boundary=boundary)
    msg_string = re.sub(r"\n\n.*", '', request.as_string())
    msg_string = chain(
        (msg_string.encode(charset), generator.NL.encode('ascii')),
        (e for e in envelope),
    )

    msg_string = b''.join(msg_string)
    msg = message_from_bytes(msg_string)  # our message

    soapmsg = None
    root = msg.get_param('start')

    # walk through sections, reconstructing pure SOAP
    for part in msg.walk():
        # skip the multipart container section
        if part.get_content_maintype() == 'multipart':
            continue

        # detect main soap section
        if (part.get('Content-ID') and part.get('Content-ID') == root) or \
                (root is None and part == msg.get_payload()[0]):
            soapmsg = part.get_payload()
            continue

        # binary packages
        cte = part.get("Content-Transfer-Encoding")

        if cte != 'base64':
            payload = b64encode(part.get_payload(decode=True))
        else:
            payload = part.get_payload()

        cid = part.get("Content-ID").strip("<>")
        cloc = part.get("Content-Location")
        numreplaces = None

        # Check for Content-ID and make replacement
        if cid:
            soapmsg, numreplaces = _join_attachment(
                                             ns_soap_env, cid, soapmsg, payload)

        # Check for Content-Location and make replacement
        if cloc and not cid and not numreplaces:
            soapmsg, numreplaces = _join_attachment(
                                            ns_soap_env, cloc, soapmsg, payload,
                                                                          False)

    if soapmsg is None:
        raise ValidationError(None, "Invalid MtoM request")

    return (soapmsg,)