001
014
015 package com.liferay.portal.servlet.filters.virtualhost;
016
017 import com.liferay.portal.LayoutFriendlyURLException;
018 import com.liferay.portal.NoSuchLayoutException;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.struts.LastPath;
024 import com.liferay.portal.kernel.util.CharPool;
025 import com.liferay.portal.kernel.util.HttpUtil;
026 import com.liferay.portal.kernel.util.StringBundler;
027 import com.liferay.portal.kernel.util.StringPool;
028 import com.liferay.portal.kernel.util.StringUtil;
029 import com.liferay.portal.kernel.util.Validator;
030 import com.liferay.portal.model.Group;
031 import com.liferay.portal.model.LayoutSet;
032 import com.liferay.portal.model.impl.LayoutImpl;
033 import com.liferay.portal.service.GroupLocalServiceUtil;
034 import com.liferay.portal.service.LayoutLocalServiceUtil;
035 import com.liferay.portal.servlet.I18nServlet;
036 import com.liferay.portal.servlet.filters.BasePortalFilter;
037 import com.liferay.portal.util.Portal;
038 import com.liferay.portal.util.PortalInstances;
039 import com.liferay.portal.util.PortalUtil;
040 import com.liferay.portal.util.PropsValues;
041 import com.liferay.portal.util.WebKeys;
042 import com.liferay.portal.webserver.WebServerServlet;
043
044 import java.util.Set;
045
046 import javax.servlet.FilterChain;
047 import javax.servlet.FilterConfig;
048 import javax.servlet.RequestDispatcher;
049 import javax.servlet.ServletContext;
050 import javax.servlet.http.HttpServletRequest;
051 import javax.servlet.http.HttpServletResponse;
052
053
063 public class VirtualHostFilter extends BasePortalFilter {
064
065 @Override
066 public void init(FilterConfig filterConfig) {
067 super.init(filterConfig);
068
069 _servletContext = filterConfig.getServletContext();
070 }
071
072 @Override
073 public boolean isFilterEnabled(
074 HttpServletRequest request, HttpServletResponse response) {
075
076 StringBuffer requestURL = request.getRequestURL();
077
078 if (isValidRequestURL(requestURL)) {
079 return true;
080 }
081 else {
082 return false;
083 }
084 }
085
086 protected boolean isDocumentFriendlyURL(
087 HttpServletRequest request, long groupId, String friendlyURL)
088 throws PortalException, SystemException {
089
090 if (friendlyURL.startsWith(_PATH_DOCUMENTS) &&
091 WebServerServlet.hasFiles(request)) {
092
093 String path = HttpUtil.fixPath(request.getPathInfo());
094
095 String[] pathArray = StringUtil.split(path, CharPool.SLASH);
096
097 if (pathArray.length == 2) {
098 try {
099 LayoutLocalServiceUtil.getFriendlyURLLayout(
100 groupId, false, friendlyURL);
101 }
102 catch (NoSuchLayoutException nsle) {
103 return true;
104 }
105 }
106 else {
107 return true;
108 }
109 }
110
111 return false;
112 }
113
114 protected boolean isValidFriendlyURL(String friendlyURL) {
115 friendlyURL = StringUtil.toLowerCase(friendlyURL);
116
117 if (PortalInstances.isVirtualHostsIgnorePath(friendlyURL) ||
118 friendlyURL.startsWith(_PATH_MODULE_SLASH) ||
119 friendlyURL.startsWith(_PRIVATE_GROUP_SERVLET_MAPPING_SLASH) ||
120 friendlyURL.startsWith(_PRIVATE_USER_SERVLET_MAPPING_SLASH) ||
121 friendlyURL.startsWith(_PUBLIC_GROUP_SERVLET_MAPPING_SLASH)) {
122
123 return false;
124 }
125
126 if (LayoutImpl.hasFriendlyURLKeyword(friendlyURL)) {
127 return false;
128 }
129
130 int code = LayoutImpl.validateFriendlyURL(friendlyURL, false);
131
132 if ((code > -1) &&
133 (code != LayoutFriendlyURLException.ENDS_WITH_SLASH)) {
134
135 return false;
136 }
137
138 return true;
139 }
140
141 protected boolean isValidRequestURL(StringBuffer requestURL) {
142 if (requestURL == null) {
143 return false;
144 }
145
146 String url = requestURL.toString();
147
148 for (String extension : PropsValues.VIRTUAL_HOSTS_IGNORE_EXTENSIONS) {
149 if (url.endsWith(extension)) {
150 return false;
151 }
152 }
153
154 return true;
155 }
156
157 @Override
158 protected void processFilter(
159 HttpServletRequest request, HttpServletResponse response,
160 FilterChain filterChain)
161 throws Exception {
162
163 long companyId = PortalInstances.getCompanyId(request);
164
165 String contextPath = PortalUtil.getPathContext();
166
167 String originalFriendlyURL = request.getRequestURI();
168
169 String friendlyURL = originalFriendlyURL;
170
171 if (Validator.isNotNull(contextPath) &&
172 friendlyURL.contains(contextPath)) {
173
174 friendlyURL = friendlyURL.substring(contextPath.length());
175 }
176
177 int pos = friendlyURL.indexOf(StringPool.SEMICOLON);
178
179 if (pos != -1) {
180 friendlyURL = friendlyURL.substring(0, pos);
181 }
182
183 friendlyURL = StringUtil.replace(
184 friendlyURL, StringPool.DOUBLE_SLASH, StringPool.SLASH);
185
186 String i18nLanguageId = null;
187 String i18nLanguageIdLowerCase = null;
188
189 Set<String> languageIds = I18nServlet.getLanguageIds();
190
191 for (String languageId : languageIds) {
192 if (StringUtil.startsWith(friendlyURL, languageId)) {
193 pos = friendlyURL.indexOf(CharPool.SLASH, 1);
194
195 if (((pos != -1) && (pos != languageId.length())) ||
196 ((pos == -1) &&
197 !StringUtil.equalsIgnoreCase(friendlyURL, languageId))) {
198
199 continue;
200 }
201
202 if (!friendlyURL.startsWith(languageId)) {
203 i18nLanguageIdLowerCase = StringUtil.toLowerCase(
204 languageId);
205 }
206
207 if (pos == -1) {
208 i18nLanguageId = languageId;
209 friendlyURL = StringPool.SLASH;
210 }
211 else {
212 i18nLanguageId = languageId.substring(0, pos);
213 friendlyURL = friendlyURL.substring(pos);
214 }
215
216 break;
217 }
218 }
219
220 friendlyURL = StringUtil.replace(
221 friendlyURL, PropsValues.WIDGET_SERVLET_MAPPING, StringPool.BLANK);
222
223 if (_log.isDebugEnabled()) {
224 _log.debug("Friendly URL " + friendlyURL);
225 }
226
227 if (!friendlyURL.equals(StringPool.SLASH) &&
228 !isValidFriendlyURL(friendlyURL)) {
229
230 _log.debug("Friendly URL is not valid");
231
232 if (Validator.isNotNull(i18nLanguageIdLowerCase)) {
233 String forwardURL = StringUtil.replace(
234 originalFriendlyURL, i18nLanguageIdLowerCase,
235 i18nLanguageId);
236
237 RequestDispatcher requestDispatcher =
238 _servletContext.getRequestDispatcher(forwardURL);
239
240 requestDispatcher.forward(request, response);
241
242 return;
243 }
244 else {
245 processFilter(
246 VirtualHostFilter.class, request, response, filterChain);
247
248 return;
249 }
250 }
251
252 LayoutSet layoutSet = (LayoutSet)request.getAttribute(
253 WebKeys.VIRTUAL_HOST_LAYOUT_SET);
254
255 if (_log.isDebugEnabled()) {
256 _log.debug("Layout set " + layoutSet);
257 }
258
259 if (layoutSet == null) {
260 processFilter(
261 VirtualHostFilter.class, request, response, filterChain);
262
263 return;
264 }
265
266 try {
267 LastPath lastPath = new LastPath(
268 contextPath, friendlyURL, request.getParameterMap());
269
270 request.setAttribute(WebKeys.LAST_PATH, lastPath);
271
272 StringBundler forwardURL = new StringBundler(5);
273
274 if (i18nLanguageId != null) {
275 forwardURL.append(i18nLanguageId);
276 }
277
278 if (originalFriendlyURL.startsWith(
279 PropsValues.WIDGET_SERVLET_MAPPING)) {
280
281 forwardURL.append(PropsValues.WIDGET_SERVLET_MAPPING);
282
283 friendlyURL = StringUtil.replaceFirst(
284 friendlyURL, PropsValues.WIDGET_SERVLET_MAPPING,
285 StringPool.BLANK);
286 }
287
288 long plid = PortalUtil.getPlidFromFriendlyURL(
289 companyId, friendlyURL);
290
291 if (plid <= 0) {
292 Group group = GroupLocalServiceUtil.getGroup(
293 layoutSet.getGroupId());
294
295 if (isDocumentFriendlyURL(
296 request, group.getGroupId(), friendlyURL)) {
297
298 processFilter(
299 VirtualHostFilter.class, request, response,
300 filterChain);
301
302 return;
303 }
304
305 if (group.isGuest() && friendlyURL.equals(StringPool.SLASH) &&
306 !layoutSet.isPrivateLayout()) {
307
308 String homeURL = PortalUtil.getRelativeHomeURL(request);
309
310 if (Validator.isNotNull(homeURL)) {
311 friendlyURL = homeURL;
312 }
313 }
314 else {
315 if (layoutSet.isPrivateLayout()) {
316 if (group.isUser()) {
317 forwardURL.append(_PRIVATE_USER_SERVLET_MAPPING);
318 }
319 else {
320 forwardURL.append(_PRIVATE_GROUP_SERVLET_MAPPING);
321 }
322 }
323 else {
324 forwardURL.append(_PUBLIC_GROUP_SERVLET_MAPPING);
325 }
326
327 forwardURL.append(group.getFriendlyURL());
328 }
329 }
330
331 forwardURL.append(friendlyURL);
332
333 if (_log.isDebugEnabled()) {
334 _log.debug("Forward to " + forwardURL);
335 }
336
337 RequestDispatcher requestDispatcher =
338 _servletContext.getRequestDispatcher(forwardURL.toString());
339
340 requestDispatcher.forward(request, response);
341 }
342 catch (Exception e) {
343 _log.error(e, e);
344
345 processFilter(
346 VirtualHostFilter.class, request, response, filterChain);
347 }
348 }
349
350 private static final String _PATH_DOCUMENTS = "/documents/";
351
352 private static final String _PATH_MODULE_SLASH =
353 Portal.PATH_MODULE + StringPool.SLASH;
354
355 private static final String _PRIVATE_GROUP_SERVLET_MAPPING =
356 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
357
358 private static final String _PRIVATE_GROUP_SERVLET_MAPPING_SLASH =
359 _PRIVATE_GROUP_SERVLET_MAPPING + StringPool.SLASH;
360
361 private static final String _PRIVATE_USER_SERVLET_MAPPING =
362 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
363
364 private static final String _PRIVATE_USER_SERVLET_MAPPING_SLASH =
365 _PRIVATE_USER_SERVLET_MAPPING + StringPool.SLASH;
366
367 private static final String _PUBLIC_GROUP_SERVLET_MAPPING =
368 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
369
370 private static final String _PUBLIC_GROUP_SERVLET_MAPPING_SLASH =
371 _PUBLIC_GROUP_SERVLET_MAPPING + StringPool.SLASH;
372
373 private static Log _log = LogFactoryUtil.getLog(VirtualHostFilter.class);
374
375 private ServletContext _servletContext;
376
377 }