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