fix #2837 Removed scriptlet usage in Admin Design page for better code maintainability.

This commit is contained in:
Shinsuke Sugaya 2024-07-28 18:03:48 +09:00
parent 8c48ac1f8a
commit e55ecd72fe
7 changed files with 67 additions and 13 deletions

View file

@ -22,6 +22,7 @@ import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
@ -47,6 +48,10 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
*/
public class AdminDesignAction extends FessAdminAction {
private static final String CACHE_AND_SESSION_INVALIDATE_STATEMENT = "<!--CACHE_AND_SESSION_INVALIDATE-->";
private static final String TRY_STATEMENT = "<!--TRY-->";
public static final String ROLE = "admin-design";
private static final Logger logger = LogManager.getLogger(AdminDesignAction.class);
@ -237,7 +242,7 @@ public class AdminDesignAction extends FessAdminAction {
final String jspType = "view";
final File jspFile = getJspFile(form.fileName, jspType);
try {
form.content = new String(FileUtil.readBytes(jspFile), Constants.UTF_8);
form.content = encodeJsp(new String(FileUtil.readBytes(jspFile), Constants.UTF_8));
} catch (final UnsupportedEncodingException e) {
throw new FessSystemException("Invalid encoding", e);
}
@ -251,7 +256,7 @@ public class AdminDesignAction extends FessAdminAction {
final String jspType = "orig/view";
final File jspFile = getJspFile(form.fileName, jspType);
try {
form.content = new String(FileUtil.readBytes(jspFile), Constants.UTF_8);
form.content = encodeJsp(new String(FileUtil.readBytes(jspFile), Constants.UTF_8));
} catch (final UnsupportedEncodingException e) {
throw new FessSystemException("Invalid encoding", e);
}
@ -272,7 +277,7 @@ public class AdminDesignAction extends FessAdminAction {
validate(form, messages -> {}, () -> asEditHtml(form));
verifyToken(() -> asEditHtml(form));
try {
write(jspFile.getAbsolutePath(), form.content.getBytes(Constants.UTF_8));
write(jspFile.getAbsolutePath(), decodeJsp(form.content).getBytes(Constants.UTF_8));
saveInfo(messages -> messages.addSuccessUpdateDesignJspFile(GLOBAL, jspFile.getAbsolutePath()));
} catch (final Exception e) {
logger.warn("Failed to update {}", form.fileName, e);
@ -351,4 +356,15 @@ public class AdminDesignAction extends FessAdminAction {
data.register("displayFileName", getJspFile(form.fileName, "view").getAbsolutePath());
});
}
public static String decodeJsp(final String value) {
return value.replaceAll("<%(?![@-])([\\s\\S]*?)%>", "&lt;%$1%&gt;").replaceAll("<%=([\\s\\S]*?)%>", "&lt;%=$1%&gt;")
.replaceAll(TRY_STATEMENT, "<% try{ %>")
.replaceAll(CACHE_AND_SESSION_INVALIDATE_STATEMENT, "<% }catch(Exception e){session.invalidate();} %>");
}
public static String encodeJsp(final String value) {
return value.replaceAll(Pattern.quote("<% try{ %>"), TRY_STATEMENT)
.replaceAll(Pattern.quote("<% }catch(Exception e){session.invalidate();} %>"), CACHE_AND_SESSION_INVALIDATE_STATEMENT);
}
}

View file

@ -95,10 +95,6 @@
<arg>"errorSystem"</arg>
<arg>"error/system.jsp"</arg>
</postConstruct>
<postConstruct name="addDesignJspFileName">
<arg>"errorRedirect"</arg>
<arg>"error/redirect.jsp"</arg>
</postConstruct>
<postConstruct name="addDesignJspFileName">
<arg>"errorBadRequest"</arg>
<arg>"error/badRequest.jsp"</arg>

View file

@ -24,7 +24,7 @@
</div>
</main>
<jsp:include page="../footer.jsp" />
<input type="hidden" id="contextPath" value="<%=request.getContextPath()%>" />
<input type="hidden" id="contextPath" value="${pageContext.request.contextPath}" />
<script type="text/javascript"
src="${fe:url('/js/jquery-3.6.3.min.js')}"></script>
<script type="text/javascript" src="${fe:url('/js/bootstrap.min.js')}"></script>
@ -32,4 +32,4 @@
<script type="text/javascript" src="${fe:url('/js/search.js')}"></script>
</body>
</html>
<% }catch(Exception e){ session.invalidate();}%>
<% }catch(Exception e){session.invalidate();} %>

View file

@ -28,7 +28,7 @@
</div>
</main>
<jsp:include page="../footer.jsp" />
<input type="hidden" id="contextPath" value="<%=request.getContextPath()%>" />
<input type="hidden" id="contextPath" value="${pageContext.request.contextPath}" />
<script type="text/javascript"
src="${fe:url('/js/jquery-3.6.3.min.js')}"></script>
<script type="text/javascript" src="${fe:url('/js/bootstrap.min.js')}"></script>

View file

@ -26,7 +26,7 @@
</div>
</main>
<jsp:include page="../footer.jsp" />
<input type="hidden" id="contextPath" value="<%=request.getContextPath()%>" />
<input type="hidden" id="contextPath" value="${pageContext.request.contextPath}" />
<script type="text/javascript"
src="${fe:url('/js/jquery-3.6.3.min.js')}"></script>
<script type="text/javascript" src="${fe:url('/js/bootstrap.min.js')}"></script>

View file

@ -24,7 +24,7 @@
</div>
</main>
<jsp:include page="../footer.jsp" />
<input type="hidden" id="contextPath" value="<%=request.getContextPath()%>" />
<input type="hidden" id="contextPath" value="${pageContext.request.contextPath}" />
<script type="text/javascript"
src="${fe:url('/js/jquery-3.6.3.min.js')}"></script>
<script type="text/javascript" src="${fe:url('/js/bootstrap.min.js')}"></script>
@ -32,4 +32,4 @@
<script type="text/javascript" src="${fe:url('/js/search.js')}"></script>
</body>
</html>
<% }catch(Exception e){ session.invalidate();}%>
<% }catch(Exception e){session.invalidate();} %>

View file

@ -0,0 +1,42 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.codelibs.fess.app.web.admin.design;
import org.codelibs.fess.unit.UnitFessTestCase;
public class AdminDesignActionTest extends UnitFessTestCase {
public void test_decodeJsp() {
assertEquals("&lt;% a %&gt;", AdminDesignAction.decodeJsp("<% a %>"));
assertEquals("&lt;%= a %&gt;", AdminDesignAction.decodeJsp("<%= a %>"));
assertEquals("&lt;% a\nb %&gt;", AdminDesignAction.decodeJsp("<% a\nb %>"));
assertEquals("&lt;%= a\nb %&gt;", AdminDesignAction.decodeJsp("<%= a\nb %>"));
assertEquals("<% a", AdminDesignAction.decodeJsp("<% a"));
assertEquals("<%= a", AdminDesignAction.decodeJsp("<%= a"));
assertEquals("<% try{ %>", AdminDesignAction.decodeJsp("<!--TRY-->"));
assertEquals("<% }catch(Exception e){session.invalidate();} %>",
AdminDesignAction.decodeJsp("<!--CACHE_AND_SESSION_INVALIDATE-->"));
assertEquals("&lt;% a %&gt; %>", AdminDesignAction.decodeJsp("<% a %> %>"));
assertEquals("&lt;% a %&gt; <%", AdminDesignAction.decodeJsp("<% a %> <%"));
assertEquals("&lt;% <% a %&gt;", AdminDesignAction.decodeJsp("<% <% a %>"));
assertEquals("%> &lt;% a %&gt;", AdminDesignAction.decodeJsp("%> <% a %>"));
}
public void test_encodeJsp() {
assertEquals("<!--TRY-->", AdminDesignAction.encodeJsp("<% try{ %>"));
assertEquals("<!--CACHE_AND_SESSION_INVALIDATE-->",
AdminDesignAction.encodeJsp("<% }catch(Exception e){session.invalidate();} %>"));
}
}