/*
* #%L
* ACS AEM Commons Bundle
* %%
* Copyright (C) 2013 Adobe
* %%
* 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.
* #L%
*/
package com.adobe.acs.commons.quickly.impl;
import com.adobe.acs.commons.quickly.QuicklyEngine;
import com.adobe.acs.commons.util.BufferingResponse;
import com.adobe.acs.commons.util.ResourceDataUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import javax.jcr.RepositoryException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Map;
/**
* ACS AEM Commons - Quickly - App HTML Injection Filter
* Injects the necessary HTML into the Request page.
*/
@Component(policy = ConfigurationPolicy.OPTIONAL)
@Property(name = "pattern",
value = ".*")
@Service
public class QuicklyFilter implements Filter {
private static final String[] REJECT_PATH_PREFIXES = new String[]{
"/libs/granite/core/content/login",
};
private static final String HTML_FILE = "/quickly/inject.html";
private static String appHTML = "";
@Reference
private QuicklyEngine quicklyEngine;
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(final ServletRequest servletRequest,
final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
if(!accepts(request)) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
final BufferingResponse capturedResponse = new BufferingResponse(response);
filterChain.doFilter(request, capturedResponse);
// Get contents
final String contents = capturedResponse.getContents();
if (contents != null && StringUtils.contains(response.getContentType(), "html")) {
final int bodyIndex = contents.indexOf("</body>");
if (bodyIndex != -1) {
final PrintWriter printWriter = response.getWriter();
printWriter.write(contents.substring(0, bodyIndex));
printWriter.write(appHTML);
printWriter.write(contents.substring(bodyIndex));
return;
}
}
if (contents != null) {
response.getWriter().write(contents);
}
}
@Override
public void destroy() {
}
private boolean accepts(final HttpServletRequest request) {
if (!StringUtils.equalsIgnoreCase("get", request.getMethod())) {
// Only inject on GET requests
return false;
} else if (StringUtils.startsWithAny(request.getRequestURI(), REJECT_PATH_PREFIXES)) {
return false;
} else if (StringUtils.equals(request.getHeader("X-Requested-With"), "XMLHttpRequest")) {
// Do not inject into XHR requests
return false;
} else if (StringUtils.endsWith(request.getHeader("Referer"), "/editor.html" + request.getRequestURI())) {
// Do not apply to pages loaded in the TouchUI editor.html
return false;
} else if (StringUtils.endsWith(request.getHeader("Referer"), "/cf")) {
// Do not apply to pages loaded in the Content Finder
return false;
}
return true;
}
@Activate
protected final void activate(final Map<String, String> config) throws IOException {
InputStream inputStream = null;
try {
inputStream = getClass().getResourceAsStream(HTML_FILE);
appHTML = IOUtils.toString(inputStream, "UTF-8");
} finally {
IOUtils.closeQuietly(inputStream);
}
}
}