# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr## This file is part of CubicWeb.## CubicWeb is free software: you can redistribute it and/or modify it under the# terms of the GNU Lesser General Public License as published by the Free# Software Foundation, either version 2.1 of the License, or (at your option)# any later version.## CubicWeb 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 Lesser General Public License for more# details.## You should have received a copy of the GNU Lesser General Public License along# with CubicWeb. If not, see <http://www.gnu.org/licenses/>."""Simple captcha library, based on PIL. Monkey patch functions in this moduleif you want something better..."""__docformat__="restructuredtext en"fromrandomimportrandint,choicefromcStringIOimportStringIOimportImage,ImageFont,ImageDraw,ImageFilterfromtimeimporttimefromcubicwebimporttagsfromcubicweb.webimportProcessFormError,formwidgetsasfwdefpil_captcha(text,fontfile,fontsize):"""Generate a captcha image. Return a PIL image object. adapted from http://code.activestate.com/recipes/440588/ """# randomly select the foreground colorfgcolor=randint(0,0xffff00)# make the background color the opposite of fgcolorbgcolor=fgcolor^0xffffff# create a font objectfont=ImageFont.truetype(fontfile,fontsize)# determine dimensions of the textdim=font.getsize(text)# create a new image slightly larger that the textimg=Image.new('RGB',(dim[0]+5,dim[1]+5),bgcolor)draw=ImageDraw.Draw(img)# draw 100 random colored boxes on the backgroundx,y=img.sizefornuminxrange(100):draw.rectangle((randint(0,x),randint(0,y),randint(0,x),randint(0,y)),fill=randint(0,0xffffff))# add the text to the imagedraw.text((3,3),text,font=font,fill=fgcolor)img=img.filter(ImageFilter.EDGE_ENHANCE_MORE)returnimgdefcaptcha(fontfile,fontsize,size=5,format='JPEG'):"""Generate an arbitrary text, return it together with a buffer containing the captcha image for the text """text=u''.join(choice('QWERTYUOPASDFGHJKLZXCVBNM')foriinrange(size))img=pil_captcha(text,fontfile,fontsize)out=StringIO()img.save(out,format)out.seek(0)returntext,outclassCaptchaWidget(fw.TextInput):defrender(self,form,field,renderer=None):# t=int(time()*100) to make sure img is not cachedsrc=form._cw.build_url('view',vid='captcha',t=int(time()*100),captchakey=field.input_name(form))img=tags.img(src=src,alt=u'captcha')img=u'<div class="captcha">%s</div>'%imgreturnimg+super(CaptchaWidget,self).render(form,field,renderer)defprocess_field_data(self,form,field):captcha=form._cw.session.data.pop(field.input_name(form),None)val=super(CaptchaWidget,self).process_field_data(form,field)ifvalisNone:returnval# required will be checked by fieldifcaptchaisNone:msg=form._cw._('unable to check captcha, please try again')raiseProcessFormError(msg)elifval.lower()!=captcha.lower():msg=form._cw._('incorrect captcha value')raiseProcessFormError(msg)returnval