Added auto-generated badges
Fix StringIO import to cStringIO Added Blender Support from piernov Added Badge Button on ListParticipant
This commit is contained in:
@@ -147,6 +147,9 @@ def main(global_config, **settings):
|
||||
## Users
|
||||
config.add_route('pict_user', '/user_picture')
|
||||
config.add_route('show_user', '/user/{user_slug:([\w-]+)?}')
|
||||
config.add_route('badge_user', '/user/{user_slug:([\w-]+)?}/badge')
|
||||
config.add_route('badge_user1', '/user/{user_slug:([\w-]+)?}/badge1')
|
||||
config.add_route('badge_user2', '/user/{user_slug:([\w-]+)?}/badge2')
|
||||
|
||||
# HTML Routes - Logged
|
||||
#config.add_route('profil', 'MesJM2L')
|
||||
|
||||
+561
@@ -0,0 +1,561 @@
|
||||
# -*- coding: utf8 -*-
|
||||
from pyramid.httpexceptions import HTTPNotFound
|
||||
from pyramid.response import Response
|
||||
import cStringIO as StringIO
|
||||
from pyramid.view import view_config
|
||||
from .models import User
|
||||
|
||||
from reportlab.pdfgen import canvas
|
||||
from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfbase.ttfonts import TTFont
|
||||
from reportlab.lib.units import mm
|
||||
import qrcode
|
||||
|
||||
# Create PDF container
|
||||
WIDTH = 85 * mm
|
||||
HEIGHT = 60 * mm
|
||||
ICONSIZE = 8 * mm
|
||||
|
||||
def Ribbon35(DispUser, canvas):
|
||||
canvas.saveState()
|
||||
canvas.rotate(35)
|
||||
offset_u=0
|
||||
if DispUser.Staff:
|
||||
# Staff
|
||||
canvas.setFillColorRGB(1,.2,.2)
|
||||
canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
canvas.setFillColorRGB(1,1,1)
|
||||
canvas.setFont('Liberation', 20)
|
||||
canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF")
|
||||
elif DispUser.is_Intervenant:
|
||||
# Intervenant
|
||||
canvas.setFillColorRGB(.3,.3,1)
|
||||
canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
canvas.setFillColorRGB(1,1,1)
|
||||
canvas.setFont('Liberation', 15)
|
||||
canvas.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant")
|
||||
else:
|
||||
# Visiteur
|
||||
canvas.setFillColorRGB(.8,.8,.8)
|
||||
canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
canvas.setFillColorRGB(0,0,0)
|
||||
canvas.setFont('Liberation', 12)
|
||||
canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur")
|
||||
canvas.restoreState()
|
||||
return canvas
|
||||
|
||||
def Ribbon45(DispUser, canvas):
|
||||
canvas.saveState()
|
||||
canvas.rotate(45)
|
||||
offset_u=0
|
||||
if DispUser.Staff:
|
||||
# Staff
|
||||
canvas.setFillColorRGB(1,.2,.2)
|
||||
canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
canvas.setFillColorRGB(1,1,1)
|
||||
canvas.setFont('Liberation', 20)
|
||||
canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF")
|
||||
elif DispUser.is_Intervenant:
|
||||
# Intervenant
|
||||
canvas.setFillColorRGB(.3,.3,1)
|
||||
canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
canvas.setFillColorRGB(1,1,1)
|
||||
canvas.setFont('Liberation', 15)
|
||||
canvas.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant")
|
||||
else:
|
||||
# Visiteur
|
||||
canvas.setFillColorRGB(.8,.8,.8)
|
||||
canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
canvas.setFillColorRGB(0,0,0)
|
||||
canvas.setFont('Liberation', 12)
|
||||
canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur")
|
||||
canvas.restoreState()
|
||||
return canvas
|
||||
|
||||
def Ribbon90(DispUser, canvas):
|
||||
canvas.saveState()
|
||||
canvas.rotate(90)
|
||||
offset_u=0
|
||||
if DispUser.Staff:
|
||||
# Staff
|
||||
canvas.setFillColorRGB(1,.2,.2)
|
||||
canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
canvas.setFillColorRGB(1,1,1)
|
||||
canvas.setFont('Liberation', 20)
|
||||
canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF")
|
||||
elif DispUser.is_Intervenant:
|
||||
# Intervenant
|
||||
canvas.setFillColorRGB(.3,.3,1)
|
||||
canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
canvas.setFillColorRGB(1,1,1)
|
||||
canvas.setFont('Liberation', 15)
|
||||
canvas.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant")
|
||||
else:
|
||||
# Visiteur
|
||||
canvas.setFillColorRGB(.8,.8,.8)
|
||||
canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
canvas.setFillColorRGB(0,0,0)
|
||||
canvas.setFont('Liberation', 12)
|
||||
canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur")
|
||||
canvas.restoreState()
|
||||
return canvas
|
||||
|
||||
def JM2L_Logo(canvas, Position="Up"):
|
||||
# Import font
|
||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
|
||||
|
||||
if Position=="Up":
|
||||
logoobject = canvas.beginText()
|
||||
logoobject.setFont('Logo', 52)
|
||||
logoobject.setFillColorRGB(.83,0,.33)
|
||||
logoobject.setTextOrigin(55, HEIGHT-50)
|
||||
logoobject.textLines("JM2L")
|
||||
canvas.drawText(logoobject)
|
||||
|
||||
yearobject = canvas.beginText()
|
||||
yearobject.setFont("Helvetica-Bold", 15)
|
||||
yearobject.setFillColorRGB(1,1,1)
|
||||
yearobject.setTextOrigin(67, HEIGHT-20)
|
||||
yearobject.setWordSpace(21)
|
||||
yearobject.textLines("2 0 1 5")
|
||||
canvas.drawText(yearobject)
|
||||
elif Position=="Down":
|
||||
logoobject = canvas.beginText()
|
||||
logoobject.setFont('Logo', 32)
|
||||
logoobject.setFillColorRGB(.83,0,.33)
|
||||
logoobject.setTextOrigin(2, 17)
|
||||
logoobject.textLines("JM2L")
|
||||
canvas.drawText(logoobject)
|
||||
|
||||
yearobject = canvas.beginText()
|
||||
yearobject.setFont("Helvetica-Bold", 10)
|
||||
yearobject.setFillColorRGB(1,1,1)
|
||||
#yearobject.setLineWidth(.1)
|
||||
#yearobject.setStrokeColorRGB(.5,.5,.5)
|
||||
yearobject.setTextRenderMode(0)
|
||||
#yearobject.setStrokeOverprint(.2)
|
||||
yearobject.setTextOrigin(9 , 35)
|
||||
yearobject.setWordSpace(13)
|
||||
yearobject.textLines("2 0 1 5")
|
||||
canvas.drawText(yearobject)
|
||||
|
||||
def Tiers_Logo(canvas, DispUser, LWidth=4, StartPos=None):
|
||||
Border = 1
|
||||
if StartPos is None:
|
||||
StartPos = ( WIDTH -70, 0 )
|
||||
StartX, StartY = StartPos
|
||||
num = 0
|
||||
canvas.setStrokeColorRGB(0.5,0.5,0.5)
|
||||
Logos = filter(lambda x:x.ThumbLinks, DispUser.tiers)
|
||||
for tiers in Logos:
|
||||
FileName = tiers.ThumbLinks.pop().split("/")[-1]
|
||||
ImagePath = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, FileName)
|
||||
# Should We compute a better positionning for logos ?
|
||||
#PosX = StartX + (( (2.0*num+1) / 2*len(Logos) )*(ICONSIZE+Border) - ((ICONSIZE+Border)/2))
|
||||
PosX = StartX + (num % LWidth) * (ICONSIZE+Border)
|
||||
if len(Logos)<=LWidth:
|
||||
# Middle of line
|
||||
PosY = StartY + 0.5 * (ICONSIZE+Border)
|
||||
else:
|
||||
# in two or more lines
|
||||
PosY = StartY + (num / LWidth) * (ICONSIZE+Border)
|
||||
canvas.setLineWidth(.1)
|
||||
canvas.drawImage(ImagePath,
|
||||
PosX, PosY, ICONSIZE, ICONSIZE,\
|
||||
preserveAspectRatio=True,
|
||||
anchor='c',
|
||||
mask=[0,3,0,3,0,3]
|
||||
)
|
||||
canvas.roundRect(PosX, PosY, ICONSIZE, ICONSIZE, radius=2, stroke=True)
|
||||
num+=1
|
||||
|
||||
def QRCode(DispUser):
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=2,
|
||||
)
|
||||
# Data of QR code
|
||||
qr.add_data('http://jm2l.linux-azur.org/user/%s' % DispUser.slug)
|
||||
qr.make(fit=True)
|
||||
|
||||
return qr.make_image()
|
||||
|
||||
@view_config(route_name='badge_user')
|
||||
def badge_user(request):
|
||||
user_slug = request.matchdict.get('user_slug', None)
|
||||
if user_slug is None or len(user_slug)==0:
|
||||
raise HTTPNotFound(u"Cet utilisateur n'a pas été reconnu")
|
||||
# Query database
|
||||
DispUser = User.by_slug(user_slug)
|
||||
if DispUser is None:
|
||||
raise HTTPNotFound()
|
||||
|
||||
# Ok let's generate a PDF Badge
|
||||
|
||||
# Register LiberationMono font
|
||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
|
||||
|
||||
pdf = StringIO.StringIO()
|
||||
|
||||
c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) )
|
||||
c.translate(mm, mm)
|
||||
|
||||
# Feed some metadata
|
||||
c.setCreator("linux-azur.org")
|
||||
c.setTitle("Badge")
|
||||
|
||||
c.saveState()
|
||||
# Logo on Top
|
||||
JM2L_Logo(c, "Down")
|
||||
|
||||
if DispUser.Staff:
|
||||
# Staff
|
||||
c.setFillColorRGB(.83,0,.33)
|
||||
c.rect(-3, HEIGHT-30, WIDTH, HEIGHT, fill=1)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFont('Liberation', 30)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT-26, "STAFF")
|
||||
elif DispUser.is_Intervenant:
|
||||
# Intervenant
|
||||
c.setFillColorRGB(.3,.3,1)
|
||||
c.rect(-3, HEIGHT-30, WIDTH, HEIGHT, fill=1)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFont('Liberation', 30)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT-26, "Intervenant")
|
||||
else:
|
||||
# Visiteur
|
||||
c.setFillColorRGB(.8,.8,.8)
|
||||
c.rect(-3, HEIGHT-30, WIDTH, HEIGHT, fill=1)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFont('Liberation', 30)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT-26, "Visiteur")
|
||||
|
||||
c.restoreState()
|
||||
|
||||
c.setFont('Liberation', 18)
|
||||
c.setStrokeColorRGB(0,0,0)
|
||||
c.setFillColorRGB(0,0,0)
|
||||
# Feed Name and SurName
|
||||
if len(DispUser.prenom) + len(DispUser.nom)>18:
|
||||
if DispUser.pseudo:
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 + 4 * mm , "%s" % DispUser.prenom )
|
||||
c.setFont('Courier', 17)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 - 2 * mm , "%s" % DispUser.nom )
|
||||
else:
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 + 2 * mm , "%s" % DispUser.prenom )
|
||||
c.setFont('Courier', 17)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 - 6 * mm , "%s" % DispUser.nom )
|
||||
else:
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 + 0 * mm , "%s %s" % (DispUser.prenom, DispUser.nom) )
|
||||
|
||||
if DispUser.pseudo:
|
||||
c.setFont("Helvetica-Oblique", 14)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 - 8 * mm , "%s" % DispUser.pseudo )
|
||||
|
||||
# Put QR code to user profile
|
||||
c.drawInlineImage(QRCode(DispUser), \
|
||||
WIDTH - 20 * mm - 7, 0, \
|
||||
20 * mm, 20 * mm, \
|
||||
preserveAspectRatio=True, \
|
||||
anchor='s')
|
||||
|
||||
Tiers_Logo(c, DispUser, 4, ( 30 * mm, 2 ))
|
||||
|
||||
c.showPage()
|
||||
c.save()
|
||||
pdf.seek(0)
|
||||
return Response(app_iter=pdf, content_type = 'application/pdf' )
|
||||
|
||||
@view_config(route_name='badge_user1')
|
||||
def badge_user1(request):
|
||||
user_slug = request.matchdict.get('user_slug', None)
|
||||
if user_slug is None or len(user_slug)==0:
|
||||
raise HTTPNotFound(u"Cet utilisateur n'a pas été reconnu")
|
||||
# Query database
|
||||
DispUser = User.by_slug(user_slug)
|
||||
if DispUser is None:
|
||||
raise HTTPNotFound()
|
||||
|
||||
# Ok let's generate a PDF Badge
|
||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
|
||||
pdf = StringIO.StringIO()
|
||||
|
||||
c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) )
|
||||
c.translate(mm, mm)
|
||||
|
||||
# Feed some metadata
|
||||
c.setCreator("linux-azur.org")
|
||||
c.setTitle("Badge")
|
||||
|
||||
c.saveState()
|
||||
|
||||
logoobject = c.beginText()
|
||||
logoobject.setFont('Logo', 52)
|
||||
logoobject.setFillColorRGB(.83,0,.33)
|
||||
logoobject.setTextOrigin(55, HEIGHT-50)
|
||||
logoobject.textLines("JM2L")
|
||||
c.drawText(logoobject)
|
||||
|
||||
|
||||
yearobject = c.beginText()
|
||||
yearobject.setFont("Helvetica-Bold", 15)
|
||||
yearobject.setFillColorRGB(1,1,1)
|
||||
yearobject.setTextOrigin(67, HEIGHT-20)
|
||||
yearobject.setWordSpace(21)
|
||||
yearobject.textLines("2 0 1 5")
|
||||
c.drawText(yearobject)
|
||||
|
||||
num = 0
|
||||
for tiers in DispUser.tiers:
|
||||
if tiers.ThumbLinks:
|
||||
FileName = tiers.ThumbLinks.pop().split("/")[-1]
|
||||
num+=1
|
||||
ImagePath = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, FileName)
|
||||
if num<6:
|
||||
c.drawImage(ImagePath,
|
||||
WIDTH -5 - num * (ICONSIZE+5), 5, ICONSIZE, ICONSIZE,\
|
||||
preserveAspectRatio=True,
|
||||
anchor='c',
|
||||
mask=[0,3,0,3,0,3])
|
||||
else:
|
||||
c.drawImage(ImagePath,
|
||||
WIDTH -5 - (num-5) * (ICONSIZE+5), 5 + ICONSIZE, ICONSIZE, ICONSIZE,\
|
||||
preserveAspectRatio=True,
|
||||
anchor='c',
|
||||
mask=[0,3,0,3,0,3])
|
||||
|
||||
|
||||
|
||||
|
||||
if 1:
|
||||
Ribbon90(DispUser, c)
|
||||
|
||||
if 0:
|
||||
c.rotate(90)
|
||||
offset_u=111
|
||||
if DispUser.Staff:
|
||||
# Staff
|
||||
c.setFillColorRGB(1,.2,.2)
|
||||
c.rect(-5, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFont('Liberation', 30)
|
||||
c.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+5, "STAFF")
|
||||
elif DispUser.is_Intervenant:
|
||||
# Intervenant
|
||||
c.setFillColorRGB(.3,.3,1)
|
||||
c.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFont('Liberation', 15)
|
||||
c.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant")
|
||||
else:
|
||||
# Visiteur
|
||||
c.setFillColorRGB(.8,.8,.8)
|
||||
c.rect(-5, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
c.setFillColorRGB(0,0,0)
|
||||
c.setFont('Liberation', 19)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2-offset_u+7, "Visiteur")
|
||||
c.restoreState()
|
||||
|
||||
c.setFont('Courier', 18)
|
||||
c.setStrokeColorRGB(0,0,0)
|
||||
c.setFillColorRGB(0,0,0)
|
||||
# Feed Name and SurName
|
||||
if len(DispUser.prenom) + len(DispUser.nom)>18:
|
||||
if DispUser.pseudo:
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 + 4 * mm , "%s" % DispUser.prenom )
|
||||
c.setFont('Courier', 17)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 - 2 * mm , "%s" % DispUser.nom )
|
||||
else:
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 + 2 * mm , "%s" % DispUser.prenom )
|
||||
c.setFont('Courier', 17)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 - 6 * mm , "%s" % DispUser.nom )
|
||||
else:
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 + 0 * mm , "%s %s" % (DispUser.prenom, DispUser.nom) )
|
||||
#c.drawCentredString(WIDTH/2, HEIGHT - 22 * mm, )
|
||||
if DispUser.pseudo:
|
||||
#c.setFont('Liberation', 14)
|
||||
c.setFont("Helvetica-Oblique", 14)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 - 8 * mm , "\"%s\"" % DispUser.pseudo )
|
||||
#c.restoreState()
|
||||
|
||||
# Put QR code to user profile
|
||||
c.drawInlineImage(QRCode(DispUser), \
|
||||
WIDTH - 20 * mm - 7, 0, \
|
||||
20 * mm, 20 * mm, \
|
||||
preserveAspectRatio=True, \
|
||||
anchor='s')
|
||||
|
||||
c.showPage()
|
||||
c.save()
|
||||
pdf.seek(0)
|
||||
return Response(app_iter=pdf, content_type = 'application/pdf' )
|
||||
|
||||
|
||||
@view_config(route_name='badge_user2')
|
||||
def badge_user2(request):
|
||||
user_slug = request.matchdict.get('user_slug', None)
|
||||
if user_slug is None or len(user_slug)==0:
|
||||
raise HTTPNotFound(u"Cet utilisateur n'a pas été reconnu")
|
||||
# Query database
|
||||
DispUser = User.by_slug(user_slug)
|
||||
if DispUser is None:
|
||||
raise HTTPNotFound()
|
||||
|
||||
# Ok let's generate a PDF Badge
|
||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
|
||||
pdf = StringIO.StringIO()
|
||||
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=2,
|
||||
)
|
||||
# Data of QR code
|
||||
qr.add_data('http://jm2l.linux-azur.org/user/%s' % DispUser.slug)
|
||||
qr.make(fit=True)
|
||||
|
||||
img = qr.make_image()
|
||||
# Create PDF container
|
||||
WIDTH = 85 * mm
|
||||
HEIGHT = 60 * mm
|
||||
ICONSIZE = 10 * mm
|
||||
c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) )
|
||||
c.translate(mm, mm)
|
||||
|
||||
# Feed some metadata
|
||||
c.setCreator("linux-azur.org")
|
||||
c.setTitle("Badge")
|
||||
|
||||
c.saveState()
|
||||
|
||||
logoobject = c.beginText()
|
||||
logoobject.setFont('Logo', 52)
|
||||
logoobject.setFillColorRGB(.83,0,.33)
|
||||
logoobject.setTextOrigin(55, HEIGHT-50)
|
||||
logoobject.textLines("JM2L")
|
||||
c.drawText(logoobject)
|
||||
|
||||
|
||||
yearobject = c.beginText()
|
||||
yearobject.setFont("Helvetica-Bold", 15)
|
||||
yearobject.setFillColorRGB(1,1,1)
|
||||
yearobject.setTextOrigin(67, HEIGHT-20)
|
||||
yearobject.setWordSpace(21)
|
||||
yearobject.textLines("2 0 1 5")
|
||||
c.drawText(yearobject)
|
||||
|
||||
num = 0
|
||||
for tiers in DispUser.tiers:
|
||||
if tiers.ThumbLinks:
|
||||
FileName = tiers.ThumbLinks.pop().split("/")[-1]
|
||||
num+=1
|
||||
ImagePath = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, FileName)
|
||||
if num<6:
|
||||
c.drawImage(ImagePath,
|
||||
WIDTH -5 - num * (ICONSIZE+5), 5, ICONSIZE, ICONSIZE,\
|
||||
preserveAspectRatio=True,
|
||||
anchor='c',
|
||||
mask=[0,3,0,3,0,3])
|
||||
else:
|
||||
c.drawImage(ImagePath,
|
||||
WIDTH -5 - (num-5) * (ICONSIZE+5), 5 + ICONSIZE, ICONSIZE, ICONSIZE,\
|
||||
preserveAspectRatio=True,
|
||||
anchor='c',
|
||||
mask=[0,3,0,3,0,3])
|
||||
|
||||
|
||||
|
||||
|
||||
if 1:
|
||||
c.rotate(35)
|
||||
offset_u=0
|
||||
if DispUser.Staff:
|
||||
# Staff
|
||||
c.setFillColorRGB(1,.2,.2)
|
||||
c.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFont('Liberation', 20)
|
||||
c.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF")
|
||||
elif DispUser.is_Intervenant:
|
||||
# Intervenant
|
||||
c.setFillColorRGB(.3,.3,1)
|
||||
c.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFont('Liberation', 15)
|
||||
c.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant")
|
||||
else:
|
||||
# Visiteur
|
||||
c.setFillColorRGB(.8,.8,.8)
|
||||
c.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
c.setFillColorRGB(0,0,0)
|
||||
c.setFont('Liberation', 12)
|
||||
c.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur")
|
||||
|
||||
if 0:
|
||||
c.rotate(90)
|
||||
offset_u=111
|
||||
if DispUser.Staff:
|
||||
# Staff
|
||||
c.setFillColorRGB(1,.2,.2)
|
||||
c.rect(-5, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFont('Liberation', 30)
|
||||
c.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+5, "STAFF")
|
||||
elif DispUser.is_Intervenant:
|
||||
# Intervenant
|
||||
c.setFillColorRGB(.3,.3,1)
|
||||
c.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFont('Liberation', 15)
|
||||
c.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant")
|
||||
else:
|
||||
# Visiteur
|
||||
c.setFillColorRGB(.8,.8,.8)
|
||||
c.rect(-5, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
|
||||
c.setFillColorRGB(0,0,0)
|
||||
c.setFont('Liberation', 19)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2-offset_u+7, "Visiteur")
|
||||
|
||||
|
||||
c.restoreState()
|
||||
|
||||
c.setFont('Courier', 18)
|
||||
c.setStrokeColorRGB(0,0,0)
|
||||
c.setFillColorRGB(0,0,0)
|
||||
# Feed Name and SurName
|
||||
if len(DispUser.prenom) + len(DispUser.nom)>18:
|
||||
if DispUser.pseudo:
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 + 4 * mm , "%s" % DispUser.prenom )
|
||||
c.setFont('Courier', 17)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 - 2 * mm , "%s" % DispUser.nom )
|
||||
else:
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 + 2 * mm , "%s" % DispUser.prenom )
|
||||
c.setFont('Courier', 17)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 - 6 * mm , "%s" % DispUser.nom )
|
||||
else:
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 + 0 * mm , "%s %s" % (DispUser.prenom, DispUser.nom) )
|
||||
#c.drawCentredString(WIDTH/2, HEIGHT - 22 * mm, )
|
||||
if DispUser.pseudo:
|
||||
#c.setFont('Liberation', 14)
|
||||
c.setFont("Helvetica-Oblique", 14)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT/2 - 8 * mm , "\"%s\"" % DispUser.pseudo )
|
||||
#c.restoreState()
|
||||
|
||||
# Put QR code to user profile
|
||||
c.drawInlineImage(img, WIDTH - 20 * mm - 7, 0, 20 * mm, 20 * mm, preserveAspectRatio=True, anchor='s')
|
||||
|
||||
c.showPage()
|
||||
c.save()
|
||||
pdf.seek(0)
|
||||
return Response(app_iter=pdf, content_type = 'application/pdf' )
|
||||
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
"""
|
||||
Thumbnailer runs with python 2.7 and 3.x.
|
||||
To run automatically with a file manager such as Nautilus, save this file
|
||||
in a directory that is listed in PATH environment variable, and create
|
||||
blender.thumbnailer file in ${HOME}/.local/share/thumbnailers/ directory
|
||||
with the following contents:
|
||||
|
||||
[Thumbnailer Entry]
|
||||
TryExec=blender-thumbnailer.py
|
||||
Exec=blender-thumbnailer.py %u %o
|
||||
MimeType=application/x-blender;
|
||||
"""
|
||||
|
||||
import struct
|
||||
|
||||
|
||||
def open_wrapper_get():
|
||||
""" wrap OS spesific read functionality here, fallback to 'open()'
|
||||
"""
|
||||
|
||||
class GFileWrapper:
|
||||
__slots__ = ("mode", "g_file")
|
||||
|
||||
def __init__(self, url, mode='r'):
|
||||
self.mode = mode # used in gzip module
|
||||
self.g_file = Gio.File.parse_name(url).read(None)
|
||||
|
||||
def read(self, size):
|
||||
return self.g_file.read_bytes(size, None).get_data()
|
||||
|
||||
def seek(self, offset, whence=0):
|
||||
self.g_file.seek(offset, [1, 0, 2][whence], None)
|
||||
return self.g_file.tell()
|
||||
|
||||
def tell(self):
|
||||
return self.g_file.tell()
|
||||
|
||||
def close(self):
|
||||
self.g_file.close(None)
|
||||
|
||||
def open_local_url(url, mode='r'):
|
||||
o = urlparse(url)
|
||||
if o.scheme == '':
|
||||
path = o.path
|
||||
elif o.scheme == 'file':
|
||||
path = unquote(o.path)
|
||||
else:
|
||||
raise(IOError('URL scheme "%s" needs gi.repository.Gio module' % o.scheme))
|
||||
return open(path, mode)
|
||||
|
||||
try:
|
||||
from gi.repository import Gio
|
||||
return GFileWrapper
|
||||
except ImportError:
|
||||
try:
|
||||
# Python 3
|
||||
from urllib.parse import urlparse, unquote
|
||||
except ImportError:
|
||||
# Python 2
|
||||
from urlparse import urlparse
|
||||
from urllib import unquote
|
||||
return open_local_url
|
||||
|
||||
|
||||
def blend_extract_thumb(path):
|
||||
import os
|
||||
open_wrapper = open_wrapper_get()
|
||||
|
||||
# def MAKE_ID(tag): ord(tag[0])<<24 | ord(tag[1])<<16 | ord(tag[2])<<8 | ord(tag[3])
|
||||
REND = 1145980242 # MAKE_ID(b'REND')
|
||||
TEST = 1414743380 # MAKE_ID(b'TEST')
|
||||
|
||||
blendfile = open_wrapper(path, 'rb')
|
||||
|
||||
head = blendfile.read(12)
|
||||
|
||||
if head[0:2] == b'\x1f\x8b': # gzip magic
|
||||
import gzip
|
||||
blendfile.close()
|
||||
blendfile = gzip.GzipFile('', 'rb', 0, open_wrapper(path, 'rb'))
|
||||
head = blendfile.read(12)
|
||||
|
||||
if not head.startswith(b'BLENDER'):
|
||||
blendfile.close()
|
||||
return None, 0, 0
|
||||
|
||||
is_64_bit = (head[7] == b'-'[0])
|
||||
|
||||
# true for PPC, false for X86
|
||||
is_big_endian = (head[8] == b'V'[0])
|
||||
|
||||
# blender pre 2.5 had no thumbs
|
||||
if head[9:11] <= b'24':
|
||||
blendfile.close()
|
||||
return None, 0, 0
|
||||
|
||||
sizeof_bhead = 24 if is_64_bit else 20
|
||||
int_endian_pair = '>ii' if is_big_endian else '<ii'
|
||||
|
||||
while True:
|
||||
bhead = blendfile.read(sizeof_bhead)
|
||||
|
||||
if len(bhead) < sizeof_bhead:
|
||||
return None, 0, 0
|
||||
|
||||
code, length = struct.unpack(int_endian_pair, bhead[0:8]) # 8 == sizeof(int) * 2
|
||||
|
||||
if code == REND:
|
||||
blendfile.seek(length, os.SEEK_CUR)
|
||||
else:
|
||||
break
|
||||
|
||||
if code != TEST:
|
||||
blendfile.close()
|
||||
return None, 0, 0
|
||||
|
||||
try:
|
||||
x, y = struct.unpack(int_endian_pair, blendfile.read(8)) # 8 == sizeof(int) * 2
|
||||
except struct.error:
|
||||
blendfile.close()
|
||||
return None, 0, 0
|
||||
|
||||
length -= 8 # sizeof(int) * 2
|
||||
|
||||
if length != x * y * 4:
|
||||
blendfile.close()
|
||||
return None, 0, 0
|
||||
|
||||
image_buffer = blendfile.read(length)
|
||||
|
||||
if len(image_buffer) != length:
|
||||
blendfile.close()
|
||||
return None, 0, 0
|
||||
|
||||
blendfile.close()
|
||||
return image_buffer, x, y
|
||||
|
||||
|
||||
def write_png(buf, width, height):
|
||||
import zlib
|
||||
|
||||
# reverse the vertical line order and add null bytes at the start
|
||||
width_byte_4 = width * 4
|
||||
raw_data = b"".join(b'\x00' + buf[span:span + width_byte_4] for span in range((height - 1) * width * 4, -1, - width_byte_4))
|
||||
|
||||
def png_pack(png_tag, data):
|
||||
chunk_head = png_tag + data
|
||||
return struct.pack("!I", len(data)) + chunk_head + struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head))
|
||||
|
||||
return b"".join([
|
||||
b'\x89PNG\r\n\x1a\n',
|
||||
png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
|
||||
png_pack(b'IDAT', zlib.compress(raw_data, 9)),
|
||||
png_pack(b'IEND', b'')])
|
||||
|
||||
|
||||
def main():
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print("Expected 2 arguments <input.blend> <output.png>")
|
||||
else:
|
||||
file_in = sys.argv[-2]
|
||||
|
||||
buf, width, height = blend_extract_thumb(file_in)
|
||||
|
||||
if buf:
|
||||
file_out = sys.argv[-1]
|
||||
|
||||
f = open(file_out, "wb")
|
||||
f.write(write_png(buf, width, height))
|
||||
f.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
import random
|
||||
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||
import StringIO
|
||||
import cStringIO as StringIO
|
||||
import math
|
||||
from pyramid.view import view_config
|
||||
from .words import TabMots
|
||||
|
||||
@@ -169,6 +169,13 @@ class User(Base):
|
||||
return u
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_Intervenant(self, year=2015):
|
||||
""" This property will return if User do an event on specified year """
|
||||
return DBSession.query(Event).join(User_Event) \
|
||||
.filter(User_Event.user_uid==self.uid) \
|
||||
.filter(Event.for_year==year).count()
|
||||
|
||||
@property
|
||||
def my_hash(self):
|
||||
m = hashlib.sha1()
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
@@ -162,7 +162,10 @@ now = datetime.datetime.now()
|
||||
<a href="javascript:alert('${u.nom}, ${u.prenom}\n${u.phone}');">
|
||||
<i class="icon-headphones"></i>
|
||||
</a>
|
||||
% endif
|
||||
% endif
|
||||
<a href="/user/${u.slug}/badge">
|
||||
<i class="icon-qrcode"></i>
|
||||
</a>
|
||||
</span>
|
||||
</td>
|
||||
<td style="text-align:center;">
|
||||
|
||||
+116
-31
@@ -2,8 +2,7 @@
|
||||
from pyramid.view import view_config, view_defaults
|
||||
from pyramid.response import Response
|
||||
from pyramid.exceptions import NotFound
|
||||
from pyramid.httpexceptions import HTTPNotFound
|
||||
from pyramid.request import Request
|
||||
from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest
|
||||
from PIL import Image
|
||||
import re, os, shutil
|
||||
from os import path
|
||||
@@ -13,6 +12,7 @@ import subprocess
|
||||
import cStringIO as StringIO
|
||||
# Database access imports
|
||||
from .models import User, Place, Tiers, Event, SallePhy
|
||||
from .blenderthumbnailer import blend_extract_thumb, write_png
|
||||
|
||||
CurrentYear = 2015
|
||||
MIN_FILE_SIZE = 1 # bytes
|
||||
@@ -27,7 +27,8 @@ ACCEPTED_MIMES = ['application/pdf',
|
||||
'application/vnd.oasis.opendocument.presentation-template',
|
||||
'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'application/vnd.oasis.opendocument.spreadsheet-template',
|
||||
'image/svg+xml'
|
||||
'image/svg+xml',
|
||||
'application/x-blender'
|
||||
]
|
||||
|
||||
|
||||
@@ -136,6 +137,38 @@ class MediaPath():
|
||||
if mime=='application/pdf':
|
||||
return "/img/PDF.png"
|
||||
|
||||
def check_blend_file(self, fileobj):
|
||||
head = fileobj.read(12)
|
||||
fileobj.seek(0)
|
||||
|
||||
if head[:2] == b'\x1f\x8b': # gzip magic
|
||||
import zlib
|
||||
head = zlib.decompress(fileobj.read(), 31)[:12]
|
||||
fileobj.seek(0)
|
||||
|
||||
if head.startswith(b'BLENDER'):
|
||||
return True
|
||||
|
||||
def get_mimetype_from_file(self, fileobj):
|
||||
mimetype = magic.from_buffer(fileobj.read(1024), mime=True)
|
||||
fileobj.seek(0)
|
||||
|
||||
# Check if the binary file is a blender file
|
||||
if ( mimetype == "application/octet-stream" or mimetype == "application/x-gzip" ) and self.check_blend_file(fileobj):
|
||||
return "application/x-blender", True
|
||||
else:
|
||||
return mimetype, False
|
||||
|
||||
|
||||
def get_mimetype(self, name):
|
||||
""" This function return the mime-type based on .type file """
|
||||
try:
|
||||
with open(self.mediapath(name) + '.type', 'r', 16) as f:
|
||||
mime = f.read()
|
||||
return mime
|
||||
except IOError:
|
||||
return None
|
||||
|
||||
@view_defaults(route_name='media_upload')
|
||||
class MediaUpload(MediaPath):
|
||||
|
||||
@@ -152,19 +185,31 @@ class MediaUpload(MediaPath):
|
||||
return self.get_mediapath(self.media_table, self.linked_id, name)
|
||||
|
||||
def validate(self, result, filecontent):
|
||||
# let's say we don't trust the uploader
|
||||
RealMime = magic.from_buffer( filecontent.read(1024), mime=True)
|
||||
""" Do some basic check to the uploaded file before to accept it """
|
||||
# Try to determine mime type from content uploaded
|
||||
found_mime = magic.from_buffer(filecontent.read(1024), mime=True)
|
||||
filecontent.seek(0)
|
||||
if RealMime!=result['type']:
|
||||
result['error'] = 'l\'extension du fichier ne correspond pas à son contenu - '
|
||||
result['error'] += "( %s vs %s )" % (RealMime, result['type'])
|
||||
|
||||
# Do a special statement for specific detected mime type
|
||||
if found_mime in ["application/octet-stream", "application/x-gzip"]:
|
||||
# Lets see if it's a bender file
|
||||
if self.check_blend_file(filecontent):
|
||||
found_mime = "application/x-blender"
|
||||
# MonKey Patch of content type
|
||||
result['type'] = found_mime
|
||||
|
||||
# Reject mime type that don't match
|
||||
if found_mime!=result['type']:
|
||||
result['error'] = 'L\'extension du fichier ne correspond pas à son contenu - '
|
||||
result['error'] += "( %s vs %s )" % (found_mime, result['type'])
|
||||
return False
|
||||
|
||||
# Accept images and mime types listed
|
||||
if not RealMime in ACCEPTED_MIMES:
|
||||
if not (IMAGE_TYPES.match(RealMime)):
|
||||
if not found_mime in ACCEPTED_MIMES:
|
||||
if not (IMAGE_TYPES.match(found_mime)):
|
||||
result['error'] = 'Ce type fichier n\'est malheureusement pas supporté. '
|
||||
result['error'] += 'Les fichiers acceptées sont les images et pdf.'
|
||||
return False
|
||||
|
||||
if result['size'] < MIN_FILE_SIZE:
|
||||
result['error'] = 'le fichier est trop petit'
|
||||
elif result['size'] > MAX_FILE_SIZE:
|
||||
@@ -173,12 +218,13 @@ class MediaUpload(MediaPath):
|
||||
# file['error'] = u'les type de fichiers acceptés sont png, jpg et gif'
|
||||
else:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_file_size(self, file):
|
||||
file.seek(0, 2) # Seek to the end of the file
|
||||
size = file.tell() # Get the position of EOF
|
||||
file.seek(0) # Reset the file position to the beginning
|
||||
def get_file_size(self, fileobj):
|
||||
fileobj.seek(0, 2) # Seek to the end of the file
|
||||
size = fileobj.tell() # Get the position of EOF
|
||||
fileobj.seek(0) # Reset the file position to the beginning
|
||||
return size
|
||||
|
||||
def thumbnailurl(self,name):
|
||||
@@ -254,9 +300,6 @@ class MediaUpload(MediaPath):
|
||||
|
||||
def docthumbnail(self, filename):
|
||||
TargetFileName = self.thumbnailpath(filename)
|
||||
# unoconv need a libre office server to be up
|
||||
Command = ["unoconv", "-f", "pdf", "-e", "PageRange=1", "--output=%s" % TargetFileName, \
|
||||
"%s[0]" % self.mediapath(filename) ]
|
||||
# let's take the thumbnail generated inside the document
|
||||
Command = ["unzip", "-p", self.mediapath(filename), "Thumbnails/thumbnail.png"]
|
||||
ThumbBytes = subprocess.check_output(Command)
|
||||
@@ -284,6 +327,40 @@ class MediaUpload(MediaPath):
|
||||
timage.convert('RGB').save( TargetFileName+".jpg", 'JPEG')
|
||||
return self.thumbnailurl( os.path.basename(TargetFileName+".jpg") )
|
||||
|
||||
def blendthumbnail(self, filename):
|
||||
blendfile = self.mediapath(filename)
|
||||
# Extract Thumb
|
||||
if 0:
|
||||
head = fileobj.read(12)
|
||||
fileobj.seek(0)
|
||||
|
||||
if head[:2] == b'\x1f\x8b': # gzip magic
|
||||
import zlib
|
||||
head = zlib.decompress(fileobj.read(), 31)[:12]
|
||||
fileobj.seek(0)
|
||||
|
||||
buf, width, height = blend_extract_thumb(blendfile)
|
||||
if buf:
|
||||
png = write_png(buf, width, height)
|
||||
TargetFileName = self.thumbnailpath(filename)
|
||||
image = Image.open(StringIO.StringIO(png))
|
||||
blender_indicator = Image.open( "jm2l/static/img/Blender_Thumb_Stamp.png" )
|
||||
image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS)
|
||||
timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0))
|
||||
# Add thumbnail
|
||||
timage.paste(
|
||||
image,
|
||||
((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2))
|
||||
# Stamp with Blender file type
|
||||
timage.paste(
|
||||
blender_indicator,
|
||||
(timage.size[0]-30, timage.size[1]-30),
|
||||
blender_indicator,
|
||||
)
|
||||
timage.save( TargetFileName+".png")
|
||||
return self.thumbnailurl( os.path.basename(TargetFileName+".png") )
|
||||
return self.ExtMimeIcon('application/x-blender')
|
||||
|
||||
def fileinfo(self,name):
|
||||
filename = self.mediapath(name)
|
||||
f, ext = os.path.splitext(name)
|
||||
@@ -295,13 +372,17 @@ class MediaUpload(MediaPath):
|
||||
name=name,
|
||||
media_table=self.media_table,
|
||||
uid=self.linked_id)
|
||||
mime = mimetypes.types_map.get(ext)
|
||||
if (IMAGE_TYPES.match(mime)):
|
||||
|
||||
mime = self.get_mimetype(name)
|
||||
if IMAGE_TYPES.match(mime):
|
||||
info['thumbnailUrl'] = self.thumbnailurl(name)
|
||||
elif mime in ACCEPTED_MIMES:
|
||||
thumb = self.thumbnailpath("%s%s" % (f, ext))
|
||||
if os.path.exists( thumb +'.jpg' ):
|
||||
info['thumbnailUrl'] = self.thumbnailurl(name)+'.jpg'
|
||||
thumbext = ".jpg"
|
||||
if mime == "application/x-blender":
|
||||
thumbext = ".png"
|
||||
if os.path.exists( thumb + thumbext ):
|
||||
info['thumbnailUrl'] = self.thumbnailurl(name)+thumbext
|
||||
else:
|
||||
info['thumbnailUrl'] = self.ExtMimeIcon(mime)
|
||||
else:
|
||||
@@ -343,7 +424,6 @@ class MediaUpload(MediaPath):
|
||||
|
||||
@view_config(request_method='DELETE', xhr=True, accept="application/json", renderer='json')
|
||||
def delete(self):
|
||||
import json
|
||||
filename = self.request.matchdict.get('name')
|
||||
try:
|
||||
os.remove(self.mediapath(filename) + '.type')
|
||||
@@ -381,11 +461,17 @@ class MediaUpload(MediaPath):
|
||||
result['name'] = os.path.basename(fieldStorage.filename)
|
||||
result['type'] = fieldStorage.type
|
||||
result['size'] = self.get_file_size(fieldStorage.file)
|
||||
|
||||
if self.validate(result, fieldStorage.file):
|
||||
with open( self.mediapath(result['name'] + '.type'), 'w') as f:
|
||||
# Keep mime-type in .type file
|
||||
with open( self.mediapath( result['name'] ) + '.type', 'w') as f:
|
||||
f.write(result['type'])
|
||||
with open( self.mediapath(result['name']), 'wb') as f:
|
||||
|
||||
# Store uploaded file
|
||||
fieldStorage.file.seek(0)
|
||||
with open( self.mediapath(result['name'] ), 'wb') as f:
|
||||
shutil.copyfileobj( fieldStorage.file , f)
|
||||
|
||||
if re.match(IMAGE_TYPES, result['type']):
|
||||
result['thumbnailUrl'] = self.createthumbnail(result['name'])
|
||||
elif result['type']=='application/pdf':
|
||||
@@ -394,8 +480,11 @@ class MediaUpload(MediaPath):
|
||||
result['thumbnailUrl'] = self.svgthumbnail(result['name'])
|
||||
elif result['type'].startswith('application/vnd'):
|
||||
result['thumbnailUrl'] = self.docthumbnail(result['name'])
|
||||
elif result['type']=='application/x-blender':
|
||||
result['thumbnailUrl'] = self.blendthumbnail(result['name'])
|
||||
else:
|
||||
result['thumbnailUrl'] = self.ExtMimeIcon(result['type'])
|
||||
|
||||
result['deleteType'] = DELETEMETHOD
|
||||
result['deleteUrl'] = self.request.route_url('media_upload',
|
||||
sep='',
|
||||
@@ -425,12 +514,8 @@ class MediaView(MediaPath):
|
||||
@view_config(request_method='GET', http_cache = (EXPIRATION_TIME, {'public':True}))
|
||||
def get(self):
|
||||
name = self.request.matchdict.get('name')
|
||||
try:
|
||||
with open( self.mediapath( os.path.basename(name) ) + '.type', 'r', 16) as f:
|
||||
test = f.read()
|
||||
self.request.response.content_type = test
|
||||
except IOError:
|
||||
pass
|
||||
self.request.response.content_type = self.get_mimetype(name)
|
||||
|
||||
try:
|
||||
self.request.response.body_file = open( self.mediapath(name), 'rb', 10000)
|
||||
except IOError:
|
||||
|
||||
Reference in New Issue
Block a user