[Dev OpenGP] [70] Added protection against dangerous attribute modifications in ogp. plugins and ogp.etree.

[ Thread Index | Date Index | More opengp.tuxfamily.org/development Archives ]


Revision: 70
Author:   nicolaf
Date:     2009-03-21 12:18:45 +0100 (Sat, 21 Mar 2009)

Log Message:
-----------
Added protection against dangerous attribute modifications in ogp.plugins and ogp.etree.

Modified Paths:
--------------
    trunk/src/lib/ogp/etree/elementmethods.py
    trunk/src/lib/ogp/plugins/plugin.py
    trunk/src/tests/etree-test.py


Modified: trunk/src/lib/ogp/etree/elementmethods.py
===================================================================
--- trunk/src/lib/ogp/etree/elementmethods.py	2009-03-20 12:35:38 UTC (rev 69)
+++ trunk/src/lib/ogp/etree/elementmethods.py	2009-03-21 11:18:45 UTC (rev 70)
@@ -8,15 +8,19 @@
 class OgpElement(ElementBase):
 	"""
 		lxml Element class providing redefined secure methods, compliant with the merge algorithm :
-		def delElements(self):
-		def append(self, newChild):
-		def insert(self, index, newChild):
-		def extend(self, elements):
-		def set(self, name, value):
-		def merge(self, peer):
-		def toString(self, xsl=None, params=None):
+		delElements(self):
+		append(self, newChild):
+		insert(self, index, newChild):
+		extend(self, elements):
+		set(self, name, value):
+		merge(self, peer):
+		toString(self, xsl=None, params=None):
 		attributes = property(__getAttributes)
-		You should NOT use other methods or modify attributes because it may crash the merge algorithm.
+		text attribute is protected : setting it to something not None deletes all subelements.
+		tail is protected : if you try to modify it, it will still be None
+		attrib if protected : you can only get a copy, so yon can't modify it without using self.set(name, value)
+		
+		You should NOT use other methods because it may crash the merge algorithm.
 	"""
 
 	def __setattr__(self, item, value):
@@ -27,10 +31,28 @@
 		if item == "text" and value is not None:
 			self.delElements()
 		if item == "tail":
-			value = None
-		
+			raise OgpXmlError('__setattr__: setting tail is forbiden, it must be None')
+		if item == "attrib":
+			raise OgpXmlError('__setattr__: setting attributes directly is forbiden, please use self.set(name, value)')
 		ElementBase.__setattr__(self, item, value)
 
+	def __getattribute__(self, item):
+		"""
+			Protects the 'attrib' attributes by returning a copy instead of the real object.
+			This returns a dict instance, not an _Attrib, but it seems to work
+		"""
+		if item == "attrib":
+			return dict(ElementBase.__getattribute__(self, item))
+		else:
+			return ElementBase.__getattribute__(self, item)
+
+	def __getRealAttrib(self):
+		"""
+			Provides a private property to access the real 'attrib' attribute.
+		"""
+		return ElementBase.__getattribute__(self, "attrib")
+	__attrib = property(__getRealAttrib)
+
 	def __getAttributes(self):
 		"""
 			Returns the attributes dict(), without the OgpXmlConsts.ATTR_BLOCK ('block') attribute.
@@ -58,10 +80,10 @@
 		"""
 		assert isinstance(blocking, bool)
 		if blocking:
-			self.attrib[OgpXmlConsts.ATTR_BLOCK] = str(blocking).lower()
+			self.__attrib[OgpXmlConsts.ATTR_BLOCK] = str(blocking).lower()
 		else:
 			try:
-				del self.attrib[OgpXmlConsts.ATTR_BLOCK]
+				del self.__attrib[OgpXmlConsts.ATTR_BLOCK]
 			except:
 				pass
 	blocking = property(__getBlocking, __setBlocking)
@@ -133,7 +155,7 @@
 			for br in parent:
 				if br is not self and br.tag == self.tag and br.attributes == newattrs:
 					raise OgpXmlError('set: element would no more be unique')
-		self.attrib[name] = value
+		self.__attrib[name] = value
 
 	def merge(self, peer):
 		"""

Modified: trunk/src/lib/ogp/plugins/plugin.py
===================================================================
--- trunk/src/lib/ogp/plugins/plugin.py	2009-03-20 12:35:38 UTC (rev 69)
+++ trunk/src/lib/ogp/plugins/plugin.py	2009-03-21 11:18:45 UTC (rev 70)
@@ -1,13 +1,33 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*
 
+def setattr(self, item, value):
+	"""
+		Plugin class and metaclass __setattr__ method
+		Throws an exception when attempting to modify the plugin name.
+	"""
+	if item == "name":
+		raise OgpPluginError('__setattr__: name is readonly.')
+	self.__dict__[item] = value
+
+class M_Plugin(type):
+	"""
+		Makes the 'name' __CLASS__ attribute readonly.
+	"""
+	__setattr__ = setattr
+
 class Plugin(object):
 	"""
-		Provides plugins' base class and plugin registration mechanism
+		Provides plugins' base class and plugin registration mechanism.
 	"""
+	
+	__metaclass__ = M_Plugin
+	
 	def __init__(self, dn):
 		self.__dn = dn
 	
+	__setattr__ = setattr
+
 	name = None # the plugin name
 	__registeredPlugins = dict()
 	
@@ -25,7 +45,7 @@
 		"""
 		try:
 			Plugin.__registeredPlugins[pluginClass.name]
-			raise OgpPluginError("registerPlugin: duplicated plugin name '" + pluginClass.name + "'")
+			raise OgpPluginError("registerPlugin: duplicated plugin name '" + pluginClass.name + "'.")
 		except:
 			pass
 		Plugin.__registeredPlugins[pluginClass.name] = pluginClass

Modified: trunk/src/tests/etree-test.py
===================================================================
--- trunk/src/tests/etree-test.py	2009-03-20 12:35:38 UTC (rev 69)
+++ trunk/src/tests/etree-test.py	2009-03-21 11:18:45 UTC (rev 70)
@@ -69,7 +69,19 @@
 print obj.toString()
 obj.text = "toto"
 print obj.text
+
+print "----PROTECTION ATTRIB----"
+try:
+	obj.attrib = {"test": "aaa"}
+except:
+	print "crash"
 print obj.toString()
-
-print "------- TOSTRING -----------"
-
+obj.set("test", "a")
+print obj.toString()
+a=obj.attrib
+a['test2'] = 'bb'
+print obj.toString()
+try:
+	obj.tail = "hkhk"
+except:
+	print "crash"


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/