Commit e4679cb4 authored by Andreas Jung's avatar Andreas Jung

      - Collector #1443: Applied patch by Simon Eisenmann that reimplements 
        the XML parser used in WebDAV fixing a memory leak.
parent d283258e
...@@ -22,23 +22,27 @@ Zope Changes ...@@ -22,23 +22,27 @@ Zope Changes
- Port ZOPE_CONFIG patch from Zope 2.7 to Zope 2.8 - Port ZOPE_CONFIG patch from Zope 2.7 to Zope 2.8
after Zope 2.8a1 after Zope 2.8a1
Bugs fixed Bugs fixed
- docutils: updated to V 0.3.5. The Zope core now contains a full copy - docutils: updated to V 0.3.5. The Zope core now contains a full copy of
of the docutils package except some GPLed files which can not be included the docutils package except some GPLed files which can not be included
with the Zope distribution due to license constraints on svn.zope.org. with the Zope distribution due to license constraints on svn.zope.org.
- docutils: moved from lib/python/docutils to lib/python/third_party/docutils - docutils: moved from lib/python/docutils to
lib/python/third_party/docutils
- Collector #1557/OFS.Image: Introducing new 'alt' property. The 'alt'
attribute is no longer taken from the 'title' property but from the new
'alt' property. The border="0" attribute is no longer part of the HTML
output except specified otherwise.
- Collector #1557/OFS.Image: Introducing new 'alt' property. The 'alt' attribute - Collector #1511: made IPCServer show up in the Control Panel under
is no longer taken from the 'title' property but from the new 'alt' property. "Network Services"
The border="0" attribute is no longer part of the HTML output except specified
otherwise.
- Collector #1511: made IPCServer show up in the Control Panel under "Network Services" - Collector #1443: Applied patch by Simon Eisenmann that reimplements
the XML parser used in WebDAV fixing a memory leak.
Zope 2.8a1 Zope 2.8a1
......
############################################################################## ##############################################################################
# #
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
# #
# This software is subject to the provisions of the Zope Public License, # This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
...@@ -11,347 +11,94 @@ ...@@ -11,347 +11,94 @@
# #
############################################################################## ##############################################################################
"""WebDAV XML parsing tools. Note that this module does just
enough for the purposes of DAV - it is not intended as a
general xml toolkit, and will probably eventually go away
in favor of a standard xml package once some issues are
worked out."""
__version__='$Revision: 1.16 $'[11:-2] """
WebDAV XML request parsing tool using xml.minidom as xml parser.
Code contributed by Simon Eisenmann, struktur AG, Stuttgart, Germany
"""
import Shared.DC.xml.xmllib __version__='$Revision: 1.15.2.1 $'[11:-2]
from Acquisition import Implicit
"""
TODO:
type_document=0 - Check the methods Node.addNode, Node.remap and Node del_attr
type_element=1 and find out if some code uses/requires these methods.
type_attribute=2
type_text=3
type_cdata=4
type_entityref=5
type_entity=6
type_procinst=7
type_comment=8
type_notation=9
=> If yes implement them, else forget them.
class Node(Implicit): NOTE: So far i didn't have any problems.
"""Common base class for Node objects.""" If you have problems please report them.
__name__=''
__value__=''
__attrs__=[]
__nodes__=[]
__nskey__=''
def name(self): return self.__name__ """
def attrs(self): return self.__attrs__
def value(self): return self.__value__
def nodes(self): return self.__nodes__
def nskey(self): return self.__nskey__
def addNode(self, node): from xml.dom import minidom
self.__nodes__.append(node.__of__(self))
def namespace(self): class Node:
nskey=self.__nskey__ """ our nodes no matter what type """
while 1:
if hasattr(self, '__nsdef__'):
val=self.__nsdef__.get(nskey, None)
if val is not None: return val
if not hasattr(self, 'aq_parent'):
return ''
self=self.aq_parent
def elements(self, name=None, ns=None ): node = None
nodes=[]
name=name and name.lower()
for node in self.__nodes__:
if node.__type__==type_element and \
((name is None) or ((node.__name__.lower())==name)) and \
((ns is None) or (node.namespace()==ns)):
nodes.append(node)
return nodes
def __getitem__(self, n): def __init__(self, node):
return self.__nodes__[n] self.node=node
def elements(self, name=None, ns=None):
nodes=[ Node(n) for n in self.node.childNodes if n.nodeType == n.ELEMENT_NODE and \
((name is None) or ((n.localName.lower())==name)) and \
((ns is None) or (n.namespaceURI==ns)) ]
return nodes
def qname(self): def qname(self):
ns=self.__nskey__ return '%s%s' % (self.namespace(), self.name())
if ns: ns='%s:' % ns
return '%s%s' % (ns, self.__name__) def addNode(self, node):
# XXX: no support for adding nodes here
raise NotImplementedError, 'addNode not implemented'
def toxml(self): def toxml(self):
return self.__value__ return self.node.toxml()
def strval(self): def strval(self):
return self.toxml() return self.toxml()
def name(self): return self.node.localName
def attrs(self): return self.node.attributes
def value(self): return self.node.nodeValue
def nodes(self): return self.node.childNodes
def nskey(self): return self.node.namespaceURI
class Document(Node): def namespace(self): return self.nskey()
def __init__(self, encoding='utf-8', stdalone=''):
self.__name__ ='document'
self.__nodes__=[]
self.encoding=encoding
self.stdalone=stdalone
self.document=self
def toxml(self):
result=['<?xml version="1.0" encoding="%s"?>' % self.encoding]
for node in self.__nodes__:
result.append(node.toxml())
return ''.join(result)
class Element(Node):
__type__=type_element
def __init__(self, name, attrs={}):
self.__name__ =name
self.__attrs__=[]
self.__nodes__=[]
self.__nsdef__={}
self.__nskey__=''
for name, val in attrs.items():
attr=Attribute(name, val)
self.__attrs__.append(attr)
self.ns_parse()
parts=self.__name__.split(':')
if len(parts) > 1:
self.__nskey__=parts[0]
self.__name__=':'.join(parts[1:])
def ns_parse(self):
nsdef=self.__nsdef__={}
for attr in self.attrs():
name, val=attr.name(), attr.value()
key=name.lower()
if key[:6]=='xmlns:':
nsdef[name[6:]]=val
elif key=='xmlns':
nsdef['']=val
def fixup(self):
self.__attrs__=map(lambda n, s=self: n.__of__(s), self.__attrs__)
def get_attr(self, name, ns=None, default=None):
for attr in self.__attrs__:
if attr.name()==name and (ns is None) or (ns==attr.namespace()):
return attr
return default
def del_attr(self, name): def del_attr(self, name):
attrs=[] # XXX: no support for removing attributes
for attr in self.__attrs__: # zope can calls this after remapping to remove namespace
if attr.name() != name: # haven't seen this happening though
attrs.append(attr) return None
self.__attrs__=attrs
def remap(self, dict, n=0, top=1): def remap(self, dict, n=0, top=1):
# The remap method effectively rewrites an element and all of its # XXX: this method is used to do some strange remapping of elements
# children, consolidating namespace declarations into the element # and namespaces .. not sure how to do this with minidom
# on which the remap function is called and fixing up namespace # and if this is even required for something
# lookup structures. # zope calls this to change namespaces in PropPatch and Lock
nsval=self.namespace() return {},0
if not nsval: nsid=''
elif not dict.has_key(nsval):
nsid='ns%d' % n
dict[nsval]=nsid
n=n+1
else: nsid=dict[nsval]
for attr in self.__attrs__:
dict, n=attr.remap(dict, n, 0)
for node in self.elements():
dict, n=node.remap(dict, n, 0)
attrs=[]
for attr in self.__attrs__:
name=attr.__name__
if not (((len(name) >= 6) and (name[:6]=='xmlns:')) or \
name=='xmlns'):
attrs.append(attr)
self.__attrs__=attrs
self.__nsdef__={}
self.__nskey__=nsid
if top:
attrs=self.__attrs__
keys=dict.keys()
keys.sort()
for key in keys:
attr=Attribute('xmlns:%s' % dict[key], key)
attrs.append(attr.__of__(self))
self.__attrs__=attrs
self.ns_parse()
return dict, n
def toxml(self): def __repr__(self):
qname=self.qname() if self.namespace():
result=['<%s' % qname] return "<Node %s (from %s)>" % (self.name(), self.namespace())
for attr in self.__attrs__: else: return "<Node %s>" % self.name()
result.append(attr.toxml())
if not self.__value__ and not self.__nodes__:
result.append('/>')
else:
result.append('>')
for node in self.__nodes__:
result.append(node.toxml())
result.append('</%s>' % qname)
return ''.join(result)
def strval(self, top=1):
if not self.__value__ and not self.__nodes__:
return ''
result=map(lambda n: n.toxml(), self.__nodes__)
return ''.join(result)
class Attribute(Node):
__type__=type_attribute
def __init__(self, name, val):
self.__name__=name
self.__value__=val
self.__nskey__=''
parts=name.split(':')
if len(parts) > 1:
pre=parts[0].lower()
if not (pre in ('xml', 'xmlns')):
self.__nskey__=parts[0]
self.__name__=':'.join(parts[1:])
def remap(self, dict, n=0, top=1): class XmlParser:
nsval=self.namespace() """ simple wrapper around minidom to support the required
if not nsval: nsid='' interfaces for zope.webdav
elif not dict.has_key(nsval): """
nsid='ns%d' % n
dict[nsval]=nsid
n=n+1
else: nsid=dict[nsval]
self.__nskey__=nsid
return dict, n
def toxml(self): dom = None
ns=self.__nskey__
if ns: ns='%s:' % ns
return ' %s%s="%s"' % (ns, self.__name__, self.__value__)
class Text(Node):
__name__='#text'
__type__=type_text
def __init__(self, val):
self.__value__=val
def toxml(self):
return escape(self.__value__)
class CData(Node):
__type__=type_cdata
__name__='#cdata'
def __init__(self, val):
self.__value__=val
def toxml(self):
return '<![CDATA[%s]]>' % self.__value__
class EntityRef(Node):
__name__='#entityref'
__type__=type_entityref
def __init__(self, val):
self.__value__=val
def toxml(self):
return '&%s;' % self.__value__
class Entity(Node):
__name__='#entity'
__type__=type_entity
def __init__(self, name, pubid, sysid, nname):
self.__value__=val
def toxml(self):
return ''
class ProcInst(Node):
__type__=type_procinst
def __init__(self, name, val):
self.__name__=name
self.__value__=val
def toxml(self):
return '<?%s %s?>' % (self.__name__, self.__value__)
class Comment(Node):
__name__='#comment'
__type__=type_comment
def __init__(self, val):
self.__value__=val
def toxml(self):
return '<!--%s-->' % self.__value__
class XmlParser(Shared.DC.xml.xmllib.XMLParser):
def __init__(self): def __init__(self):
Shared.DC.xml.xmllib.XMLParser.__init__(self)
self.root=None
self.node=None
def parse(self, data):
# prepending a XML preample to make xmllib happy
# (Collector #863)
if not data.startswith("<?xml"):
data = '<?xml version="1.0" ?>\n' + data
self.feed(data)
self.close()
return self.root
def add(self, node):
self.node.addNode(node)
def push(self, node):
self.node.addNode(node)
self.node=self.node.__nodes__[-1]
def pop(self):
self.node=self.node.aq_parent
def unknown_starttag(self, name, attrs):
node=Element(name, attrs)
self.push(node)
# Fixup aq chain!
self.node.fixup()
def unknown_endtag(self, name):
self.pop()
def handle_xml(self, encoding, stdalone):
self.root=Document(encoding, stdalone)
self.node=self.root
def handle_doctype(self, tag, pubid, syslit, data):
pass pass
def handle_entity(self, name, strval, pubid, syslit, ndata): def parse(self, data):
self.add(Entity(name, strval, pubid, syslit, ndata)) self.dom=minidom.parseString(data)
return Node(self.dom)
def handle_cdata(self, data):
self.add(CData(data))
def handle_proc(self, name, data):
self.add(ProcInst(name, data))
def handle_comment(self, data):
self.add(Comment(data))
def handle_data(self, data):
self.add(Text(data))
def unknown_entityref(self, data):
self.add(EntityRef(data))
def escape(data, rmap={}):
data=data.replace( "&", "&amp;")
data=data.replace( "<", "&lt;")
data=data.replace( ">", "&gt;")
for key, val in rmap.items():
data=data.replace( key, val)
return data
def remap(data, dict={'DAV:': 'd'}):
root=XmlParser().parse(data)
root.elements()[0].remap(dict, 0)
return root.toxml()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment