[gen] Added attribute 'xml' on every field allowing to customize the XML marshalling process. [gen] Added new layout 'xml', now different from the 'view' layout, allowing to define which fields are to be dumped in the XML version of some object. [gen] Security fix in ToolMixin::getUser. [gen] Bugfix in Mixin::getUrl. [shared] dav.py: method 'get' can now accept parameters. [shared] xml_parser: changes to the XmlMarshaller (due to XML-related changes).
This commit is contained in:
parent
f055ec1754
commit
c53654a1a1
19 changed files with 119 additions and 80 deletions
|
@ -1,6 +1,6 @@
|
|||
# ------------------------------------------------------------------------------
|
||||
import os, re, httplib, sys, stat, urlparse, time, socket, xml.sax
|
||||
from urllib import quote
|
||||
import urllib
|
||||
from StringIO import StringIO
|
||||
from mimetypes import guess_type
|
||||
from base64 import encodestring
|
||||
|
@ -19,7 +19,7 @@ class FormDataEncoder:
|
|||
|
||||
def marshalValue(self, name, value):
|
||||
if isinstance(value, basestring):
|
||||
return '%s=%s' % (name, quote(str(value)))
|
||||
return '%s=%s' % (name, urllib.quote(str(value)))
|
||||
elif isinstance(value, float):
|
||||
return '%s:float=%s' % (name, value)
|
||||
elif isinstance(value, int):
|
||||
|
@ -109,7 +109,13 @@ class HttpResponse:
|
|||
# Return an unmarshalled version of the XML content, for
|
||||
# easy use in Python.
|
||||
try:
|
||||
return XmlUnmarshaller(utf8=self.utf8).parse(self.body)
|
||||
parser = XmlUnmarshaller(utf8=self.utf8)
|
||||
res = parser.parse(self.body)
|
||||
if parser.rootTag == 'exception':
|
||||
# This is an exception: "res" contains the traceback
|
||||
raise ResourceError('Distant server exception: ' \
|
||||
'%s' % res)
|
||||
return res
|
||||
except xml.sax.SAXParseException, se:
|
||||
raise ResourceError('Invalid XML response (%s)'%str(se))
|
||||
|
||||
|
@ -153,10 +159,10 @@ class Resource:
|
|||
# Add credentials if present
|
||||
if not (self.username and self.password): return
|
||||
if headers.has_key('Authorization'): return
|
||||
credentials = '%s:%s' % (self.username,self.password)
|
||||
credentials = credentials.replace('\012','')
|
||||
credentials = '%s:%s' % (self.username, self.password)
|
||||
credentials = credentials.replace('\012', '')
|
||||
headers['Authorization'] = "Basic %s" % encodestring(credentials)
|
||||
headers['User-Agent'] = 'WebDAV.client'
|
||||
headers['User-Agent'] = 'Appy'
|
||||
headers['Host'] = self.host
|
||||
headers['Connection'] = 'close'
|
||||
headers['Accept'] = '*/*'
|
||||
|
@ -241,9 +247,14 @@ class Resource:
|
|||
if type =='fileName': body.close()
|
||||
return res
|
||||
|
||||
def get(self, uri=None, headers={}):
|
||||
'''Perform a HTTP GET on the server.'''
|
||||
def get(self, uri=None, headers={}, params=None):
|
||||
'''Perform a HTTP GET on the server. Parameters can be given as a dict
|
||||
in p_params.'''
|
||||
if not uri: uri = self.uri
|
||||
# Encode and append params if given
|
||||
if params:
|
||||
sep = ('?' in uri) and '&' or '?'
|
||||
uri = '%s%s%s' % (uri, sep, urllib.urlencode(params))
|
||||
return self.send('GET', uri, headers=headers)
|
||||
rss = get
|
||||
|
||||
|
|
|
@ -322,6 +322,8 @@ class XmlUnmarshaller(XmlParser):
|
|||
# knowing that the value is a 'string' is not sufficient).
|
||||
self.conversionFunctions = conversionFunctions
|
||||
self.utf8 = utf8
|
||||
# Remember the name of the root tag
|
||||
self.rootTag = None
|
||||
|
||||
def encode(self, value):
|
||||
'''Depending on self.utf8 we may need to encode p_value.'''
|
||||
|
@ -354,6 +356,9 @@ class XmlUnmarshaller(XmlParser):
|
|||
previousElem = None
|
||||
if self.env.currentElem:
|
||||
previousElem = self.env.currentElem.name
|
||||
else:
|
||||
# We are walking the root tag
|
||||
self.rootTag = elem
|
||||
e = XmlParser.startElement(self, elem, attrs)
|
||||
# Determine the type of the element.
|
||||
elemType = 'unicode' # Default value
|
||||
|
@ -668,15 +673,11 @@ class XmlMarshaller:
|
|||
elif fieldType == 'dict': self.dumpDict(res, value)
|
||||
elif isRef:
|
||||
if value:
|
||||
if self.objectType == 'appy':
|
||||
suffix = '/xml'
|
||||
else:
|
||||
suffix = ''
|
||||
if type(value) in sequenceTypes:
|
||||
for elem in value:
|
||||
self.dumpField(res, 'url', elem.absolute_url()+suffix)
|
||||
self.dumpField(res, 'url', elem.absolute_url())
|
||||
else:
|
||||
self.dumpField(res, 'url', value.absolute_url()+suffix)
|
||||
self.dumpField(res, 'url', value.absolute_url())
|
||||
elif fieldType in ('list', 'tuple'):
|
||||
# The previous condition must be checked before this one because
|
||||
# referred objects may be stored in lists or tuples, too.
|
||||
|
@ -814,27 +815,19 @@ class XmlMarshaller:
|
|||
self.dumpField(res, field.getName(),field.get(instance),
|
||||
fieldType=fieldType)
|
||||
elif objectType == 'appy':
|
||||
for field in instance.getAppyTypes('view', None):
|
||||
# Dump base attributes
|
||||
for name in ('created', 'creator', 'modified'):
|
||||
self.dumpField(res, name, getattr(instance, name))
|
||||
for field in instance.getAppyTypes('xml', None):
|
||||
# Dump only needed fields
|
||||
if (field.type == 'Computed') and not field.plainText:
|
||||
# Ignore fields used for producing custom chunks of HTML
|
||||
# within the web UI.
|
||||
continue
|
||||
if field.name in self.fieldsToExclude: continue
|
||||
if (type(self.fieldsToMarshall) in sequenceTypes) \
|
||||
and (field.name not in self.fieldsToMarshall): continue
|
||||
# Determine field type and value
|
||||
fieldType = 'basic'
|
||||
if field.type == 'File':
|
||||
fieldType = 'file'
|
||||
v = field.getValue(instance)
|
||||
elif field.type == 'Ref':
|
||||
fieldType = 'ref'
|
||||
v = field.getValue(instance, appy=False)
|
||||
else:
|
||||
v = field.getValue(instance)
|
||||
fieldType = (field.type == 'File') and 'file' or 'basic'
|
||||
v = field.getXmlValue(instance, field.getValue(instance))
|
||||
self.dumpField(res, field.name, v, fieldType=fieldType)
|
||||
# Dump the object history.
|
||||
# Dump the object history
|
||||
if hasattr(instance.aq_base, 'workflow_history'):
|
||||
histTag = self.getTagName('history')
|
||||
eventTag = self.getTagName('event')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue