1
14
15 package com.liferay.portal.captcha.simplecaptcha;
16
17 import com.liferay.portal.kernel.captcha.Captcha;
18 import com.liferay.portal.kernel.captcha.CaptchaException;
19 import com.liferay.portal.kernel.captcha.CaptchaMaxChallengesException;
20 import com.liferay.portal.kernel.captcha.CaptchaTextException;
21 import com.liferay.portal.kernel.log.Log;
22 import com.liferay.portal.kernel.log.LogFactoryUtil;
23 import com.liferay.portal.kernel.util.ContentTypes;
24 import com.liferay.portal.kernel.util.InstancePool;
25 import com.liferay.portal.kernel.util.ParamUtil;
26 import com.liferay.portal.kernel.util.Randomizer;
27 import com.liferay.portal.kernel.util.Validator;
28 import com.liferay.portal.util.PortalUtil;
29 import com.liferay.portal.util.PropsValues;
30 import com.liferay.portal.util.WebKeys;
31
32 import java.io.IOException;
33
34 import javax.portlet.PortletRequest;
35 import javax.portlet.PortletResponse;
36 import javax.portlet.PortletSession;
37
38 import javax.servlet.http.HttpServletRequest;
39 import javax.servlet.http.HttpServletResponse;
40 import javax.servlet.http.HttpSession;
41
42 import nl.captcha.backgrounds.BackgroundProducer;
43 import nl.captcha.gimpy.GimpyRenderer;
44 import nl.captcha.noise.NoiseProducer;
45 import nl.captcha.servlet.CaptchaServletUtil;
46 import nl.captcha.text.producer.TextProducer;
47 import nl.captcha.text.renderer.WordRenderer;
48
49
54 public class SimpleCaptchaImpl implements Captcha {
55
56 public SimpleCaptchaImpl() {
57 initBackgroundProducers();
58 initGimpyRenderers();
59 initNoiseProducers();
60 initTextProducers();
61 initWordRenderers();
62 }
63
64 public void check(HttpServletRequest request) throws CaptchaException {
65 if (!isEnabled(request)) {
66 return;
67 }
68
69 HttpSession session = request.getSession();
70
71 String captchaText = (String)session.getAttribute(WebKeys.CAPTCHA_TEXT);
72
73 if (captchaText == null) {
74 _log.error(
75 "Captcha text is null. User " + request.getRemoteUser() +
76 " may be trying to circumvent the captcha.");
77
78 throw new CaptchaTextException();
79 }
80
81 if (!captchaText.equals(ParamUtil.getString(request, "captchaText"))) {
82 if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) &&
83 (Validator.isNotNull(request.getRemoteUser()))) {
84
85 Integer count = (Integer)session.getAttribute(
86 WebKeys.CAPTCHA_COUNT);
87
88 if (count == null) {
89 count = new Integer(1);
90 }
91 else {
92 count = new Integer(count.intValue() + 1);
93 }
94
95 session.setAttribute(WebKeys.CAPTCHA_COUNT, count);
96 }
97
98 throw new CaptchaTextException();
99 }
100
101 if (_log.isDebugEnabled()) {
102 _log.debug("Captcha text is valid");
103 }
104
105 session.removeAttribute(WebKeys.CAPTCHA_TEXT);
106 }
107
108 public void check(PortletRequest portletRequest) throws CaptchaException {
109 if (!isEnabled(portletRequest)) {
110 return;
111 }
112
113 PortletSession portletSession = portletRequest.getPortletSession();
114
115 String captchaText = (String)portletSession.getAttribute(
116 WebKeys.CAPTCHA_TEXT);
117
118 if (captchaText == null) {
119 _log.error(
120 "Captcha text is null. User " + portletRequest.getRemoteUser() +
121 " may be trying to circumvent the captcha.");
122
123 throw new CaptchaTextException();
124 }
125
126 if (!captchaText.equals(
127 ParamUtil.getString(portletRequest, "captchaText"))) {
128
129 if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) &&
130 (Validator.isNotNull(portletRequest.getRemoteUser()))) {
131
132 Integer count = (Integer)portletSession.getAttribute(
133 WebKeys.CAPTCHA_COUNT);
134
135 if (count == null) {
136 count = new Integer(1);
137 }
138 else {
139 count = new Integer(count.intValue() + 1);
140 }
141
142 portletSession.setAttribute(WebKeys.CAPTCHA_COUNT, count);
143 }
144
145 throw new CaptchaTextException();
146 }
147
148 if (_log.isDebugEnabled()) {
149 _log.debug("Captcha text is valid");
150 }
151
152 portletSession.removeAttribute(WebKeys.CAPTCHA_TEXT);
153 }
154
155 public String getTaglibPath() {
156 return _TAGLIB_PATH;
157 }
158
159 public boolean isEnabled(HttpServletRequest request)
160 throws CaptchaException {
161
162 if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) {
163 HttpSession session = request.getSession();
164
165 Integer count = (Integer)session.getAttribute(
166 WebKeys.CAPTCHA_COUNT);
167
168 if (count != null && count >= PropsValues.CAPTCHA_MAX_CHALLENGES) {
169 throw new CaptchaMaxChallengesException();
170 }
171
172 if ((count != null) &&
173 (PropsValues.CAPTCHA_MAX_CHALLENGES <= count.intValue())) {
174
175 return false;
176 }
177 else {
178 return true;
179 }
180 }
181 else if (PropsValues.CAPTCHA_MAX_CHALLENGES < 0) {
182 return false;
183 }
184 else {
185 return true;
186 }
187 }
188
189 public boolean isEnabled(PortletRequest portletRequest)
190 throws CaptchaException {
191
192 if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) {
193 PortletSession portletSession = portletRequest.getPortletSession();
194
195 Integer count = (Integer)portletSession.getAttribute(
196 WebKeys.CAPTCHA_COUNT);
197
198 if (count != null && count >= PropsValues.CAPTCHA_MAX_CHALLENGES) {
199 throw new CaptchaMaxChallengesException();
200 }
201
202 if ((count != null) &&
203 (PropsValues.CAPTCHA_MAX_CHALLENGES <= count.intValue())) {
204
205 return false;
206 }
207 else {
208 return true;
209 }
210 }
211 else if (PropsValues.CAPTCHA_MAX_CHALLENGES < 0) {
212 return false;
213 }
214 else {
215 return true;
216 }
217 }
218
219 public void serveImage(
220 HttpServletRequest request, HttpServletResponse response)
221 throws IOException {
222
223 HttpSession session = request.getSession();
224
225 nl.captcha.Captcha simpleCaptcha = getSimpleCaptcha();
226
227 session.setAttribute(WebKeys.CAPTCHA_TEXT, simpleCaptcha.getAnswer());
228
229 response.setContentType(ContentTypes.IMAGE_JPEG);
230
231 CaptchaServletUtil.writeImage(
232 response.getOutputStream(), simpleCaptcha.getImage());
233 }
234
235 public void serveImage(
236 PortletRequest portletRequest, PortletResponse portletResponse)
237 throws IOException {
238
239 PortletSession portletSession = portletRequest.getPortletSession();
240
241 nl.captcha.Captcha simpleCaptcha = getSimpleCaptcha();
242
243 portletSession.setAttribute(
244 WebKeys.CAPTCHA_TEXT, simpleCaptcha.getAnswer());
245
246 HttpServletResponse response = PortalUtil.getHttpServletResponse(
247 portletResponse);
248
249 CaptchaServletUtil.writeImage(
250 response.getOutputStream(), simpleCaptcha.getImage());
251 }
252
253 protected BackgroundProducer getBackgroundProducer() {
254 if (_backgroundProducers.length == 1) {
255 return _backgroundProducers[0];
256 }
257
258 Randomizer randomizer = Randomizer.getInstance();
259
260 int pos = randomizer.nextInt(_backgroundProducers.length);
261
262 return _backgroundProducers[pos];
263 }
264
265 protected GimpyRenderer getGimpyRenderer() {
266 if (_gimpyRenderers.length == 1) {
267 return _gimpyRenderers[0];
268 }
269
270 Randomizer randomizer = Randomizer.getInstance();
271
272 int pos = randomizer.nextInt(_gimpyRenderers.length);
273
274 return _gimpyRenderers[pos];
275 }
276
277 protected int getHeight() {
278 return PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_HEIGHT;
279 }
280
281 protected NoiseProducer getNoiseProducer() {
282 if (_noiseProducers.length == 1) {
283 return _noiseProducers[0];
284 }
285
286 Randomizer randomizer = Randomizer.getInstance();
287
288 int pos = randomizer.nextInt(_noiseProducers.length);
289
290 return _noiseProducers[pos];
291 }
292
293 protected nl.captcha.Captcha getSimpleCaptcha() {
294 nl.captcha.Captcha.Builder captchaBuilder =
295 new nl.captcha.Captcha.Builder(getWidth(), getHeight());
296
297 captchaBuilder.addText(getTextProducer(), getWordRenderer());
298 captchaBuilder.addBackground(getBackgroundProducer());
299 captchaBuilder.gimp(getGimpyRenderer());
300 captchaBuilder.addNoise(getNoiseProducer());
301 captchaBuilder.addBorder();
302
303 return captchaBuilder.build();
304 }
305
306 protected TextProducer getTextProducer() {
307 if (_textProducers.length == 1) {
308 return _textProducers[0];
309 }
310
311 Randomizer randomizer = Randomizer.getInstance();
312
313 int pos = randomizer.nextInt(_textProducers.length);
314
315 return _textProducers[pos];
316 }
317
318 protected int getWidth() {
319 return PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_WIDTH;
320 }
321
322 protected WordRenderer getWordRenderer() {
323 if (_wordRenderers.length == 1) {
324 return _wordRenderers[0];
325 }
326
327 Randomizer randomizer = Randomizer.getInstance();
328
329 int pos = randomizer.nextInt(_wordRenderers.length);
330
331 return _wordRenderers[pos];
332 }
333
334 protected void initBackgroundProducers() {
335 String[] backgroundProducerClassNames =
336 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_BACKGROUND_PRODUCERS;
337
338 _backgroundProducers = new BackgroundProducer[
339 backgroundProducerClassNames.length];
340
341 for (int i = 0; i < backgroundProducerClassNames.length; i++) {
342 String backgroundProducerClassName =
343 backgroundProducerClassNames[i];
344
345 _backgroundProducers[i] = (BackgroundProducer)InstancePool.get(
346 backgroundProducerClassName);
347 }
348 }
349
350 protected void initGimpyRenderers() {
351 String[] gimpyRendererClassNames =
352 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_GIMPY_RENDERERS;
353
354 _gimpyRenderers = new GimpyRenderer[
355 gimpyRendererClassNames.length];
356
357 for (int i = 0; i < gimpyRendererClassNames.length; i++) {
358 String gimpyRendererClassName =
359 gimpyRendererClassNames[i];
360
361 _gimpyRenderers[i] = (GimpyRenderer)InstancePool.get(
362 gimpyRendererClassName);
363 }
364 }
365
366 protected void initNoiseProducers() {
367 String[] noiseProducerClassNames =
368 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_NOISE_PRODUCERS;
369
370 _noiseProducers = new NoiseProducer[noiseProducerClassNames.length];
371
372 for (int i = 0; i < noiseProducerClassNames.length; i++) {
373 String noiseProducerClassName = noiseProducerClassNames[i];
374
375 _noiseProducers[i] = (NoiseProducer)InstancePool.get(
376 noiseProducerClassName);
377 }
378 }
379
380 protected void initTextProducers() {
381 String[] textProducerClassNames =
382 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_TEXT_PRODUCERS;
383
384 _textProducers = new TextProducer[textProducerClassNames.length];
385
386 for (int i = 0; i < textProducerClassNames.length; i++) {
387 String textProducerClassName = textProducerClassNames[i];
388
389 _textProducers[i] = (TextProducer)InstancePool.get(
390 textProducerClassName);
391 }
392 }
393
394 protected void initWordRenderers() {
395 String[] wordRendererClassNames =
396 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_WORD_RENDERERS;
397
398 _wordRenderers = new WordRenderer[wordRendererClassNames.length];
399
400 for (int i = 0; i < wordRendererClassNames.length; i++) {
401 String wordRendererClassName = wordRendererClassNames[i];
402
403 _wordRenderers[i] = (WordRenderer)InstancePool.get(
404 wordRendererClassName);
405 }
406 }
407
408 private static final String _TAGLIB_PATH =
409 "/html/taglib/ui/captcha/simplecaptcha.jsp";
410
411 private static Log _log = LogFactoryUtil.getLog(SimpleCaptchaImpl.class);
412
413 private BackgroundProducer[] _backgroundProducers;
414 private GimpyRenderer[] _gimpyRenderers;
415 private NoiseProducer[] _noiseProducers;
416 private TextProducer[] _textProducers;
417 private WordRenderer[] _wordRenderers;
418
419 }