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
1 merge request!20Add 'remember me' button
Pipeline #651 failed
......@@ -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