001
014
015 package com.liferay.portal.captcha.simplecaptcha;
016
017 import com.liferay.portal.kernel.captcha.Captcha;
018 import com.liferay.portal.kernel.captcha.CaptchaException;
019 import com.liferay.portal.kernel.captcha.CaptchaMaxChallengesException;
020 import com.liferay.portal.kernel.captcha.CaptchaTextException;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.util.ContentTypes;
024 import com.liferay.portal.kernel.util.InstancePool;
025 import com.liferay.portal.kernel.util.ParamUtil;
026 import com.liferay.portal.kernel.util.Randomizer;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.util.PortalUtil;
029 import com.liferay.portal.util.PropsValues;
030 import com.liferay.portal.util.WebKeys;
031
032 import java.io.IOException;
033
034 import javax.portlet.PortletRequest;
035 import javax.portlet.PortletResponse;
036 import javax.portlet.PortletSession;
037
038 import javax.servlet.http.HttpServletRequest;
039 import javax.servlet.http.HttpServletResponse;
040 import javax.servlet.http.HttpSession;
041
042 import nl.captcha.backgrounds.BackgroundProducer;
043 import nl.captcha.gimpy.GimpyRenderer;
044 import nl.captcha.noise.NoiseProducer;
045 import nl.captcha.servlet.CaptchaServletUtil;
046 import nl.captcha.text.producer.TextProducer;
047 import nl.captcha.text.renderer.WordRenderer;
048
049
052 public class SimpleCaptchaImpl implements Captcha {
053
054 public SimpleCaptchaImpl() {
055 initBackgroundProducers();
056 initGimpyRenderers();
057 initNoiseProducers();
058 initTextProducers();
059 initWordRenderers();
060 }
061
062 public void check(HttpServletRequest request) throws CaptchaException {
063 if (!isEnabled(request)) {
064 return;
065 }
066
067 HttpSession session = request.getSession();
068
069 String captchaText = (String)session.getAttribute(WebKeys.CAPTCHA_TEXT);
070
071 if (captchaText == null) {
072 _log.error(
073 "Captcha text is null. User " + request.getRemoteUser() +
074 " may be trying to circumvent the captcha.");
075
076 throw new CaptchaTextException();
077 }
078
079 if (!captchaText.equals(ParamUtil.getString(request, "captchaText"))) {
080 if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) &&
081 (Validator.isNotNull(request.getRemoteUser()))) {
082
083 Integer count = (Integer)session.getAttribute(
084 WebKeys.CAPTCHA_COUNT);
085
086 if (count == null) {
087 count = new Integer(1);
088 }
089 else {
090 count = new Integer(count.intValue() + 1);
091 }
092
093 session.setAttribute(WebKeys.CAPTCHA_COUNT, count);
094 }
095
096 throw new CaptchaTextException();
097 }
098
099 if (_log.isDebugEnabled()) {
100 _log.debug("Captcha text is valid");
101 }
102
103 session.removeAttribute(WebKeys.CAPTCHA_TEXT);
104 }
105
106 public void check(PortletRequest portletRequest) throws CaptchaException {
107 if (!isEnabled(portletRequest)) {
108 return;
109 }
110
111 PortletSession portletSession = portletRequest.getPortletSession();
112
113 String captchaText = (String)portletSession.getAttribute(
114 WebKeys.CAPTCHA_TEXT);
115
116 if (captchaText == null) {
117 _log.error(
118 "Captcha text is null. User " + portletRequest.getRemoteUser() +
119 " may be trying to circumvent the captcha.");
120
121 throw new CaptchaTextException();
122 }
123
124 if (!captchaText.equals(
125 ParamUtil.getString(portletRequest, "captchaText"))) {
126
127 if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) &&
128 (Validator.isNotNull(portletRequest.getRemoteUser()))) {
129
130 Integer count = (Integer)portletSession.getAttribute(
131 WebKeys.CAPTCHA_COUNT);
132
133 if (count == null) {
134 count = new Integer(1);
135 }
136 else {
137 count = new Integer(count.intValue() + 1);
138 }
139
140 portletSession.setAttribute(WebKeys.CAPTCHA_COUNT, count);
141 }
142
143 throw new CaptchaTextException();
144 }
145
146 if (_log.isDebugEnabled()) {
147 _log.debug("Captcha text is valid");
148 }
149
150 portletSession.removeAttribute(WebKeys.CAPTCHA_TEXT);
151 }
152
153 public String getTaglibPath() {
154 return _TAGLIB_PATH;
155 }
156
157 public boolean isEnabled(HttpServletRequest request)
158 throws CaptchaException {
159
160 if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) {
161 HttpSession session = request.getSession();
162
163 Integer count = (Integer)session.getAttribute(
164 WebKeys.CAPTCHA_COUNT);
165
166 if (count != null && count >= PropsValues.CAPTCHA_MAX_CHALLENGES) {
167 throw new CaptchaMaxChallengesException();
168 }
169
170 if ((count != null) &&
171 (PropsValues.CAPTCHA_MAX_CHALLENGES <= count.intValue())) {
172
173 return false;
174 }
175 else {
176 return true;
177 }
178 }
179 else if (PropsValues.CAPTCHA_MAX_CHALLENGES < 0) {
180 return false;
181 }
182 else {
183 return true;
184 }
185 }
186
187 public boolean isEnabled(PortletRequest portletRequest)
188 throws CaptchaException {
189
190 if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) {
191 PortletSession portletSession = portletRequest.getPortletSession();
192
193 Integer count = (Integer)portletSession.getAttribute(
194 WebKeys.CAPTCHA_COUNT);
195
196 if (count != null && count >= PropsValues.CAPTCHA_MAX_CHALLENGES) {
197 throw new CaptchaMaxChallengesException();
198 }
199
200 if ((count != null) &&
201 (PropsValues.CAPTCHA_MAX_CHALLENGES <= count.intValue())) {
202
203 return false;
204 }
205 else {
206 return true;
207 }
208 }
209 else if (PropsValues.CAPTCHA_MAX_CHALLENGES < 0) {
210 return false;
211 }
212 else {
213 return true;
214 }
215 }
216
217 public void serveImage(
218 HttpServletRequest request, HttpServletResponse response)
219 throws IOException {
220
221 HttpSession session = request.getSession();
222
223 nl.captcha.Captcha simpleCaptcha = getSimpleCaptcha();
224
225 session.setAttribute(WebKeys.CAPTCHA_TEXT, simpleCaptcha.getAnswer());
226
227 response.setContentType(ContentTypes.IMAGE_JPEG);
228
229 CaptchaServletUtil.writeImage(
230 response.getOutputStream(), simpleCaptcha.getImage());
231 }
232
233 public void serveImage(
234 PortletRequest portletRequest, PortletResponse portletResponse)
235 throws IOException {
236
237 PortletSession portletSession = portletRequest.getPortletSession();
238
239 nl.captcha.Captcha simpleCaptcha = getSimpleCaptcha();
240
241 portletSession.setAttribute(
242 WebKeys.CAPTCHA_TEXT, simpleCaptcha.getAnswer());
243
244 HttpServletResponse response = PortalUtil.getHttpServletResponse(
245 portletResponse);
246
247 CaptchaServletUtil.writeImage(
248 response.getOutputStream(), simpleCaptcha.getImage());
249 }
250
251 protected BackgroundProducer getBackgroundProducer() {
252 if (_backgroundProducers.length == 1) {
253 return _backgroundProducers[0];
254 }
255
256 Randomizer randomizer = Randomizer.getInstance();
257
258 int pos = randomizer.nextInt(_backgroundProducers.length);
259
260 return _backgroundProducers[pos];
261 }
262
263 protected GimpyRenderer getGimpyRenderer() {
264 if (_gimpyRenderers.length == 1) {
265 return _gimpyRenderers[0];
266 }
267
268 Randomizer randomizer = Randomizer.getInstance();
269
270 int pos = randomizer.nextInt(_gimpyRenderers.length);
271
272 return _gimpyRenderers[pos];
273 }
274
275 protected int getHeight() {
276 return PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_HEIGHT;
277 }
278
279 protected NoiseProducer getNoiseProducer() {
280 if (_noiseProducers.length == 1) {
281 return _noiseProducers[0];
282 }
283
284 Randomizer randomizer = Randomizer.getInstance();
285
286 int pos = randomizer.nextInt(_noiseProducers.length);
287
288 return _noiseProducers[pos];
289 }
290
291 protected nl.captcha.Captcha getSimpleCaptcha() {
292 nl.captcha.Captcha.Builder captchaBuilder =
293 new nl.captcha.Captcha.Builder(getWidth(), getHeight());
294
295 captchaBuilder.addText(getTextProducer(), getWordRenderer());
296 captchaBuilder.addBackground(getBackgroundProducer());
297 captchaBuilder.gimp(getGimpyRenderer());
298 captchaBuilder.addNoise(getNoiseProducer());
299 captchaBuilder.addBorder();
300
301 return captchaBuilder.build();
302 }
303
304 protected TextProducer getTextProducer() {
305 if (_textProducers.length == 1) {
306 return _textProducers[0];
307 }
308
309 Randomizer randomizer = Randomizer.getInstance();
310
311 int pos = randomizer.nextInt(_textProducers.length);
312
313 return _textProducers[pos];
314 }
315
316 protected int getWidth() {
317 return PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_WIDTH;
318 }
319
320 protected WordRenderer getWordRenderer() {
321 if (_wordRenderers.length == 1) {
322 return _wordRenderers[0];
323 }
324
325 Randomizer randomizer = Randomizer.getInstance();
326
327 int pos = randomizer.nextInt(_wordRenderers.length);
328
329 return _wordRenderers[pos];
330 }
331
332 protected void initBackgroundProducers() {
333 String[] backgroundProducerClassNames =
334 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_BACKGROUND_PRODUCERS;
335
336 _backgroundProducers = new BackgroundProducer[
337 backgroundProducerClassNames.length];
338
339 for (int i = 0; i < backgroundProducerClassNames.length; i++) {
340 String backgroundProducerClassName =
341 backgroundProducerClassNames[i];
342
343 _backgroundProducers[i] = (BackgroundProducer)InstancePool.get(
344 backgroundProducerClassName);
345 }
346 }
347
348 protected void initGimpyRenderers() {
349 String[] gimpyRendererClassNames =
350 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_GIMPY_RENDERERS;
351
352 _gimpyRenderers = new GimpyRenderer[
353 gimpyRendererClassNames.length];
354
355 for (int i = 0; i < gimpyRendererClassNames.length; i++) {
356 String gimpyRendererClassName =
357 gimpyRendererClassNames[i];
358
359 _gimpyRenderers[i] = (GimpyRenderer)InstancePool.get(
360 gimpyRendererClassName);
361 }
362 }
363
364 protected void initNoiseProducers() {
365 String[] noiseProducerClassNames =
366 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_NOISE_PRODUCERS;
367
368 _noiseProducers = new NoiseProducer[noiseProducerClassNames.length];
369
370 for (int i = 0; i < noiseProducerClassNames.length; i++) {
371 String noiseProducerClassName = noiseProducerClassNames[i];
372
373 _noiseProducers[i] = (NoiseProducer)InstancePool.get(
374 noiseProducerClassName);
375 }
376 }
377
378 protected void initTextProducers() {
379 String[] textProducerClassNames =
380 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_TEXT_PRODUCERS;
381
382 _textProducers = new TextProducer[textProducerClassNames.length];
383
384 for (int i = 0; i < textProducerClassNames.length; i++) {
385 String textProducerClassName = textProducerClassNames[i];
386
387 _textProducers[i] = (TextProducer)InstancePool.get(
388 textProducerClassName);
389 }
390 }
391
392 protected void initWordRenderers() {
393 String[] wordRendererClassNames =
394 PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_WORD_RENDERERS;
395
396 _wordRenderers = new WordRenderer[wordRendererClassNames.length];
397
398 for (int i = 0; i < wordRendererClassNames.length; i++) {
399 String wordRendererClassName = wordRendererClassNames[i];
400
401 _wordRenderers[i] = (WordRenderer)InstancePool.get(
402 wordRendererClassName);
403 }
404 }
405
406 private static final String _TAGLIB_PATH =
407 "/html/taglib/ui/captcha/simplecaptcha.jsp";
408
409 private static Log _log = LogFactoryUtil.getLog(SimpleCaptchaImpl.class);
410
411 private BackgroundProducer[] _backgroundProducers;
412 private GimpyRenderer[] _gimpyRenderers;
413 private NoiseProducer[] _noiseProducers;
414 private TextProducer[] _textProducers;
415 private WordRenderer[] _wordRenderers;
416
417 }