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.StringBundler;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.StringUtil;
024 import com.liferay.portal.kernel.util.Validator;
025 import com.liferay.portal.model.Group;
026 import com.liferay.portal.model.LayoutSet;
027 import com.liferay.portal.model.impl.LayoutImpl;
028 import com.liferay.portal.service.GroupLocalServiceUtil;
029 import com.liferay.portal.servlet.AbsoluteRedirectsResponse;
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
037 import java.util.Set;
038
039 import javax.servlet.FilterChain;
040 import javax.servlet.FilterConfig;
041 import javax.servlet.RequestDispatcher;
042 import javax.servlet.ServletContext;
043 import javax.servlet.http.HttpServletRequest;
044 import javax.servlet.http.HttpServletResponse;
045 import javax.servlet.http.HttpSession;
046
047
061 public class VirtualHostFilter extends BasePortalFilter {
062
063 public void init(FilterConfig filterConfig) {
064 super.init(filterConfig);
065
066 _servletContext = filterConfig.getServletContext();
067 }
068
069 protected boolean isValidFriendlyURL(String friendlyURL) {
070 friendlyURL = friendlyURL.toLowerCase();
071
072 if (PortalInstances.isVirtualHostsIgnorePath(friendlyURL) ||
073 friendlyURL.startsWith(
074 _PRIVATE_GROUP_SERVLET_MAPPING + StringPool.SLASH) ||
075 friendlyURL.startsWith(
076 _PUBLIC_GROUP_SERVLET_MAPPING + StringPool.SLASH) ||
077 friendlyURL.startsWith(
078 _PRIVATE_USER_SERVLET_MAPPING + StringPool.SLASH) ||
079 friendlyURL.startsWith(_PATH_C) ||
080 friendlyURL.startsWith(_PATH_COMBO) ||
081 friendlyURL.startsWith(_PATH_DELEGATE) ||
082 friendlyURL.startsWith(_PATH_DISPLAY_CHART) ||
083 friendlyURL.startsWith(_PATH_DOCUMENTS) ||
084 friendlyURL.startsWith(_PATH_DTD) ||
085 friendlyURL.startsWith(_PATH_FACEBOOK) ||
086 friendlyURL.startsWith(_PATH_GOOGLE_GADGET) ||
087 friendlyURL.startsWith(_PATH_HTML) ||
088 friendlyURL.startsWith(_PATH_IMAGE) ||
089 friendlyURL.startsWith(_PATH_LANGUAGE) ||
090 friendlyURL.startsWith(_PATH_NETVIBES) ||
091 friendlyURL.startsWith(_PATH_PBHS) ||
092 friendlyURL.startsWith(_PATH_POLLER) ||
093 friendlyURL.startsWith(_PATH_SHAREPOINT) ||
094 friendlyURL.startsWith(_PATH_SITEMAP_XML) ||
095 friendlyURL.startsWith(_PATH_SOFTWARE_CATALOG) ||
096 friendlyURL.startsWith(_PATH_VTI) ||
097 friendlyURL.startsWith(_PATH_WAP) ||
098 friendlyURL.startsWith(_PATH_WIDGET) ||
099 friendlyURL.startsWith(_PATH_XMLRPC)) {
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
138
139
140
141 response = new AbsoluteRedirectsResponse(request, response);
142
143
144
145
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 friendlyURL = request.getRequestURI();
193
194 if ((Validator.isNotNull(contextPath)) &&
195 (friendlyURL.indexOf(contextPath) != -1)) {
196
197 friendlyURL = friendlyURL.substring(contextPath.length());
198 }
199
200 friendlyURL = StringUtil.replace(
201 friendlyURL, StringPool.DOUBLE_SLASH, StringPool.SLASH);
202
203 String i18nLanguageId = null;
204
205 Set<String> languageIds = I18nServlet.getLanguageIds();
206
207 for (String languageId : languageIds) {
208 if (friendlyURL.startsWith(languageId)) {
209 int pos = friendlyURL.indexOf(StringPool.SLASH, 1);
210
211 if (((pos != -1) && (pos != languageId.length())) ||
212 ((pos == -1) && !friendlyURL.equals(languageId))) {
213
214 continue;
215 }
216
217 if (pos == -1) {
218 i18nLanguageId = friendlyURL;
219 friendlyURL = StringPool.SLASH;
220 }
221 else {
222 i18nLanguageId = friendlyURL.substring(0, pos);
223 friendlyURL = friendlyURL.substring(pos);
224 }
225
226 break;
227 }
228 }
229
230 if (_log.isDebugEnabled()) {
231 _log.debug("Friendly URL " + friendlyURL);
232 }
233
234 if (!friendlyURL.equals(StringPool.SLASH) &&
235 !isValidFriendlyURL(friendlyURL)) {
236
237 _log.debug("Friendly URL is not valid");
238
239 processFilter(
240 VirtualHostFilter.class, request, response, filterChain);
241
242 return;
243 }
244
245 LayoutSet layoutSet = (LayoutSet)request.getAttribute(
246 WebKeys.VIRTUAL_HOST_LAYOUT_SET);
247
248 if (_log.isDebugEnabled()) {
249 _log.debug("Layout set " + layoutSet);
250 }
251
252 if (layoutSet != null) {
253 try {
254 LastPath lastPath = new LastPath(
255 contextPath, friendlyURL, request.getParameterMap());
256
257 request.setAttribute(WebKeys.LAST_PATH, lastPath);
258
259 StringBundler prefix = new StringBundler(2);
260
261 Group group = GroupLocalServiceUtil.getGroup(
262 layoutSet.getGroupId());
263
264 if (layoutSet.isPrivateLayout()) {
265 if (group.isUser()) {
266 prefix.append(_PRIVATE_USER_SERVLET_MAPPING);
267 }
268 else {
269 prefix.append(_PRIVATE_GROUP_SERVLET_MAPPING);
270 }
271 }
272 else {
273 prefix.append(_PUBLIC_GROUP_SERVLET_MAPPING);
274 }
275
276 prefix.append(group.getFriendlyURL());
277
278 StringBundler forwardURL = new StringBundler(6);
279
280 if (i18nLanguageId != null) {
281 forwardURL.append(i18nLanguageId);
282 }
283
284 if (friendlyURL.startsWith(
285 PropsValues.WIDGET_SERVLET_MAPPING)) {
286
287 forwardURL.append(PropsValues.WIDGET_SERVLET_MAPPING);
288
289 friendlyURL = StringUtil.replaceFirst(
290 friendlyURL, PropsValues.WIDGET_SERVLET_MAPPING,
291 StringPool.BLANK);
292 }
293
294 long plid = PortalUtil.getPlidFromFriendlyURL(
295 companyId, friendlyURL);
296
297 if (plid <= 0) {
298 forwardURL.append(prefix);
299 }
300
301 forwardURL.append(friendlyURL);
302
303 if (_log.isDebugEnabled()) {
304 _log.debug("Forward to " + forwardURL);
305 }
306
307 RequestDispatcher requestDispatcher =
308 _servletContext.getRequestDispatcher(forwardURL.toString());
309
310 requestDispatcher.forward(request, response);
311
312 return;
313 }
314 catch (Exception e) {
315 _log.error(e, e);
316 }
317 }
318
319 processFilter(VirtualHostFilter.class, request, response, filterChain);
320 }
321
322 private static final String _PATH_C = "/c/";
323
324 private static final String _PATH_COMBO = "/combo/";
325
326 private static final String _PATH_DELEGATE = "/delegate/";
327
328 private static final String _PATH_DISPLAY_CHART = "/display_chart";
329
330 private static final String _PATH_DOCUMENTS = "/documents/";
331
332 private static final String _PATH_DTD = "/dtd/";
333
334 private static final String _PATH_FACEBOOK = "/facebook/";
335
336 private static final String _PATH_GOOGLE_GADGET = "/google_gadget/";
337
338 private static final String _PATH_HTML = "/html/";
339
340 private static final String _PATH_IMAGE = "/image/";
341
342 private static final String _PATH_LANGUAGE = "/language/";
343
344 private static final String _PATH_NETVIBES = "/netvibes/";
345
346 private static final String _PATH_PBHS = "/pbhs/";
347
348 private static final String _PATH_POLLER = "/poller/";
349
350 private static final String _PATH_SHAREPOINT = "/sharepoint/";
351
352 private static final String _PATH_SITEMAP_XML = "/sitemap.xml";
353
354 private static final String _PATH_SOFTWARE_CATALOG = "/software_catalog";
355
356 private static final String _PATH_VTI = "/_vti_";
357
358 private static final String _PATH_WAP = "/wap/";
359
360 private static final String _PATH_WIDGET = "/widget/";
361
362 private static final String _PATH_XMLRPC = "/xmlrpc/";
363
364 private static final String _PRIVATE_GROUP_SERVLET_MAPPING =
365 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
366
367 private static final String _PRIVATE_USER_SERVLET_MAPPING =
368 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
369
370 private static final String _PUBLIC_GROUP_SERVLET_MAPPING =
371 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
372
373 private static Log _log = LogFactoryUtil.getLog(VirtualHostFilter.class);
374
375 private ServletContext _servletContext;
376
377 }