MobilFilter.java
/*
* Copyright (C) 2000 - 2025 Silverpeas
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* As a special exception to the terms and conditions of version 3.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* Open Source Software ("FLOSS") applications as described in Silverpeas's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* "https://www.silverpeas.org/legal/floss_exception.html"
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.silverpeas.bridge;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.silverpeas.components.gallery.model.Media;
import org.silverpeas.components.gallery.model.MediaPK;
import org.silverpeas.components.gallery.service.GalleryService;
import org.silverpeas.components.gallery.service.MediaServiceProvider;
import org.silverpeas.components.quickinfo.model.News;
import org.silverpeas.components.quickinfo.model.QuickInfoService;
import org.silverpeas.components.quickinfo.model.QuickInfoServiceProvider;
import org.silverpeas.core.contribution.publication.model.PublicationDetail;
import org.silverpeas.core.contribution.publication.model.PublicationPK;
import org.silverpeas.core.contribution.publication.service.PublicationService;
import org.silverpeas.core.questioncontainer.container.model.QuestionContainerPK;
import org.silverpeas.core.questioncontainer.container.service.QuestionContainerService;
import org.silverpeas.core.security.token.TokenGenerator;
import org.silverpeas.core.security.token.TokenGeneratorProvider;
import org.silverpeas.core.security.token.synchronizer.SynchronizerToken;
import org.silverpeas.core.util.URLUtil;
import org.silverpeas.core.web.mvc.controller.MainSessionController;
import org.silverpeas.kernel.bundle.ResourceLocator;
import org.silverpeas.kernel.bundle.SettingBundle;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MobilFilter implements Filter {
//private static final SilverLogger logger = SilverLogger.getLogger("silverpeas.core.security");
public static final String SESSION_TOKEN_KEY = "X-STKN";
public static final String SESSION_PARAMS_KEY = "SESSION_PARAMS_KEY";
private static String[] urlsAllowed = null;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
String url = request.getRequestURL().toString();
if (url.contains("spmobile") && res != null) {
String csp = response.getHeader("Content-Security-Policy");
if (csp != null && !csp.contains("img-src")) {
csp += "; img-src * data: blob:;";
response.setHeader("Content-Security-Policy", csp);
}
}
// the session could not exist
final SafeSessionManager session = new SafeSessionManager(request);
final Boolean mobileAlreadyDetected = session.getAttribute("isMobile", Boolean.class);
if (mobileAlreadyDetected != null && !mobileAlreadyDetected) {
chain.doFilter(req, res);
return;
}
final String userAgent = request.getHeader("User-Agent");
if (userAgent != null) {
final boolean isMobile = Boolean.TRUE.equals(mobileAlreadyDetected)
|| userAgent.contains("Android")
|| userAgent.contains("iPhone");
session.setAttribute("isMobile", isMobile);
final boolean tablet = session.getAttribute("tablet", Boolean.class, false);
boolean redirect = isRedirect(url);
if (isMobile && !url.contains("sso") && !url.contains("services") &&
!url.contains("spmobile") && !url.contains(URLUtil.getApplicationURL() + "/chat/") &&
!url.contains(URLUtil.getApplicationURL() + "/media/") &&
!url.contains(URLUtil.getApplicationURL() + "/visio/") &&
!url.contains(URLUtil.getApplicationURL() + "/util/") && (!tablet) &&
!url.contains("attached_file") && !url.contains("Ticket") &&
!url.contains("LinkFile/Key") &&
!url.contains("Logout") &&
!url.contains("FileServer/vignette") &&
!url.contains("FileServer/thumbnail") &&
!url.contains("GalleryInWysiwyg/dummy") && redirect) {
String params = "";
if (url.contains("Publication")) {
String id = url.substring(url.lastIndexOf("/") + 1);
PublicationDetail pub = getPubBm().getDetail(new PublicationPK(id));
String appId = pub.getInstanceId();
params = "?shortcutContentType=Publication&shortcutContentId=" + id + "&shortcutAppId=" +
appId;
} else if (url.contains("/File/")) {
String id = url.substring(url.lastIndexOf("/") + 1);
String l = request.getParameter("ContentLanguage");
params = "?shortcutContentType=Attachment&shortcutContentId=" + id + "&shortcutRole=" + l;
} else if (url.contains("/Topic/")) {
// sample : /silverpeas/Topic/6278?ComponentId=kmelia2431
String id = url.substring(url.lastIndexOf("/")+1);
String appId = ((HttpServletRequest) req).getParameter("ComponentId");
params = "?shortcutContentType=Folder&shortcutContentId=" + id + "&shortcutAppId=" + appId;
} else if (url.contains("Form")) {
// sample : /silverpeas/Form/1?ComponentId=formsOnline1
String id = url.substring(url.lastIndexOf("/") + 1);
String appId = req.getParameter("ComponentId");
params = "?shortcutContentType=Form&shortcutContentId=" + id + "&shortcutAppId=" + appId;
} else if (url.contains("Media")) {
String id = url.substring(url.lastIndexOf("/") + 1);
Media media = getGalleryService().getMedia(new MediaPK(id));
String appId = media.getInstanceId();
params = "?shortcutContentType=Media&shortcutContentId=" + id + "&shortcutAppId=" + appId;
} else if (url.contains("RprocessManager")) {
params = extractWorkflowParameters(req);
} else if (url.toLowerCase().contains("survey")) {
params = extractSurveyParameters(req);
} else if (url.contains("autoRedirect.jsp")) {
QuickInfoService service = QuickInfoServiceProvider.getQuickInfoService();
String subUrl = req.getParameter("goto");
if (subUrl.contains("Rquickinfo")) {
String appId = subUrl.replace("/Rquickinfo/", "");
appId = appId.substring(0, appId.indexOf("/"));
String contributionId = subUrl.substring(subUrl.indexOf("Id=") + 3);
News n = service.getNews(contributionId);
String id = n.getPublicationId();
params =
"?shortcutContentType=News&shortcutContentId=" + id + "&shortcutAppId=" + appId +
"&shortcutContributionId=" + contributionId;
} else if (subUrl.contains("RformsOnline")) {
String appId = subUrl.replace("/RformsOnline/", "");
appId = appId.substring(0, appId.indexOf("/"));
String id = subUrl.substring(subUrl.indexOf("Id=") + 3);
params =
"?shortcutContentType=Component&shortcutContentId=" + id + "&shortcutAppId=" + appId;
} else if (subUrl.contains("Rblog")) {
String appId = subUrl.replace("/Rblog/", "");
appId = appId.substring(0, appId.indexOf("/"));
String id = subUrl.substring(subUrl.indexOf("Id=") + 3);
params =
"?shortcutContentType=Publication&shortcutContentId=" + id + "&shortcutAppId=" +
appId;
} else if (subUrl.contains("Rgallery")) {
String appId = subUrl.replace("/Rgallery/", "");
appId = appId.substring(0, appId.indexOf("/"));
String id = subUrl.substring(subUrl.indexOf("Id=") + 3);
params =
"?shortcutContentType=Media&shortcutContentId=" + id + "&shortcutAppId=" + appId;
} else if (subUrl.contains("Rkmelia")) {
/*
Example : /silverpeas/autoRedirect
.jsp?domainId=0&goto=%2FRkmelia%2Fkmelia1%2FsearchResult%3FType%3DPublication%26Id
%3D24
*/
String appId = subUrl.replace("/Rkmelia/", "");
appId = appId.substring(0, appId.indexOf("/"));
String id = subUrl.substring(subUrl.indexOf("Id=") + 3);
params =
"?shortcutContentType=Publication&shortcutContentId=" + id + "&shortcutAppId=" +
appId;
}
} else if (url.contains("Contribution")) {
String contributionId = url.substring(url.lastIndexOf("/") + 1);
params = "?shortcutContentType=Event&shortcutContributionId=" + contributionId;
} else if (url.contains("Space")) {
String spaceId = url.substring(url.lastIndexOf("/") + 1);
params = "?shortcutContentType=Space&shortcutAppId=" + spaceId;
} else if (url.contains("Component")) {
String appId = url.substring(url.lastIndexOf("/") + 1);
params = "?shortcutContentType=Component&shortcutAppId=" + appId;
} else if (url.contains("/needSession")) {
String appId = url.replaceAll("/needSession","");
params = "?shortcutContentType=Url&shortcutAppId=" + appId;
} else if (!url.contains("AuthenticationServlet") &&
(url.endsWith("silverpeas") || url.endsWith("silverpeas/") ||
url.contains("/silverpeas/"))) {
// simple redirection on mobile login page
params = "";
} else {
chain.doFilter(req, res);
return;
}
SynchronizerToken token = session.getAttribute(SESSION_TOKEN_KEY, SynchronizerToken.class);
MainSessionController controller = session.getAttribute(
MainSessionController.MAIN_SESSION_CONTROLLER_ATT, MainSessionController.class);
if (controller != null && token == null) {
//logger.warn("security.web.protection.token is disable");
// generate fake token for auto login without token security
TokenGenerator generator =
TokenGeneratorProvider.getTokenGenerator(SynchronizerToken.class);
token = generator.generate();
session.setAttribute(SESSION_TOKEN_KEY, token);
}
if (session.getAttribute(SESSION_PARAMS_KEY, String.class) != null && params.isEmpty()) {
params = session.removeAttribute(SESSION_PARAMS_KEY, String.class);
}
String aDestinationPage = "/silverpeas/spmobile/spmobil.jsp" + params;
session.setAttribute(SESSION_PARAMS_KEY, params);
String urlWithSessionID = response.encodeRedirectURL(aDestinationPage);
response.sendRedirect(urlWithSessionID);
return;
}
}
chain.doFilter(req, res);
}
private String extractSurveyParameters(final ServletRequest req) {
String url = ((HttpServletRequest) req).getRequestURL().toString();
String id = "";
String appId = "";
String contentType;
if (url.contains("Rsurvey")) {
String subUrl = url.substring(url.indexOf("/Rsurvey"));
appId = subUrl.replace("/Rsurvey/", "");
appId = appId.substring(0, appId.indexOf("/"));
contentType = "Component";
} else {
id = url.substring(url.lastIndexOf("/") + 1);
QuestionContainerPK pk = new QuestionContainerPK(id, null, null);
appId =
QuestionContainerService.get().getQuestionContainer(pk, null).getComponentInstanceId();
contentType = "QuestionContainer";
}
String params =
"?shortcutContentType=" + contentType + "&shortcutContentId=" + id + "&shortcutAppId=" +
appId;
return params;
}
private String extractWorkflowParameters(final ServletRequest req) {
/*
Url example :
/RprocessManager/demandeCongesSimple5/searchResult?Type=ProcessInstance&Id=22&role=Responsable
*/
String url = ((HttpServletRequest) req).getRequestURL().toString();
Pattern pattern = Pattern.compile("\\w+" + "/RprocessManager/" + "(?<appId>\\w+)/\\w+");
Matcher parameters = pattern.matcher(url);
parameters.find();
String appId = parameters.group("appId");
String contentType = ((HttpServletRequest) req).getParameter("Type");
String id = ((HttpServletRequest) req).getParameter("Id");
String role = ((HttpServletRequest) req).getParameter("role");
String params =
"?shortcutContentType=" + contentType + "&shortcutContentId=" + id + "&shortcutAppId=" +
appId + "&shortcutRole=" + role;
return params;
}
private boolean isRedirect(final String url) {
String urlRes = url.toLowerCase();
if (urlsAllowed != null) {
for (int i = 0; i < urlsAllowed.length; i++) {
if (!urlsAllowed[i].isEmpty() && urlRes.contains(urlsAllowed[i].toLowerCase())) {
return false;
}
}
}
if (urlRes.contains("weblib")) {
return false;
}
if (urlRes.toLowerCase().endsWith(".css")) {
return false;
}
if (urlRes.toLowerCase().endsWith(".gif")) {
return false;
}
if (urlRes.toLowerCase().endsWith(".jpg")) {
return false;
}
if (urlRes.toLowerCase().endsWith(".png")) {
return false;
}
return true;
}
@Override
public void init(FilterConfig arg0) throws ServletException {
SettingBundle config = ResourceLocator.getSettingBundle("org.silverpeas.mobile.mobileSettings");
String urls = config.getString("mobile.redirection.disabled.urls");
urlsAllowed = urls.split(",");
}
private PublicationService getPubBm() {
return PublicationService.get();
}
private GalleryService getGalleryService() {
return MediaServiceProvider.getMediaService();
}
}