1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.captcha;
24  
25  import com.liferay.portal.kernel.configuration.Configuration;
26  import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
27  import com.liferay.portal.kernel.util.ParamUtil;
28  import com.liferay.portal.kernel.util.Validator;
29  import com.liferay.portal.util.PropsFiles;
30  import com.liferay.portal.util.PropsValues;
31  import com.liferay.portal.util.WebKeys;
32  
33  import javax.portlet.PortletRequest;
34  import javax.portlet.PortletSession;
35  
36  import javax.servlet.http.HttpServletRequest;
37  import javax.servlet.http.HttpSession;
38  
39  import nl.captcha.servlet.CaptchaProducer;
40  import nl.captcha.util.Helper;
41  
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  
45  /**
46   * <a href="CaptchaUtil.java.html"><b><i>View Source</i></b></a>
47   *
48   * @author Brian Wing Shun Chan
49   *
50   */
51  public class CaptchaUtil {
52  
53      public static void check(HttpServletRequest request)
54          throws CaptchaTextException {
55  
56          _instance._check(request);
57      }
58  
59      public static void check(PortletRequest portletRequest)
60          throws CaptchaTextException {
61  
62          _instance._check(portletRequest);
63      }
64  
65      public static CaptchaProducer getCaptchaProducer() {
66          return _instance._getCaptchaProducer();
67      }
68  
69      public static boolean isEnabled(HttpServletRequest request) {
70          return _instance._isEnabled(request);
71      }
72  
73      public static boolean isEnabled(PortletRequest portletRequest) {
74          return _instance._isEnabled(portletRequest);
75      }
76  
77      private CaptchaUtil() {
78          _configuration = ConfigurationFactoryUtil.getConfiguration(
79              CaptchaUtil.class.getClassLoader(), PropsFiles.CAPTCHA);
80          _captchaProducer = (CaptchaProducer)Helper.ThingFactory.loadImpl(
81              Helper.ThingFactory.CPROD, _configuration.getProperties());
82      }
83  
84      private void _check(HttpServletRequest request)
85          throws CaptchaTextException {
86  
87          if (!_isEnabled(request)) {
88              return;
89          }
90  
91          HttpSession session = request.getSession();
92  
93          String captchaText = (String)session.getAttribute(WebKeys.CAPTCHA_TEXT);
94  
95          if (captchaText == null) {
96              if (_log.isErrorEnabled()) {
97                  _log.error(
98                      "Captcha text is null. User " + request.getRemoteUser() +
99                          " may be trying to circumvent the captcha.");
100             }
101 
102             throw new CaptchaTextException();
103         }
104 
105         if (!captchaText.equals(ParamUtil.getString(request, "captchaText"))) {
106             throw new CaptchaTextException();
107         }
108 
109         if (_log.isDebugEnabled()) {
110             _log.debug("Captcha text is valid");
111         }
112 
113         session.removeAttribute(WebKeys.CAPTCHA_TEXT);
114 
115         if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) &&
116             (Validator.isNotNull(request.getRemoteUser()))) {
117 
118             Integer count = (Integer)session.getAttribute(
119                 WebKeys.CAPTCHA_COUNT);
120 
121             if (count == null) {
122                 count = new Integer(1);
123             }
124             else {
125                 count = new Integer(count.intValue() + 1);
126             }
127 
128             session.setAttribute(WebKeys.CAPTCHA_COUNT, count);
129         }
130     }
131 
132     private void _check(PortletRequest portletRequest)
133         throws CaptchaTextException {
134 
135         if (!_isEnabled(portletRequest)) {
136             return;
137         }
138 
139         PortletSession portletSession = portletRequest.getPortletSession();
140 
141         String captchaText = (String)portletSession.getAttribute(
142             WebKeys.CAPTCHA_TEXT);
143 
144         if (captchaText == null) {
145             if (_log.isErrorEnabled()) {
146                 _log.error(
147                     "Captcha text is null. User " +
148                         portletRequest.getRemoteUser() +
149                             " may be trying to circumvent the captcha.");
150             }
151 
152             throw new CaptchaTextException();
153         }
154 
155         if (!captchaText.equals(
156                 ParamUtil.getString(portletRequest, "captchaText"))) {
157 
158             throw new CaptchaTextException();
159         }
160 
161         if (_log.isDebugEnabled()) {
162             _log.debug("Captcha text is valid");
163         }
164 
165         portletSession.removeAttribute(WebKeys.CAPTCHA_TEXT);
166 
167         if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) &&
168             (Validator.isNotNull(portletRequest.getRemoteUser()))) {
169 
170             Integer count = (Integer)portletSession.getAttribute(
171                 WebKeys.CAPTCHA_COUNT);
172 
173             if (count == null) {
174                 count = new Integer(1);
175             }
176             else {
177                 count = new Integer(count.intValue() + 1);
178             }
179 
180             portletSession.setAttribute(WebKeys.CAPTCHA_COUNT, count);
181         }
182     }
183 
184     private CaptchaProducer _getCaptchaProducer() {
185         return _captchaProducer;
186     }
187 
188     private boolean _isEnabled(HttpServletRequest request) {
189         if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) {
190             HttpSession session = request.getSession();
191 
192             Integer count = (Integer)session.getAttribute(
193                 WebKeys.CAPTCHA_COUNT);
194 
195             if ((count != null) &&
196                 (PropsValues.CAPTCHA_MAX_CHALLENGES <= count.intValue())) {
197 
198                 return false;
199             }
200             else {
201                 return true;
202             }
203         }
204         else if (PropsValues.CAPTCHA_MAX_CHALLENGES < 0) {
205             return false;
206         }
207         else {
208             return true;
209         }
210     }
211 
212     private boolean _isEnabled(PortletRequest portletRequest) {
213         if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) {
214             PortletSession portletSession = portletRequest.getPortletSession();
215 
216             Integer count = (Integer)portletSession.getAttribute(
217                 WebKeys.CAPTCHA_COUNT);
218 
219             if ((count != null) &&
220                 (PropsValues.CAPTCHA_MAX_CHALLENGES <= count.intValue())) {
221 
222                 return false;
223             }
224             else {
225                 return true;
226             }
227         }
228         else if (PropsValues.CAPTCHA_MAX_CHALLENGES < 0) {
229             return false;
230         }
231         else {
232             return true;
233         }
234     }
235 
236     private static Log _log = LogFactory.getLog(CaptchaUtil.class);
237 
238     private static CaptchaUtil _instance = new CaptchaUtil();
239 
240     private Configuration _configuration;
241     private CaptchaProducer _captchaProducer;
242 
243 }