/** * * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved. * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * Copyright (c) 2009-2014 Câmara dos Deputados. Todos os direitos reservados. * * e-Democracia é um software livre; você pode redistribuí-lo e/ou modificá-lo dentro * dos termos da Licença Pública Geral Menor GNU como publicada pela Fundação do * Software Livre (FSF); na versão 2.1 da Licença, ou (na sua opinião) qualquer versão. * * Este programa é distribuído na esperança de que possa ser útil, mas SEM NENHUMA GARANTIA; * sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. * Veja a Licença Pública Geral Menor GNU para maiores detalhes. * */ package com.liferay.portal.captcha.simplecaptcha; import java.io.IOException; import javax.portlet.PortletRequest; import javax.portlet.PortletSession; import javax.portlet.ResourceRequest; import javax.portlet.ResourceResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import nl.captcha.backgrounds.BackgroundProducer; import nl.captcha.gimpy.GimpyRenderer; import nl.captcha.noise.NoiseProducer; import nl.captcha.servlet.CaptchaServletUtil; import nl.captcha.text.producer.TextProducer; import nl.captcha.text.renderer.WordRenderer; import com.liferay.portal.kernel.captcha.Captcha; import com.liferay.portal.kernel.captcha.CaptchaException; import com.liferay.portal.kernel.captcha.CaptchaMaxChallengesException; import com.liferay.portal.kernel.captcha.CaptchaTextException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.util.InstancePool; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.Randomizer; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.util.PropsValues; import com.liferay.portal.util.WebKeys; /** * @author Brian Wing Shun Chan * @author Daniel Sanz */ public class SimpleCaptchaImpl implements Captcha { public SimpleCaptchaImpl() { initBackgroundProducers(); initGimpyRenderers(); initNoiseProducers(); initTextProducers(); initWordRenderers(); } public void check(HttpServletRequest request) throws CaptchaException { if (!isEnabled(request)) { return; } if (!validateChallenge(request)) { incrementCounter(request); checkMaxChallenges(request); throw new CaptchaTextException(); } if (_log.isDebugEnabled()) { _log.debug("Captcha text is valid"); } } public void check(PortletRequest portletRequest) throws CaptchaException { if (!isEnabled(portletRequest)) { return; } if (!validateChallenge(portletRequest)) { incrementCounter(portletRequest); checkMaxChallenges(portletRequest); throw new CaptchaTextException(); } if (_log.isDebugEnabled()) { _log.debug("Captcha text is valid"); } } public String getTaglibPath() { return _TAGLIB_PATH; } public boolean isEnabled(HttpServletRequest request) throws CaptchaException { checkMaxChallenges(request); if (PropsValues.CAPTCHA_MAX_CHALLENGES >= 0) { return true; } else { return false; } } public boolean isEnabled(PortletRequest portletRequest) throws CaptchaException { checkMaxChallenges(portletRequest); if (PropsValues.CAPTCHA_MAX_CHALLENGES >= 0) { return true; } else { return false; } } public void serveImage( HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession session = request.getSession(); nl.captcha.Captcha simpleCaptcha = getSimpleCaptcha(); session.setAttribute(WebKeys.CAPTCHA_TEXT, simpleCaptcha.getAnswer()); response.setContentType("image/png"); CaptchaServletUtil.writeImage( response.getOutputStream(), simpleCaptcha.getImage()); } public void serveImage( ResourceRequest resourceRequest, ResourceResponse resourceResponse) throws IOException { PortletSession portletSession = resourceRequest.getPortletSession(); nl.captcha.Captcha simpleCaptcha = getSimpleCaptcha(); portletSession.setAttribute( WebKeys.CAPTCHA_TEXT, simpleCaptcha.getAnswer()); resourceResponse.setContentType("image/png"); CaptchaServletUtil.writeImage( resourceResponse.getPortletOutputStream(), simpleCaptcha.getImage()); } protected void checkMaxChallenges(HttpServletRequest request) throws CaptchaMaxChallengesException { if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) { HttpSession session = request.getSession(); Integer count = (Integer)session.getAttribute( WebKeys.CAPTCHA_COUNT); checkMaxChallenges(count); } } protected void checkMaxChallenges(Integer count) throws CaptchaMaxChallengesException { if ((count != null) && (count > PropsValues.CAPTCHA_MAX_CHALLENGES)) { throw new CaptchaMaxChallengesException(); } } protected void checkMaxChallenges(PortletRequest portletRequest) throws CaptchaMaxChallengesException { if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) { PortletSession portletSession = portletRequest.getPortletSession(); Integer count = (Integer)portletSession.getAttribute( WebKeys.CAPTCHA_COUNT); checkMaxChallenges(count); } } protected BackgroundProducer getBackgroundProducer() { if (_backgroundProducers.length == 1) { return _backgroundProducers[0]; } Randomizer randomizer = Randomizer.getInstance(); int pos = randomizer.nextInt(_backgroundProducers.length); return _backgroundProducers[pos]; } protected GimpyRenderer getGimpyRenderer() { if (_gimpyRenderers.length == 1) { return _gimpyRenderers[0]; } Randomizer randomizer = Randomizer.getInstance(); int pos = randomizer.nextInt(_gimpyRenderers.length); return _gimpyRenderers[pos]; } protected int getHeight() { return PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_HEIGHT; } protected NoiseProducer getNoiseProducer() { if (_noiseProducers.length == 1) { return _noiseProducers[0]; } Randomizer randomizer = Randomizer.getInstance(); int pos = randomizer.nextInt(_noiseProducers.length); return _noiseProducers[pos]; } protected nl.captcha.Captcha getSimpleCaptcha() { nl.captcha.Captcha.Builder captchaBuilder = new nl.captcha.Captcha.Builder(getWidth(), getHeight()); captchaBuilder.addText(getTextProducer(), getWordRenderer()); captchaBuilder.addBackground(getBackgroundProducer()); captchaBuilder.gimp(getGimpyRenderer()); captchaBuilder.addNoise(getNoiseProducer()); captchaBuilder.addBorder(); return captchaBuilder.build(); } protected TextProducer getTextProducer() { if (_textProducers.length == 1) { return _textProducers[0]; } Randomizer randomizer = Randomizer.getInstance(); int pos = randomizer.nextInt(_textProducers.length); return _textProducers[pos]; } protected int getWidth() { return PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_WIDTH; } protected WordRenderer getWordRenderer() { if (_wordRenderers.length == 1) { return _wordRenderers[0]; } Randomizer randomizer = Randomizer.getInstance(); int pos = randomizer.nextInt(_wordRenderers.length); return _wordRenderers[pos]; } protected void incrementCounter(HttpServletRequest request) { if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) && Validator.isNotNull(request.getRemoteUser())) { HttpSession session = request.getSession(); Integer count = (Integer)session.getAttribute( WebKeys.CAPTCHA_COUNT); session.setAttribute( WebKeys.CAPTCHA_COUNT, incrementCounter(count)); } } protected Integer incrementCounter(Integer count) { if (count == null) { count = new Integer(1); } else { count = new Integer(count.intValue() + 1); } return count; } protected void incrementCounter(PortletRequest portletRequest) { if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) && Validator.isNotNull(portletRequest.getRemoteUser())) { PortletSession portletSession = portletRequest.getPortletSession(); Integer count = (Integer)portletSession.getAttribute( WebKeys.CAPTCHA_COUNT); portletSession.setAttribute( WebKeys.CAPTCHA_COUNT, incrementCounter(count)); } } protected void initBackgroundProducers() { String[] backgroundProducerClassNames = PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_BACKGROUND_PRODUCERS; _backgroundProducers = new BackgroundProducer[ backgroundProducerClassNames.length]; for (int i = 0; i < backgroundProducerClassNames.length; i++) { String backgroundProducerClassName = backgroundProducerClassNames[i]; _backgroundProducers[i] = (BackgroundProducer)InstancePool.get( backgroundProducerClassName); } } protected void initGimpyRenderers() { String[] gimpyRendererClassNames = PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_GIMPY_RENDERERS; _gimpyRenderers = new GimpyRenderer[ gimpyRendererClassNames.length]; for (int i = 0; i < gimpyRendererClassNames.length; i++) { String gimpyRendererClassName = gimpyRendererClassNames[i]; _gimpyRenderers[i] = (GimpyRenderer)InstancePool.get( gimpyRendererClassName); } } protected void initNoiseProducers() { String[] noiseProducerClassNames = PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_NOISE_PRODUCERS; _noiseProducers = new NoiseProducer[noiseProducerClassNames.length]; for (int i = 0; i < noiseProducerClassNames.length; i++) { String noiseProducerClassName = noiseProducerClassNames[i]; _noiseProducers[i] = (NoiseProducer)InstancePool.get( noiseProducerClassName); } } protected void initTextProducers() { String[] textProducerClassNames = PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_TEXT_PRODUCERS; _textProducers = new TextProducer[textProducerClassNames.length]; for (int i = 0; i < textProducerClassNames.length; i++) { String textProducerClassName = textProducerClassNames[i]; _textProducers[i] = (TextProducer)InstancePool.get( textProducerClassName); } } protected void initWordRenderers() { String[] wordRendererClassNames = PropsValues.CAPTCHA_ENGINE_SIMPLECAPTCHA_WORD_RENDERERS; _wordRenderers = new WordRenderer[wordRendererClassNames.length]; for (int i = 0; i < wordRendererClassNames.length; i++) { String wordRendererClassName = wordRendererClassNames[i]; _wordRenderers[i] = (WordRenderer)InstancePool.get( wordRendererClassName); } } protected boolean validateChallenge(HttpServletRequest request) throws CaptchaException { HttpSession session = request.getSession(); String captchaText = (String)session.getAttribute(WebKeys.CAPTCHA_TEXT); if (captchaText == null) { _log.error( "Captcha text is null. User " + request.getRemoteUser() + " may be trying to circumvent the captcha."); throw new CaptchaTextException(); } boolean valid = captchaText.equals( ParamUtil.getString(request, "captchaText")); if (valid) { session.removeAttribute(WebKeys.CAPTCHA_TEXT); } return valid; } protected boolean validateChallenge(PortletRequest portletRequest) throws CaptchaException { PortletSession portletSession = portletRequest.getPortletSession(); String captchaText = (String)portletSession.getAttribute( WebKeys.CAPTCHA_TEXT); if (captchaText == null) { _log.error( "Captcha text is null. User " + portletRequest.getRemoteUser() + " may be trying to circumvent the captcha."); throw new CaptchaTextException(); } boolean valid = captchaText.equals( ParamUtil.getString(portletRequest, "captchaText")); if (valid) { portletSession.removeAttribute(WebKeys.CAPTCHA_TEXT); } return valid; } private static final String _TAGLIB_PATH = "/html/taglib/ui/captcha/simplecaptcha.jsp"; private static Log _log = LogFactoryUtil.getLog(SimpleCaptchaImpl.class); private BackgroundProducer[] _backgroundProducers; private GimpyRenderer[] _gimpyRenderers; private NoiseProducer[] _noiseProducers; private TextProducer[] _textProducers; private WordRenderer[] _wordRenderers; }