Compare commits

...

8 Commits

3 changed files with 177 additions and 1 deletions

View File

@ -19,7 +19,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import net.i2p.I2PAppContext;
import net.i2p.app.*;
import static net.i2p.app.ClientAppState.*;

View File

@ -0,0 +1,158 @@
package net.i2p.servlet.filters;
import java.io.IOException;
import java.io.File;
import java.util.Properties;
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.net.URISyntaxException;
import java.net.URL;
import net.i2p.data.DataHelper;
import net.i2p.I2PAppContext;
import net.i2p.data.Destination;
import net.i2p.data.PrivateKeyFile;
import net.i2p.I2PException;
import net.i2p.util.Log;
/**
* @since 0.9.50
*/
public class XI2PLocationFilter implements Filter {
private String X_I2P_LOCATION = null;
Log _log = I2PAppContext.getGlobalContext().logManager().getLog(XI2PLocationFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
if (_log.shouldInfo())
_log.info("Preconfiguring X-I2P-LOCATION header location Filter");
}
private synchronized void setLocation(String xi2plocation) {
if (X_I2P_LOCATION != null)
return ;
if (xi2plocation == null)
return ;
if (xi2plocation.equals(""))
return ;
X_I2P_LOCATION = xi2plocation;
}
public String getXI2PLocation(String host, String port) {
File configDir = I2PAppContext.getGlobalContext().getConfigDir();
File tunnelConfig = new File(configDir, "i2ptunnel.config");
boolean isSingleFile = tunnelConfig.exists();
if (!isSingleFile) {
File tunnelConfigD = new File(configDir, "i2ptunnel.config.d");
File[] configFiles = tunnelConfigD.listFiles(new net.i2p.util.FileSuffixFilter(".config"));
for (int fnum=0; fnum < configFiles.length; fnum++) {
Properties tunnelProps = new Properties();
try {
DataHelper.loadProps(tunnelProps, configFiles[fnum]);
if ( host.equals(tunnelProps.getProperty("targetHost")) && port.equals(tunnelProps.getProperty("targetPort")) ) {
File keyFile = new File(configDir, tunnelProps.getProperty("privKeyFile"));
if (keyFile != null) {
PrivateKeyFile pkf = new PrivateKeyFile(keyFile);
try {
Destination rv = pkf.getDestination();
if (rv != null)
return rv.toBase32();
} catch (I2PException e) {
_log.error("I2PException Unable to set X-I2P-LOCATION, keys arent ready. This is probably safe to ignore and will go away after the first run." + e);
return null;
} catch (IOException e) {
_log.error("IOE Unable to set X-I2P-LOCATION, location is uninitialized due file not found. This probably means the keys aren't ready. This is probably safe to ignore." + e);
return null;
}
}
_log.error("Unable to set X-I2P-LOCATION, location is target not found in any I2PTunnel config file. This should never happen.");
return null;
}
} catch (IOException ioe) {
_log.error("IOE Unable to set X-I2P-LOCATION, location is uninitialized. This is probably safe to ignore. location='" + ioe + "'");
return null;
}
}
} else {
int i = -1;
while (true) {
Properties tunnelProps = new Properties();
// next config in the file
i++;
if (i == 0) {
try {
DataHelper.loadProps(tunnelProps, tunnelConfig);
String checkHost = tunnelProps.getProperty("tunnel."+String.valueOf(i)+".targetHost");
if (checkHost == null) {
break;
}
if ( host.equals(checkHost) && port.equals(tunnelProps.getProperty("tunnel."+String.valueOf(i)+".targetPort")) ) {
File keyFile = new File(configDir, tunnelProps.getProperty("privKeyFile"));
if (keyFile != null) {
PrivateKeyFile pkf = new PrivateKeyFile(keyFile);
try {
Destination rv = pkf.getDestination();
if (rv != null)
return rv.toBase32();
} catch (I2PException e) {
_log.error("I2PException Unable to set X-I2P-LOCATION, keys arent ready. This is probably safe to ignore and will go away after the first run." + e);
return null;
} catch (IOException e) {
_log.error("IOE Unable to set X-I2P-LOCATION, location is uninitialized due file not found. This probably means the keys aren't ready. This is probably safe to ignore." + e);
return null;
}
}
_log.error("Unable to set X-I2P-LOCATION, location is target not found in any I2PTunnel config file. This should never happen.");
return null;
}
} catch (IOException ioe) {
_log.error("IOE Unable to set X-I2P-LOCATION, location is uninitialized. This is probably safe to ignore. location='" + ioe + "'");
return null;
}
}
}
}
return null;
}
@Override
public void destroy() {
}
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException,
ServletException {
if (X_I2P_LOCATION == null) {
setLocation(getXI2PLocation(request.getLocalAddr(), String.valueOf(request.getLocalPort())));
}
if (X_I2P_LOCATION != null) {
final HttpServletRequest httpRequest = (HttpServletRequest) request;
final HttpServletResponse httpResponse = (HttpServletResponse) response;
final String requestUri = httpRequest.getRequestURL().toString();
URL url = new URL(requestUri);
String domain = url.getHost();
if (domain != null) {
if (!domain.endsWith(".i2p")) {
httpResponse.addHeader("X-I2P-LOCATION", X_I2P_LOCATION+url.getPath());
}
}
}
chain.doFilter(request, response);
}
}

View File

@ -42,5 +42,24 @@ to serve static html files and images.
<Arg>net.i2p.servlet.I2PDefaultServlet</Arg>
<Arg>/</Arg>
</Call>
<Call name="addFilter">
<Arg>
<New class="org.eclipse.jetty.servlet.FilterHolder" >
<Arg>
<New class="net.i2p.servlet.filters.XI2PLocationFilter" />
</Arg>
</New>
</Arg>
<Arg>/*</Arg>
<Arg>
<Call class="java.util.EnumSet" name="of" >
<Arg>
<Call class="javax.servlet.DispatcherType" name="valueOf" >
<Arg>REQUEST</Arg>
</Call>
</Arg>
</Call>
</Arg>
</Call>
</Configure>