Captcha code not working on webpy

516 Views Asked by At

I know there is a lot of text, but I don't believe this is actually a hard problem to solve. For a TLDR, check out the end of the question.

So, I am trying to implement a basic captcha-like form in my web.py app. This code is taken from http://kzar.co.uk/blog/2009/07/14/web.py-captcha. I am just showing a basic test example I am working on, trying to figure out what is going wrong in my bigger app.

What happens is, when I press enter on the index page, even if I get the code right (which I verify by printing the 'word' variable in captcha.py to terminal), I still get an error saying my captcha is invalid. I have tried everything, and checked both the session variable as well as the word variable, but no matter what I am told that my code is wrong. Here is the entire test app.

test.py:

import web
from web import form
from captcha import getCaptcha

render = web.template.render('templates/')

urls = (
    '/', 'index',
    '/captcha.gif', 'captcha'
)
app = web.application(urls, locals())

if web.config.get('_session') is None:
    session = web.session.Session(app, web.session.DiskStore('sessions'), initializer={'captcha': ''})
    web.config._session = session
else:
    session = web.config._session

vcaptcha = form.Validator('Please enter the code',  lambda x:x == session.captcha)

enquiry_form = form.Form(
    form.Textbox("captcha", vcaptcha, description="Validation Code", pre="<img src='/captcha.gif' valign=center><br>", class_="standard", style="width:70px;"),
)

class index:
    # Display the create match page
    def GET(self):
        form = enquiry_form()
        return render.captcha(form)

    # Save the data    
    def POST(self): 
        form = enquiry_form()
        if not form.validates():    # If there is an issue
            return render.captcha(form)    # Return them to the create page
        else:
            return "Success!"

class captcha:
    def GET(self):
        web.header("Content-Type", "image/gif")
        captcha = getCaptcha()
        session.captcha = captcha[0]
        return captcha[1].read()

if __name__ == "__main__":
    app = web.application(urls, globals())
    app.run()

captcha.py:

from PIL import Image, ImageDraw, ImageFont
import cStringIO, random

def getCaptcha():
    im = Image.new("RGB", (175, 60))
    draw = ImageDraw.Draw(im)

    for x in range(0, 175):
        for y in range(0, 60):
            draw.point((x, y), (135, 191, 107))

    font = ImageFont.truetype('static/ZXX Camo.otf', 50)

    alphabet = 'abcdefghijklmnopqrstuvwxyz'

    word = ''
    for i in range(5):
        word = word + alphabet[random.randint(0, len(alphabet) -1)]

    draw.text((5, 5), word, font=font, fill=(0, 0, 0))

    f = cStringIO.StringIO()
    im.save(f, "GIF")
    f.seek(0)
    return word, f

captcha.html:

$def with (form)
<head>
    <link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon">
</head>
<h1>Testing Captcha</h1>

<form name="main" method="post">
$:form.render()    
</form>

The font I am using is available here: http://dl.dropbox.com/u/20517415/ZXX.zip

I am totally perplexed by what is happening here. I believe the code at fault here is the validation code lambda x:x == session.captcha. I have tried many different versions of this line, and nothing seems to work. Most perplexing is that I can even change the line to be lambda x:x != session.captcha, and it STILL doesn't work. I would appreciate your help. I have been looking at this for awhile and have no idea what is wrong.

TLDR; Some basic CAPTCHA-like code I am working with on a web.py app does not recognize a correct code entry, and I have provided the source files for you to inspect what is wrong.

1

There are 1 best solutions below

0
On

For those who find this through google:

The solution was simple. I was reinitializing the app instance, which meant that I was creating a new session every time, without a session.captcha var. And because the way web.py handles the validation, it did not send out an error explaining that there was an AttributeError. So, all I had to do was remove the app declaration in __main__.

Also, this code wouldn't work without disabling debug mode, because web.py session variables are weird =/