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

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

pep8 fixes

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