source: products/qPloneCaptchas/trunk/utils.py @ 615

Last change on this file since 615 was 615, checked in by piv, 17 years ago

added version 0.4.1

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