1   /**
2    * Copyright (c) 2000-2009 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.captcha.Captcha;
26  import com.liferay.portal.kernel.captcha.CaptchaTextException;
27  import com.liferay.portal.kernel.configuration.Configuration;
28  import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
31  import com.liferay.portal.kernel.util.ParamUtil;
32  import com.liferay.portal.kernel.util.Validator;
33  import com.liferay.portal.util.PortalUtil;
34  import com.liferay.portal.util.PropsFiles;
35  import com.liferay.portal.util.PropsValues;
36  import com.liferay.portal.util.WebKeys;
37  
38  import java.io.IOException;
39  
40  import javax.portlet.PortletRequest;
41  import javax.portlet.PortletResponse;
42  import javax.portlet.PortletSession;
43  
44  import javax.servlet.http.HttpServletRequest;
45  import javax.servlet.http.HttpServletResponse;
46  import javax.servlet.http.HttpSession;
47  
48  import nl.captcha.servlet.CaptchaProducer;
49  import nl.captcha.util.Helper;
50  
51  /**
52   * <a href="CaptchaImpl.java.html"><b><i>View Source</i></b></a>
53   *
54   * @author Brian Wing Shun Chan
55   *
56   */
57  public class CaptchaImpl implements Captcha {
58  
59      private CaptchaImpl() {
60          _configuration = ConfigurationFactoryUtil.getConfiguration(
61              CaptchaImpl.class.getClassLoader(), PropsFiles.CAPTCHA);
62          _captchaProducer = (CaptchaProducer)Helper.ThingFactory.loadImpl(
63              Helper.ThingFactory.CPROD, _configuration.getProperties());
64      }
65  
66      public void check(HttpServletRequest request)
67          throws CaptchaTextException {
68  
69          if (!isEnabled(request)) {
70              return;
71          }
72  
73          HttpSession session = request.getSession();
74  
75          String captchaText = (String)session.getAttribute(WebKeys.CAPTCHA_TEXT);
76  
77          if (captchaText == null) {
78              if (_log.isErrorEnabled()) {
79                  _log.error(
80                      "Captcha text is null. User " + request.getRemoteUser() +
81                          " may be trying to circumvent the captcha.");
82              }
83  
84              throw new CaptchaTextException();
85          }
86  
87          if (!captchaText.equals(ParamUtil.getString(request, "captchaText"))) {
88              throw new CaptchaTextException();
89          }
90  
91          if (_log.isDebugEnabled()) {
92              _log.debug("Captcha text is valid");
93          }
94  
95          session.removeAttribute(WebKeys.CAPTCHA_TEXT);
96  
97          if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) &&
98              (Validator.isNotNull(request.getRemoteUser()))) {
99  
100             Integer count = (Integer)session.getAttribute(
101                 WebKeys.CAPTCHA_COUNT);
102 
103             if (count == null) {
104                 count = new Integer(1);
105             }
106             else {
107                 count = new Integer(count.intValue() + 1);
108             }
109 
110             session.setAttribute(WebKeys.CAPTCHA_COUNT, count);
111         }
112     }
113 
114     public void check(PortletRequest portletRequest)
115         throws CaptchaTextException {
116 
117         if (!isEnabled(portletRequest)) {
118             return;
119         }
120 
121         PortletSession portletSession = portletRequest.getPortletSession();
122 
123         String captchaText = (String)portletSession.getAttribute(
124             WebKeys.CAPTCHA_TEXT);
125 
126         if (captchaText == null) {
127             if (_log.isErrorEnabled()) {
128                 _log.error(
129                     "Captcha text is null. User " +
130                         portletRequest.getRemoteUser() +
131                             " may be trying to circumvent the captcha.");
132             }
133 
134             throw new CaptchaTextException();
135         }
136 
137         if (!captchaText.equals(
138                 ParamUtil.getString(portletRequest, "captchaText"))) {
139 
140             throw new CaptchaTextException();
141         }
142 
143         if (_log.isDebugEnabled()) {
144             _log.debug("Captcha text is valid");
145         }
146 
147         portletSession.removeAttribute(WebKeys.CAPTCHA_TEXT);
148 
149         if ((PropsValues.CAPTCHA_MAX_CHALLENGES > 0) &&
150             (Validator.isNotNull(portletRequest.getRemoteUser()))) {
151 
152             Integer count = (Integer)portletSession.getAttribute(
153                 WebKeys.CAPTCHA_COUNT);
154 
155             if (count == null) {
156                 count = new Integer(1);
157             }
158             else {
159                 count = new Integer(count.intValue() + 1);
160             }
161 
162             portletSession.setAttribute(WebKeys.CAPTCHA_COUNT, count);
163         }
164     }
165 
166     public boolean isEnabled(HttpServletRequest request) {
167         if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) {
168             HttpSession session = request.getSession();
169 
170             Integer count = (Integer)session.getAttribute(
171                 WebKeys.CAPTCHA_COUNT);
172 
173             if ((count != null) &&
174                 (PropsValues.CAPTCHA_MAX_CHALLENGES <= count.intValue())) {
175 
176                 return false;
177             }
178             else {
179                 return true;
180             }
181         }
182         else if (PropsValues.CAPTCHA_MAX_CHALLENGES < 0) {
183             return false;
184         }
185         else {
186             return true;
187         }
188     }
189 
190     public boolean isEnabled(PortletRequest portletRequest) {
191         if (PropsValues.CAPTCHA_MAX_CHALLENGES > 0) {
192             PortletSession portletSession = portletRequest.getPortletSession();
193 
194             Integer count = (Integer)portletSession.getAttribute(
195                 WebKeys.CAPTCHA_COUNT);
196 
197             if ((count != null) &&
198                 (PropsValues.CAPTCHA_MAX_CHALLENGES <= count.intValue())) {
199 
200                 return false;
201             }
202             else {
203                 return true;
204             }
205         }
206         else if (PropsValues.CAPTCHA_MAX_CHALLENGES < 0) {
207             return false;
208         }
209         else {
210             return true;
211         }
212     }
213 
214     public void serveImage(
215             HttpServletRequest request, HttpServletResponse response)
216         throws IOException {
217 
218         HttpSession session = request.getSession();
219 
220         String captchaText = _captchaProducer.createText();
221 
222         session.setAttribute(WebKeys.CAPTCHA_TEXT, captchaText);
223 
224         _captchaProducer.createImage(response.getOutputStream(), captchaText);
225     }
226 
227     public void serveImage(
228             PortletRequest portletRequest, PortletResponse portletResponse)
229         throws IOException {
230 
231         PortletSession portletSession = portletRequest.getPortletSession();
232 
233         String captchaText = _captchaProducer.createText();
234 
235         portletSession.setAttribute(WebKeys.CAPTCHA_TEXT, captchaText);
236 
237         HttpServletResponse response = PortalUtil.getHttpServletResponse(
238             portletResponse);
239 
240         _captchaProducer.createImage(response.getOutputStream(), captchaText);
241     }
242 
243     private static Log _log = LogFactoryUtil.getLog(CaptchaImpl.class);
244 
245     private Configuration _configuration;
246     private CaptchaProducer _captchaProducer;
247 
248 }