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