source: products/quintagroup.plonecaptchas/trunk/quintagroup/plonecaptchas/utils.py @ 1871

Last change on this file since 1871 was 1871, checked in by liebster, 14 years ago

Revert 2726 to 2589 commits for tagging plone-3 compatible version

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