-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi Danilo, thanks for this important fix, I am sorry it took a bit longer to review it. Also thanks for the discussion on IRC, I really enjoyed getting behind what this code does (and I almost fully succeeded ... ;-) With the issues solved as discussed, this is good to land code-wise. Please consider my other two suggestions below. review approve code Cheers, Henning Am 28.03.2011 13:22, schrieb Данило Шеган: > === modified file 'lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py' > --- lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py 2011-02-18 18:16:34 +0000 > +++ lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py 2011-03-28 11:22:31 +0000 > @@ -183,6 +183,15 @@ > self.assertEqual( > u"It's late.", self.subscription_filter.description) > > + def test_modify_description_xss_safeguard(self): > + # The description can be modified. > + > + # Modify, save, and start a new transaction. Oops, something wrong with the comments here ... > + self.ws_subscription_filter.description = u"> <>" > + error = self.assertRaises( > + BadRequest, self.ws_subscription_filter.lp_save) > + self.assertEqual(400, error.response.status) > + > def test_modify_statuses(self): > # The statuses field can be modified. > self.assertEqual(set(), self.subscription_filter.statuses) > > === modified file 'lib/lp/bugs/model/bugsubscriptionfilter.py' > --- lib/lp/bugs/model/bugsubscriptionfilter.py 2011-03-22 14:53:26 +0000 > +++ lib/lp/bugs/model/bugsubscriptionfilter.py 2011-03-28 11:22:31 +0000 > @@ -22,6 +22,7 @@ > from canonical.database.sqlbase import sqlvalues > from canonical.launchpad import searchbuilder > from canonical.launchpad.interfaces.lpstorm import IStore > +from lazr.restful.error import expose > from lp.bugs.enum import BugNotificationLevel > from lp.bugs.interfaces.bugsubscriptionfilter import IBugSubscriptionFilter > from lp.bugs.interfaces.bugtask import ( > @@ -62,7 +63,20 @@ > > other_parameters = Unicode() > > - description = Unicode() > + _description = Unicode('description') > + > + def _get_description(self): > + return self._description > + > + def _set_description(self, description): > + if ('<' in description or '>' in description or > + '"' in description or '&' in description): I don't like multi-line conditions. Can you please use an intermediate variable? Ore would a regular expression be too expensive here? re.find('[<>"&]', description), I think. > + raise expose(ValueError( > + 'BugSubscriptionFilter description cannot contain ' > + 'any of <, >, " or &.')) > + self._description = description > + > + description = property(_get_description, _set_description) > > def _get_statuses(self): > """Return a frozenset of statuses to filter on.""" > > === modified file 'lib/lp/bugs/model/tests/test_bugsubscriptionfilter.py' > --- lib/lp/bugs/model/tests/test_bugsubscriptionfilter.py 2011-03-21 18:20:09 +0000 > +++ lib/lp/bugs/model/tests/test_bugsubscriptionfilter.py 2011-03-28 11:22:31 +0000 > @@ -70,6 +70,21 @@ > self.assertEqual(u"foo", bug_subscription_filter.other_parameters) > self.assertEqual(u"bar", bug_subscription_filter.description) > > + def test_description(self): > + """Test the description property.""" > + bug_subscription_filter = BugSubscriptionFilter() > + bug_subscription_filter.description = u"foo" > + self.assertEqual(u"foo", bug_subscription_filter.description) > + > + def test_description_xss_safeguard(self): > + """description property disallows a few HTML characters.""" > + bug_subscription_filter = BugSubscriptionFilter() > + def set_description(filter, value): > + filter.description = value > + self.assertRaises(ValueError, > + setattr, bug_subscription_filter, 'description', > + u'