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
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)
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, )
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,)