1
14
15 package com.liferay.portal.servlet.filters.virtualhost;
16
17 import com.liferay.portal.LayoutFriendlyURLException;
18 import com.liferay.portal.kernel.log.Log;
19 import com.liferay.portal.kernel.log.LogFactoryUtil;
20 import com.liferay.portal.kernel.struts.LastPath;
21 import com.liferay.portal.kernel.util.CharPool;
22 import com.liferay.portal.kernel.util.StringBundler;
23 import com.liferay.portal.kernel.util.StringPool;
24 import com.liferay.portal.kernel.util.StringUtil;
25 import com.liferay.portal.kernel.util.Validator;
26 import com.liferay.portal.model.Group;
27 import com.liferay.portal.model.LayoutSet;
28 import com.liferay.portal.model.impl.LayoutImpl;
29 import com.liferay.portal.service.GroupLocalServiceUtil;
30 import com.liferay.portal.servlet.AbsoluteRedirectsResponse;
31 import com.liferay.portal.servlet.I18nServlet;
32 import com.liferay.portal.servlet.filters.BasePortalFilter;
33 import com.liferay.portal.util.PortalInstances;
34 import com.liferay.portal.util.PortalUtil;
35 import com.liferay.portal.util.PropsValues;
36 import com.liferay.portal.util.WebKeys;
37
38 import java.util.Set;
39
40 import javax.servlet.FilterChain;
41 import javax.servlet.FilterConfig;
42 import javax.servlet.RequestDispatcher;
43 import javax.servlet.ServletContext;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46 import javax.servlet.http.HttpSession;
47
48
63 public class VirtualHostFilter extends BasePortalFilter {
64
65 public void init(FilterConfig filterConfig) {
66 super.init(filterConfig);
67
68 _servletContext = filterConfig.getServletContext();
69 }
70
71 protected boolean isValidFriendlyURL(String friendlyURL) {
72 friendlyURL = friendlyURL.toLowerCase();
73
74 if (PortalInstances.isVirtualHostsIgnorePath(friendlyURL) ||
75 friendlyURL.startsWith(
76 _PRIVATE_GROUP_SERVLET_MAPPING + StringPool.SLASH) ||
77 friendlyURL.startsWith(
78 _PUBLIC_GROUP_SERVLET_MAPPING + StringPool.SLASH) ||
79 friendlyURL.startsWith(
80 _PRIVATE_USER_SERVLET_MAPPING + StringPool.SLASH) ||
81 friendlyURL.startsWith(_PATH_C) ||
82 friendlyURL.startsWith(_PATH_DELEGATE) ||
83 friendlyURL.startsWith(_PATH_DISPLAY_CHART) ||
84 friendlyURL.startsWith(_PATH_DOCUMENT) ||
85 friendlyURL.startsWith(_PATH_DTD) ||
86 friendlyURL.startsWith(_PATH_FACEBOOK) ||
87 friendlyURL.startsWith(_PATH_GOOGLE_GADGET) ||
88 friendlyURL.startsWith(_PATH_HTML) ||
89 friendlyURL.startsWith(_PATH_IMAGE) ||
90 friendlyURL.startsWith(_PATH_LANGUAGE) ||
91 friendlyURL.startsWith(_PATH_NETVIBES) ||
92 friendlyURL.startsWith(_PATH_PBHS) ||
93 friendlyURL.startsWith(_PATH_POLLER) ||
94 friendlyURL.startsWith(_PATH_SHAREPOINT) ||
95 friendlyURL.startsWith(_PATH_SITEMAP_XML) ||
96 friendlyURL.startsWith(_PATH_SOFTWARE_CATALOG) ||
97 friendlyURL.startsWith(_PATH_VTI) ||
98 friendlyURL.startsWith(_PATH_WAP) ||
99 friendlyURL.startsWith(_PATH_WIDGET)) {
100
101 return false;
102 }
103
104 int code = LayoutImpl.validateFriendlyURL(friendlyURL);
105
106 if ((code > -1) &&
107 (code != LayoutFriendlyURLException.ENDS_WITH_SLASH)) {
108
109 return false;
110 }
111
112 return true;
113 }
114
115 protected boolean isValidRequestURL(StringBuffer requestURL) {
116 if (requestURL == null) {
117 return false;
118 }
119
120 String url = requestURL.toString();
121
122 for (String extension : PropsValues.VIRTUAL_HOSTS_IGNORE_EXTENSIONS) {
123 if (url.endsWith(extension)) {
124 return false;
125 }
126 }
127
128 return true;
129 }
130
131 protected void processFilter(
132 HttpServletRequest request, HttpServletResponse response,
133 FilterChain filterChain)
134 throws Exception {
135
136 request.setCharacterEncoding(StringPool.UTF8);
137
139
141 response = new AbsoluteRedirectsResponse(request, response);
142
143
146 long companyId = PortalInstances.getCompanyId(request);
147
148 if (_log.isDebugEnabled()) {
149 _log.debug("Company id " + companyId);
150 }
151
152 PortalUtil.getCurrentCompleteURL(request);
153 PortalUtil.getCurrentURL(request);
154
155 HttpSession session = request.getSession();
156
157 Boolean httpsInitial = (Boolean)session.getAttribute(
158 WebKeys.HTTPS_INITIAL);
159
160 if (httpsInitial == null) {
161 httpsInitial = Boolean.valueOf(request.isSecure());
162
163 session.setAttribute(WebKeys.HTTPS_INITIAL, httpsInitial);
164
165 if (_log.isDebugEnabled()) {
166 _log.debug("Setting httpsInitial to " + httpsInitial);
167 }
168 }
169
170 if (!isFilterEnabled()) {
171 processFilter(
172 VirtualHostFilter.class, request, response, filterChain);
173
174 return;
175 }
176
177 StringBuffer requestURL = request.getRequestURL();
178
179 if (_log.isDebugEnabled()) {
180 _log.debug("Received " + requestURL);
181 }
182
183 if (!isValidRequestURL(requestURL)) {
184 processFilter(
185 VirtualHostFilter.class, request, response, filterChain);
186
187 return;
188 }
189
190 String contextPath = PortalUtil.getPathContext();
191
192 String originalFriendlyURL = request.getRequestURI();
193
194 String friendlyURL = originalFriendlyURL;
195
196 if ((Validator.isNotNull(contextPath)) &&
197 (friendlyURL.indexOf(contextPath) != -1)) {
198
199 friendlyURL = friendlyURL.substring(contextPath.length());
200 }
201
202 friendlyURL = StringUtil.replace(
203 friendlyURL, StringPool.DOUBLE_SLASH, StringPool.SLASH);
204
205 String i18nLanguageId = null;
206
207 Set<String> languageIds = I18nServlet.getLanguageIds();
208
209 for (String languageId : languageIds) {
210 if (friendlyURL.startsWith(languageId)) {
211 int pos = friendlyURL.indexOf(CharPool.SLASH, 1);
212
213 if (((pos != -1) && (pos != languageId.length())) ||
214 ((pos == -1) && !friendlyURL.equals(languageId))) {
215
216 continue;
217 }
218
219 if (pos == -1) {
220 i18nLanguageId = friendlyURL;
221 friendlyURL = StringPool.SLASH;
222 }
223 else {
224 i18nLanguageId = friendlyURL.substring(0, pos);
225 friendlyURL = friendlyURL.substring(pos);
226 }
227
228 break;
229 }
230 }
231
232 friendlyURL = StringUtil.replace(
233 friendlyURL, PropsValues.WIDGET_SERVLET_MAPPING, StringPool.BLANK);
234
235 if (_log.isDebugEnabled()) {
236 _log.debug("Friendly URL " + friendlyURL);
237 }
238
239 if (!friendlyURL.equals(StringPool.SLASH) &&
240 !isValidFriendlyURL(friendlyURL)) {
241
242 _log.debug("Friendly URL is not valid");
243
244 processFilter(
245 VirtualHostFilter.class, request, response, filterChain);
246
247 return;
248 }
249
250 LayoutSet layoutSet = (LayoutSet)request.getAttribute(
251 WebKeys.VIRTUAL_HOST_LAYOUT_SET);
252
253 if (_log.isDebugEnabled()) {
254 _log.debug("Layout set " + layoutSet);
255 }
256
257 if (layoutSet != null) {
258 try {
259 LastPath lastPath = new LastPath(
260 contextPath, friendlyURL, request.getParameterMap());
261
262 request.setAttribute(WebKeys.LAST_PATH, lastPath);
263
264 StringBundler prefix = new StringBundler(2);
265
266 Group group = GroupLocalServiceUtil.getGroup(
267 layoutSet.getGroupId());
268
269 if (layoutSet.isPrivateLayout()) {
270 if (group.isUser()) {
271 prefix.append(_PRIVATE_USER_SERVLET_MAPPING);
272 }
273 else {
274 prefix.append(_PRIVATE_GROUP_SERVLET_MAPPING);
275 }
276 }
277 else {
278 prefix.append(_PUBLIC_GROUP_SERVLET_MAPPING);
279 }
280
281 prefix.append(group.getFriendlyURL());
282
283 StringBundler forwardURL = new StringBundler(6);
284
285 if (i18nLanguageId != null) {
286 forwardURL.append(i18nLanguageId);
287 }
288
289 if (originalFriendlyURL.startsWith(
290 PropsValues.WIDGET_SERVLET_MAPPING)) {
291
292 forwardURL.append(PropsValues.WIDGET_SERVLET_MAPPING);
293
294 friendlyURL = StringUtil.replaceFirst(
295 friendlyURL, PropsValues.WIDGET_SERVLET_MAPPING,
296 StringPool.BLANK);
297 }
298
299 long plid = PortalUtil.getPlidFromFriendlyURL(
300 companyId, friendlyURL);
301
302 if (plid <= 0) {
303 forwardURL.append(prefix);
304 }
305
306 forwardURL.append(friendlyURL);
307
308 if (_log.isDebugEnabled()) {
309 _log.debug("Forward to " + forwardURL);
310 }
311
312 RequestDispatcher requestDispatcher =
313 _servletContext.getRequestDispatcher(forwardURL.toString());
314
315 requestDispatcher.forward(request, response);
316
317 return;
318 }
319 catch (Exception e) {
320 _log.error(e, e);
321 }
322 }
323
324 processFilter(VirtualHostFilter.class, request, response, filterChain);
325 }
326
327 private static final String _PATH_C = "/c/";
328
329 private static final String _PATH_DELEGATE = "/delegate/";
330
331 private static final String _PATH_DISPLAY_CHART = "/display_chart";
332
333 private static final String _PATH_DOCUMENT = "/document/";
334
335 private static final String _PATH_DTD = "/dtd/";
336
337 private static final String _PATH_FACEBOOK = "/facebook/";
338
339 private static final String _PATH_GOOGLE_GADGET = "/google_gadget/";
340
341 private static final String _PATH_HTML = "/html/";
342
343 private static final String _PATH_IMAGE = "/image/";
344
345 private static final String _PATH_LANGUAGE = "/language/";
346
347 private static final String _PATH_NETVIBES = "/netvibes/";
348
349 private static final String _PATH_PBHS = "/pbhs/";
350
351 private static final String _PATH_POLLER = "/poller/";
352
353 private static final String _PATH_SHAREPOINT = "/sharepoint/";
354
355 private static final String _PATH_SITEMAP_XML = "/sitemap.xml";
356
357 private static final String _PATH_SOFTWARE_CATALOG = "/software_catalog";
358
359 private static final String _PATH_VTI = "/_vti_";
360
361 private static final String _PATH_WAP = "/wap/";
362
363 private static final String _PATH_WIDGET = "/widget/";
364
365 private static final String _PRIVATE_GROUP_SERVLET_MAPPING =
366 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
367
368 private static final String _PRIVATE_USER_SERVLET_MAPPING =
369 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
370
371 private static final String _PUBLIC_GROUP_SERVLET_MAPPING =
372 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
373
374 private static Log _log = LogFactoryUtil.getLog(VirtualHostFilter.class);
375
376 private ServletContext _servletContext;
377
378 }