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

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

fixed PIL imports

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