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

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

pyflakes fixes

File size: 5.1 KB
Line 
1import os
2import re
3import math
4try:
5    import hashlib as md5
6    md5.md5
7except ImportError:
8    import md5
9from string import atoi
10from random import randint
11
12from DateTime import DateTime
13
14from quintagroup.captcha.core.data import basic_english
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)
18
19try:
20    import Crypto.Cipher.DES as Crypto
21    Crypto
22except ImportError:
23    import Crypto
24
25
26def encrypt1(s):
27    return md5.md5(s).hexdigest().upper()
28
29
30def getTransform(x, y, a, p, o):
31    return (math.sin((y + o[0]) * p) * a + x, math.sin((x + o[1]) * p) * a + y)
32
33
34def gen_captcha(**kwargs):
35    """Generate a captcha image"""
36    try:
37        from App import ImageFile
38        ImageFile
39    except ImportError:
40        import ImageFile
41    from PIL import Image
42    from PIL import ImageFont
43    from PIL import ImageDraw
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
66    ALL_FONTS = ('Bd', 'It', 'MoBI', 'Mono', 'Se',
67                 'BI', 'MoBd', 'MoIt', 'SeBd', '')
68    rand_font = random.choice(ALL_FONTS)
69    rand_font_path = FONT_PATH + '/vera/Vera%s.ttf' % rand_font
70    font = ImageFont.truetype(rand_font_path, fnt_sz)
71    textSize = font.getsize(text)
72
73#------------------------------render   background1 -----------------------
74    image = Image.new('RGB', (textSize[0] + 7, textSize[1] + 7), bkground)
75    image.paste(bkground)
76#------------------------------render       Text2 ------------------------
77    draw = ImageDraw.Draw(image)
78    alignment = (random.uniform(0, 1), random.uniform(0, 1))
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
82    draw.text((x, y), text, font=font, fill=font_color)
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):
96            x, y = getTransform(i * r, j * r, amplitude, period, offset)
97
98            # Clamp the edges so we don't get black undefined areas
99            x = max(0, min(image.size[0] - 1, x))
100            y = max(0, min(image.size[1] - 1, y))
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 = []
110    for j in xrange(yPoints - 1):
111        for i in xrange(xPoints - 1):
112            mesh.append((
113                # Destination rectangle
114                (i * r, j * r,
115                 (i + 1) * r, (j + 1) * r),
116                # Source quadrilateral
117                (xRows[j][i],         yRows[j][i],
118                 xRows[j + 1][i],     yRows[j + 1][i],
119                 xRows[j + 1][i + 1], yRows[j + 1][i + 1],
120                 xRows[j][i + 1],     yRows[j][i + 1]),
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
131    return {'src': src, 'size': size}
132
133
134def getWord(index):
135    words = basic_english.words.split()
136    return words[index]
137
138
139def getIndex(word):
140    words = basic_english.words.split()
141    try:
142        res = words.index(word)
143    except ValueError:
144        res = len(words) + 1
145    return res
146
147
148def getCaptchasCount(dynamic):
149    if dynamic:
150        return len(basic_english.words.split())
151    else:
152        return CAPTCHAS_COUNT
153
154
155def formKey(num):
156    def normalize(s):
157        return (not len(s) % 8 and s) or normalize(s + str(randint(0, 9)))
158
159    return normalize('%s_%i_' % (str(DateTime().timeTime()), num))
160
161
162def encrypt(key, s):
163    return toHex(Crypto.new(key).encrypt(s))
164
165
166def decrypt(key, s):
167    return Crypto.new(key).decrypt(toStr(s))
168
169
170def parseKey(s):
171    ps = re.match('^(.+?)_(.+?)_', s)
172    if ps is None:
173        return {'date': '', 'key': ''}
174    return {'date': ps.group(1), 'key': ps.group(2)}
175
176
177def toHex(s):
178    lst = []
179    for ch in s:
180        hv = hex(ord(ch)).replace('0x', '')
181        if len(hv) == 1:
182            hv = '0' + hv
183        lst.append(hv)
184
185    return reduce(lambda x, y: x + y, lst)
186
187
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.