def test_derivative_permissions(self): Media.objects.filter(record=self.record).delete() media = Media.objects.create(record=self.record, name='tiff', mimetype='image/tiff', storage=self.storage) with open(os.path.join(os.path.dirname(__file__), 'test_data', 'dcmetro.tif'), 'rb') as f: media.save_file('dcmetro.tif', f) user1 = User.objects.create(username='******') user2 = User.objects.create(username='******') AccessControl.objects.create(content_object=self.collection, user=user1, read=True) AccessControl.objects.create(content_object=self.collection, user=user2, read=True) AccessControl.objects.create(content_object=self.storage, user=user1, read=True) AccessControl.objects.create(content_object=self.storage, user=user2, read=True, restrictions=dict(width=200, height=200)) result1 = get_image_for_record(self.record, width=400, height=400, user=user1) result2 = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(400, Image.open(result1).size[0]) self.assertEqual(200, Image.open(result2).size[0]) result3 = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(result2, result3) media.delete()
def test_derivative_permissions(self): no_signals() Media.objects.filter(record=self.record).delete() media = Media.objects.create(record=self.record, name='tiff', mimetype='image/tiff', storage=self.storage) with open(os.path.join(os.path.dirname(__file__), 'test_data', 'dcmetro.tif'), 'rb') as f: media.save_file('dcmetro.tif', f) user1 = User.objects.create(username='******') user2 = User.objects.create(username='******') AccessControl.objects.create(content_object=self.collection, user=user1, read=True) AccessControl.objects.create(content_object=self.collection, user=user2, read=True) AccessControl.objects.create(content_object=self.storage, user=user1, read=True) AccessControl.objects.create(content_object=self.storage, user=user2, read=True, restrictions=dict(width=200, height=200)) result1 = get_image_for_record(self.record, width=400, height=400, user=user1) result2 = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(400, Image.open(result1).size[0]) self.assertEqual(200, Image.open(result2).size[0]) result3 = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(result2, result3) media.delete()
def view(self, request): def filename(title): return re.sub('[^A-Za-z0-9_. ]+', '-', title)[:32] def write(output, image, index, title, prefix=None): if image: output.write(image, ('%s%s %s%s' % ( os.path.join(prefix, '') if prefix else '', str(index + 1).zfill(4), filename(title), os.path.splitext(image)[1]) ).encode('ascii', 'replace')) presentation = self.obj passwords = request.session.get('passwords', dict()) response = HttpResponse(mimetype='application/zip') response['Content-Disposition'] = 'attachment; filename=%s.zip' % filename(presentation.title) items = presentation.items.filter(hidden=False) memory = StringIO() output = zipfile.ZipFile(memory, 'w') for index, item in enumerate(items): write(output, get_image_for_record(item.record, self.user, passwords=passwords), index, item.record.title) write(output, get_image_for_record(item.record, self.user, 100, 100, passwords), index, item.record.title, 'thumb') output.close() response.write(memory.getvalue()) return response
def view(self, request): def filename(title): return re.sub('[^A-Za-z0-9_. ]+', '-', title)[:32] def write(output, image, index, title, prefix=None): if image: output.write(image, ('%s%s %s%s' % ( os.path.join(prefix, '') if prefix else '', str(index + 1).zfill(4), filename(title or 'Slide %s' % (index + 1)), os.path.splitext(image)[1]) ).encode('ascii', 'replace')) def metadata_file(tempfile, record): t = Template("{% load data %}{% metadata record %}") c = Context({'record': record, 'request': request}) tempfile.write(smart_str(t.render(c))) tempfile.flush() return tempfile.name presentation = self.obj passwords = request.session.get('passwords', dict()) items = presentation.items.filter(hidden=False) tempfile = NamedTemporaryFile(suffix='.zip') output = zipfile.ZipFile(tempfile, 'w') tempjsonfile = NamedTemporaryFile(suffix='.json') metadata = presentation_detail(request, presentation.id) tempjsonfile.write(metadata.content) tempjsonfile.flush() output.write(tempjsonfile.name, os.path.join('metadata', 'metadata.json')) for index, item in enumerate(items): write(output, get_image_for_record(item.record, self.user, passwords=passwords), index, item.record.title) write(output, get_image_for_record(item.record, self.user, 100, 100, passwords), index, item.record.title, 'thumb') tempmetadatafile = NamedTemporaryFile(suffix='.html') write(output, metadata_file(tempmetadatafile, item.record), index, item.record.title, 'metadata') output.close() tempfile.flush() tempfile.seek(0) wrapper = FileWrapper(tempfile) response = HttpResponse(wrapper, content_type='application/zip') response['Content-Disposition'] = 'attachment; filename=%s.zip' % filename(presentation.title) response['Content-Length'] = os.path.getsize(tempfile.name) return response
def view(self, request): def filename(title): return re.sub('[^A-Za-z0-9_. ]+', '-', title)[:32] def write(output, image, index, title, prefix=None): if image: output.write(image, ('%s%s %s%s' % ( os.path.join(prefix, '') if prefix else '', str(index + 1).zfill(4), filename(title), os.path.splitext(image)[1]) ).encode('ascii', 'replace')) def metadata_file(tempfile, record): t = Template("{% load data %}{% metadata record %}") c = Context({'record': record, 'request': request}) tempfile.write(t.render(c)) tempfile.flush() return tempfile.name presentation = self.obj passwords = request.session.get('passwords', dict()) items = presentation.items.filter(hidden=False) tempfile = NamedTemporaryFile(suffix='.zip') output = zipfile.ZipFile(tempfile, 'w') tempjsonfile = NamedTemporaryFile(suffix='.json') metadata = presentation_detail(request, presentation.id) tempjsonfile.write(metadata.content) tempjsonfile.flush() output.write(tempjsonfile.name, os.path.join('metadata', 'metadata.json')) for index, item in enumerate(items): write(output, get_image_for_record(item.record, self.user, passwords=passwords), index, item.record.title) write(output, get_image_for_record(item.record, self.user, 100, 100, passwords), index, item.record.title, 'thumb') tempmetadatafile = NamedTemporaryFile(suffix='.html') write(output, metadata_file(tempmetadatafile, item.record), index, item.record.title, 'metadata') output.close() tempfile.flush() tempfile.seek(0) wrapper = FileWrapper(tempfile) response = HttpResponse(wrapper, mimetype='application/zip') response['Content-Disposition'] = 'attachment; filename=%s.zip' % filename(presentation.title) response['Content-Length'] = os.path.getsize(tempfile.name) return response
def retrieve_image(request, recordid, record, width=None, height=None): passwords = request.session.get('passwords', dict()) force_reprocess = request.GET.has_key('reprocess') path = get_image_for_record( recordid, request.user, int(width or 100000), int(height or 100000), passwords, force_reprocess=force_reprocess) if not path: logging.error("get_image_for_record failed for record.id %s" % recordid) raise Http404() Activity.objects.create(event='media-download-image', request=request, content_object=Record.objects.get(id=recordid), data=dict(width=width, height=height)) try: response = HttpResponse(content=file(path, 'rb').read(), mimetype='image/jpeg') if request.GET.has_key('forcedl'): # if filename was used for record stub, remove extension here to # prevent duplication if record.endswith('jpg'): record = record[:-3] response["Content-Disposition"] = "attachment; filename=%s.jpg" % record return response except IOError: logging.error("IOError: %s" % path) raise Http404()
def retrieve_image(request, recordid, record, width=None, height=None): passwords = request.session.get('passwords', dict()) force_reprocess = 'reprocess' in request.GET path = get_image_for_record(recordid, request.user, int(width or 100000), int(height or 100000), passwords, force_reprocess=force_reprocess) if not path: logging.error("get_image_for_record failed for record.id %s" % recordid) raise Http404() Activity.objects.create(event='media-download-image', request=request, content_object=Record.objects.get(id=recordid), data=dict(width=width, height=height)) try: response = HttpResponse(content=file(path, 'rb').read(), content_type='image/jpeg') if 'forcedl' in request.GET: # if filename was used for record stub, remove extension here to # prevent duplication if record.endswith('jpg'): record = record[:-3] response["Content-Disposition"] = \ "attachment; filename=%s.jpg" % record return response except IOError: logging.error("IOError: %s" % path) raise Http404()
def drawCard(index, item): p.saveState() p.translate(0, height / 3 * (2 - index % 3)) # retrieve record while making sure it's accessible to presentation owner record = Record.filter_one_by_access(presentation.owner, item.record.id) if record: image = get_image_for_record(record, presentation.owner, 800, 800, passwords) if image: p.drawImage(image, inch / 2, inch / 2, width=width / 2 - inch, height=height / 3 - inch, preserveAspectRatio=True) f = Frame(width / 2 + inch / 2, inch / 2, width=width / 2 - inch, height=height / 3 - inch, leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0) data = [] data.append(getParagraph('%s/%s' % (index + 1, len(items)), styles['SlideNumber'])) values = item.get_fieldvalues(owner=request.user) for value in values: v = value.value if len(value.value) < 100 else value.value[:100] + '...' v = remove_rels_from_a_tags(v) data.append(getParagraph('<b>%s:</b> %s' % (value.resolved_label, v), styles['Data'])) annotation = item.annotation if annotation: data.append(getParagraph('<b>%s:</b> %s' % ('Annotation', annotation), styles['Data'])) data = filter(None, data) f.addFromList(data, p) if data: p.setFont('Helvetica', 8) p.setFillColorRGB(0, 0, 0) p.drawRightString(width - inch / 2, inch / 2, '...') p.restoreState()
def retrieve_image(request, recordid, record, width=None, height=None): if DEBUG: print 'storage/views.py -- retrieve_image' print 'record = ' + record print 'record_id = ' + recordid print 'width = '+ str(width) +' and height = '+str(height) passwords = request.session.get('passwords', dict()) #print 'record image path ' + record.get_absolute_url() path = get_image_for_record(recordid, request.user, int(width or 100000), int(height or 100000), passwords) if not path: #raise Http404() if DEBUG: print "THUMBNAIL UNAVAILABLE - NO PATH" return HttpResponseRedirect(reverse('static', args=('images/thumbnail_unavailable.png',))) Activity.objects.create(event='media-download-image', request=request, content_object=Record.objects.get(id=recordid), data=dict(width=width, height=height)) try: response = HttpResponse(content=file(path, 'rb').read(), mimetype='image/jpeg') if request.GET.has_key('forcedl'): response["Content-Disposition"] = "attachment; filename=%s.jpg" % record return response except IOError: logging.error("IOError: %s" % path) #raise Http404() print "THUMBNAIL UNAVAILABLE - IO ERROR" return HttpResponseRedirect(reverse('static', args=('images/thumbnail_unavailable.png',)))
def retrieve_iiif_image(request, recordid, record): passwords = request.session.get('passwords', dict()) force_reprocess = 'reprocess' in request.GET path = get_image_for_record( recordid, request.user, passwords=passwords, force_reprocess=force_reprocess, loris_name=True, # Loris does not deal with spaces in filenames ) if not path: logging.error("get_image_for_record failed for record.id %s" % recordid) raise Http404() record_obj = Record.objects.get(id=recordid) Activity.objects.create(event='media-download-image', request=request, content_object=record_obj, data=dict()) return handle_loris_request(request, path, recordid, record)
def retrieve_image(request, recordid, record, width=None, height=None): passwords = request.session.get('passwords', dict()) path = get_image_for_record(recordid, request.user, int(width or 100000), int(height or 100000), passwords) if not path: logging.error("get_image_for_record failed for record.id %s" % recordid) raise Http404() Activity.objects.create(event='media-download-image', request=request, content_object=Record.objects.get(id=recordid), data=dict(width=width, height=height)) try: response = HttpResponse(content=file(path, 'rb').read(), mimetype='image/jpeg') if request.GET.has_key('forcedl'): response[ "Content-Disposition"] = "attachment; filename=%s.jpg" % record return response except IOError: logging.error("IOError: %s" % path) raise Http404()
def drawCard(index, item): p.saveState() p.translate(0, height / 3 * (2 - index % 3)) # retrieve record while making sure it's accessible to presentation owner record = Record.filter_one_by_access(presentation.owner, item.record.id) if record: image = get_image_for_record(record, presentation.owner, 800, 800, passwords) if image: p.drawImage(image, inch / 2, inch / 2, width=width / 2 - inch, height=height / 3 - inch, preserveAspectRatio=True) f = Frame(width / 2 + inch / 2, inch / 2, width=width / 2 - inch, height = height / 3 - inch, leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0) data = [] data.append(getParagraph('%s/%s' % (index + 1, len(items)), styles['SlideNumber'])) values = item.get_fieldvalues(owner=request.user) for value in values: v = value.value if len(value.value) < 100 else value.value[:100] + '...' data.append(getParagraph('<b>%s:</b> %s' % (value.resolved_label, v), styles['Data'])) annotation = item.annotation if annotation: data.append(getParagraph('<b>%s:</b> %s' % ('Annotation', annotation), styles['Data'])) data = filter(None, data) f.addFromList(data, p) if data: p.setFont('Helvetica', 8) p.setFillColorRGB(0, 0, 0) p.drawRightString(width - inch / 2, inch / 2, '...') p.restoreState()
def retrieve_image(request, recordid, record, width=None, height=None): print 'retrieve_image' passwords = request.session.get('passwords', dict()) path = get_image_for_record(recordid, request.user, int(width or 100000), int(height or 100000), passwords) if not path: #raise Http404() print "THUMBNAIL UNAVAILABLE - NO PATH" return HttpResponseRedirect(reverse('static', args=('images/thumbnail_unavailable.png',))) Activity.objects.create(event='media-download-image', request=request, content_object=Record.objects.get(id=recordid), data=dict(width=width, height=height)) try: response = HttpResponse(content=file(path, 'rb').read(), mimetype='image/jpeg') if request.GET.has_key('forcedl'): response["Content-Disposition"] = "attachment; filename=%s.jpg" % record return response except IOError: logging.error("IOError: %s" % path) #raise Http404() print "THUMBNAIL UNAVAILABLE - IO ERROR" return HttpResponseRedirect(reverse('static', args=('images/thumbnail_unavailable.png',)))
def test_access_through_presentation(self): no_signals() Media.objects.filter(record=self.record).delete() media = Media.objects.create(record=self.record, name='tiff', mimetype='image/tiff', storage=self.storage) with open(os.path.join(os.path.dirname(__file__), 'test_data', 'dcmetro.tif'), 'rb') as f: media.save_file('dcmetro.tif', f) user1 = User.objects.create(username='******') user2 = User.objects.create(username='******') AccessControl.objects.create(content_object=self.collection, user=user1, read=True) storage_acl = AccessControl.objects.create(content_object=self.storage, user=user1, read=True) presentation = Presentation.objects.create(title='test47949074', owner=user1) presentation.items.create(record=self.record, order=1) # user2 has no access to storage or collection, so should not get result result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(None, result) # give access to presentation AccessControl.objects.create(content_object=presentation, user=user2, read=True) # user2 has no access to storage yet, so still should not get result result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(None, result) # give user2 access to storage user2_storage_acl = AccessControl.objects.create(content_object=self.storage, user=user2, read=True) # now user2 should get the image result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(400, Image.open(result).size[0]) # limit user2 image size user2_storage_acl.restrictions = dict(width=200, height=200) user2_storage_acl.save() # we should now get a smaller image result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(200, Image.open(result).size[0]) # password protect the presentation presentation.password='******' presentation.save() # user2 has not provided presentation password, so should not get result result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(None, result) # with presentation password, image should be returned result = get_image_for_record(self.record, width=400, height=400, user=user2, passwords={presentation.id: 'secret'}) self.assertEqual(200, Image.open(result).size[0])
def test_access_through_presentation(self): Media.objects.filter(record=self.record).delete() media = Media.objects.create(record=self.record, name='tiff', mimetype='image/tiff', storage=self.storage) with open(os.path.join(os.path.dirname(__file__), 'test_data', 'dcmetro.tif'), 'rb') as f: media.save_file('dcmetro.tif', f) user1 = User.objects.create(username='******') user2 = User.objects.create(username='******') AccessControl.objects.create(content_object=self.collection, user=user1, read=True) storage_acl = AccessControl.objects.create(content_object=self.storage, user=user1, read=True) presentation = Presentation.objects.create(title='test47949074', owner=user1) presentation.items.create(record=self.record, order=1) # user2 has no access to storage or collection, so should not get result result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(None, result) # give access to presentation AccessControl.objects.create(content_object=presentation, user=user2, read=True) # user2 has no access to storage yet, so still should not get result result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(None, result) # give user2 access to storage user2_storage_acl = AccessControl.objects.create(content_object=self.storage, user=user2, read=True) # now user2 should get the image result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(400, Image.open(result).size[0]) # limit user2 image size user2_storage_acl.restrictions = dict(width=200, height=200) user2_storage_acl.save() # we should now get a smaller image result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(200, Image.open(result).size[0]) # password protect the presentation presentation.password='******' presentation.save() # user2 has not provided presentation password, so should not get result result = get_image_for_record(self.record, width=400, height=400, user=user2) self.assertEqual(None, result) # with presentation password, image should be returned result = get_image_for_record(self.record, width=400, height=400, user=user2, passwords={presentation.id: 'secret'}) self.assertEqual(200, Image.open(result).size[0])
def retrieve_image(request, recordid, record, width=None, height=None): passwords = request.session.get('passwords', dict()) path = get_image_for_record(recordid, request.user, int(width or 100000), int(height or 100000), passwords) if not path: raise Http404() Activity.objects.create(event='media-download-image', request=request, content_object=Record.objects.get(id=recordid), data=dict(width=width, height=height)) try: response = HttpResponse(content=file(path, 'rb').read(), mimetype='image/jpeg') if request.GET.has_key('forcedl'): response["Content-Disposition"] = "attachment; filename=%s.jpg" % record return response except IOError: logging.error("IOError: %s" % path) raise Http404()
def view(self, request): presentation = self.obj passwords = request.session.get('passwords', dict()) response = HttpResponse(mimetype='application/pdf') pagesize = getattr(pagesizes, settings.PDF_PAGESIZE) width, height = pagesize class DocTemplate(BaseDocTemplate): def afterPage(self): self.handle_nextPageTemplate('Later') def column_frame(left): return Frame(left, inch / 2, width=width / 2 - 0.75 * inch, height=height - inch, leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0, showBoundary=False) def prepare_first_page(canvas, document): p1 = Paragraph(presentation.title, styles['Heading']) p2 = Paragraph(presentation.owner.get_full_name(), styles['SubHeading']) avail_width = width - inch avail_height = height - inch w1, h1 = p1.wrap(avail_width, avail_height) w2, h2 = p2.wrap(avail_width, avail_height) f = Frame(inch / 2, inch / 2, width - inch, height - inch, leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0) f.addFromList([p1, p2], canvas) document.pageTemplate.frames[0].height -= h1 + h2 + inch / 2 document.pageTemplate.frames[1].height -= h1 + h2 + inch / 2 canvas.saveState() canvas.setStrokeColorRGB(0, 0, 0) canvas.line(width / 2, inch / 2, width / 2, height - inch - h1 - h2) canvas.restoreState() def prepare_later_page(canvas, document): canvas.saveState() canvas.setStrokeColorRGB(0, 0, 0) canvas.line(width / 2, inch / 2, width / 2, height - inch / 2) canvas.restoreState() def getStyleSheet(): stylesheet = StyleSheet1() stylesheet.add( ParagraphStyle(name='Normal', fontName='Times-Roman', fontSize=8, leading=10, spaceAfter=18)) stylesheet.add( ParagraphStyle(name='SlideNumber', parent=stylesheet['Normal'], alignment=TA_RIGHT, fontSize=6, leading=8, rightIndent=3, spaceAfter=0)) stylesheet.add( ParagraphStyle(name='Heading', parent=stylesheet['Normal'], fontSize=20, leading=24, alignment=TA_CENTER, spaceAfter=0)) stylesheet.add( ParagraphStyle(name='SubHeading', parent=stylesheet['Normal'], fontSize=16, leading=20, alignment=TA_CENTER)) return stylesheet styles = getStyleSheet() items = presentation.items.filter(hidden=False) content = [] for index, item in enumerate(items): text = [] values = item.get_fieldvalues(owner=request.user) for value in values: text.append('<b>%s</b>: %s<br />' % (value.resolved_label, value.value)) annotation = item.annotation if annotation: text.append('<b>%s</b>: %s<br />' % ('Annotation', annotation)) try: p = Paragraph(''.join(text), styles['Normal']) except (AttributeError, KeyError, IndexError): # this sometimes triggers an error in reportlab p = None if p: image = get_image_for_record(item.record, presentation.owner, 100, 100, passwords) if image: try: i = flowables.Image(image, kind='proportional', width=1 * inch, height=1 * inch) p = flowables.ParagraphAndImage(p, i) except IOError: pass content.append( flowables.KeepTogether([ Paragraph('%s/%s' % (index + 1, len(items)), styles['SlideNumber']), p ])) first_template = PageTemplate(id='First', frames=[ column_frame(inch / 2), column_frame(width / 2 + 0.25 * inch) ], pagesize=pagesize, onPage=prepare_first_page) later_template = PageTemplate(id='Later', frames=[ column_frame(inch / 2), column_frame(width / 2 + 0.25 * inch) ], pagesize=pagesize, onPage=prepare_later_page) doc = DocTemplate(response) doc.addPageTemplates([first_template, later_template]) doc.build(content) return response
def _process_slides(self, outfile): for n in range(2, len(self.items) + 2): item = self.items[n - 2] x = xml.dom.minidom.parseString(self.slide_template) xr = xml.dom.minidom.parseString(self.slide_rel_template) xn = xml.dom.minidom.parseString(self.slide_notes_template) xnr = xml.dom.minidom.parseString(self.slide_notes_rel_template) record = item.record # insert notes fieldvalues = list(item.get_fieldvalues()) if fieldvalues: fieldvalues[0]._subitem = False for i in range(1, len(fieldvalues)): fieldvalues[i]._subitem = (fieldvalues[i].field == fieldvalues[i - 1].field and fieldvalues[i].group == fieldvalues[i - 1].group) body = xn.getElementsByTagName('p:txBody').item(0) def appendText(text): ap1 = xn.createElement('a:p') ar = xn.createElement('a:r') arPr = xn.createElement('a:rPr') arPr.setAttribute('dirty','0') arPr.setAttribute('lang','en-US') arPr.setAttribute('smtClean','0') at = xn.createElement('a:t') txt = xn.createTextNode(text) at.appendChild(txt) ar.appendChild(arPr) ar.appendChild(at) ap1.appendChild(ar) body.appendChild(ap1) for value in fieldvalues: appendText('%s%s: %s' % ( value._subitem and 'sub' or '', value.resolved_label, value.value or '')) annotation = item.annotation if annotation: appendText('Annotation: %s' % annotation) # update the slide number in notes e = filter(lambda e: e.getAttribute('type') == 'slidenum', xn.getElementsByTagName('a:fld'))[0] e.getElementsByTagName('a:t').item(0).firstChild.nodeValue = n # insert title for e in x.getElementsByTagName('a:t'): t = e.firstChild.nodeValue if t == 'title': t = item.title or '' e.firstChild.nodeValue = t # insert image if available image = get_image_for_record(record, self.user, 800, 600) if image: # add image to outfile with file(image, 'rb') as f: content = f.read() name = 'image%s.jpg' % n self.additional_content_types.setdefault('image/jpeg;jpg', None) outfile.writestr('ppt/media/' + name, content) # find image placeholder e = filter(lambda e: e.getAttribute('descr') == 'image', x.getElementsByTagName('p:cNvPr'))[0] e = e.parentNode.parentNode embedId = e.getElementsByTagName('a:blip')[0].getAttribute('r:embed') try: width, height = Image.open(image).size except IOError: width, height = None, None if width and height: offset = e.getElementsByTagName('a:off')[0] extent = e.getElementsByTagName('a:ext')[0] px = int(offset.getAttribute('x')) py = int(offset.getAttribute('y')) pw = int(extent.getAttribute('cx')) ph = int(extent.getAttribute('cy')) imageratio = width * 1.0 / height ratio = pw * 1.0 / ph if imageratio > ratio: new_h = height * pw / width new_w = pw new_x = px new_y = py + (ph - new_h) / 2 else: new_h = ph new_w = width * ph / height new_x = px + (pw - new_w) / 2 new_y = py offset.setAttribute('x', str(new_x)) offset.setAttribute('y', str(new_y)) extent.setAttribute('cx', str(new_w)) extent.setAttribute('cy', str(new_h)) # add image to slide relation rel = filter(lambda e: e.getAttribute('Id') == embedId, xr.getElementsByTagName('Relationship'))[0] self.placeholder_image = 'ppt' + rel.getAttribute('Target')[2:] rel.setAttribute('Target', '../media/' + name) # add notes to slide relation rel2 = filter(lambda e: e.getAttribute('Type') == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide", xr.getElementsByTagName('Relationship'))[0] rel2.setAttribute('Target', '../notesSlides/notesSlide%s.xml' % n) # add slide to notes relation rel3 = filter(lambda e: e.getAttribute('Type') == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide", xnr.getElementsByTagName('Relationship'))[0] rel3.setAttribute('Target', '../slides/slide%s.xml' % n) else: self.remove_placeholder_image = False outfile.writestr('ppt/slides/slide%s.xml' % n, standalone(x.toxml(encoding="UTF-8"))) outfile.writestr('ppt/slides/_rels/slide%s.xml.rels' % n, standalone(xr.toxml(encoding="UTF-8"))) outfile.writestr('ppt/notesSlides/notesSlide%s.xml' % n, standalone(xn.toxml(encoding="UTF-8"))) outfile.writestr('ppt/notesSlides/_rels/notesSlide%s.xml.rels' % n, standalone(xnr.toxml(encoding="UTF-8")))
def view(self, request, id, name): return_url = request.GET.get('next', reverse('presentation-browse')) presentation = Presentation.get_by_id_for_request(id, request) if not presentation: if not request.user.is_authenticated(): return HttpResponseRedirect(reverse('login') + '?next=' + request.get_full_path()) else: return HttpResponseRedirect(return_url) passwords = request.session.get('passwords', dict()) response = HttpResponse(mimetype='application/pdf') pagesize = getattr(pagesizes, settings.PDF_PAGESIZE) width, height = pagesize class DocTemplate(BaseDocTemplate): def afterPage(self): self.handle_nextPageTemplate('Later') def column_frame(left): return Frame(left, inch / 2, width=width / 2 - 0.75 * inch, height = height - inch, leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0, showBoundary=False) def prepare_first_page(canvas, document): p1 = Paragraph(presentation.title, styles['Heading']) p2 = Paragraph(presentation.owner.get_full_name(), styles['SubHeading']) avail_width = width - inch avail_height = height - inch w1, h1 = p1.wrap(avail_width, avail_height) w2, h2 = p2.wrap(avail_width, avail_height) f = Frame(inch / 2, inch / 2, width - inch, height - inch, leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0) f.addFromList([p1, p2], canvas) document.pageTemplate.frames[0].height -= h1 + h2 + inch / 2 document.pageTemplate.frames[1].height -= h1 + h2 + inch / 2 canvas.saveState() canvas.setStrokeColorRGB(0, 0, 0) canvas.line(width / 2, inch / 2, width / 2, height - inch - h1 - h2) canvas.restoreState() def prepare_later_page(canvas, document): canvas.saveState() canvas.setStrokeColorRGB(0, 0, 0) canvas.line(width / 2, inch / 2, width / 2, height - inch / 2) canvas.restoreState() styles = getStyleSheet() items = presentation.items.filter(hidden=False) content = [] for index, item in enumerate(items): text = [] values = item.get_fieldvalues(owner=request.user) for value in values: text.append('<b>%s</b>: %s<br />' % (value.resolved_label, value.value)) annotation = item.annotation if annotation: text.append('<b>%s</b>: %s<br />' % ('Annotation', annotation)) try: p = Paragraph(''.join(text), styles['Normal']) except (AttributeError, KeyError, IndexError): # this sometimes triggers an error in reportlab p = None if p: image = get_image_for_record(item.record, presentation.owner, 100, 100, passwords) if image: try: i = flowables.Image(image, kind='proportional', width=1 * inch, height=1 * inch) p = flowables.ParagraphAndImage(p, i) except IOError: pass content.append(flowables.KeepTogether( [Paragraph('%s/%s' % (index + 1, len(items)), styles['SlideNumber']), p])) first_template = PageTemplate(id='First', frames=[column_frame(inch / 2), column_frame(width / 2 + 0.25 * inch)], pagesize=pagesize, onPage=prepare_first_page) later_template = PageTemplate(id='Later', frames=[column_frame(inch / 2), column_frame(width / 2 + 0.25 * inch)], pagesize=pagesize, onPage=prepare_later_page) doc = DocTemplate(response) doc.addPageTemplates([first_template, later_template]) doc.build(content) return response
def _process_slides(self, outfile): for n in range(2, len(self.items) + 2): item = self.items[n - 2] x = xml.dom.minidom.parseString(self.slide_template) xr = xml.dom.minidom.parseString(self.slide_rel_template) xn = xml.dom.minidom.parseString(self.slide_notes_template) xnr = xml.dom.minidom.parseString(self.slide_notes_rel_template) record = item.record # insert notes fieldvalues = list(item.get_fieldvalues()) if fieldvalues: fieldvalues[0]._subitem = False for i in range(1, len(fieldvalues)): fieldvalues[i]._subitem = ( fieldvalues[i].field == fieldvalues[i - 1].field and fieldvalues[i].group == fieldvalues[i - 1].group) body = xn.getElementsByTagName('p:txBody').item(0) def append_text(text): ap1 = xn.createElement('a:p') ar = xn.createElement('a:r') ar_pr = xn.createElement('a:rPr') ar_pr.setAttribute('dirty', '0') ar_pr.setAttribute('lang', 'en-US') ar_pr.setAttribute('smtClean', '0') at = xn.createElement('a:t') txt = xn.createTextNode(text) at.appendChild(txt) ar.appendChild(ar_pr) ar.appendChild(at) ap1.appendChild(ar) body.appendChild(ap1) for value in fieldvalues: append_text('%s%s: %s' % (value._subitem and 'sub' or '', value.resolved_label, value.value or '')) annotation = item.annotation if annotation: append_text('Annotation: %s' % annotation) # update the slide number in notes e = filter(lambda e: e.getAttribute('type') == 'slidenum', xn.getElementsByTagName('a:fld'))[0] e.getElementsByTagName('a:t').item(0).firstChild.nodeValue = n # insert title for e in x.getElementsByTagName('a:t'): t = e.firstChild.nodeValue if t == 'title': t = item.title or '' e.firstChild.nodeValue = t # insert image if available try: image = get_image_for_record( record, self.user, getattr(settings, 'PPTEXPORT_WIDTH', 800), getattr(settings, 'PPTEXPORT_HEIGHT', 600)) except: image = None if image and os.path.isfile(image): # add image to outfile with file(image, 'rb') as f: content = f.read() name = 'image%s.jpg' % n self.additional_content_types.setdefault( 'image/jpeg;jpg', None) outfile.writestr('ppt/media/' + name, content) # find image placeholder e = filter(lambda e: e.getAttribute('descr') == 'image', x.getElementsByTagName('p:cNvPr'))[0] e = e.parentNode.parentNode embed_id = e.getElementsByTagName('a:blip')[0].getAttribute( 'r:embed') try: width, height = Image.open(image).size except IOError: width, height = None, None if width and height: offset = e.getElementsByTagName('a:off')[0] extent = e.getElementsByTagName('a:ext')[0] px = int(offset.getAttribute('x')) py = int(offset.getAttribute('y')) pw = int(extent.getAttribute('cx')) ph = int(extent.getAttribute('cy')) imageratio = width * 1.0 / height ratio = pw * 1.0 / ph if imageratio > ratio: new_h = height * pw / width new_w = pw new_x = px new_y = py + (ph - new_h) / 2 else: new_h = ph new_w = width * ph / height new_x = px + (pw - new_w) / 2 new_y = py offset.setAttribute('x', str(new_x)) offset.setAttribute('y', str(new_y)) extent.setAttribute('cx', str(new_w)) extent.setAttribute('cy', str(new_h)) # add image to slide relation rel = filter(lambda e: e.getAttribute('Id') == embed_id, xr.getElementsByTagName('Relationship'))[0] self.placeholder_image = 'ppt' + rel.getAttribute( 'Target')[2:] rel.setAttribute('Target', '../media/' + name) # add notes to slide relation rel2 = filter( lambda e: e.getAttribute('Type') == "http://schemas.openxmlformats.org/officeDocument/" "2006/relationships/notesSlide", xr.getElementsByTagName('Relationship'))[0] rel2.setAttribute('Target', '../notesSlides/notesSlide%s.xml' % n) # add slide to notes relation rel3 = filter( lambda e: e.getAttribute('Type') == "http://schemas.openxmlformats.org/officeDocument/" "2006/relationships/slide", xnr.getElementsByTagName('Relationship'))[0] rel3.setAttribute('Target', '../slides/slide%s.xml' % n) else: self.remove_placeholder_image = False outfile.writestr('ppt/slides/slide%s.xml' % n, standalone(x.toxml(encoding="UTF-8"))) outfile.writestr('ppt/slides/_rels/slide%s.xml.rels' % n, standalone(xr.toxml(encoding="UTF-8"))) outfile.writestr('ppt/notesSlides/notesSlide%s.xml' % n, standalone(xn.toxml(encoding="UTF-8"))) outfile.writestr('ppt/notesSlides/_rels/notesSlide%s.xml.rels' % n, standalone(xnr.toxml(encoding="UTF-8")))
def view(self, request): def filename(title): return re.sub('[^A-Za-z0-9_. ]+', '-', title)[:32] presentation = self.obj passwords = request.session.get('passwords', dict()) items = presentation.items.filter(hidden=False) tempfile = NamedTemporaryFile(suffix='.zip') output = zipfile.ZipFile(tempfile, 'w') template_name = getattr(settings, 'PRESENTATION_VIEWER_TEMPLATE', 'presentation_viewer.html') page = loader.render_to_string( template_name, { 'presentation': self.obj, 'return_url': '/exit', 'manifest_url': '/presentation/manifest.json', }) manifest = raw_manifest(request, self.obj.id, self.obj.name, offline=True) output.writestr('presentation/index.html', page) output.writestr('presentation/manifest.json', json.dumps(manifest)) for static_file in STATIC_FILES: path = finders.find(static_file) if path: output.write(path, 'static/' + static_file) package_files_dir = os.path.join(os.path.dirname(__file__), 'mirador_package') for root, dirs, files in os.walk(package_files_dir): for f in files: path = os.path.join(root, f) output.write(path, os.path.relpath(path, package_files_dir)) for item in items: image = get_image_for_record(item.record, self.user, passwords=passwords) outpath = item.record.get_image_url( force_reprocess=False, handler='storage-retrieve-iiif-image', ) if image: output.write(image, outpath) image = get_image_for_record(item.record, self.user, 100, 100, passwords=passwords) if image: output.write( image, 'thumbs' + outpath, ) output.writestr( reverse('presentation-blank-slide', kwargs=dict(extra='')).strip('/'), transparent_png(request, None).content) output.writestr( reverse('presentation-missing-slide', kwargs=dict(extra='')).strip('/'), missing_png(request, None).content) output.close() tempfile.flush() tempfile.seek(0) wrapper = FileWrapper(tempfile) response = HttpResponse(wrapper, content_type='application/zip') response['Content-Disposition'] = \ 'attachment; filename=%s.zip' % filename(presentation.title) response['Content-Length'] = os.path.getsize(tempfile.name) return response
def view(self, request): presentation = self.obj passwords = request.session.get('passwords', dict()) response = HttpResponse(content_type='application/pdf') pagesize = getattr(pagesizes, settings.PDF_PAGESIZE) width, height = pagesize class DocTemplate(BaseDocTemplate): def afterPage(self): self.handle_nextPageTemplate('Later') def column_frame(left): return Frame(left, inch / 2, width=width / 2 - 0.75 * inch, height=height - inch, leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0, showBoundary=False) def prepare_first_page(canvas, document): p1 = Paragraph(presentation.title, styles['Heading']) p2 = Paragraph(presentation.owner.get_full_name(), styles['SubHeading']) avail_width = width - inch # TODO: determine if the complaint about height being undeclared is just pycharm or if its a problem # if it is possibly a problem "it's better to be explicit" so refactor avail_height = height - inch w1, h1 = p1.wrap(avail_width, avail_height) w2, h2 = p2.wrap(avail_width, avail_height) f = Frame(inch / 2, inch / 2, width - inch, height - inch, leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0) f.addFromList([p1, p2], canvas) document.pageTemplate.frames[0].height -= h1 + h2 + inch / 2 document.pageTemplate.frames[1].height -= h1 + h2 + inch / 2 canvas.saveState() canvas.setStrokeColorRGB(0, 0, 0) canvas.line(width / 2, inch / 2, width / 2, height - inch - h1 - h2) canvas.restoreState() def prepare_later_page(canvas, document): canvas.saveState() canvas.setStrokeColorRGB(0, 0, 0) canvas.line(width / 2, inch / 2, width / 2, height - inch / 2) canvas.restoreState() def getStyleSheet(): stylesheet = StyleSheet1() stylesheet.add(ParagraphStyle(name='Normal', fontName='Times-Roman', fontSize=8, leading=10, spaceAfter=18)) stylesheet.add(ParagraphStyle(name='SlideNumber', parent=stylesheet['Normal'], alignment=TA_RIGHT, fontSize=6, leading=8, rightIndent=3, spaceAfter=0)) stylesheet.add(ParagraphStyle(name='Heading', parent=stylesheet['Normal'], fontSize=20, leading=24, alignment=TA_CENTER, spaceAfter=0)) stylesheet.add(ParagraphStyle(name='SubHeading', parent=stylesheet['Normal'], fontSize=16, leading=20, alignment=TA_CENTER)) return stylesheet styles = getStyleSheet() items = presentation.items.filter(hidden=False) content = [] for index, item in enumerate(items): text = [] values = item.get_fieldvalues(owner=request.user) for value in values: log.debug('value for cleaning = %s' % value.value) value.value = remove_rels_from_a_tags(value.value) log.debug('cleaned value = %s' % value.value) text.append('<b>%s</b>: %s<br />' % (value.resolved_label, value.value)) annotation = item.annotation if annotation: text.append('<b>%s</b>: %s<br />' % ('Annotation', annotation)) try: p = Paragraph(''.join(text), styles['Normal']) except (AttributeError, KeyError, IndexError): # this sometimes triggers an error in reportlab p = None if p: image = get_image_for_record(item.record, presentation.owner, 100, 100, passwords) if image: try: i = flowables.Image(image, kind='proportional', width=1 * inch, height=1 * inch) p = flowables.ParagraphAndImage(p, i) except IOError: pass content.append(flowables.KeepTogether( [Paragraph('%s/%s' % (index + 1, len(items)), styles['SlideNumber']), p])) first_template = PageTemplate(id='First', frames=[column_frame(inch / 2), column_frame(width / 2 + 0.25 * inch)], pagesize=pagesize, onPage=prepare_first_page) later_template = PageTemplate(id='Later', frames=[column_frame(inch / 2), column_frame(width / 2 + 0.25 * inch)], pagesize=pagesize, onPage=prepare_later_page) doc = DocTemplate(response) doc.addPageTemplates([first_template, later_template]) doc.build(content) response['Content-Disposition'] = 'filename="' + smart_str(presentation.title) + '.pdf"' return response