00001
00002
00003 '''SOAP messaging parsing.
00004 '''
00005
00006 from ZSI import _copyright, _child_elements, EvaluateException, TC
00007 import multifile, mimetools, urllib
00008 from base64 import decodestring as b64decode
00009 import cStringIO as StringIO
00010
00011
00012 def Opaque(uri, tc, ps, **keywords):
00013 '''Resolve a URI and return its content as a string.
00014 '''
00015 source = urllib.urlopen(uri, **keywords)
00016 enc = source.info().getencoding()
00017 if enc in ['7bit', '8bit', 'binary']: return source.read()
00018
00019 data = StringIO.StringIO()
00020 mimetools.decode(source, data, enc)
00021 return data.getvalue()
00022
00023
00024 def XML(uri, tc, ps, **keywords):
00025 '''Resolve a URI and return its content as an XML DOM.
00026 '''
00027 source = urllib.urlopen(uri, **keywords)
00028 enc = source.info().getencoding()
00029 if enc in ['7bit', '8bit', 'binary']:
00030 data = source
00031 else:
00032 data = StringIO.StringIO()
00033 mimetools.decode(source, data, enc)
00034 data.seek(0)
00035 dom = ps.readerclass().fromStream(data)
00036 return _child_elements(dom)[0]
00037
00038
00039 class NetworkResolver:
00040 '''A resolver that support string and XML.
00041 '''
00042
00043 def __init__(self, prefix=None):
00044 self.allowed = prefix or []
00045
00046 def _check_allowed(self, uri):
00047 for a in self.allowed:
00048 if uri.startswith(a): return
00049 raise EvaluateException("Disallowed URI prefix")
00050
00051 def Opaque(self, uri, tc, ps, **keywords):
00052 self._check_allowed(uri)
00053 return Opaque(uri, tc, ps, **keywords)
00054
00055 def XML(self, uri, tc, ps, **keywords):
00056 self._check_allowed(uri)
00057 return XML(uri, tc, ps, **keywords)
00058
00059 def Resolve(self, uri, tc, ps, **keywords):
00060 if isinstance(tc, TC.XML):
00061 return XML(uri, tc, ps, **keywords)
00062 return Opaque(uri, tc, ps, **keywords)
00063
00064
00065 class MIMEResolver:
00066 '''Multi-part MIME resolver -- SOAP With Attachments, mostly.
00067 '''
00068
00069 def __init__(self, ct, f, next=None, uribase='thismessage:/',
00070 seekable=0, **kw):
00071
00072
00073 for param in ct.split(';'):
00074 a = param.strip()
00075 if a.startswith('boundary='):
00076 if a[9] in [ '"', "'" ]:
00077 boundary = a[10:-1]
00078 else:
00079 boundary = a[9:]
00080 break
00081 else:
00082 raise ValueError('boundary parameter not found')
00083
00084 self.id_dict, self.loc_dict, self.parts = {}, {}, []
00085 self.next = next
00086 self.base = uribase
00087
00088 mf = multifile.MultiFile(f, seekable)
00089 mf.push(boundary)
00090 while mf.next():
00091 head = mimetools.Message(mf)
00092 body = StringIO.StringIO()
00093 mimetools.decode(mf, body, head.getencoding())
00094 body.seek(0)
00095 part = (head, body)
00096 self.parts.append(part)
00097 key = head.get('content-id')
00098 if key:
00099 if key[0] == '<' and key[-1] == '>': key = key[1:-1]
00100 self.id_dict[key] = part
00101 key = head.get('content-location')
00102 if key: self.loc_dict[key] = part
00103 mf.pop()
00104
00105 def GetSOAPPart(self):
00106 '''Get the SOAP body part.
00107 '''
00108 head, part = self.parts[0]
00109 return StringIO.StringIO(part.getvalue())
00110
00111 def get(self, uri):
00112 '''Get the content for the bodypart identified by the uri.
00113 '''
00114 if uri.startswith('cid:'):
00115
00116 head, part = self.id_dict[uri[4:]]
00117 return StringIO.StringIO(part.getvalue())
00118 if self.loc_dict.has_key(uri):
00119 head, part = self.loc_dict[uri]
00120 return StringIO.StringIO(part.getvalue())
00121 return None
00122
00123 def Opaque(self, uri, tc, ps, **keywords):
00124 content = self.get(uri)
00125 if content: return content.getvalue()
00126 if not self.next: raise EvaluateException("Unresolvable URI " + uri)
00127 return self.next.Opaque(uri, tc, ps, **keywords)
00128
00129 def XML(self, uri, tc, ps, **keywords):
00130 content = self.get(uri)
00131 if content:
00132 dom = ps.readerclass().fromStream(content)
00133 return _child_elements(dom)[0]
00134 if not self.next: raise EvaluateException("Unresolvable URI " + uri)
00135 return self.next.XML(uri, tc, ps, **keywords)
00136
00137 def Resolve(self, uri, tc, ps, **keywords):
00138 if isinstance(tc, TC.XML):
00139 return self.XML(uri, tc, ps, **keywords)
00140 return self.Opaque(uri, tc, ps, **keywords)
00141
00142 def __getitem__(self, cid):
00143 head, body = self.id_dict[cid]
00144 newio = StringIO.StringIO(body.getvalue())
00145 return newio
00146
00147 if __name__ == '__main__': print _copyright