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

Last change on this file since 3600 was 3600, checked in by vmaksymiv, 11 years ago

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