/*
* This file is part of the Wayback archival access software
* (http://archive-access.sourceforge.net/projects/wayback/).
*
* Licensed to the Internet Archive (IA) by one or more individual
* contributors.
*
* The IA licenses this file to You 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.archive.wayback.webapp;
import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.archive.net.UURI;
import org.archive.net.UURIFactory;
import org.archive.util.ArchiveUtils;
import org.archive.wayback.util.Timestamp;
import org.archive.wayback.util.url.UrlOperations;
import org.archive.wayback.util.webapp.AbstractRequestHandler;
/**
* @author brad
*
*/
public class ServerRelativeArchivalRedirect extends AbstractRequestHandler {
private static final Logger LOGGER = Logger.getLogger(
ServerRelativeArchivalRedirect.class.getName());
boolean useCollection = false;
private String matchHost = null;
private int matchPort = -1;
private String replayPrefix;
private boolean handleRequestWithCollection(HttpServletRequest httpRequest,
HttpServletResponse httpResponse) throws ServletException,
IOException {
boolean handled = false;
// hope that it's a server relative request, with a valid referrer:
String referer = httpRequest.getHeader("Referer");
if(referer != null) {
UURI uri = UURIFactory.getInstance(referer);
String path = uri.getPath();
int secondSlash = path.indexOf('/',1);
if(secondSlash > -1) {
String collection = path.substring(0,secondSlash);
String remainder = path.substring(secondSlash+1);
int thirdSlash = remainder.indexOf('/');
if(thirdSlash > -1) {
String datespec = remainder.substring(0,thirdSlash);
String url = ArchiveUtils.addImpliedHttpIfNecessary(
remainder.substring(thirdSlash+1));
String thisPath = httpRequest.getRequestURI();
String queryString = httpRequest.getQueryString();
if (queryString != null) {
thisPath += "?" + queryString;
}
String resolved = UrlOperations.resolveUrl(url, thisPath);
String contextPath = httpRequest.getContextPath();
String finalUrl = uri.getScheme() + "://" +
uri.getAuthority() + contextPath + collection + "/"
+ datespec + "/" + resolved;
// cross your fingers!!!
LOGGER.info("Server-Relative-Redirect:\t" + referer + "\t"
+ thisPath + "\t" + finalUrl);
// Gotta make sure this is properly cached, or
// weird things happen:
httpResponse.addHeader("Vary", "Referer");
httpResponse.sendRedirect(finalUrl);
handled = true;
}
}
}
return handled;
}
private boolean handleRequestWithoutCollection(HttpServletRequest httpRequest,
HttpServletResponse httpResponse) throws ServletException,
IOException {
boolean handled = false;
// hope that it's a server relative request, with a valid referrer:
String referer = httpRequest.getHeader("Referer");
if(referer != null) {
LOGGER.fine("referer:" + referer);
UURI uri = UURIFactory.getInstance(referer);
String path = uri.getPath();
String remainder = path.substring(1);
int thirdSlash = remainder.indexOf('/');
LOGGER.fine("referer:(" + referer + ") remain(" + remainder + ") 3rd("+thirdSlash+")");
if(thirdSlash > -1) {
String datespec = remainder.substring(0,thirdSlash);
String url = ArchiveUtils.addImpliedHttpIfNecessary(
remainder.substring(thirdSlash+1));
String thisPath = httpRequest.getRequestURI();
String queryString = httpRequest.getQueryString();
if (queryString != null) {
thisPath += "?" + queryString;
}
String resolved = UrlOperations.resolveUrl(url, thisPath);
String contextPath = httpRequest.getContextPath();
String finalUrl = uri.getScheme() + "://" +
uri.getAuthority() + contextPath + "/"
+ datespec + "/" + resolved;
// cross your fingers!!!
LOGGER.info("Server-Relative-Redirect:\t" + referer + "\t"
+ thisPath + "\t" + finalUrl);
// Gotta make sure this is properly cached, or
// weird things happen:
httpResponse.addHeader("Vary", "Referer");
httpResponse.sendRedirect(finalUrl);
handled = true;
}
}
return handled;
}
public boolean handleRequest(HttpServletRequest httpRequest,
HttpServletResponse httpResponse) throws ServletException,
IOException {
if(matchHost != null) {
if(!matchHost.equals(httpRequest.getServerName())) {
LOGGER.fine("Wrong host for ServerRelativeRed(" +
httpRequest.getServerName() +")");
return false;
}
}
if(matchPort != -1) {
if(matchPort != httpRequest.getLocalPort()) {
LOGGER.fine("Wrong port for ServerRealtiveRed(" +
httpRequest.getServerName() + ")(" +
httpRequest.getLocalPort() +") :" +
httpRequest.getRequestURI());
return false;
}
}
boolean handled = useCollection ?
handleRequestWithCollection(httpRequest, httpResponse):
handleRequestWithoutCollection(httpRequest, httpResponse);
if(!handled) {
if(replayPrefix != null) {
String thisPath = httpRequest.getRequestURI();
String queryString = httpRequest.getQueryString();
if (queryString != null) {
thisPath += "?" + queryString;
}
if(thisPath.startsWith("/http://")) {
// assume a replay request:
StringBuilder sb = new StringBuilder(thisPath.length() + replayPrefix.length() + 16);
sb.append(replayPrefix);
sb.append(Timestamp.currentTimestamp().getDateStr());
sb.append(thisPath);
httpResponse.sendRedirect(sb.toString());
handled = true;
}
}
}
return handled;
}
/**
* @return the useCollection
*/
public boolean isUseCollection() {
return useCollection;
}
/**
* @param useCollection the useCollection to set
*/
public void setUseCollection(boolean useCollection) {
this.useCollection = useCollection;
}
/**
* @return the matchHost
*/
public String getMatchHost() {
return matchHost;
}
/**
* @param matchHost the matchHost to set
*/
public void setMatchHost(String matchHost) {
this.matchHost = matchHost;
}
/**
* @return the matchPort
*/
public int getMatchPort() {
return matchPort;
}
/**
* @param matchPort the matchPort to set
*/
public void setMatchPort(int matchPort) {
this.matchPort = matchPort;
}
/**
* @return the replayPrefix
*/
public String getReplayPrefix() {
return replayPrefix;
}
/**
* @param replayPrefix the replayPrefix to set
*/
public void setReplayPrefix(String replayPrefix) {
this.replayPrefix = replayPrefix;
}
}