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

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

from captcha.conf import settings 

from captcha.models import CaptchaStore 

import django 

from django.core.exceptions import ImproperlyConfigured 

5 ↛ 6line 5 didn't jump to line 6, because the condition on line 5 was never trueif django.VERSION < (1, 10): # NOQA 

from django.core.urlresolvers import reverse, NoReverseMatch # NOQA 

else: # NOQA 

from django.urls import reverse, NoReverseMatch # NOQA 

from django.forms import ValidationError 

from django.forms.fields import CharField, MultiValueField 

from django.forms.widgets import TextInput, MultiWidget, HiddenInput 

from django.utils.translation import ugettext_lazy 

from django.utils import timezone 

from django.template.loader import render_to_string 

from django.utils.safestring import mark_safe 

from six import u 

 

 

class BaseCaptchaTextInput(MultiWidget): 

""" 

Base class for Captcha widgets 

""" 

def __init__(self, attrs=None): 

widgets = ( 

HiddenInput(attrs), 

TextInput(attrs), 

) 

super(BaseCaptchaTextInput, self).__init__(widgets, attrs) 

 

def decompress(self, value): 

if value: 

return value.split(',') 

return [None, None] 

 

def fetch_captcha_store(self, name, value, attrs=None, generator=None): 

""" 

Fetches a new CaptchaStore 

This has to be called inside render 

""" 

try: 

reverse('captcha-image', args=('dummy',)) 

except NoReverseMatch: 

raise ImproperlyConfigured('Make sure you\'ve included captcha.urls as explained in the INSTALLATION section on http://readthedocs.org/docs/django-simple-captcha/en/latest/usage.html#installation') 

 

45 ↛ 46line 45 didn't jump to line 46, because the condition on line 45 was never true if settings.CAPTCHA_GET_FROM_POOL: 

key = CaptchaStore.pick() 

else: 

key = CaptchaStore.generate_key(generator) 

 

# these can be used by format_output and render 

self._value = [key, u('')] 

self._key = key 

self.id_ = self.build_attrs(attrs).get('id', None) 

 

def id_for_label(self, id_): 

56 ↛ 58line 56 didn't jump to line 58, because the condition on line 56 was never false if id_: 

return id_ + '_1' 

return id_ 

 

def image_url(self): 

return reverse('captcha-image', kwargs={'key': self._key}) 

 

def audio_url(self): 

return reverse('captcha-audio', kwargs={'key': self._key}) if settings.CAPTCHA_FLITE_PATH else None 

 

def refresh_url(self): 

return reverse('captcha-refresh') 

 

 

class CaptchaTextInput(BaseCaptchaTextInput): 

def __init__(self, attrs=None, **kwargs): 

self._args = kwargs 

self._args['output_format'] = self._args.get('output_format') or settings.CAPTCHA_OUTPUT_FORMAT 

self._args['field_template'] = self._args.get('field_template') or settings.CAPTCHA_FIELD_TEMPLATE 

# self._args['id_prefix'] = self._args.get('id_prefix') 

 

77 ↛ 78line 77 didn't jump to line 78, because the condition on line 77 was never true if self._args['output_format'] is None and self._args['field_template'] is None: 

raise ImproperlyConfigured('You MUST define either CAPTCHA_FIELD_TEMPLATE or CAPTCHA_OUTPUT_FORMAT setting. Please refer to http://readthedocs.org/docs/django-simple-captcha/en/latest/usage.html#installation') 

 

if self._args['output_format']: 

for key in ('image', 'hidden_field', 'text_field'): 

if '%%(%s)s' % key not in self._args['output_format']: 

raise ImproperlyConfigured('All of %s must be present in your CAPTCHA_OUTPUT_FORMAT setting. Could not find %s' % ( 

', '.join(['%%(%s)s' % k for k in ('image', 'hidden_field', 'text_field')]), 

'%%(%s)s' % key 

)) 

 

super(CaptchaTextInput, self).__init__(attrs) 

 

def build_attrs(self, *args, **kwargs): 

ret = super(CaptchaTextInput, self).build_attrs(*args, **kwargs) 

if self._args.get('id_prefix') and 'id' in ret: 

ret['id'] = '%s_%s' % (self._args.get('id_prefix'), ret['id']) 

return ret 

 

def id_for_label(self, id_): 

ret = super(CaptchaTextInput, self).id_for_label(id_) 

if self._args.get('id_prefix') and 'id' in ret: 

ret = '%s_%s' % (self._args.get('id_prefix'), ret) 

return ret 

 

def format_output(self, rendered_widgets): 

# hidden_field, text_field = rendered_widgets 

if self._args['output_format']: 

ret = self._args['output_format'] % { 

'image': self.image_and_audio, 

'hidden_field': self.hidden_field, 

'text_field': self.text_field 

} 

return ret 

 

112 ↛ exitline 112 didn't return from function 'format_output', because the condition on line 112 was never false elif self._args['field_template']: 

context = { 

'image': mark_safe(self.image_and_audio), 

'hidden_field': mark_safe(self.hidden_field), 

'text_field': mark_safe(self.text_field) 

} 

return render_to_string(settings.CAPTCHA_FIELD_TEMPLATE, context) 

 

def render(self, name, value, attrs=None, renderer=None): 

self.fetch_captcha_store(name, value, attrs, self._args.get('generator')) 

 

context = { 

'image': self.image_url(), 

'name': name, 

'key': self._key, 

'id': u'%s_%s' % (self._args.get('id_prefix'), attrs.get('id')) if self._args.get('id_prefix') else attrs.get('id') 

} 

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

context.update({'audio': self.audio_url()}) 

 

self.image_and_audio = render_to_string(settings.CAPTCHA_IMAGE_TEMPLATE, context) 

self.hidden_field = render_to_string(settings.CAPTCHA_HIDDEN_FIELD_TEMPLATE, context) 

self.text_field = render_to_string(settings.CAPTCHA_TEXT_FIELD_TEMPLATE, context) 

 

extra_kwargs = {} 

137 ↛ 141line 137 didn't jump to line 141, because the condition on line 137 was never false if django.VERSION >= (1, 11): 

# https://docs.djangoproject.com/en/1.11/ref/forms/widgets/#django.forms.Widget.render 

extra_kwargs['renderer'] = renderer 

 

return super(CaptchaTextInput, self).render(name, self._value, attrs=attrs, **extra_kwargs) 

 

def _render(self, template_name, context, renderer=None): 

return self.format_output(None) 

 

 

class CaptchaField(MultiValueField): 

def __init__(self, *args, **kwargs): 

fields = ( 

CharField(show_hidden_initial=True), 

CharField(), 

) 

if 'error_messages' not in kwargs or 'invalid' not in kwargs.get('error_messages'): 

154 ↛ 156line 154 didn't jump to line 156, because the condition on line 154 was never false if 'error_messages' not in kwargs: 

kwargs['error_messages'] = {} 

kwargs['error_messages'].update({'invalid': ugettext_lazy('Invalid CAPTCHA')}) 

 

kwargs['widget'] = kwargs.pop('widget', CaptchaTextInput( 

output_format=kwargs.pop('output_format', None), 

id_prefix=kwargs.pop('id_prefix', None), 

generator=kwargs.pop('generator', None) 

)) 

 

super(CaptchaField, self).__init__(fields, *args, **kwargs) 

 

def compress(self, data_list): 

if data_list: 

return ','.join(data_list) 

return None 

 

def clean(self, value): 

super(CaptchaField, self).clean(value) 

response, value[1] = (value[1] or '').strip().lower(), '' 

174 ↛ 176line 174 didn't jump to line 176, because the condition on line 174 was never false if not settings.CAPTCHA_GET_FROM_POOL: 

CaptchaStore.remove_expired() 

if settings.CAPTCHA_TEST_MODE and response.lower() == 'passed': 

# automatically pass the test 

try: 

# try to delete the captcha based on its hash 

CaptchaStore.objects.get(hashkey=value[0]).delete() 

except CaptchaStore.DoesNotExist: 

# ignore errors 

pass 

elif not self.required and not response: 

pass 

else: 

try: 

CaptchaStore.objects.get(response=response, hashkey=value[0], expiration__gt=timezone.now()).delete() 

except CaptchaStore.DoesNotExist: 

raise ValidationError(getattr(self, 'error_messages', {}).get('invalid', ugettext_lazy('Invalid CAPTCHA'))) 

return value