Skip to content
Snippets Groups Projects
Commit 2b9a3561 authored by kaiyou's avatar kaiyou
Browse files

Add more sample captchas

parent 77983842
No related branches found
No related tags found
No related merge requests found
......@@ -41,19 +41,69 @@ class DummyCaptchaField(fields.CaptchaField):
)
class GeneratedTextImageCaptchaField(fields.CaptchaField):
class ImageCaptchaField(fields.CaptchaField):
""" Image-based captcha base class, displays an image and requests that the
user inputs some text deduced from the image.
"""
widget = widgets.TextInput()
def __init__(self, *args, **kwargs):
self.font = ImageFont.truetype("captcha.ttf", 14)
self.bgcolor = "#ffffff"
self.fgcolor = "#ff6677"
super(ImageCaptchaField, self).__init__(*args, **kwargs)
def __call__(self, **kwargs):
png = io.BytesIO()
self.make_image(self.context["challenge"]).save(png, "PNG")
output = base64.b64encode(png.getvalue()).decode("ascii")
return widgets.HTMLString(
'<p>{}</p>'.format(self.context["challenge"]) +
'<p><img src="data:image/png;base64,{}"></p>'.format(output)
+ super(ImageCaptchaField, self).__call__(**kwargs)
)
def make_char(self, char, rotation_range=15):
""" Renders a character
"""
drawn = " {} ".format(char)
rotation = random.randrange(-rotation_range, rotation_range)
image = Image.new("L", self.font.getsize(drawn), self.bgcolor)
draw = ImageDraw.Draw(image)
draw.text((0, 0), drawn, font=self.font, fill=self.fgcolor)
return image.rotate(rotation, expand=0, resample=Image.BICUBIC) \
.crop(image.getbbox())
def make_text(self, text, **kwargs):
""" Renders a text
"""
size = self.font.getsize(text)
size = (size[0] * 2, int(size[1] * 1.4))
image = Image.new("RGB", size, self.bgcolor)
xpos = 2
for char in text:
charimage = self.make_char(char)
image.paste(charimage, (xpos, 4, xpos + charimage.size[0], 4 + charimage.size[1]))
xpos = xpos + 2 + charimage.size[0]
return image.crop((0, 0, xpos + 1, size[1]))
def make_image(self, challenge):
pass
def _value(self):
return ""
class GeneratedTextImageCaptchaField(ImageCaptchaField):
""" Generate a random text and build a fuzzy image based on that text.
This is the most common historical captcha type, although pretty easily
defeated by OCR nowadays.
"""
widget = widgets.TextInput()
charset = string.ascii_uppercase + string.digits
def _value(self):
return ""
def challenge(self):
self.label = "Please copy the following text: "
length = random.randint(5,8)
......@@ -62,34 +112,5 @@ class GeneratedTextImageCaptchaField(fields.CaptchaField):
def check(self, challenge, form, field):
return challenge.lower() == field.data.lower()
def make_image(self, text):
font = ImageFont.truetype("captcha.ttf", 14)
size = font.getsize(text)
size = (size[0] * 2, int(size[1] * 1.4))
image = Image.new("RGB", size, "#ffffff")
xpos = 2
for char in text:
drawn = " {} ".format(char)
fgimage = Image.new("RGB", size, "#000000")
charimage = Image.new("L", font.getsize(drawn), "#000000")
chardraw = ImageDraw.Draw(charimage)
chardraw.text((0, 0), drawn, font=font, fill="#ffffff")
charimage = charimage.rotate(random.randrange(-15,15), expand=0, resample=Image.BICUBIC)
charimage = charimage.crop(charimage.getbbox())
maskimage = Image.new("L", size)
maskimage.paste(charimage, (xpos, 4, xpos + charimage.size[0], 4 + charimage.size[1]))
size = maskimage.size
image = Image.composite(fgimage, image, maskimage)
xpos = xpos + 2 + charimage.size[0]
image = image.crop((0, 0, xpos + 1, size[1]))
return image
def __call__(self, **kwargs):
image = self.make_image(self.context["challenge"])
image_png = io.BytesIO()
image.save(image_png, "PNG")
image_string = base64.b64encode(image_png.getvalue()).decode("ascii")
return widgets.HTMLString(
'<img src="data:image/png;base64,{}">'.format(image_string) +
super(GeneratedTextImageCaptchaField, self).__call__(**kwargs)
)
def make_image(self, challenge):
return self.make_text(challenge)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment