def get_data_for_zip_export(self): meeting_data = { 'title': safe_unicode(self.title), 'start': safe_unicode(self.start.isoformat()), 'end': safe_unicode(self.end and self.end.isoformat() or ''), 'location': safe_unicode(self.location), 'committee': { 'oguid': safe_unicode(self.committee.oguid.id), 'title': safe_unicode(self.committee.title), }, 'agenda_items': map(methodcaller('get_data_for_zip_export'), self.agenda_items), } if self.has_protocol_document(): document = self.protocol_document.resolve_document() meeting_data.update({ 'protocol': { 'checksum': (IBumblebeeDocument(document).get_checksum()), 'file': normalize_path( safe_unicode('{}.docx'.format(document.Title()))), 'modified': safe_unicode(get_localzone().localize( document.modified().asdatetime().replace( tzinfo=None)).isoformat()), } }) return meeting_data
def generate_zip(self): response = self.request.response with ZipGenerator() as generator: # Protocol generator.add_file(*self.get_protocol()) # Agenda items self.add_agenda_items_attachments(generator) if is_word_meeting_implementation_enabled(): self.add_agenda_item_proposal_documents(generator) # Agenda items list generator.add_file(*self.get_agendaitem_list()) # Return zip zip_file = generator.generate() filename = '{}.zip'.format(normalize_path(self.model.title)) response.setHeader( "Content-Disposition", 'inline; filename="{0}"'.format( safe_unicode(filename).encode('utf-8'))) response.setHeader("Content-type", "application/zip") response.setHeader("Content-Length", os.stat(zip_file.name).st_size) return filestream_iterator(zip_file.name, 'rb')
def get_data_for_zip_export(self): meeting_data = { 'title': safe_unicode(self.title), 'start': safe_unicode(self.start.isoformat()), 'end': safe_unicode(self.end and self.end.isoformat() or ''), 'location': safe_unicode(self.location), 'committee': { 'oguid': safe_unicode(self.committee.oguid.id), 'title': safe_unicode(self.committee.title), }, 'agenda_items': map(methodcaller('get_data_for_zip_export'), self.agenda_items), } if self.has_protocol_document(): document = self.protocol_document.resolve_document() meeting_data.update({ 'protocol': { 'checksum': (IBumblebeeDocument(document) .get_checksum()), 'file': normalize_path(safe_unicode('{}.docx'.format( document.Title()))), 'modified': safe_unicode( get_localzone().localize( document.modified().asdatetime() .replace(tzinfo=None) ).isoformat()), } }) return meeting_data
def generate_zip(self): response = self.request.response with ZipGenerator() as generator: # Protocol generator.add_file(*self.get_protocol()) # Agenda items self.add_agenda_items_attachments(generator) self.add_agenda_item_proposal_documents(generator) # Agenda items list try: generator.add_file(*self.get_agendaitem_list()) except AgendaItemListMissingTemplate: pass generator.add_file(*self.get_meeting_json()) # Return zip zip_file = generator.generate() filename = '{}.zip'.format(normalize_path(self.model.title)) response.setHeader( "Content-Disposition", 'inline; filename="{0}"'.format( safe_unicode(filename).encode('utf-8'))) response.setHeader("Content-type", "application/zip") response.setHeader( "Content-Length", os.stat(zip_file.name).st_size) return filestream_iterator(zip_file.name, 'rb')
def get_agenda_item_filename(self, document, agenda_item_number): return normalize_path(u'{}/{}'.format( translate( _(u'title_agenda_item', default=u'Agenda item ${agenda_item_number}', mapping={u'number': agenda_item_number}), context=getRequest(), ), safe_unicode(self.get_filename(document))))
def get_agenda_item_filename(self, document, agenda_item_number): return normalize_path(u'{}/{}'.format( translate( _(u'title_agenda_item', default=u'Agenda item ${agenda_item_number}', mapping={u'number': agenda_item_number}), context=getRequest(), ), safe_unicode(self.get_filename(document))) )
def __call__(self): job_id = require_job_id_parameter(self.request) job = require_job(self.request, self.model, job_id) zip_file = job.get_zip_file() filename = u'{}.zip'.format(normalize_path(self.model.title)) set_attachment_content_disposition( self.request, filename, file=zip_file) return stream_data(zip_file)
def debug_excerpt_docxcompose(self): if not self.is_manager(): raise Forbidden if self.agenda_item.is_paragraph: raise NotFound excerpt_protocol_data = ExcerptProtocolData( self.meeting, [self.agenda_item]) header_template = self.agenda_item.get_excerpt_header_template() suffix_template = self.agenda_item.get_excerpt_suffix_template() with ZipGenerator() as generator: if header_template: sablon = Sablon(header_template).process( excerpt_protocol_data.as_json()) generator.add_file( u'000_excerpt_header_template.docx', StringIO(sablon.file_data)) document = self.agenda_item.resolve_document() filename = u'001_agenda_item_{}.docx'.format( safe_unicode(document.Title())) generator.add_file(filename, document.file.open()) if suffix_template: sablon = Sablon(suffix_template).process( excerpt_protocol_data.as_json()) generator.add_file( u'002_excerpt_suffix_template.docx', StringIO(sablon.file_data)) # Return zip response = self.request.response zip_file = generator.generate() filename = '{}.zip'.format(normalize_path(self.meeting.title)) response.setHeader( "Content-Disposition", 'inline; filename="{0}"'.format( safe_unicode(filename).encode('utf-8'))) response.setHeader("Content-type", "application/zip") response.setHeader( "Content-Length", os.stat(zip_file.name).st_size) return filestream_iterator(zip_file.name, 'rb')
def debug_excerpt_docxcompose(self): if not api.user.has_permission('cmf.ManagePortal'): raise Forbidden if self.agenda_item.is_paragraph: raise NotFound excerpt_protocol_data = ExcerptProtocolData( self.meeting, [self.agenda_item]) header_template = self.agenda_item.get_excerpt_header_template() suffix_template = self.agenda_item.get_excerpt_suffix_template() with ZipGenerator() as generator: if header_template: sablon = Sablon(header_template).process( excerpt_protocol_data.as_json()) generator.add_file( u'000_excerpt_header_template.docx', StringIO(sablon.file_data)) document = self.agenda_item.resolve_document() filename = u'001_agenda_item_{}.docx'.format( safe_unicode(document.Title())) generator.add_file(filename, document.file.open()) if suffix_template: sablon = Sablon(suffix_template).process( excerpt_protocol_data.as_json()) generator.add_file( u'002_excerpt_suffix_template.docx', StringIO(sablon.file_data)) # Return zip response = self.request.response zip_file = generator.generate() filename = '{}.zip'.format(normalize_path(self.meeting.title)) response.setHeader( "Content-Disposition", 'inline; filename="{0}"'.format( safe_unicode(filename).encode('utf-8'))) response.setHeader("Content-type", "application/zip") response.setHeader( "Content-Length", os.stat(zip_file.name).st_size) return filestream_iterator(zip_file.name, 'rb')
def __call__(self): response = self.request.response with ZipGenerator() as generator: zipper = MeetingDocumentZipper(self.model, generator) zip_file = zipper.get_zip_file() filename = '{}.zip'.format(normalize_path(self.model.title)) set_attachment_content_disposition(self.request, filename) # the following headers must be set manually as # set_attachment_content_disposition expects a Named(Blob)File response.setHeader( 'Content-type', 'application/zip') response.setHeader( 'Content-Length', os.stat(zip_file.name).st_size) return filestream_iterator(zip_file.name, 'rb')
def __call__(self): with ZipGenerator() as generator: self.add_header_sablon(generator) for index, agenda_item in enumerate(self.meeting.agenda_items, 1): self.add_agenda_item(index, agenda_item, generator) self.add_suffix_sablon(index, generator) # Return zip response = self.request.response zip_file = generator.generate() filename = '{}.zip'.format(normalize_path(self.meeting.title)) response.setHeader( "Content-Disposition", 'inline; filename="{0}"'.format( safe_unicode(filename).encode('utf-8'))) response.setHeader("Content-type", "application/zip") response.setHeader("Content-Length", os.stat(zip_file.name).st_size) return filestream_iterator(zip_file.name, 'rb')
def __call__(self): with ZipGenerator() as generator: self.add_header_sablon(generator) for index, agenda_item in enumerate(self.meeting.agenda_items, 1): self.add_agenda_item(index, agenda_item, generator) self.add_suffix_sablon(index, generator) # Return zip response = self.request.response zip_file = generator.generate() filename = '{}.zip'.format(normalize_path(self.meeting.title)) response.setHeader( "Content-Disposition", 'inline; filename="{0}"'.format( safe_unicode(filename).encode('utf-8'))) response.setHeader("Content-type", "application/zip") response.setHeader( "Content-Length", os.stat(zip_file.name).st_size) return filestream_iterator(zip_file.name, 'rb')
def test_backslashes_are_converted_to_forward_slashes(self): self.assertEquals(u'foo/bar/baz', normalize_path(u'foo/bar\\baz'))
def test_umlauts_are_stripped(self): self.assertEquals(u'aou', normalize_path(u'äöü'))
def test_brackets_are_allowed(self): self.assertEquals(u'Foo', normalize_path(u'(Foo)'))
def test_spaces_are_allowed(self): self.assertEquals(u'Foo Bar', normalize_path(u'Foo Bar'))
def test_alphanumeric_characters_are_allowed(self): self.assertEquals(u'Foo1/Bar2', normalize_path(u'Foo1/Bar2'))
def get_document_filename_for_zip(self, document): return normalize_path(u'{} {}/{}{}'.format( self.number, safe_unicode(self.get_title()), safe_unicode(document.Title()), os.path.splitext(document.file.filename)[1]))
def get_filename(self, document): return normalize_path(document.get_filename())
def test_blacklisted_characters_are_not_allowed(self): self.assertEquals(u'X-Y', normalize_path('X"*:<>?|+,;=[]!@Y'))
def test_dots_hyphens_and_underscores_are_allowed(self): self.assertEquals(u'foo-bar_baz/foo.bar.baz', normalize_path(u'foo-bar_baz/foo.bar.baz'))
def test_path_normalization(self): self.assertEquals(u'bar', normalize_path('foo/../bar')) self.assertEquals(u'bar', normalize_path('./bar'))