Commit 7ca5fac4 authored by Jérome Perrin's avatar Jérome Perrin

Prepare for Zope not setting content-type automatically

Prepare for https://github.com/zopefoundation/Zope/pull/1075 ( Zope 4.8.7 )

See merge request nexedi/erp5!1707
parents 88c614ad 36177abf
Pipeline #25509 failed with stage
container.REQUEST.RESPONSE.setHeader('content-type', 'text/html')
print '<html><head><meta http-equiv="refresh" content="%s"></head><body>' % refresh_interval print '<html><head><meta http-equiv="refresh" content="%s"></head><body>' % refresh_interval
for table in 'message', 'message_queue': for table in 'message', 'message_queue':
......
...@@ -2,14 +2,10 @@ ...@@ -2,14 +2,10 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/> <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
...@@ -24,18 +20,6 @@ ...@@ -24,18 +20,6 @@
<key> <string>_asgns</string> </key> <key> <string>_asgns</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item> <item>
<key> <string>name_subpath</string> </key> <key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value> <value> <string>traverse_subpath</string> </value>
...@@ -49,13 +33,25 @@ ...@@ -49,13 +33,25 @@
</value> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>content_type</string> </key>
<value> <string></string> </value> <value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Base_viewDict</string> </value> <value> <string>Base_viewDict</string> </value>
</item> </item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
<html>
<body>
<table width="100%" tal:define="pformat nocall: modules/pprint/pformat">
<tal:block tal:repeat="item python: sorted(modules['six'].iteritems(context.showDict()))">
<tr tal:attributes="bgcolor python: '#dddd88' if repeat['item'].odd() else '#88dddd'">
<td tal:content="python: item[0]" />
<td><pre tal:content="python: pformat(item[1])" /></td>
</tr>
</tal:block>
</table>
</body>
</html>
\ No newline at end of file
...@@ -174,6 +174,26 @@ class TestERP5Administration(InventoryAPITestCase): ...@@ -174,6 +174,26 @@ class TestERP5Administration(InventoryAPITestCase):
'Category group/level1/test_group on object %s is missing.' % person.getRelativeUrl(), 'Category group/level1/test_group on object %s is missing.' % person.getRelativeUrl(),
str(consistency_error.getTranslatedMessage())) str(consistency_error.getTranslatedMessage()))
def test_Base_viewDict(self):
# modules and documents
self.assertTrue(self.portal.person_module.Base_viewDict())
self.assertTrue(self.portal.person_module.newContent().Base_viewDict())
# base categories and categories
base_category = self.portal.portal_categories.contentValues()[0]
self.assertTrue(base_category.Base_viewDict())
self.assertTrue(base_category.newContent().Base_viewDict())
self.assertTrue(base_category.Base_viewDict()) # base category with content
# workflows
workflow = self.portal.portal_workflow.newContent(portal_type='Workflow')
state = workflow.newContent(portal_type='Workflow State', title='Some State')
self.assertTrue(state.Base_viewDict())
transition = workflow.newContent(portal_type='Workflow Transition',
title='Some Transition')
transition.setReference('change_something')
transition.setGuardRoleList(['Assignee', 'Assignor'])
transition.setCategoryList('destination/' + transition.getPath())
self.assertTrue(transition.Base_viewDict())
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
......
...@@ -4,6 +4,10 @@ Presentation Layout ?portal_skin=CI_slideshow ...@@ -4,6 +4,10 @@ Presentation Layout ?portal_skin=CI_slideshow
================================================================================ ================================================================================
""" """
import re import re
from Products.PythonScripts.standard import html_quote
container.REQUEST.RESPONSE.setHeader('content-type', 'text/html')
def getSlideList(content): def getSlideList(content):
return re.findall(r'<section[^>]*?>(.*?)</section>', content, re.S) return re.findall(r'<section[^>]*?>(.*?)</section>', content, re.S)
...@@ -82,11 +86,10 @@ document = context ...@@ -82,11 +86,10 @@ document = context
# wkhtmltopdf # wkhtmltopdf
document_output_type = document.REQUEST.form.get("output", default=None) document_output_type = document.REQUEST.form.get("output", default=None)
document_reference = document.getReference()
document_content = removeEmptyDetails(document.getTextContent()) document_content = removeEmptyDetails(document.getTextContent())
document_theme = getThemeFromFirstFollowUpProduct(document_reference) document_theme = getThemeFromFirstFollowUpProduct(document.getReference())
document_title = document.getTitle() document_title = html_quote(document.getTitle())
document_description = document.getDescription() document_description = html_quote(document.getDescription())
document_creation_date = document.getCreationDate() document_creation_date = document.getCreationDate()
document_creation_year = document_creation_date.strftime('%Y') if document_creation_date else '' document_creation_year = document_creation_date.strftime('%Y') if document_creation_date else ''
document_theme_logo_url = "NXD-Media.Logo." + document_theme.capitalize() document_theme_logo_url = "NXD-Media.Logo." + document_theme.capitalize()
......
...@@ -280,18 +280,6 @@ class TestERP5Category(ERP5TypeTestCase): ...@@ -280,18 +280,6 @@ class TestERP5Category(ERP5TypeTestCase):
self.assertEqual(len(om['2'].getRelatedValueList('abc')), 1) self.assertEqual(len(om['2'].getRelatedValueList('abc')), 1)
self.assertEqual(len(om['2'].Base_zSearchRelatedObjectsByCategory(category_uid = om['2'].getUid())),1) self.assertEqual(len(om['2'].Base_zSearchRelatedObjectsByCategory(category_uid = om['2'].getUid())),1)
def test_09_Base_viewDictWithCategoryWithSubCategory(
self, quiet=quiet, run=run_all_test):
if not run: return
if not quiet:
self.logMessage('Make sure Base_viewDict is working for categories with sub categories')
portal_categories = self.getCategoryTool()
base_category = portal_categories.activity
self.assertTrue(len(base_category.Base_viewDict())>0)
base_category.newContent(id='toto',title='Toto')
self.assertTrue(len(base_category.Base_viewDict())>0)
def test_getAcquiredCategoryList(self): def test_getAcquiredCategoryList(self):
# create a base category # create a base category
ctool = self.getCategoryTool() ctool = self.getCategoryTool()
......
...@@ -74,6 +74,11 @@ class TestERP5Form(ERP5TypeTestCase): ...@@ -74,6 +74,11 @@ class TestERP5Form(ERP5TypeTestCase):
self.assertTrue(self.form.formUnProxify()) self.assertTrue(self.form.formUnProxify())
self.assertTrue(self.form.formShowRelatedProxyFields()) self.assertTrue(self.form.formShowRelatedProxyFields())
def test_publish_set_content_type(self):
resp = self.publish(self.form.getPath())
self.assertIn(b"test string field", resp.getBody())
self.assertEqual(resp.getHeader('Content-Type'), 'text/html; charset=utf-8')
class TestProxify(ERP5TypeTestCase): class TestProxify(ERP5TypeTestCase):
......
...@@ -239,20 +239,6 @@ class TestERP5Workflow(ERP5TypeTestCase): ...@@ -239,20 +239,6 @@ class TestERP5Workflow(ERP5TypeTestCase):
def test_InteractionGuards(self): def test_InteractionGuards(self):
self.test_TransitionGuards(transition_type='Interaction Workflow Interaction') self.test_TransitionGuards(transition_type='Interaction Workflow Interaction')
def test_Base_viewDict(self):
"""
verify that Base_viewDict view can be accessed
"""
workflow = self.workflow_module.newContent(portal_type='Workflow')
state = workflow.newContent(portal_type='Workflow State', title='Some State')
state.Base_viewDict()
transition = workflow.newContent(portal_type='Workflow Transition',
title='Some Transition')
transition.setReference('change_something')
transition.setGuardRoleList(['Assignee', 'Assignor'])
transition.setCategoryList('destination/' + transition.getPath())
transition.Base_viewDict()
# XXX: When ERP5Workflow was designed for Configurator, it was deemed # XXX: When ERP5Workflow was designed for Configurator, it was deemed
# necessary for WorkflowTool to not be viewable by Anonymous but # necessary for WorkflowTool to not be viewable by Anonymous but
# DCWorkflow portal_workflow inherits all permissions from the Site # DCWorkflow portal_workflow inherits all permissions from the Site
......
...@@ -25,6 +25,7 @@ MAIN FILE: generate presentation in different output formats ...@@ -25,6 +25,7 @@ MAIN FILE: generate presentation in different output formats
import re import re
from Products.PythonScripts.standard import html_quote
from base64 import b64encode from base64 import b64encode
blank = '' blank = ''
...@@ -34,7 +35,7 @@ pref = context.getPortalObject().portal_preferences ...@@ -34,7 +35,7 @@ pref = context.getPortalObject().portal_preferences
# ------------------ HTML cleanup/converter methods ---------------------------- # ------------------ HTML cleanup/converter methods ----------------------------
def getHeaderSlideTitle(my_doc): def getHeaderSlideTitle(my_doc):
return '<h1>' + my_doc.getTitle() + '</h1>' return '<h1>' + html_quote(my_doc.getTitle()) + '</h1>'
def getSlideList(my_content): def getSlideList(my_content):
return re.findall(r'<section[^>]*?>(.*?)</section>', my_content, re.S) return re.findall(r'<section[^>]*?>(.*?)</section>', my_content, re.S)
......
"""List all skins that are present in more than one skin folder, ordered by """List all skins that are present in more than one skin folder, ordered by
priority. priority.
""" """
container.REQUEST.RESPONSE.setHeader('content-type', 'text/html')
# make sure context is the skins tool # make sure context is the skins tool
stool = context.portal_skins stool = context.portal_skins
......
container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/html')
print "<html><body><h1 class='test-script-title'>Title is : " + parameter + "</h1></body></html>" print "<html><body><h1 class='test-script-title'>Title is : " + parameter + "</h1></body></html>"
return printed return printed
...@@ -18,6 +18,7 @@ def format_date(date): ...@@ -18,6 +18,7 @@ def format_date(date):
creation_date = format_date(context.getCreationDate()) creation_date = format_date(context.getCreationDate())
modification_date = format_date(context.getModificationDate()) modification_date = format_date(context.getModificationDate())
owner = context.Base_getOwnerTitle() owner = context.Base_getOwnerTitle()
container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/html')
return """ return """
<html> <html>
<body> <body>
......
...@@ -16,6 +16,7 @@ checked_uids_objs.sort(key=lambda x:x.getId()) ...@@ -16,6 +16,7 @@ checked_uids_objs.sort(key=lambda x:x.getId())
# we produce html for easier Selenium parsing # we produce html for easier Selenium parsing
table = "\n".join(["<tr><td>%s</td><td>%s</td></tr>" % ( table = "\n".join(["<tr><td>%s</td><td>%s</td></tr>" % (
x.getUid(), x.getId()) for x in checked_uids_objs]) x.getUid(), x.getId()) for x in checked_uids_objs])
container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/html')
return """<html> return """<html>
<head><title>len(checked_uids) == %d</title></head> <head><title>len(checked_uids) == %d</title></head>
<body> <body>
......
...@@ -42,4 +42,5 @@ if not error_list: ...@@ -42,4 +42,5 @@ if not error_list:
if error_list: if error_list:
result = ''.join(error_list) result = ''.join(error_list)
container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/html')
return '<html><body><span id="result">%s</span></body></html>' % result return '<html><body><span id="result">%s</span></body></html>' % result
...@@ -35,4 +35,5 @@ if not error_list: ...@@ -35,4 +35,5 @@ if not error_list:
if error_list: if error_list:
result = ''.join(error_list) result = ''.join(error_list)
container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/html')
return '<html><body><span id="result">%s</span></body></html>' % result return '<html><body><span id="result">%s</span></body></html>' % result
...@@ -33,4 +33,5 @@ if not error_list: ...@@ -33,4 +33,5 @@ if not error_list:
if error_list: if error_list:
result = ''.join(error_list) result = ''.join(error_list)
container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/html')
return '<html><body><span id="result">%s</span></body></html>' % result return '<html><body><span id="result">%s</span></body></html>' % result
...@@ -418,7 +418,7 @@ Hé Hé Hé!""", page.asText().strip()) ...@@ -418,7 +418,7 @@ Hé Hé Hé!""", page.asText().strip())
appropriate language of that default document. appropriate language of that default document.
Note: due to generic ERP5 Web implementation this test highly depends Note: due to generic ERP5 Web implementation this test highly depends
on WebSection_geDefaulttDocumentValueList on WebSection_geDefaultDocumentValueList
""" """
self.setupWebSite() self.setupWebSite()
websection = self.setupWebSection() websection = self.setupWebSection()
...@@ -1579,6 +1579,39 @@ Hé Hé Hé!""", page.asText().strip()) ...@@ -1579,6 +1579,39 @@ Hé Hé Hé!""", page.asText().strip())
check(document2, date2) check(document2, date2)
check(document2, date3) check(document2, date3)
def test_default_page_displayed(self):
web_page = self.portal.web_page_module.newContent(
portal_type='Web Page',
text_content='<h1>Hello !</h1>',
content_type='text/html',
reference=self.id()
)
web_page.publish()
web_site = self.portal.web_site_module.newContent(
portal_type='Web Site',
aggregate_value=web_page,
)
web_site.publish()
web_section = web_site.newContent(
portal_type='Web Section',
aggregate_value=web_page,
)
self.tic()
for context in web_site, web_section:
self.assertTrue(context.getDefaultPageDisplayed())
resp = self.publish(context.getPath(), handle_errors=False)
self.assertEqual(resp.getStatus(), 200)
self.assertEqual(resp.getHeader('Content-type'), 'text/html; charset=utf-8')
self.assertIn(b'<h1>Hello !</h1>', resp.getBody())
context.setDefaultPageDisplayed(False)
resp = self.publish(context.getPath(), handle_errors=False)
self.assertEqual(resp.getStatus(), 200)
self.assertEqual(resp.getHeader('Content-type'), 'text/html; charset=utf-8')
self.assertNotIn(b'<h1>Hello !</h1>', resp.getBody())
class TestERP5WebWithSimpleSecurity(ERP5TypeTestCase): class TestERP5WebWithSimpleSecurity(ERP5TypeTestCase):
""" """
Test for erp5_web with simple security. Test for erp5_web with simple security.
......
...@@ -418,10 +418,6 @@ class TestConvertedWorkflow(TestERP5WorkflowMixin): ...@@ -418,10 +418,6 @@ class TestConvertedWorkflow(TestERP5WorkflowMixin):
self.assertEqual(tuple(getattr(text_document3, permission_key)), self.assertEqual(tuple(getattr(text_document3, permission_key)),
('Assignee', 'Assignor', 'Auditor', 'Author')) ('Assignee', 'Assignor', 'Auditor', 'Author'))
def test_15_testGuardsAreNotMessingUpBase_viewDict(self):
# check Base_viewDict is available on workflow's transition
self.workflow.transition_delete_action.Base_viewDict()
def test_16_testWorklistViewIsAccessible(self): def test_16_testWorklistViewIsAccessible(self):
# check worklist view is available on workflow # check worklist view is available on workflow
self.workflow.worklist_1_draft_test_workflow_document_list.view() self.workflow.worklist_1_draft_test_workflow_document_list.view()
......
...@@ -37,6 +37,7 @@ from Products.ERP5Type import Permissions, PropertySheet ...@@ -37,6 +37,7 @@ from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.Utils import deprecated, guessEncodingFromText from Products.ERP5Type.Utils import deprecated, guessEncodingFromText
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from Products.PythonScripts.standard import html_quote
from erp5.component.tool.ContributionTool import MAX_REPEAT from erp5.component.tool.ContributionTool import MAX_REPEAT
from Products.ZSQLCatalog.SQLCatalog import Query, NegatedQuery from Products.ZSQLCatalog.SQLCatalog import Query, NegatedQuery
from AccessControl import Unauthorized from AccessControl import Unauthorized
...@@ -818,7 +819,7 @@ class Document(DocumentExtensibleTraversableMixin, XMLObject, UrlMixin, ...@@ -818,7 +819,7 @@ class Document(DocumentExtensibleTraversableMixin, XMLObject, UrlMixin,
return str(subject) return str(subject)
security.declareProtected(Permissions.View, 'asEntireHTML') security.declareProtected(Permissions.View, 'asEntireHTML')
def asEntireHTML(self, **kw): def asEntireHTML(self, REQUEST=None, **kw):
""" """
Returns a complete HTML representation of the document Returns a complete HTML representation of the document
(with body tags, etc.). Adds if necessary a base (with body tags, etc.). Adds if necessary a base
...@@ -833,9 +834,11 @@ class Document(DocumentExtensibleTraversableMixin, XMLObject, UrlMixin, ...@@ -833,9 +834,11 @@ class Document(DocumentExtensibleTraversableMixin, XMLObject, UrlMixin,
# if base is defined yet. # if base is defined yet.
html = str(html) html = str(html)
if not html.find('<base') >= 0: if not html.find('<base') >= 0:
base = '<base href="%s"/>' % self.getContentBaseURL() base = '<base href="%s"/>' % html_quote(self.getContentBaseURL())
html = html.replace('<head>', '<head>%s' % base, 1) html = html.replace('<head>', '<head>%s' % base, 1)
self.setConversion(html, mime='text/html', format='base-html') self.setConversion(html, mime='text/html', format='base-html')
if REQUEST is not None:
REQUEST.RESPONSE.setHeader('Content-Type', 'text/html')
return html return html
security.declarePrivate('_asHTML') security.declarePrivate('_asHTML')
......
def escape(data):
"""
Escape &, <, and > in a string of data.
This is a copy of the xml.sax.saxutils.escape function.
"""
# must do ampersand first
data = data.replace("&", "&amp;")
data = data.replace(">", "&gt;")
data = data.replace("<", "&lt;")
return data
from pprint import pformat
ret = '<html><body><table width=100%>\n'
property_dict = context.showDict().items()
i = 0
for k,v in sorted(property_dict):
if (i % 2) == 0:
c = '#88dddd'
else:
c = '#dddd88'
i += 1
ret += '<tr bgcolor="%s"><td >%s</td><td><pre>%s</pre></td></tr>\n' % (escape(c), escape(k), escape(pformat(v)))
ret += '</table></body></html>\n'
return ret
...@@ -49,7 +49,7 @@ from AccessControl import Unauthorized, ClassSecurityInfo ...@@ -49,7 +49,7 @@ from AccessControl import Unauthorized, ClassSecurityInfo
from DateTime import DateTime from DateTime import DateTime
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
from zExceptions import Redirect from zExceptions import Redirect
from Acquisition import aq_base from Acquisition import aq_base, aq_get
from Products.PageTemplates.Expressions import SecureModuleImporter from Products.PageTemplates.Expressions import SecureModuleImporter
from zExceptions import Forbidden from zExceptions import Forbidden
...@@ -676,7 +676,13 @@ class ERP5Form(Base, ZMIForm, ZopePageTemplate): ...@@ -676,7 +676,13 @@ class ERP5Form(Base, ZMIForm, ZopePageTemplate):
raise AccessControl_Unauthorized('This document is not authorized for view.') raise AccessControl_Unauthorized('This document is not authorized for view.')
else: else:
container = None container = None
pt = getattr(self,self.pt) pt = getattr(self, self.pt)
request = aq_get(self, 'REQUEST', None)
if request is not None:
response = request.response
if 'content-type' not in response.headers:
response.setHeader('content-type', self.content_type)
extra_context = dict( container=container, extra_context = dict( container=container,
template=self, template=self,
form=self, form=self,
......
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