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

Last change on this file since 2180 was 2180, checked in by kroman0, 12 years ago

Fixed DeprecationWarning? for plone4

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