def test_access_to_private_content_not_allowed_via_rich_text(self): try: from plone.app.textfield.value import RichTextValue except ImportError: return from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate foobar = create_private_document(self.portal, 'foobar') login(self.portal, TEST_USER_NAME) foobar.text = RichTextValue(u'Secret.', 'text/plain', 'text/html') self.assertEqual( self.portal.portal_workflow.getInfoFor(foobar, 'review_state'), 'private') # Check that guarded_getattr is happy for the current user. self.assertEqual(guarded_getattr(self.portal, 'foobar'), foobar) self.assertEqual( guarded_getattr(self.portal.foobar, 'text'), foobar.text) # Access to text.output may be more restricted than access to the # text object itself, but this makes no sense, so we switch that # off in this test. # self.assertRaises( # Unauthorized, guarded_getattr, self.portal.foobar.text, 'output') self.portal.foobar.text.__allow_access_to_unprotected_subobjects__ = 1 self.assertEqual( guarded_getattr(self.portal.foobar.text, 'output'), '<p>Secret.</p>') TEMPLATE = '<p tal:content="structure python:%s" />' pt = ZopePageTemplate( 'mytemplate', TEMPLATE % "'access {0.foobar.text.output}'.format(context)") hack_pt(pt, context=self.portal) self.assertEqual(pt.pt_render(), '<p>access <p>Secret.</p></p>') # Check the same for anonymous. logout() self.assertRaises( Unauthorized, guarded_getattr, self.portal, 'foobar') self.assertRaises( Unauthorized, guarded_getattr, self.portal.foobar, 'text') # *If* somehow anonymous can access the text, then we have allowed # access to the output as well. self.assertEqual( guarded_getattr(self.portal.foobar.text, 'output'), '<p>Secret.</p>') # But for the template anonymous would need access to everything, # which rightly fails. self.assertRaises(Unauthorized, pt.pt_render) # Test the simpler access without str.format for the current user. login(self.portal, TEST_USER_NAME) pt = ZopePageTemplate( 'mytemplate', TEMPLATE % "context.foobar.text.output") hack_pt(pt, context=self.portal) self.assertEqual(pt.pt_render(), '<p><p>Secret.</p></p>') # and for anonymous logout() self.assertRaises(Unauthorized, pt.pt_render)
def test_cook_zope2_page_templates_good_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', GOOD_UNICODE) hack_pt(pt) self.assertEqual(pt.pt_render().strip(), '<p>none</p>') hack_pt(pt, self.app) self.assertEqual( pt.pt_render().strip(), '<p><application at ></p>')
def test_cook_zope2_page_templates_good_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', unicode(GOOD_UNICODE)) hack_pt(pt) self.assertEqual(pt.pt_render().strip(), '<p>none</p>') hack_pt(pt, self.portal) self.assertEqual( pt.pt_render().strip(), '<p><plonesite at plone></p>')
def test_cook_zope2_page_templates_good_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', unicode(GOOD_UNICODE)) hack_pt(pt) self.assertEqual(pt.pt_render().strip(), '<p>none</p>') hack_pt(pt, self.portal) self.assertEqual(pt.pt_render().strip(), '<p><plonesite at plone></p>')
def test_cook_zope2_page_templates_good_str(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', GOOD_STR) hack_pt(pt) self.assertEqual(pt.pt_render().strip(), '<p>none</p>') hack_pt(pt, context=self.portal) self.assertEqual(pt.pt_render().strip(), '<p><plonesite at plone></p>')
def test_cook_zope2_page_templates_good_str(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', GOOD_STR) hack_pt(pt) self.assertEqual(pt.pt_render().strip(), '<p>none</p>') hack_pt(pt, context=self.portal) self.assertEqual( pt.pt_render().strip(), '<p><plonesite at plone></p>')
def test_cook_zope2_page_templates_bad_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', BAD_UNICODE) hack_pt(pt) with self.assertRaises(Unauthorized) as err: pt.pt_render() self.assertEqual( "You are not allowed to access '__class__' in this context", str(err.exception))
def test_access_to_private_content_not_allowed_in_any_way(self): # This is a more general version of the rich text one. from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate foobar = create_private_document(self.portal, 'foobar') login(self.portal, TEST_USER_NAME) self.assertEqual( self.portal.portal_workflow.getInfoFor(foobar, 'review_state'), 'private') TEMPLATE = '<p tal:content="structure python:%s" />' # attribute access # If access to context.foobar.Title was allowed, it would still only # say 'bound method ATDocument.Title', without giving the actual title, # but there may be other attributes that give worse info. pt = ZopePageTemplate( 'mytemplate', TEMPLATE % "'access {0.foobar.Title}'.format(context)") hack_pt(pt, context=self.portal) login(self.portal, TEST_USER_NAME) # We replace ATDocument with Document to make the tests pass # with ATContentTypes and plone.app.contenttypes. self.assertEqual( pt.pt_render().replace('ATDocument', 'Document'), '<p>access <bound method Document.Title of ' '<Document at /plone/foobar>></p>') logout() self.assertRaises(Unauthorized, pt.pt_render) # key access pt = ZopePageTemplate('mytemplate', TEMPLATE % "'{0[foobar]}'.format(context)") hack_pt(pt, context=self.portal) login(self.portal, TEST_USER_NAME) self.assertEqual(pt.pt_render().replace('ATDocument', 'Document'), '<p><Document at foobar></p>') logout() self.assertRaises(Unauthorized, pt.pt_render) # Prepare a list so we can test item access. self.portal.testlist = [foobar] pt = ZopePageTemplate('mytemplate', TEMPLATE % "'{0.testlist}'.format(context)") hack_pt(pt, context=self.portal) # If you have such a list, you *can* see an id. self.assertEqual(pt.pt_render().replace('ATDocument', 'Document'), u'<p>[<Document at /plone/foobar>]</p>') # But you cannot access an item. pt = ZopePageTemplate('mytemplate', TEMPLATE % "'{0.testlist[0]}'.format(context)") hack_pt(pt, context=self.portal) self.assertRaises(Unauthorized, pt.pt_render) # except as authenticated user login(self.portal, TEST_USER_NAME) self.assertEqual(pt.pt_render().replace('ATDocument', 'Document'), '<p><Document at foobar></p>')
def test_cook_zope2_page_templates_bad_key_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', BAD_KEY_UNICODE) hack_pt(pt, self.app) self.assertEqual( pt.pt_render(), '<p>access by key: <Folder at test_folder_1_></p>') self.app.test_folder_1_.__roles__ = ['Manager'] with self.assertRaises(Unauthorized) as err: pt.pt_render() self.assertEqual( "You are not allowed to access 'test_folder_1_' in this context", str(err.exception))
def test_cook_zope2_page_templates_bad_key_str(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', BAD_KEY_STR) hack_pt(pt, self.app) self.assertEqual( pt.pt_render(), '<p>access by key: {}</p>'.format( escape(repr(self.app.test_folder_1_)))) self.app.test_folder_1_.__roles__ = ['Manager'] with self.assertRaises(Unauthorized) as err: pt.pt_render() self.assertEqual( "You are not allowed to access 'test_folder_1_' in this context", str(err.exception))
def test_cook_zope2_page_templates_bad_attr_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', BAD_ATTR_UNICODE) hack_pt(pt) with self.assertRaises(Unauthorized) as err: pt.pt_render() self.assertEqual( "You are not allowed to access '__class__' in this context", str(err.exception)) hack_pt(pt, context=self.app) with self.assertRaises(Unauthorized) as err: pt.pt_render() self.assertEqual( "You are not allowed to access '__class__' in this context", str(err.exception))
def test_access_to_private_content_not_allowed_via_any_attribute(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate # If access to _delObject would be allowed, it would still only say # something like 'bound method _delObject', without actually deleting # anything, because methods are not executed in str.format, but there # may be @properties that give an attacker secret info. pt = ZopePageTemplate( 'mytemplate', """<p tal:content="python:'{0._delObject}'.format(context)" />""") hack_pt(pt, context=self.app) with self.assertRaises(Unauthorized) as err: pt.pt_render() self.assertEqual( "You are not allowed to access '_delObject' in this context", str(err.exception))
def test_cook_zope2_page_templates_good_format_attr_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', GOOD_FORMAT_ATTR_UNICODE) hack_pt(pt, self.app) self.assertEqual( pt.pt_render().strip(), '<p>title of <Application at > is Zope</p>')
def test_cook_zope2_page_templates_good_format_attr_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', GOOD_FORMAT_ATTR_UNICODE) hack_pt(pt, self.portal) self.assertEqual( pt.pt_render().strip(), '<p>title of <PloneSite at plone> is Plone site</p>')
def pt_render(self, source=0, extra_context={}): doc_xml = ZopePageTemplate.pt_render(self, source=source, extra_context=extra_context) # Unmarshall arguments to __call__ API args = extra_context.get("options", []) kwargs = extra_context.copy() if kwargs.has_key("options"): del kwargs["options"] if kwargs.has_key("context"): del kwargs["context"] batch_mode = extra_context.get("batch_mode", 0) request = extra_context.get("REQUEST", None) if not request: request = get_request() if request.get("debug", 0): return doc_xml report_tool = getToolByName(self, "portal_report") pdf = report_tool.renderPDF(self.pdf_stylesheet, doc_xml, context=self.pt_getContext()["here"], *args, **kwargs) if request and not batch_mode: request.RESPONSE.setHeader("Content-Type", "application/pdf") request.RESPONSE.setHeader("Content-Length", len(pdf)) request.RESPONSE.setHeader("Content-Disposition", "inline;filename=%s.pdf" % self.title_or_id()) return pdf
def pt_render(self, source=0, extra_context={}): doc_xml = ZopePageTemplate.pt_render(self, source=source, extra_context=extra_context) # Unmarshall arguments to __call__ API args = extra_context.get('options', []) kwargs = extra_context.copy() if kwargs.has_key('options'): del kwargs['options'] if kwargs.has_key('context'): del kwargs['context'] batch_mode = extra_context.get('batch_mode', 0) request = extra_context.get('REQUEST', None) if not request: request = get_request() if request.get('debug', 0): return doc_xml report_tool = getToolByName(self, 'portal_report') pdf = report_tool.renderPDF(self.pdf_stylesheet, doc_xml, context=self.pt_getContext()['here'], *args, **kwargs) if request and not batch_mode: request.RESPONSE.setHeader('Content-Type', 'application/pdf') request.RESPONSE.setHeader('Content-Length', len(pdf)) request.RESPONSE.setHeader( 'Content-Disposition', 'inline;filename=%s.pdf' % self.title_or_id()) return pdf
def get_mail_body(self, fields, request, context): """Returns the mail-body with footer. """ schema = get_fields(context) all_fields = [f for f in fields # TODO # if not (f.isLabel() or f.isFileField()) and not (getattr(self, # 'showAll', True) and f.getServerSide())] if not (INamedFile.providedBy(fields[f])) and not (getattr(self, 'showAll', True) and IFieldExtender(schema[f]).serverSide) ] # which fields should we show? if getattr(self, 'showAll', True): live_fields = all_fields else: live_fields = [ f for f in all_fields if f in getattr(self, 'showFields', ())] if not getattr(self, 'includeEmpties', True): all_fields = live_fields live_fields = [f for f in all_fields if fields[f]] for f in all_fields: value = fields[f] if value: live_fields.append(f) #bare_fields = [schema[f] for f in live_fields] bare_fields = dict([(f, fields[f]) for f in live_fields]) bodyfield = self.body_pt # pass both the bare_fields (fgFields only) and full fields. # bare_fields for compatability with older templates, # full fields to enable access to htmlValue replacer = DollarVarReplacer(fields).sub extra = { 'data': bare_fields, 'fields': dict([(i, j.title) for i, j in getFieldsInOrder(schema)]), 'mailer': self, 'body_pre': self.body_pre and replacer(self.body_pre), 'body_post': self.body_post and replacer(self.body_post), 'body_footer': self.body_footer and replacer(self.body_footer), } template = ZopePageTemplate(self.__name__) template.write(bodyfield) template = template.__of__(context) body = template.pt_render(extra_context=extra) # if isinstance(body, unicode): #body = body.encode("utf-8") #keyid = getattr(self, 'gpg_keyid', None) #encryption = gpg and keyid # if encryption: #bodygpg = gpg.encrypt(body, keyid) # if bodygpg.strip(): #body = bodygpg return body
def pt_render(self, source=0, extra_context={}): doc_xml = ZopePageTemplate.pt_render(self, source=source, extra_context=extra_context) # Unmarshall arguments to __call__ API args = extra_context.get('options', []) kwargs = extra_context.copy() if kwargs.has_key('options'): del kwargs['options'] if kwargs.has_key('context'): del kwargs['context'] batch_mode = extra_context.get('batch_mode', 0) request = extra_context.get('REQUEST', None) if not request: request = get_request() if request.get('debug',0): return doc_xml report_tool = getToolByName(self, 'portal_report') pdf = report_tool.renderPDF(self.pdf_stylesheet, doc_xml, context=self.pt_getContext()['here'], *args, **kwargs) if request and not batch_mode: request.RESPONSE.setHeader('Content-Type','application/pdf') request.RESPONSE.setHeader('Content-Length',len(pdf)) request.RESPONSE.setHeader('Content-Disposition','inline;filename=%s.pdf' % self.title_or_id()) return pdf
def test_cook_zope2_page_templates_good_format_attr_str(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', GOOD_FORMAT_ATTR_STR) hack_pt(pt, self.app) self.assertEqual( pt.pt_render().strip(), '<p>title of <Application at > is Zope</p>')
def assert_is_checked_via_security_manager(self, pt_content): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate from AccessControl.SecurityManager import setSecurityPolicy from AccessControl.SecurityManagement import noSecurityManager from AccessControl.SecurityManagement import getSecurityManager pt = ZopePageTemplate('mytemplate', pt_content) noSecurityManager() old_security_policy = setSecurityPolicy(UnauthorizedSecurityPolicy()) try: hack_pt(pt, context=self.app) with self.assertRaises(Unauthorized) as err: pt.pt_render() self.assertEqual('Nothing is allowed!', str(err.exception)) finally: setSecurityPolicy(old_security_policy)
def test_cook_zope2_page_templates_good_format_attr_str(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', GOOD_FORMAT_ATTR_STR) hack_pt(pt, self.portal) self.assertEqual( pt.pt_render().strip(), '<p>title of <PloneSite at plone> is Plone site</p>')
def assert_is_checked_via_security_manager(self, pt_content): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate from AccessControl.SecurityManager import setSecurityPolicy from AccessControl.SecurityManagement import noSecurityManager from AccessControl.SecurityManagement import getSecurityManager pt = ZopePageTemplate('mytemplate', pt_content) noSecurityManager() old_security_policy = setSecurityPolicy(UnauthorizedSecurityPolicy()) getSecurityManager() try: hack_pt(pt, context=self.app) with self.assertRaises(Unauthorized) as err: pt.pt_render() self.assertEqual("Nothing is allowed!", str(err.exception)) finally: setSecurityPolicy(old_security_policy)
def test_cook_zope2_page_templates_aq_parent(self): # Accessing aq_parent should be allowed normally. from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', AQ_TEST) hack_pt(pt, context=self.portal) self.assertEqual( pt.pt_render().strip(), u'<p>parent of <PloneSite at plone> is ' u'<Application at ></p>')
def test_cook_zope2_page_templates_bad_key_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', BAD_KEY_UNICODE) hack_pt(pt, self.portal) create_private_document(self.portal, 'secret') login(self.portal, TEST_USER_NAME) self.assertEqual(pt.pt_render().replace('ATDocument', 'Document'), '<p>access by key: <Document at secret></p>') logout() self.assertRaises(Unauthorized, pt.pt_render)
def test_cook_zope2_page_templates_bad_key_unicode(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', BAD_KEY_UNICODE) hack_pt(pt, self.portal) create_private_document(self.portal, 'secret') login(self.portal, TEST_USER_NAME) self.assertEqual( pt.pt_render().replace('ATDocument', 'Document'), '<p>access by key: <Document at secret></p>') logout() self.assertRaises(Unauthorized, pt.pt_render)
def test_cook_zope2_page_templates_bad_item_str(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate secret = create_private_document(self.portal, 'secret') login(self.portal, TEST_USER_NAME) self.portal.testlist = [secret] pt = ZopePageTemplate('mytemplate', BAD_ITEM_STR) hack_pt(pt, self.portal.testlist) self.assertEqual(pt.pt_render().replace('ATDocument', 'Document'), '<p>access by item: <Document at secret></p>') logout() self.assertRaises(Unauthorized, pt.pt_render)
def test_cook_zope2_page_templates_bad_item_str(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate secret = create_private_document(self.portal, 'secret') login(self.portal, TEST_USER_NAME) self.portal.testlist = [secret] pt = ZopePageTemplate('mytemplate', BAD_ITEM_STR) hack_pt(pt, self.portal.testlist) self.assertEqual( pt.pt_render().replace('ATDocument', 'Document'), '<p>access by item: <Document at secret></p>') logout() self.assertRaises(Unauthorized, pt.pt_render)
def get_mail_body(self, unsorted_data, request, context): """Returns the mail-body with footer. """ schema = get_schema(context) form = DummyFormView(context, request) form.schema = schema form.prefix = 'form' form._update() widgets = {name: widget.render() for name, widget in form.w.items()} data = filter_fields(self, schema, unsorted_data) bodyfield = self.body_pt # pass both the bare_fields (fgFields only) and full fields. # bare_fields for compatability with older templates, # full fields to enable access to htmlValue if isinstance(self.body_pre, basestring): body_pre = self.body_pre else: body_pre = self.body_pre.output if isinstance(self.body_post, basestring): body_post = self.body_post else: body_post = self.body_post.output if isinstance(self.body_footer, basestring): body_footer = self.body_footer else: body_footer = self.body_footer.output extra = { 'data': data, 'fields': OrderedDict([(i, j.title) for i, j in getFieldsInOrder(schema)]), 'widgets': widgets, 'mailer': self, 'body_pre': body_pre and lnbr(dollar_replacer(body_pre, data)), 'body_post': body_post and lnbr(dollar_replacer(body_post, data)), 'body_footer': body_footer and lnbr(dollar_replacer(body_footer, data)), } template = ZopePageTemplate(self.__name__) template.write(bodyfield) template = template.__of__(context) return template.pt_render(extra_context=extra)
def get_mail_body(self, unsorted_data, request, context): """Returns the mail-body with footer. """ schema = get_schema(context) form = DummyFormView(context, request) form.schema = schema form.prefix = "form" form._update() widgets = filter_widgets(self, form.w) data = filter_fields(self, schema, unsorted_data) bodyfield = self.body_pt # pass both the bare_fields (fgFields only) and full fields. # bare_fields for compatability with older templates, # full fields to enable access to htmlValue if isinstance(self.body_pre, six.string_types): body_pre = self.body_pre else: body_pre = self.body_pre.output if isinstance(self.body_post, six.string_types): body_post = self.body_post else: body_post = self.body_post.output if isinstance(self.body_footer, six.string_types): body_footer = self.body_footer else: body_footer = self.body_footer.output extra = { "data": data, "fields": OrderedDict([(i, j.title) for i, j in getFieldsInOrder(schema)]), "widgets": widgets, "mailer": self, "body_pre": body_pre and lnbr(dollar_replacer(body_pre, data)), "body_post": body_post and lnbr(dollar_replacer(body_post, data)), "body_footer": body_footer and lnbr(dollar_replacer(body_footer, data)), } template = ZopePageTemplate(self.__name__) template.write(bodyfield) template = template.__of__(context) return template.pt_render(extra_context=extra)
def add_subscriber_in_period(self, context, period, subscriber, form, data): request = self.request subscriber.first_name = data.get("first_name") subscriber.last_name = data.get("last_name") subscriber.email = data.get("email") subscriber.number_of_people = int(data.get("number_of_people")) subscriber.reindexObject() period.reindexObject() mailer = get_actions(context).get("mailer") if not mailer: return extra_form = DummyFormView(context, request) extra_form.schema = form.schema extra_form.prefix = "form" extra_form._update() subscriber_fields = [x[0] for x in getFieldsInOrder(ISubscriber)] subscriber_fields.append("period") widgets = filter_widgets(extra_form.widgets, subscriber_fields) data = filter_fields(data, extra_form.schema, subscriber_fields) bodyfield = mailer.body_pt extra = { "data": data, "fields": OrderedDict([(i, j.title) for i, j in getFieldsInOrder(extra_form.schema)], ), "widgets": widgets, "mailer": mailer, "body_pre": "", "body_post": "", "body_footer": "", } template = ZopePageTemplate(mailer.__name__) template.write(bodyfield) template = template.__of__(context) subscriber.all_informations = RichTextValue( template.pt_render(extra_context=extra), ) subscriber.reindexObject()
def replaceIncludes(path): # Find the page template based on the path and remove path from dict document = self._resolvePath(path) document_text = ZopePageTemplate.pt_render( document, extra_context=extra_context) # Find the type of the embedded document document_type = document.content_type # Prepare a subdirectory to store embedded objects actual_idx = next(self.document_counter) dir_name = '%s%d' % (self._OLE_directory_prefix, actual_idx) if sub_document: # sub-document means sub-directory dir_name = sub_document + '/' + dir_name # Get the stylesheet of the embedded openoffice document ooo_stylesheet = document.ooo_stylesheet if ooo_stylesheet: ooo_stylesheet = getattr(here, ooo_stylesheet) # If ooo_stylesheet is dynamic, call it try: ooo_stylesheet = ooo_stylesheet() except AttributeError: pass temp_builder = OOoBuilder(ooo_stylesheet) stylesheet = temp_builder.extract('styles.xml') else: stylesheet = None # Start recursion if necessary sub_attached_files_dict = {} if 'office:include' in document_text: # small optimisation to avoid recursion if possible (document_text, sub_attached_files_dict) = self.renderIncludes( document_text, dir_name, extra_context, request) # Attach content, style and settings if any attached_files_dict[dir_name] = dict(document=document_text, doc_type=document_type, stylesheet=stylesheet) attached_files_dict.update(sub_attached_files_dict) # Build the new tag new_path = './%s' % dir_name.split('/')[-1] return new_path
def replaceIncludes(path): # Find the page template based on the path and remove path from dict document = self._resolvePath(path) document_text = ZopePageTemplate.pt_render(document, extra_context=extra_context) # Find the type of the embedded document document_type = document.content_type # Prepare a subdirectory to store embedded objects actual_idx = self.document_counter.next() dir_name = '%s%d'%(self._OLE_directory_prefix, actual_idx) if sub_document: # sub-document means sub-directory dir_name = sub_document + '/' + dir_name # Get the stylesheet of the embedded openoffice document ooo_stylesheet = document.ooo_stylesheet if ooo_stylesheet: ooo_stylesheet = getattr(here, ooo_stylesheet) # If ooo_stylesheet is dynamic, call it try: ooo_stylesheet = ooo_stylesheet() except AttributeError: pass temp_builder = OOoBuilder(ooo_stylesheet) stylesheet = temp_builder.extract('styles.xml') else: stylesheet = None # Start recursion if necessary sub_attached_files_dict = {} if 'office:include' in document_text: # small optimisation to avoid recursion if possible (document_text, sub_attached_files_dict ) = self.renderIncludes(document_text, dir_name, extra_context, request) # Attach content, style and settings if any attached_files_dict[dir_name] = dict(document=document_text, doc_type=document_type, stylesheet=stylesheet) attached_files_dict.update(sub_attached_files_dict) # Build the new tag new_path = './%s' % dir_name.split('/')[-1] return new_path
def test_access_to_private_content_not_allowed_in_any_way(self): # This is a more general version of the rich text one. from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate foobar = create_private_document(self.portal, 'foobar') login(self.portal, TEST_USER_NAME) self.assertEqual( self.portal.portal_workflow.getInfoFor(foobar, 'review_state'), 'private') TEMPLATE = '<p tal:content="structure python:%s" />' # attribute access # If access to context.foobar.Title was allowed, it would still only # say 'bound method ATDocument.Title', without giving the actual title, # but there may be other attributes that give worse info. pt = ZopePageTemplate( 'mytemplate', TEMPLATE % "'access {0.foobar.Title}'.format(context)") hack_pt(pt, context=self.portal) login(self.portal, TEST_USER_NAME) # We replace ATDocument with Document to make the tests pass # with ATContentTypes and plone.app.contenttypes. self.assertEqual( pt.pt_render().replace('ATDocument', 'Document'), '<p>access <bound method Document.Title of ' '<Document at /plone/foobar>></p>') logout() self.assertRaises(Unauthorized, pt.pt_render) # key access pt = ZopePageTemplate( 'mytemplate', TEMPLATE % "'{0[foobar]}'.format(context)") hack_pt(pt, context=self.portal) login(self.portal, TEST_USER_NAME) self.assertEqual( pt.pt_render().replace('ATDocument', 'Document'), '<p><Document at foobar></p>') logout() self.assertRaises(Unauthorized, pt.pt_render) # Prepare a list so we can test item access. self.portal.testlist = [foobar] pt = ZopePageTemplate( 'mytemplate', TEMPLATE % "'{0.testlist}'.format(context)") hack_pt(pt, context=self.portal) # If you have such a list, you *can* see an id. self.assertEqual( pt.pt_render().replace('ATDocument', 'Document'), u'<p>[<Document at /plone/foobar>]</p>') # But you cannot access an item. pt = ZopePageTemplate( 'mytemplate', TEMPLATE % "'{0.testlist[0]}'.format(context)") hack_pt(pt, context=self.portal) self.assertRaises(Unauthorized, pt.pt_render) # except as authenticated user login(self.portal, TEST_USER_NAME) self.assertEqual( pt.pt_render().replace('ATDocument', 'Document'), '<p><Document at foobar></p>')
def pt_render(self, source=0, extra_context={}): # Get request request = extra_context.get('REQUEST', self.REQUEST) # Get parent object (the one to render this template on) here = getattr(self, 'aq_parent', None) if here is None: # This is a system error raise ValueError, 'Can not render a template without a parent acquisition context' # Retrieve master document ooo_document = None # If script is setting, call it if self.ooo_script_name: ooo_script = getattr(here, self.ooo_script_name) ooo_document = ooo_script(self.ooo_stylesheet) else: ooo_document = getattr(here, self.ooo_stylesheet) format = request.get('format') try: # If style is dynamic, call it if getattr(aq_base(ooo_document), '__call__', None) is not None: request.set('format', None) ooo_document = ooo_document() finally: request.set('format', format) # Create a new builder instance ooo_builder = OOoBuilder(ooo_document) # Pass builder instance as extra_context extra_context['ooo_builder'] = ooo_builder # And render page template doc_xml = ZopePageTemplate.pt_render(self, source=source, extra_context=extra_context) if isinstance(doc_xml, unicode): doc_xml = doc_xml.encode('utf-8') # Replace the includes (doc_xml,attachments_dict) = self.renderIncludes(here, doc_xml, extra_context, request) try: default_styles_text = ooo_builder.extract('styles.xml') except AttributeError: default_styles_text = None # Add the associated files for dir_name, document_dict in attachments_dict.iteritems(): # Special case : the document is an OOo one if document_dict['doc_type'].startswith(self._OOo_content_type_root) or \ document_dict['doc_type'].startswith(self._ODF_content_type_root): ooo_builder.addFileEntry(full_path=dir_name, media_type=document_dict['doc_type']) ooo_builder.addFileEntry(full_path=dir_name + '/content.xml', media_type='text/xml', content=document_dict['document']) styles_text = default_styles_text if document_dict.has_key('stylesheet') and document_dict['stylesheet']: styles_text = document_dict['stylesheet'] if styles_text: ooo_builder.addFileEntry(full_path=dir_name + '/styles.xml', media_type='text/xml', content=styles_text) else: # Generic case ooo_builder.addFileEntry(full_path=dir_name, media_type=document_dict['doc_type'], content=document_dict['document']) # Replace content.xml in master openoffice template ooo_builder.replace(self.ooo_xml_file_id, doc_xml) # Old templates correction try: self.OLE_documents_zipstring except AttributeError: self.OLE_documents_zipstring = None # Convert if necessary opts = extra_context.get("options", dict()) # Get batch_mode batch_mode = opts.get('batch_mode', None) # If the file has embedded OLE documents, restore it if self.OLE_documents_zipstring: additional_builder = OOoBuilder( self.OLE_documents_zipstring ) for name in additional_builder.getNameList(): ooo_builder.replace(name, additional_builder.extract(name) ) # Update the META informations ooo_builder.updateManifest() # Produce final result if batch_mode: ooo = ooo_builder.render() else: ooo = ooo_builder.render(name=self.title or self.id, source=source) if DevelopmentMode: # Validate XML in development mode from Products.ERP5OOo.tests.utils import Validator err_list = Validator().validate(ooo) if err_list: LOG('ERP5OOo', PROBLEM, 'Validation of %s failed:\n%s' % (self.getId(), ''.join(err_list))) extension = None mimetype = ooo_builder.getMimeType() mimetypes_registry = self.getPortalObject().mimetypes_registry mimetype_object_list = mimetypes_registry.lookup(mimetype) for mimetype_object in mimetype_object_list: if mimetype_object.extensions: extension = mimetype_object.extensions[0] break elif mimetype_object.globs: extension = mimetype_object.globs.strip('*.') break if extension: filename = '%s.%s' % (self._getFileName(), extension) else: filename = self._getFileName() from Products.ERP5Type.Document import newTempOOoDocument tmp_ooo = newTempOOoDocument(self, self.title_or_id()) tmp_ooo.edit(data=ooo, filename=filename, content_type=mimetype,) format = opts.get('format', request.get('format', None)) if format: # Performance improvement: # We already have OOo format data, so we do not need to call # convertToBaseFormat(), but just copy it into base_data property. tmp_ooo.setBaseData(ooo) tmp_ooo.setBaseContentType(mimetype) if request is not None and not batch_mode and not source: return tmp_ooo.index_html(REQUEST=request, RESPONSE=request.RESPONSE, format=format) return tmp_ooo.convert(format)[1]
def pt_render(self, source=0, extra_context={}): if source: return ZopePageTemplate.pt_render(self, source=source, extra_context=extra_context) # Get request request = extra_context.get('REQUEST', self.REQUEST) # Get parent object (the one to render this template on) here = getattr(self, 'aq_parent', None) if here is None: # This is a system error raise ValueError( 'Can not render a template without a parent acquisition context' ) # Retrieve master document ooo_document = None # If script is setting, call it if self.ooo_script_name: ooo_script = getattr(here, self.ooo_script_name) ooo_document = ooo_script(self.ooo_stylesheet) else: ooo_document = getattr(here, self.ooo_stylesheet) format = request.get('format') try: # If style is dynamic, call it if getattr(aq_base(ooo_document), '__call__', None) is not None: request.set('format', None) ooo_document = ooo_document() finally: request.set('format', format) # Create a new builder instance ooo_builder = OOoBuilder(ooo_document) # Pass builder instance as extra_context extra_context['ooo_builder'] = ooo_builder # And render page template doc_xml = ZopePageTemplate.pt_render(self, source=source, extra_context=extra_context) doc_xml = convert_to_xml_compatible_string(doc_xml).encode('utf-8') # Replace the includes (doc_xml, attachments_dict) = self.renderIncludes(here, doc_xml, extra_context, request) try: default_styles_text = ooo_builder.extract('styles.xml') except AttributeError: default_styles_text = None # Add the associated files for dir_name, document_dict in six.iteritems(attachments_dict): # Special case : the document is an OOo one if document_dict['doc_type'].startswith(self._OOo_content_type_root) or \ document_dict['doc_type'].startswith(self._ODF_content_type_root): ooo_builder.addFileEntry(full_path=dir_name, media_type=document_dict['doc_type']) ooo_builder.addFileEntry(full_path=dir_name + '/content.xml', media_type='text/xml', content=document_dict['document']) styles_text = default_styles_text if 'stylesheet' in document_dict and document_dict[ 'stylesheet']: styles_text = document_dict['stylesheet'] if styles_text: ooo_builder.addFileEntry(full_path=dir_name + '/styles.xml', media_type='text/xml', content=styles_text) else: # Generic case ooo_builder.addFileEntry(full_path=dir_name, media_type=document_dict['doc_type'], content=document_dict['document']) # Replace content.xml in master openoffice template ooo_builder.replace(self.ooo_xml_file_id, doc_xml) # Old templates correction try: self.OLE_documents_zipstring except AttributeError: self.OLE_documents_zipstring = None # Convert if necessary opts = extra_context.get("options", {}) # Get batch_mode batch_mode = opts.get('batch_mode', None) # If the file has embedded OLE documents, restore them if self.OLE_documents_zipstring: additional_builder = OOoBuilder(self.OLE_documents_zipstring) for name in additional_builder.getNameList(): if name not in ('META-INF/manifest.xml', ): # We don't replace manifest ooo_builder.replace(name, additional_builder.extract(name)) # Update the META information ooo_builder.updateManifest() # Produce final result if batch_mode: ooo = ooo_builder.render() else: ooo = ooo_builder.render(name=self.title or self.id, source=source) extension = None mimetype = ooo_builder.getMimeType() mimetypes_registry = self.getPortalObject().mimetypes_registry mimetype_object_list = mimetypes_registry.lookup(mimetype) for mimetype_object in mimetype_object_list: if mimetype_object.extensions: extension = mimetype_object.extensions[0] break elif mimetype_object.globs: extension = mimetype_object.globs.strip('*.') break if extension: filename = '%s.%s' % (self._getFileName(), extension) else: filename = self._getFileName() tmp_ooo = self.newContent(temp_object=True, portal_type='OOo Document', id=self.title_or_id()) tmp_ooo.edit( data=ooo, filename=filename, content_type=mimetype, ) format = opts.get('format', request.get('format', None)) if format: # Performance improvement: # We already have OOo format data, so we do not need to call # convertToBaseFormat(), but just copy it into base_data property. tmp_ooo.setBaseData(ooo) tmp_ooo.setBaseContentType(mimetype) if request is not None and not batch_mode and not source: return tmp_ooo.index_html(REQUEST=request, RESPONSE=request.RESPONSE, format=format) return tmp_ooo.convert(format)[1]
def get_mail_body(self, fields, request, context): """Returns the mail-body with footer. """ schema = get_fields(context) all_fields = [ f for f in fields # TODO # if not (f.isLabel() or f.isFileField()) and not (getattr(self, # 'showAll', True) and f.getServerSide())] if not (self._is_file_data(fields[f])) and not (getattr(self, 'showAll', True) and IFieldExtender(schema[f]).serverSide) ] # which fields should we show? if getattr(self, 'showAll', True): live_fields = all_fields else: showFields = getattr(self, 'showFields', []) if showFields is None: showFields = [] live_fields = [f for f in all_fields if f in showFields] if not getattr(self, 'includeEmpties', True): all_fields = live_fields live_fields = [f for f in all_fields if fields[f]] for f in all_fields: value = fields[f] if value: live_fields.append(f) # bare_fields = [schema[f] for f in live_fields] bare_fields = OrderedDict([(f, fields[f]) for f in live_fields]) bodyfield = self.body_pt # pass both the bare_fields (fgFields only) and full fields. # bare_fields for compatability with older templates, # full fields to enable access to htmlValue replacer = DollarVarReplacer(fields).sub extra = { 'data': bare_fields, 'fields': OrderedDict([(i, j.title) for i, j in getFieldsInOrder(schema)]), 'mailer': self, 'body_pre': self.body_pre and replacer(self.body_pre), 'body_post': self.body_post and replacer(self.body_post), 'body_footer': self.body_footer and replacer(self.body_footer), } template = ZopePageTemplate(self.__name__) template.write(bodyfield) template = template.__of__(context) body = template.pt_render(extra_context=extra) # if isinstance(body, unicode): # body = body.encode("utf-8") # keyid = getattr(self, 'gpg_keyid', None) # encryption = gpg and keyid # if encryption: # bodygpg = gpg.encrypt(body, keyid) # if bodygpg.strip(): # body = bodygpg return body
def get_mail_body(self, unsorted_data, request, context): """Returns the mail-body with footer. """ schema = get_schema(context) data = OrderedDict( [x for x in getFieldsInOrder(schema) if x[0] in unsorted_data] ) data.update(unsorted_data) all_data = [ f for f in data # TODO # if not (f.isLabel() or f.isFileField()) and not (getattr(self, # 'showAll', True) and f.getServerSide())] if not (self._is_file_data(data[f])) and not ( getattr(self, 'showAll', True) and IFieldExtender(schema[f]).serverSide ) ] # which data should we show? if getattr(self, 'showAll', True): live_data = all_data else: showFields = getattr(self, 'showFields', []) if showFields is None: showFields = [] live_data = [ f for f in all_data if f in showFields] if not getattr(self, 'includeEmpties', True): all_data = live_data live_data = [f for f in all_data if data[f]] for f in all_data: value = data[f] if value: live_data.append(f) bare_data = OrderedDict([(f, data[f]) for f in live_data]) bodyfield = self.body_pt # pass both the bare_fields (fgFields only) and full fields. # bare_fields for compatability with older templates, # full fields to enable access to htmlValue replacer = DollarVarReplacer(data).sub extra = { 'data': bare_data, 'fields': OrderedDict([ (i, j.title) for i, j in getFieldsInOrder(schema) ]), 'mailer': self, 'body_pre': self.body_pre and replacer(self.body_pre), 'body_post': self.body_post and replacer(self.body_post), 'body_footer': self.body_footer and replacer(self.body_footer), } template = ZopePageTemplate(self.__name__) template.write(bodyfield) template = template.__of__(context) body = template.pt_render(extra_context=extra) # if isinstance(body, unicode): # body = body.encode("utf-8") # keyid = getattr(self, 'gpg_keyid', None) # encryption = gpg and keyid # if encryption: # bodygpg = gpg.encrypt(body, keyid) # if bodygpg.strip(): # body = bodygpg return body
def get_mail_body(self, unsorted_data, request, context): """Returns the mail-body with footer. """ schema = get_schema(context) form = DummyFormView(context, request) form.schema = schema form.prefix = 'form' form._update() widgets = {name: widget.render() for name, widget in form.w.items()} data = OrderedDict( [x for x in getFieldsInOrder(schema) if x[0] in unsorted_data] ) data.update(unsorted_data) all_data = [ f for f in data # TODO # if not (f.isLabel() or f.isFileField()) and not (getattr(self, # 'showAll', True) and f.getServerSide())] if not (self._is_file_data(data[f])) and not ( getattr(self, 'showAll', True) and IFieldExtender(schema[f]).serverSide ) ] # which data should we show? if getattr(self, 'showAll', True): live_data = all_data else: showFields = getattr(self, 'showFields', []) if showFields is None: showFields = [] live_data = [ f for f in all_data if f in showFields] if not getattr(self, 'includeEmpties', True): all_data = live_data live_data = [f for f in all_data if data[f]] for f in all_data: value = data[f] if value: live_data.append(f) bare_data = OrderedDict([(f, data[f]) for f in live_data]) bodyfield = self.body_pt # pass both the bare_fields (fgFields only) and full fields. # bare_fields for compatability with older templates, # full fields to enable access to htmlValue if isinstance(self.body_pre, basestring): body_pre = self.body_pre else: body_pre = self.body_pre.output if isinstance(self.body_post, basestring): body_post = self.body_post else: body_post = self.body_post.output if isinstance(self.body_footer, basestring): body_footer = self.body_footer else: body_footer = self.body_footer.output extra = { 'data': bare_data, 'fields': OrderedDict([ (i, j.title) for i, j in getFieldsInOrder(schema) ]), 'widgets': widgets, 'mailer': self, 'body_pre': body_pre and lnbr(dollar_replacer(body_pre, data)), 'body_post': body_post and lnbr(dollar_replacer(body_post, data)), 'body_footer': body_footer and lnbr( dollar_replacer(body_footer, data)), } template = ZopePageTemplate(self.__name__) template.write(bodyfield) template = template.__of__(context) return template.pt_render(extra_context=extra)