1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
############################################################################################
# #
# The code below is from the pycaptcha-0.4 package ( http://releases.navi.cx/pycaptcha/ ) #
# Copyright (c) 2004 Micah Dowty (see COPYING in this directory for further details ) # #
# and adapted by Bertrand Neron, for the purpose of Mobyle # #
# #
############################################################################################
import random, string, time
try:
import Image
except ImportError:
from PIL import Image
from Mobyle.Captcha import Words , Backgrounds , Text , Distortions
def randomIdentifier(alphabet = string.ascii_letters + string.digits,
length = 24):
return "".join([random.choice(alphabet) for i in xrange(length)])
class PseudoGimpy():
"""A relatively easy CAPTCHA that's somewhat easy on the eyes
The render() function generates the CAPTCHA image at the given size by
combining Layer instances from self.layers.
"""
minCorrectSolutions = 1
maxIncorrectSolutions = 0
defaultSize = (256,96)
def __init__(self):
self.solutions = []
self.valid = True
# Each test has a unique identifier, used to refer to that test
# later, and a creation time so it can expire later.
self.id = randomIdentifier()
self.creationTime = time.time()
self._layers = self.getLayers()
def addSolution(self, solution):
self.solutions.append(solution)
def testSolutions(self, solutions):
"""Test whether the given solutions are sufficient for this CAPTCHA.
A given CAPTCHA can only be tested once, after that it is invalid
and always returns False. This makes random guessing much less effective.
"""
if not self.valid:
return False
self.valid = False
numCorrect = 0
numIncorrect = 0
for solution in solutions:
if solution in self.solutions:
numCorrect += 1
else:
numIncorrect += 1
return numCorrect >= self.minCorrectSolutions and \
numIncorrect <= self.maxIncorrectSolutions
def getImage(self):
"""Get a PIL image representing this CAPTCHA test, creating it if necessary"""
if not self._image:
self._image = self.render()
return self._image
def getLayers(self):
word = Words.defaultWordList.pick()
self.addSolution(word)
return [
random.choice([
Backgrounds.CroppedImage(),
Backgrounds.TiledImage(),
]),
Text.TextLayer(word, borderSize=1),
Distortions.SineWarp(),
]
def render(self, size=None):
"""Render this CAPTCHA, returning a PIL image"""
if size is None:
size = self.defaultSize
img = Image.new("RGB", size)
return self._renderList(self._layers, Image.new("RGB", size))
def _renderList(self, l, img):
for i in l:
if type(i) == tuple or type(i) == list:
img = self._renderList(i, img)
else:
img = i.render(img) or img
return img
|