source: products/quintagroup.captcha.core/trunk/quintagroup/captcha/core/utils.py @ 3217

Last change on this file since 3217 was 3217, checked in by vmaksymiv, 13 years ago

pep8 fix

File size: 5.1 KB
RevLine 
[797]1import os
2import re
3import math
[2180]4try:
5    import hashlib as md5
[3144]6    md5.md5
[2180]7except ImportError:
8    import md5
[797]9from string import atoi
10from random import randint
11
12from DateTime import DateTime
13
[1954]14from quintagroup.captcha.core.data import basic_english
[3132]15#import quintagroup.captcha.core configuration values
16from quintagroup.captcha.core.config import (DEFAULT_IMAGE_SIZE, DEFAULT_BG,
17    DEFAULT_FONT_COLOR, DEFAULT_DISTORTION, CAPTCHAS_COUNT)
[797]18
19try:
20    import Crypto.Cipher.DES as Crypto
[3144]21    Crypto
[3132]22except ImportError:
[797]23    import Crypto
24
[3128]25
[1874]26def encrypt1(s):
[2180]27    return md5.md5(s).hexdigest().upper()
[1874]28
[3128]29
[797]30def getTransform(x, y, a, p, o):
[3128]31    return (math.sin((y + o[0]) * p) * a + x, math.sin((x + o[1]) * p) * a + y)
[797]32
[3128]33
[797]34def gen_captcha(**kwargs):
35    """Generate a captcha image"""
[3097]36    try:
37        from App import ImageFile
[3144]38        ImageFile
[3097]39    except ImportError:
40        import ImageFile
41    from PIL import Image
42    from PIL import ImageFont
43    from PIL import ImageDraw
[797]44    import random
45    from PIL import ImageFile as pyImageFile
46    import sys
47    sys.modules['ImageFile'] = pyImageFile
48    from cStringIO import StringIO
49
50    text = kwargs.get('text', None)
51    fnt_sz = kwargs.get('size', DEFAULT_IMAGE_SIZE)
52    bkground = kwargs.get('bkground', DEFAULT_BG)
53    font_color = kwargs.get('font_color', DEFAULT_FONT_COLOR)
54    distortion = kwargs.get('distortion', DEFAULT_DISTORTION)
55
56    period = distortion[0]
57    amplitude = distortion[1]
58    offset = distortion[2]
59
60    outFile = StringIO()
61
62    DATA_PATH = os.path.abspath(os.path.dirname(__file__)) + '/data'
63    FONT_PATH = DATA_PATH + '/fonts'
64
65    #select font for captcha text
[3128]66    ALL_FONTS = ('Bd', 'It', 'MoBI', 'Mono', 'Se',
67                 'BI', 'MoBd', 'MoIt', 'SeBd', '')
[797]68    rand_font = random.choice(ALL_FONTS)
[3128]69    rand_font_path = FONT_PATH + '/vera/Vera%s.ttf' % rand_font
70    font = ImageFont.truetype(rand_font_path, fnt_sz)
[797]71    textSize = font.getsize(text)
72
73#------------------------------render   background1 -----------------------
[3128]74    image = Image.new('RGB', (textSize[0] + 7, textSize[1] + 7), bkground)
[797]75    image.paste(bkground)
76#------------------------------render       Text2 ------------------------
77    draw = ImageDraw.Draw(image)
[3128]78    alignment = (random.uniform(0, 1), random.uniform(0, 1))
[797]79    x = int((image.size[0] - textSize[0]) * alignment[0] + 0.5)
80    y = int((image.size[1] - textSize[1]) * alignment[1] + 0.5)
81
[3128]82    draw.text((x, y), text, font=font, fill=font_color)
[797]83
84#------------------------------render       Distortion -----------------------
85    r = 1
86    xPoints = image.size[0] / r + 2
87    yPoints = image.size[1] / r + 2
88
89    # Create a list of arrays with transformed points
90    xRows = []
91    yRows = []
92    for j in xrange(yPoints):
93        xRow = []
94        yRow = []
95        for i in xrange(xPoints):
[3128]96            x, y = getTransform(i * r, j * r, amplitude, period, offset)
[797]97
98            # Clamp the edges so we don't get black undefined areas
[3128]99            x = max(0, min(image.size[0] - 1, x))
100            y = max(0, min(image.size[1] - 1, y))
[797]101
102            xRow.append(x)
103            yRow.append(y)
104        xRows.append(xRow)
105        yRows.append(yRow)
106
107    # Create the mesh list, with a transformation for
108    # each square between points on the grid
109    mesh = []
[3128]110    for j in xrange(yPoints - 1):
111        for i in xrange(xPoints - 1):
[797]112            mesh.append((
113                # Destination rectangle
[3128]114                (i * r, j * r,
115                 (i + 1) * r, (j + 1) * r),
[797]116                # Source quadrilateral
[3217]117                (xRows[j][i], yRows[j][i],
118                 xRows[j + 1][i], yRows[j + 1][i],
[3128]119                 xRows[j + 1][i + 1], yRows[j + 1][i + 1],
[3217]120                 xRows[j][i + 1], yRows[j][i + 1]),
[797]121                ))
122
123    img = image.transform(image.size, Image.MESH, mesh, Image.BILINEAR)
124
125    # save the image to a file
126    img.save(outFile, format='jpeg')
127    outFile.seek(0)
128    src = outFile.read()
129    size = len(src)
130    sys.modules['ImageFile'] = ImageFile
[3128]131    return {'src': src, 'size': size}
[797]132
133
134def getWord(index):
135    words = basic_english.words.split()
136    return words[index]
137
[3128]138
[797]139def getIndex(word):
140    words = basic_english.words.split()
141    try:
142        res = words.index(word)
143    except ValueError:
[3144]144        res = len(words) + 1
[797]145    return res
146
[3128]147
[853]148def getCaptchasCount(dynamic):
149    if dynamic:
[797]150        return len(basic_english.words.split())
[853]151    else:
152        return CAPTCHAS_COUNT
[797]153
[3128]154
[797]155def formKey(num):
156    def normalize(s):
[3128]157        return (not len(s) % 8 and s) or normalize(s + str(randint(0, 9)))
[797]158
[3128]159    return normalize('%s_%i_' % (str(DateTime().timeTime()), num))
[797]160
[3128]161
[797]162def encrypt(key, s):
163    return toHex(Crypto.new(key).encrypt(s))
164
[3128]165
[797]166def decrypt(key, s):
167    return Crypto.new(key).decrypt(toStr(s))
168
[3128]169
[797]170def parseKey(s):
171    ps = re.match('^(.+?)_(.+?)_', s)
172    if ps is None:
173        return {'date': '', 'key': ''}
[3128]174    return {'date': ps.group(1), 'key': ps.group(2)}
[797]175
[3128]176
[797]177def toHex(s):
178    lst = []
179    for ch in s:
180        hv = hex(ord(ch)).replace('0x', '')
181        if len(hv) == 1:
[3128]182            hv = '0' + hv
[797]183        lst.append(hv)
184
[3128]185    return reduce(lambda x, y: x + y, lst)
[797]186
[3128]187
[797]188def toStr(s):
189    return s and chr(atoi(s[:2], base=16)) + toStr(s[2:]) or ''
Note: See TracBrowser for help on using the repository browser.