= Notification Text Escaping = There are a number of user actions that may generate on-screen notifications, such as moving a bug or deleting a branch. Some of these notifications display potentially unsafe text that is obtained from the user. In order to prevent a cross-site-scripting attack, HTML characters in notifications must be escaped. However, there are special cases where notifications from known safe sources must be allowed to pass HTML through. This document exercises these mechanisms. >>> from lp.services.webapp.notifications import ( ... NotificationResponse, NotificationRequest) >>> def new_response(): ... response = NotificationResponse() ... request = NotificationRequest() ... request.response = response ... response._request = request ... return response >>> Plain text passed into the object's addNotification() method is unchanged: >>> response = new_response() >>> response.addNotification('clean') >>> for notification in response.notifications: ... print notification.message clean But text containing markup is CGI-escaped: >>> response = new_response() >>> response.addNotification(u'
dirty') >>> for notification in response.notifications: ... notification.message u'<br/>dirty' If the object passed to addNotification() publishes the IStructuredString interface, then a string will be returned with the appropriate sections escaped and unescaped. >>> from lp.services.webapp.interfaces import IStructuredString >>> from lp.services.webapp.menu import structured >>> msg = u'%(escaped)s' >>> structured_text = structured(msg, escaped=u'
foo') >>> IStructuredString.providedBy(structured_text) True >>> structured_text.escapedtext u'<br/>foo' >>> response = new_response() >>> response.addNotification(structured_text) >>> for notification in response.notifications: ... notification.message u'<br/>foo' Passing an object to addNotification() that is an instance of zope.i18n.Message will be escaped in the same manner as raw text. >>> import zope.i18n >>> msgtxt = zope.i18n.Message(u'
foo') >>> response = new_response() >>> response.addNotification(msgtxt) >>> for notification in response.notifications: ... notification.message u'<br/>foo' To pass internationalized text that contains markup, one may call structured() directly with an internationalized object. structured() performs the translation and substitution, and the resulting object may then be passed to addNotification(). >>> from lp import _ >>> msgid = _(u'%(evil)s') >>> escapee = '' >>> text = structured(msgid, evil=escapee) >>> text.escapedtext u'<evil/>' >>> response = new_response() >>> response.addNotification(text) >>> for notification in response.notifications: ... notification.message u'<evil/>'