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

Last change on this file since 241 was 1, checked in by myroslav, 14 years ago

Building directory structure

  • Property svn:eol-style set to native
File size: 4.6 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    return {'date': ps.group(1), 'key':ps.group(2)}
148
149def toHex(s):
150    lst = []
151    for ch in s:
152        hv = hex(ord(ch)).replace('0x', '')
153        if len(hv) == 1:
154            hv = '0'+hv
155        lst.append(hv)
156
157    return reduce(lambda x,y:x+y, lst)
158
159def toStr(s):
160    return s and chr(atoi(s[:2], base=16)) + toStr(s[2:]) or ''
Note: See TracBrowser for help on using the repository browser.