Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

from captcha.conf import settings 

from captcha.helpers import captcha_image_url 

from captcha.models import CaptchaStore 

from django.http import HttpResponse, Http404 

from django.core.exceptions import ImproperlyConfigured 

from ranged_response import RangedFileResponse 

import random 

import tempfile 

import os 

import subprocess 

import six 

 

try: 

from cStringIO import StringIO 

except ImportError: 

from io import BytesIO as StringIO 

 

from PIL import Image, ImageDraw, ImageFont 

 

try: 

import json 

except ImportError: 

from django.utils import simplejson as json 

 

# Distance of the drawn text from the top of the captcha image 

DISTNACE_FROM_TOP = 4 

 

 

def getsize(font, text): 

30 ↛ 33line 30 didn't jump to line 33, because the condition on line 30 was never false if hasattr(font, 'getoffset'): 

return tuple([x + y for x, y in zip(font.getsize(text), font.getoffset(text))]) 

else: 

return font.getsize(text) 

 

 

def makeimg(size): 

37 ↛ 40line 37 didn't jump to line 40, because the condition on line 37 was never false if settings.CAPTCHA_BACKGROUND_COLOR == "transparent": 

image = Image.new('RGBA', size) 

else: 

image = Image.new('RGB', size, settings.CAPTCHA_BACKGROUND_COLOR) 

return image 

 

 

def captcha_image(request, key, scale=1): 

try: 

store = CaptchaStore.objects.get(hashkey=key) 

except CaptchaStore.DoesNotExist: 

# HTTP 410 Gone status so that crawlers don't index these expired urls. 

return HttpResponse(status=410) 

 

text = store.challenge 

 

if isinstance(settings.CAPTCHA_FONT_PATH, six.string_types): 

fontpath = settings.CAPTCHA_FONT_PATH 

elif isinstance(settings.CAPTCHA_FONT_PATH, (list, tuple)): 

fontpath = random.choice(settings.CAPTCHA_FONT_PATH) 

else: 

raise ImproperlyConfigured('settings.CAPTCHA_FONT_PATH needs to be a path to a font or list of paths to fonts') 

 

60 ↛ 63line 60 didn't jump to line 63, because the condition on line 60 was never false if fontpath.lower().strip().endswith('ttf'): 

font = ImageFont.truetype(fontpath, settings.CAPTCHA_FONT_SIZE * scale) 

else: 

font = ImageFont.load(fontpath) 

 

if settings.CAPTCHA_IMAGE_SIZE: 

size = settings.CAPTCHA_IMAGE_SIZE 

else: 

size = getsize(font, text) 

size = (size[0] * 2, int(size[1] * 1.4)) 

 

image = makeimg(size) 

xpos = 2 

 

charlist = [] 

for char in text: 

if char in settings.CAPTCHA_PUNCTUATION and len(charlist) >= 1: 

charlist[-1] += char 

else: 

charlist.append(char) 

for char in charlist: 

fgimage = Image.new('RGB', size, settings.CAPTCHA_FOREGROUND_COLOR) 

charimage = Image.new('L', getsize(font, ' %s ' % char), '#000000') 

chardraw = ImageDraw.Draw(charimage) 

chardraw.text((0, 0), ' %s ' % char, font=font, fill='#ffffff') 

85 ↛ 87line 85 didn't jump to line 87, because the condition on line 85 was never false if settings.CAPTCHA_LETTER_ROTATION: 

charimage = charimage.rotate(random.randrange(*settings.CAPTCHA_LETTER_ROTATION), expand=0, resample=Image.BICUBIC) 

charimage = charimage.crop(charimage.getbbox()) 

maskimage = Image.new('L', size) 

 

maskimage.paste(charimage, (xpos, DISTNACE_FROM_TOP, xpos + charimage.size[0], DISTNACE_FROM_TOP + charimage.size[1])) 

size = maskimage.size 

image = Image.composite(fgimage, image, maskimage) 

xpos = xpos + 2 + charimage.size[0] 

 

if settings.CAPTCHA_IMAGE_SIZE: 

# centering captcha on the image 

tmpimg = makeimg(size) 

tmpimg.paste(image, (int((size[0] - xpos) / 2), int((size[1] - charimage.size[1]) / 2 - DISTNACE_FROM_TOP))) 

image = tmpimg.crop((0, 0, size[0], size[1])) 

else: 

image = image.crop((0, 0, xpos + 1, size[1])) 

draw = ImageDraw.Draw(image) 

 

for f in settings.noise_functions(): 

draw = f(draw, image) 

for f in settings.filter_functions(): 

image = f(image) 

 

out = StringIO() 

image.save(out, "PNG") 

out.seek(0) 

 

response = HttpResponse(content_type='image/png') 

response.write(out.read()) 

response['Content-length'] = out.tell() 

 

return response 

 

 

def captcha_audio(request, key): 

121 ↛ 136line 121 didn't jump to line 136, because the condition on line 121 was never false if settings.CAPTCHA_FLITE_PATH: 

try: 

store = CaptchaStore.objects.get(hashkey=key) 

except CaptchaStore.DoesNotExist: 

# HTTP 410 Gone status so that crawlers don't index these expired urls. 

return HttpResponse(status=410) 

 

text = store.challenge 

129 ↛ 130line 129 didn't jump to line 130, because the condition on line 129 was never true if 'captcha.helpers.math_challenge' == settings.CAPTCHA_CHALLENGE_FUNCT: 

text = text.replace('*', 'times').replace('-', 'minus') 

else: 

text = ', '.join(list(text)) 

path = str(os.path.join(tempfile.gettempdir(), '%s.wav' % key)) 

subprocess.call([settings.CAPTCHA_FLITE_PATH, "-t", text, "-o", path]) 

# Add arbitrary noise if sox is installed 

136 ↛ 149line 136 didn't jump to line 149, because the condition on line 136 was never false if settings.CAPTCHA_SOX_PATH: 

arbnoisepath = str(os.path.join(tempfile.gettempdir(), '%s_arbitrary.wav') % key) 

mergedpath = str(os.path.join(tempfile.gettempdir(), '%s_merged.wav') % key) 

subprocess.call([settings.CAPTCHA_SOX_PATH, '-r', '8000', '-n', arbnoisepath, 'synth', '4', 'brownnoise']) 

subprocess.call([settings.CAPTCHA_SOX_PATH, '-m', arbnoisepath, path, mergedpath]) 

os.remove(arbnoisepath) 

os.remove(path) 

os.rename(mergedpath, path) 

 

145 ↛ 149line 145 didn't jump to line 149, because the condition on line 145 was never false if os.path.isfile(path): 

response = RangedFileResponse(request, open(path, 'rb'), content_type='audio/wav') 

response['Content-Disposition'] = 'attachment; filename="{}.wav"'.format(key) 

return response 

raise Http404 

 

 

def captcha_refresh(request): 

""" Return json with new captcha for ajax refresh request """ 

154 ↛ 155line 154 didn't jump to line 155, because the condition on line 154 was never true if not request.is_ajax(): 

raise Http404 

 

new_key = CaptchaStore.pick() 

to_json_response = { 

'key': new_key, 

'image_url': captcha_image_url(new_key), 

} 

return HttpResponse(json.dumps(to_json_response), content_type='application/json')