propagate from branch 'i2p.i2p' (head b3d611a1fe034bc89963c54179d5bef3a3147950)

to branch 'i2p.i2p.zzz.jetty6' (head c83bf7bd62d0e07be0d965f062f01b01864be4d2)
This commit is contained in:
zzz
2012-01-14 18:04:39 +00:00
135 changed files with 4252 additions and 6998 deletions

View File

@ -172,8 +172,9 @@ Applications:
By welterde.
See licenses/LICENSE-GPLv2.txt
Jetty 5.1.15:
Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
Jetty 6.1.26:
Copyright 1995-2009 Mort Bay Consulting Pty Ltd
See licenses/LICENSE-Jetty.txt
See licenses/LICENSE-Apache2.0.txt
See licenses/NOTICE-Commons-Logging.txt
@ -215,8 +216,10 @@ Applications:
Copyright (C) 2005 <susi23@mail.i2p>
GPLv2 (or any later version)
See licenses/LICENSE-GPLv2.txt
Uses Apache Jakarta Standard Tag Library 1.1.2:
See licenses/LICENSE-Apache2.0.txt
Uses Glassfish Standard Tag Library (JSTL) 1.2:
Common Development and Distribution License (CDDL) version 1.0 + GNU General Public License (GPL) version 2
See https://glassfish.dev.java.net/public/CDDL+GPL.html
See licenses/LICENSE-GPLv2.txt
SusiMail:
Copyright (C) 2004-2005 <susi23@mail.i2p>
@ -228,6 +231,10 @@ Applications:
Bundles systray4j-2.4.1:
See licenses/LICENSE-LGPLv2.1.txt
Tomcat 6.0.35:
Copyright 1999-2011 The Apache Software Foundation
See licenses/LICENSE-Apache2.0.txt
See licenses/NOTICE-Tomcat.txt
Other Applications and Libraries

View File

@ -84,7 +84,7 @@ public class Servlet extends HttpServlet {
this.thread.setDaemon(true);
this.thread.setName("Addressbook");
this.thread.start();
System.out.println("INFO: Starting Addressbook " + Daemon.VERSION);
//System.out.println("INFO: Starting Addressbook " + Daemon.VERSION);
//System.out.println("INFO: config root under " + args[0]);
}

View File

@ -19,6 +19,7 @@
<pathelement location="../../ministreaming/java/build/obj" />
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
</classpath>
</depend>
</target>
@ -34,7 +35,7 @@
debug="true" deprecation="on" source="1.5" target="1.5"
destdir="./build/obj"
includeAntRuntime="false"
classpath="../../../core/java/build/i2p.jar:../../jetty/jettylib/org.mortbay.jetty.jar:../../jetty/jettylib/javax.servlet.jar:../../ministreaming/java/build/mstreaming.jar" >
classpath="../../../core/java/build/i2p.jar:../../jetty/jettylib/org.mortbay.jetty.jar:../../jetty/jettylib/javax.servlet.jar:../../jetty/jettylib/jetty-util.jar:../../ministreaming/java/build/mstreaming.jar" >
<compilerarg line="${javac.compilerargs}" />
</javac>
</target>

View File

@ -43,17 +43,16 @@ import org.klomp.snark.SnarkManager;
import org.klomp.snark.Storage;
import org.klomp.snark.TrackerClient;
import org.mortbay.http.HttpResponse;
import org.mortbay.jetty.servlet.Default;
import org.mortbay.util.Resource;
import org.mortbay.util.URI;
import org.mortbay.jetty.servlet.DefaultServlet;
import org.mortbay.resource.Resource;
import org.mortbay.util.URIUtil;
/**
* We extend Default instead of HTTPServlet so we can handle
* i2psnark/ file requests with http:// instead of the flaky and
* often-blocked-by-the-browser file://
*/
public class I2PSnarkServlet extends Default {
public class I2PSnarkServlet extends DefaultServlet {
private I2PAppContext _context;
private Log _log;
private SnarkManager _manager;
@ -99,13 +98,17 @@ public class I2PSnarkServlet extends Default {
* and we can't get any resources (like icons) out of the .war
*/
@Override
protected Resource getResource(String pathInContext) throws IOException
public Resource getResource(String pathInContext)
{
if (pathInContext == null || pathInContext.equals("/") || pathInContext.equals("/index.jsp") ||
pathInContext.equals("/index.html") || pathInContext.startsWith("/_icons/"))
return super.getResource(pathInContext);
// files in the i2psnark/ directory
return _resourceBase.addPath(pathInContext);
try {
return _resourceBase.addPath(pathInContext);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
@ -113,10 +116,11 @@ public class I2PSnarkServlet extends Default {
* @since 0.8.3
*/
@Override
public void handleGet(HttpServletRequest request, HttpServletResponse response, String pathInContext, Resource resource, boolean endsWithSlash) throws ServletException, IOException {
if (resource.getName().startsWith("jar:file:"))
response.setHeader("Cache-Control", "max-age=86400"); // cache for a day
super.handleGet(request, response, pathInContext, resource, endsWithSlash);
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
////////////////////////////////////
//if (resource.getName().startsWith("jar:file:"))
// response.setHeader("Cache-Control", "max-age=86400"); // cache for a day
super.doGet(request, response);
}
/**
@ -144,7 +148,7 @@ public class I2PSnarkServlet extends Default {
// since we are not overriding handle*(), do this here
String method = req.getMethod();
if (!(method.equals("GET") || method.equals("HEAD") || method.equals("POST"))) {
resp.sendError(HttpResponse.__405_Method_Not_Allowed);
resp.sendError(405);
return;
}
_themePath = "/themes/snark/" + _manager.getTheme() + '/';
@ -157,20 +161,20 @@ public class I2PSnarkServlet extends Default {
if (path.endsWith("/")) {
// bypass the horrid Resource.getListHTML()
String pathInfo = req.getPathInfo();
String pathInContext = URI.addPaths(path, pathInfo);
String pathInContext = URIUtil.addPaths(path, pathInfo);
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=UTF-8");
Resource resource = getResource(pathInContext);
if (resource == null || (!resource.exists())) {
resp.sendError(HttpResponse.__404_Not_Found);
resp.sendError(404);
} else {
String base = URI.addPaths(req.getRequestURI(), "/");
String base = URIUtil.addPaths(req.getRequestURI(), "/");
String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null);
if (listing != null)
resp.getWriter().write(listing);
else // shouldn't happen
resp.sendError(HttpResponse.__404_Not_Found);
resp.sendError(404);
}
} else {
super.service(req, resp);
@ -1680,7 +1684,7 @@ public class I2PSnarkServlet extends Default {
StringBuilder buf=new StringBuilder(4096);
buf.append(DOCTYPE + "<HTML><HEAD><TITLE>");
String title = URI.decodePath(base);
String title = URIUtil.decodePath(base);
if (title.startsWith("/i2psnark/"))
title = title.substring("/i2psnark/".length());
@ -1783,7 +1787,7 @@ public class I2PSnarkServlet extends Default {
.append(_("Priority")).append("</th>");
buf.append("</tr></thead>\n");
buf.append("<tr><td colspan=\"" + (showPriority ? '4' : '3') + "\" class=\"ParentDir\"><A HREF=\"");
buf.append(URI.addPaths(base,"../"));
buf.append(URIUtil.addPaths(base,"../"));
buf.append("\"><img alt=\"\" border=\"0\" src=\"" + _imgPath + "up.png\"> ")
.append(_("Up to higher level directory")).append("</A></td></tr>\n");
@ -1793,7 +1797,7 @@ public class I2PSnarkServlet extends Default {
boolean showSaveButton = false;
for (int i=0 ; i< ls.length ; i++)
{
String encoded=URI.encodePath(ls[i]);
String encoded=URIUtil.encodePath(ls[i]);
// bugfix for I2P - Backport from Jetty 6 (zero file lengths and last-modified times)
// http://jira.codehaus.org/browse/JETTY-361?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel#issue-tabs
// See resource.diff attachment
@ -1849,9 +1853,9 @@ public class I2PSnarkServlet extends Default {
}
}
String path=URI.addPaths(base,encoded);
String path=URIUtil.addPaths(base,encoded);
if (item.isDirectory() && !path.endsWith("/"))
path=URI.addPaths(path,"/");
path=URIUtil.addPaths(path,"/");
String icon = toIcon(item);
if (complete) {

View File

@ -31,6 +31,8 @@ public class RunStandalone {
if (!workDirCreated)
System.err.println("ERROR: Unable to create Jetty temporary work directory");
throw new RuntimeException("unsupported");
/****
try {
_server = new Server("jetty-i2psnark.xml");
// just blow up NPE if we don't have a context
@ -39,13 +41,17 @@ public class RunStandalone {
} catch (Exception e) {
e.printStackTrace();
}
****/
}
public void stop() {
throw new RuntimeException("unsupported");
/****
try {
_server.stop();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
****/
}
}

View File

@ -52,13 +52,11 @@
</target>
<!-- TODO: Move the web classes from the jar to the war - they are not part of the API
- This will require sponge to rewrite some seedless stuff that uses it.
-->
<!-- The web classes are now in the war not the jar - they are not part of the API -->
<target name="jar" depends="builddep, compile, jarUpToDate, listChangedFiles" unless="jar.uptodate" >
<!-- set if unset -->
<property name="workspace.changes.j.tr" value="" />
<jar destfile="./build/i2ptunnel.jar" basedir="./build/obj" includes="**/*.class">
<jar destfile="./build/i2ptunnel.jar" basedir="./build/obj" includes="**/*.class" excludes="**/EditBean.class **/IndexBean.class" >
<manifest>
<attribute name="Main-Class" value="net.i2p.i2ptunnel.I2PTunnel" />
<attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
@ -67,6 +65,7 @@
<attribute name="Workspace-Changes" value="${workspace.changes.j.tr}" />
</manifest>
</jar>
<jar destfile="./build/temp-beans.jar" basedir="./build/obj" includes="**/EditBean.class **/IndexBean.class" />
</target>
<target name="jarUpToDate">
@ -128,9 +127,12 @@
</exec>
</target>
<!-- The web classes are now in the war not the jar - they are not part of the API -->
<target name="war" depends="precompilejsp, bundle, warUpToDate, listChangedFiles2" unless="war.uptodate" >
<!-- set if unset -->
<property name="workspace.changes.w.tr" value="" />
<copy file="build/obj/net/i2p/i2ptunnel/web/EditBean.class" todir="../jsp/WEB-INF/classes/net/i2p/i2ptunnel/web" />
<copy file="build/obj/net/i2p/i2ptunnel/web/IndexBean.class" todir="../jsp/WEB-INF/classes/net/i2p/i2ptunnel/web" />
<war destfile="build/i2ptunnel.war" webxml="../jsp/web-out.xml"
basedir="../jsp/" excludes="web.xml, web-fragment.xml, web-out.xml, **/*.java, *.jsp">
<manifest>
@ -169,11 +171,14 @@
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
<pathelement location="../../jetty/jettylib/commons-el.jar" />
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
<pathelement location="../../jetty/jettylib/ant.jar" />
<pathelement location="build/i2ptunnel.jar" />
<pathelement location="build/temp-beans.jar" />
</classpath>
<arg value="-d" />
<arg value="../jsp/WEB-INF/classes" />
<arg value="-v" />
<arg value="-p" />
<arg value="net.i2p.i2ptunnel.jsp" />
<arg value="-webinc" />
@ -190,7 +195,9 @@
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
<pathelement location="../../jetty/jettylib/commons-el.jar" />
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
<pathelement location="build/i2ptunnel.jar" />
<pathelement location="build/temp-beans.jar" />
</classpath>
</javac>
<copy file="../jsp/web.xml" tofile="../jsp/web-out.xml" />

View File

@ -2,6 +2,7 @@
// NOTE: Do the header carefully so there is no whitespace before the <?xml... line
%><%@page pageEncoding="UTF-8"
%><%@page trimDirectiveWhitespaces="true"
%><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
%><%
String tun = request.getParameter("tunnel");

View File

@ -1,4 +1,6 @@
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"%><?xml version="1.0" encoding="UTF-8"?>
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
%><%@page trimDirectiveWhitespaces="true"
%><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<jsp:useBean class="net.i2p.i2ptunnel.web.EditBean" id="editBean" scope="request" />
<jsp:useBean class="net.i2p.i2ptunnel.web.Messages" id="intl" scope="request" />

View File

@ -1,4 +1,6 @@
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"%><?xml version="1.0" encoding="UTF-8"?>
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
%><%@page trimDirectiveWhitespaces="true"
%><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<jsp:useBean class="net.i2p.i2ptunnel.web.EditBean" id="editBean" scope="request" />
<jsp:useBean class="net.i2p.i2ptunnel.web.Messages" id="intl" scope="request" />

View File

@ -6,6 +6,7 @@
request.setCharacterEncoding("UTF-8");
%><%@page pageEncoding="UTF-8"
%><%@page trimDirectiveWhitespaces="true"
%><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.IndexBean"
%><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

View File

@ -0,0 +1,16 @@
Apache Tomcat
Copyright 1999-2011 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
The Windows Installer is built with the Nullsoft
Scriptable Install Sysem (NSIS), which is
open source software. The original software and
related information is available at
http://nsis.sourceforge.net.
Java compilation software for JSP pages is provided by Eclipse,
which is open source software. The original software and
related information is available at
http://www.eclipse.org.

View File

@ -0,0 +1,14 @@
This is Apache Tomcat 6.x, supporting Servlet 2.5 and JSP 2.1.
The Glassfish JSP 2.1 bundled in Jetty 6 is way too old.
Retrieved from the file
apache-tomcat-6.0.35-deployer.tar.gz
minus the following files and directores:
build.xml
deployer-howto.html
images/*
lib/catalina*
LICENSE (see ../../../licenses/LICENSE-Apache2.0.txt, it's also inside every jar)
RELEASE-NOTES

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,12 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="all" name="jetty">
<property name="jetty.base" value="jetty-5.1.15" />
<property name="jetty.sha1" value="3a7a3de50f86f0cdb23c33aec632ea7f44132c5e" />
<property name="jetty.filename" value="${jetty.base}.tgz" />
<property name="jetty.url" value="http://dist.codehaus.org/jetty/jetty-5.1.x/${jetty.filename}" />
<property name="jetty.ver" value="6.1.26" />
<property name="jetty.base" value="jetty-${jetty.ver}" />
<property name="jetty.sha1" value="9485913f1a1945a849a90f1a34853d22350bc524" />
<property name="jetty.filename" value="${jetty.base}.zip" />
<property name="jetty.url" value="http://dist.codehaus.org/jetty/${jetty.base}/${jetty.filename}" />
<property name="verified.filename" value="verified.txt" />
<property name="javac.compilerargs" value="" />
<property name="tomcat.lib" value="apache-tomcat-deployer/lib" />
<target name="all" depends="build" />
@ -64,26 +66,74 @@
</target>
<target name="extractJettylib" unless="jetty.zip.extracted" >
<!-- for .tgz -->
<!--
<gunzip src="${jetty.filename}" dest="jetty.tar" />
<untar src="jetty.tar" dest="." />
-->
<!-- for .zip -->
<unzip src="${jetty.filename}" dest="." />
<mkdir dir="jettylib" />
<copy todir="jettylib" preservelastmodified="true" >
<fileset dir="${jetty.base}/lib">
<include name="*.jar" />
</fileset>
<fileset dir="${jetty.base}/ext">
<include name="ant.jar" />
<include name="commons-el.jar" />
<include name="commons-logging.jar" />
<include name="jasper-compiler.jar" />
<include name="jasper-runtime.jar" />
</fileset>
</copy>
<!-- We copy everything to names without the version numbers so we
can update them later. Where there was something similar in Jetty 5,
we use the same names so they will overwrite the Jetty 5 jar on upgrade.
Otherwise we use the same name as the symlink in Ubuntu /usr/share/java.
Reasons for inclusion:
start.jar: Needed for clients.config startup of eepsites
jetty-util-xxx.jar: LifeCycle (base class for stuff), URIUtil (used in i2psnark)
jetty-sslengine-xxx.jar: SSL NIO Connector for console
jetty-java5-threadpool-xxx.jar: Concurrent thread pool for eepsite
glassfish 2.1: Not used, too old, see Tomcat below.
jetty-rewrite-handler: Not used by I2P, but only 20KB and could be useful for eepsites
All of these are available in the Ubuntu packages libjetty-java and libjetty-extra-java
-->
<copy preservelastmodified="true" file="${jetty.base}/start.jar" tofile="jettylib/jetty-start.jar" />
<copy file="${jetty.base}/lib/${jetty.base}.jar" tofile="jettylib/org.mortbay.jetty.jar" />
<copy preservelastmodified="true" file="${jetty.base}/lib/jetty-util-${jetty.ver}.jar" tofile="jettylib/jetty-util.jar" />
<copy preservelastmodified="true" file="${jetty.base}/lib/ext/jetty-java5-threadpool-${jetty.ver}.jar" tofile="jettylib/jetty-java5-threadpool.jar" />
<copy preservelastmodified="true" file="${jetty.base}/lib/ext/jetty-rewrite-handler-${jetty.ver}.jar" tofile="jettylib/jetty-rewrite-handler.jar" />
<copy preservelastmodified="true" file="${jetty.base}/lib/ext/jetty-sslengine-${jetty.ver}.jar" tofile="jettylib/jetty-sslengine.jar" />
<copy file="${jetty.base}/lib/jsp-2.1/ant-1.6.5.jar" tofile="jettylib/ant.jar" />
<delete file="jetty.tar" />
<delete dir="${jetty.base}" />
<!-- commons-logging.jar not in Jetty 6 but we have it in launch4j so copy it over, we need it
for org.apache.jasper.JspC compiler
-->
<copy preservelastmodified="true" file="../../installer/lib/launch4j/lib/commons-logging.jar" todir="jettylib/" />
<ant target="copyTomcatLib" />
</target>
<!-- Tomcat.
The glassfish jars bundled in Jetty 6 are way too old.
For compatibility with very old I2P installations where the classpath
was set individually in wrapper.config, we rename and combine the jars as follows:
jasper.jar : jasper-runtime.jar
jasper-el.jar + el-api.jar : commons-el.jar
servlet-api.jar + jsp-api.jar : javax.servlet.jar
tomcat-juli.jar : commons-logging.jar
empty jar : jasper-compiler.jar
Also, take NOTICE and LICENSE out of each one, we bundle those separately.
-->
<target name="copyTomcatLib" >
<jar destfile="jettylib/jasper-runtime.jar" >
<zipfileset excludes="META-INF/LICENSE META-INF/NOTICE" src="${tomcat.lib}/jasper.jar" />
</jar>
<jar destfile="jettylib/commons-el.jar" duplicate="preserve" >
<zipfileset excludes="META-INF/LICENSE META-INF/NOTICE" src="${tomcat.lib}/jasper-el.jar" />
<zipfileset excludes="META-INF/**/*" src="${tomcat.lib}/el-api.jar" />
</jar>
<jar destfile="jettylib/javax.servlet.jar" duplicate="preserve" >
<zipfileset excludes="META-INF/LICENSE META-INF/NOTICE" src="${tomcat.lib}/servlet-api.jar" />
<zipfileset excludes="META-INF/**/*" src="${tomcat.lib}/jsp-api.jar" />
</jar>
<jar destfile="jettylib/commons-logging.jar" >
<zipfileset excludes="META-INF/LICENSE META-INF/NOTICE" src="${tomcat.lib}/tomcat-juli.jar" />
</jar>
<jar destfile="jettylib/jasper-compiler.jar" />
</target>
<target name="build" depends="jar" />
<target name="builddep" />
<target name="compile" depends="builddep, ensureJettylib" >
<mkdir dir="./build" />
@ -93,7 +143,7 @@
debug="true" source="1.5" target="1.5"
destdir="./build/obj"
includeAntRuntime="false"
classpath="./jettylib/commons-logging.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar" >
classpath="../../core/java/build/i2p.jar:./jettylib/commons-logging.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar:./jettylib/jetty-util.jar" >
<compilerarg line="${javac.compilerargs}" />
</javac>
</target>
@ -112,10 +162,14 @@
</exec>
</target>
<!-- With Jetty 5 we replaced classes in the jar, but with Jetty 6 we
put our stuff in its own jar so we can work with standard Jetty 6 packages
-->
<target name="jar" depends="compile, jarUpToDate, listChangedFiles" unless="jar.uptodate" >
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<jar destfile="./jettylib/org.mortbay.jetty.jar" basedir="./build/obj" includes="**/*.class" update="true" >
<copy todir="build/obj" file="resources/log4j.properties" />
<jar destfile="./jettylib/jetty-i2p.jar" basedir="./build/obj" includes="**/*.class log4j.properties" >
<manifest>
<attribute name="Build-Date" value="${build.timestamp}" />
<attribute name="Base-Revision" value="${workspace.version}" />
@ -125,7 +179,7 @@
</target>
<target name="jarUpToDate">
<uptodate property="jar.uptodate" targetfile="jettylib/org.mortbay.jetty.jar" >
<uptodate property="jar.uptodate" targetfile="jettylib/jetty-i2p.jar" >
<srcfiles dir= "build/obj" includes="**/*.class" />
</uptodate>
<condition property="shouldListChanges" >

View File

@ -0,0 +1,175 @@
// ========================================================================
// Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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 net.i2p.jetty;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
import org.mortbay.jetty.Server;
import org.mortbay.log.Logger;
/**
* Modified from Jetty 6.1.26 StdErrLog.java and Slf4jLog.java
*
* Usage: org.mortbay.log.Log.setLog(new I2PLogger(ctx));
*
* @since Jetty 6
*/
public class I2PLogger implements Logger
{
private final Log _log;
StringBuilder _buffer = new StringBuilder();
public I2PLogger()
{
this(I2PAppContext.getGlobalContext());
}
public I2PLogger(I2PAppContext ctx)
{
_log = ctx.logManager().getLog(Server.class);
if (System.getProperty("DEBUG") != null)
setDebugEnabled(true);
}
public boolean isDebugEnabled()
{
return _log.shouldLog(Log.DEBUG);
}
public void setDebugEnabled(boolean enabled)
{
if (enabled)
_log.setMinimumPriority(Log.DEBUG);
else
// LogManager.getDefaultLimit() returns a String, not worth it
_log.setMinimumPriority(Log.ERROR);
}
public void info(String msg,Object arg0, Object arg1)
{
if (arg0 == null && arg1 == null) {
_log.info(msg);
} else if (_log.shouldLog(Log.INFO)) {
synchronized(_buffer) {
format(msg,arg0,arg1);
_log.info(_buffer.toString());
}
}
}
public void debug(String msg,Throwable th)
{
_log.debug(msg,th);
}
public void debug(String msg,Object arg0, Object arg1)
{
if (arg0 == null && arg1 == null) {
_log.debug(msg);
} else if (_log.shouldLog(Log.DEBUG)) {
synchronized(_buffer) {
format(msg,arg0,arg1);
_log.debug(_buffer.toString());
}
}
}
public void warn(String msg,Object arg0, Object arg1)
{
if (arg0 == null && arg1 == null) {
_log.warn(msg);
} else if (_log.shouldLog(Log.WARN)) {
synchronized(_buffer) {
format(msg,arg0,arg1);
_log.warn(_buffer.toString());
}
}
}
public void warn(String msg, Throwable th)
{
// This doesn't cover ClassNotFoundException, etc.
//if (th instanceof RuntimeException || th instanceof Error)
_log.error(msg, th);
//else
// _log.warn(msg,th);
}
private void format(String msg, Object arg0, Object arg1)
{
_buffer.setLength(0);
int i0=msg==null?-1:msg.indexOf("{}");
int i1=i0<0?-1:msg.indexOf("{}",i0+2);
if (i0>=0)
{
format(msg.substring(0,i0));
format(String.valueOf(arg0==null?"null":arg0));
if (i1>=0)
{
format(msg.substring(i0+2,i1));
format(String.valueOf(arg1==null?"null":arg1));
format(msg.substring(i1+2));
}
else
{
format(msg.substring(i0+2));
if (arg1!=null)
{
_buffer.append(' ');
format(String.valueOf(arg1));
}
}
}
else
{
format(msg);
if (arg0!=null)
{
_buffer.append(' ');
format(String.valueOf(arg0));
}
if (arg1!=null)
{
_buffer.append(' ');
format(String.valueOf(arg1));
}
}
}
private void format(String msg)
{
if (msg == null)
_buffer.append("null");
else
_buffer.append(msg);
}
public Logger getLogger(String name)
{
return this;
}
@Override
public String toString()
{
return "I2PLogger";
}
}

View File

@ -0,0 +1,513 @@
//========================================================================
//Copyright 1997-2006 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//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 net.i2p.jetty;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Locale;
import java.util.TimeZone;
import javax.servlet.http.Cookie;
import org.mortbay.component.AbstractLifeCycle;
import org.mortbay.jetty.HttpHeaders;
import org.mortbay.jetty.Request;
import org.mortbay.jetty.RequestLog;
import org.mortbay.jetty.Response;
import org.mortbay.jetty.servlet.PathMap;
import org.mortbay.log.Log;
import org.mortbay.util.DateCache;
import org.mortbay.util.RolloverFileOutputStream;
import org.mortbay.util.StringUtil;
import org.mortbay.util.TypeUtil;
import org.mortbay.util.Utf8StringBuffer;
/**
* This {@link RequestLog} implementation outputs logs in the pseudo-standard NCSA common log format.
* Configuration options allow a choice between the standard Common Log Format (as used in the 3 log format)
* and the Combined Log Format (single log format).
* This log format can be output by most web servers, and almost all web log analysis software can understand
* these formats.
*
* ** I2P Mods **
*
* For Jetty 5, this extended NCSARequestLog to
* override log() to put in the requestor's destination hash,
* instead of 127.0.0.1,
* which is placed in the X-I2P-DestHash field in the request headers
* by I2PTunnelHTTPServer.
* But we also had to modify NCSARequestLog to do so, to change private
* fields to protected.
*
* So that we will work with system Jetty 6 packages, we just copy the whole thing
* and modify log() as required.
* We leave the package as org.mortbay.http for compatibility with old
* jetty.xml files.
*
* @author Greg Wilkins
* @author Nigel Canonizado
*
*/
public class I2PRequestLog extends AbstractLifeCycle implements RequestLog
{
private String _filename;
private boolean _extended;
private boolean _append;
private int _retainDays;
private boolean _closeOut;
private boolean _preferProxiedForAddress;
private String _logDateFormat="dd/MMM/yyyy:HH:mm:ss Z";
private String _filenameDateFormat = null;
private Locale _logLocale = Locale.getDefault();
private String _logTimeZone = "GMT";
private String[] _ignorePaths;
private boolean _logLatency = false;
private boolean _logCookies = false;
private boolean _logServer = false;
private transient OutputStream _out;
private transient OutputStream _fileOut;
private transient DateCache _logDateCache;
private transient PathMap _ignorePathMap;
private transient Writer _writer;
private transient ArrayList _buffers;
private transient char[] _copy;
public I2PRequestLog()
{
_extended = true;
_append = true;
_retainDays = 31;
}
/* ------------------------------------------------------------ */
/**
* @param filename The filename for the request log. This may be in the format expected by {@link RolloverFileOutputStream}
*/
public I2PRequestLog(String filename)
{
_extended = true;
_append = true;
_retainDays = 31;
setFilename(filename);
}
/* ------------------------------------------------------------ */
/**
* @param filename The filename for the request log. This may be in the format expected by {@link RolloverFileOutputStream}
*/
public void setFilename(String filename)
{
if (filename != null)
{
filename = filename.trim();
if (filename.length() == 0)
filename = null;
}
_filename = filename;
}
public String getFilename()
{
return _filename;
}
public String getDatedFilename()
{
if (_fileOut instanceof RolloverFileOutputStream)
return ((RolloverFileOutputStream)_fileOut).getDatedFilename();
return null;
}
/* ------------------------------------------------------------ */
/**
* @param format Format for the timestamps in the log file. If not set,
* the pre-formated request timestamp is used.
*/
public void setLogDateFormat(String format)
{
_logDateFormat = format;
}
public String getLogDateFormat()
{
return _logDateFormat;
}
public void setLogLocale(Locale logLocale)
{
_logLocale = logLocale;
}
public Locale getLogLocale()
{
return _logLocale;
}
public void setLogTimeZone(String tz)
{
_logTimeZone = tz;
}
public String getLogTimeZone()
{
return _logTimeZone;
}
public void setRetainDays(int retainDays)
{
_retainDays = retainDays;
}
public int getRetainDays()
{
return _retainDays;
}
public void setExtended(boolean extended)
{
_extended = extended;
}
public boolean isExtended()
{
return _extended;
}
public void setAppend(boolean append)
{
_append = append;
}
public boolean isAppend()
{
return _append;
}
public void setIgnorePaths(String[] ignorePaths)
{
_ignorePaths = ignorePaths;
}
public String[] getIgnorePaths()
{
return _ignorePaths;
}
public void setLogCookies(boolean logCookies)
{
_logCookies = logCookies;
}
public boolean getLogCookies()
{
return _logCookies;
}
public boolean getLogServer()
{
return _logServer;
}
public void setLogServer(boolean logServer)
{
_logServer=logServer;
}
public void setLogLatency(boolean logLatency)
{
_logLatency = logLatency;
}
public boolean getLogLatency()
{
return _logLatency;
}
public void setPreferProxiedForAddress(boolean preferProxiedForAddress)
{
_preferProxiedForAddress = preferProxiedForAddress;
}
/* ------------------------------------------------------------ */
public void log(Request request, Response response)
{
if (!isStarted())
return;
try
{
if (_ignorePathMap != null && _ignorePathMap.getMatch(request.getRequestURI()) != null)
return;
if (_fileOut == null)
return;
Utf8StringBuffer u8buf;
StringBuffer buf;
synchronized(_writer)
{
int size=_buffers.size();
u8buf = size==0?new Utf8StringBuffer(160):(Utf8StringBuffer)_buffers.remove(size-1);
buf = u8buf.getStringBuffer();
}
synchronized(buf) // for efficiency until we can use StringBuilder
{
if (_logServer)
{
buf.append(request.getServerName());
buf.append(' ');
}
String addr = null;
if (_preferProxiedForAddress)
{
addr = request.getHeader(HttpHeaders.X_FORWARDED_FOR);
}
if (addr == null) {
// TODO offer B32 option
addr = request.getHeader("X-I2P-DestHash");
if(addr != null)
addr += ".i2p";
else
addr = request.getRemoteAddr();
}
buf.append(addr);
buf.append(" - ");
String user = request.getRemoteUser();
buf.append((user == null)? " - " : user);
buf.append(" [");
if (_logDateCache!=null)
buf.append(_logDateCache.format(request.getTimeStamp()));
else
buf.append(request.getTimeStampBuffer().toString());
buf.append("] \"");
buf.append(request.getMethod());
buf.append(' ');
request.getUri().writeTo(u8buf);
buf.append(' ');
buf.append(request.getProtocol());
buf.append("\" ");
int status = response.getStatus();
if (status<=0)
status=404;
buf.append((char)('0'+((status/100)%10)));
buf.append((char)('0'+((status/10)%10)));
buf.append((char)('0'+(status%10)));
long responseLength=response.getContentCount();
if (responseLength >=0)
{
buf.append(' ');
if (responseLength > 99999)
buf.append(Long.toString(responseLength));
else
{
if (responseLength > 9999)
buf.append((char)('0' + ((responseLength / 10000)%10)));
if (responseLength > 999)
buf.append((char)('0' + ((responseLength /1000)%10)));
if (responseLength > 99)
buf.append((char)('0' + ((responseLength / 100)%10)));
if (responseLength > 9)
buf.append((char)('0' + ((responseLength / 10)%10)));
buf.append((char)('0' + (responseLength)%10));
}
buf.append(' ');
}
else
buf.append(" - ");
}
if (!_extended && !_logCookies && !_logLatency)
{
synchronized(_writer)
{
buf.append(StringUtil.__LINE_SEPARATOR);
int l=buf.length();
if (l>_copy.length)
l=_copy.length;
buf.getChars(0,l,_copy,0);
_writer.write(_copy,0,l);
_writer.flush();
u8buf.reset();
_buffers.add(u8buf);
}
}
else
{
synchronized(_writer)
{
int l=buf.length();
if (l>_copy.length)
l=_copy.length;
buf.getChars(0,l,_copy,0);
_writer.write(_copy,0,l);
u8buf.reset();
_buffers.add(u8buf);
// TODO do outside synchronized scope
if (_extended)
logExtended(request, response, _writer);
// TODO do outside synchronized scope
if (_logCookies)
{
Cookie[] cookies = request.getCookies();
if (cookies == null || cookies.length == 0)
_writer.write(" -");
else
{
_writer.write(" \"");
for (int i = 0; i < cookies.length; i++)
{
if (i != 0)
_writer.write(';');
_writer.write(cookies[i].getName());
_writer.write('=');
_writer.write(cookies[i].getValue());
}
_writer.write('\"');
}
}
if (_logLatency)
{
_writer.write(' ');
_writer.write(TypeUtil.toString(System.currentTimeMillis() - request.getTimeStamp()));
}
_writer.write(StringUtil.__LINE_SEPARATOR);
_writer.flush();
}
}
}
catch (IOException e)
{
Log.warn(e);
}
}
/* ------------------------------------------------------------ */
protected void logExtended(Request request,
Response response,
Writer writer) throws IOException
{
String referer = request.getHeader(HttpHeaders.REFERER);
if (referer == null)
writer.write("\"-\" ");
else
{
writer.write('"');
writer.write(referer);
writer.write("\" ");
}
String agent = request.getHeader(HttpHeaders.USER_AGENT);
if (agent == null)
writer.write("\"-\" ");
else
{
writer.write('"');
writer.write(agent);
writer.write('"');
}
}
/* ------------------------------------------------------------ */
protected void doStart() throws Exception
{
if (_logDateFormat!=null)
{
_logDateCache = new DateCache(_logDateFormat, _logLocale);
_logDateCache.setTimeZoneID(_logTimeZone);
}
if (_filename != null)
{
_fileOut = new RolloverFileOutputStream(_filename,_append,_retainDays,TimeZone.getTimeZone(_logTimeZone),_filenameDateFormat,null);
_closeOut = true;
Log.info("Opened "+getDatedFilename());
}
else
_fileOut = System.err;
_out = _fileOut;
if (_ignorePaths != null && _ignorePaths.length > 0)
{
_ignorePathMap = new PathMap();
for (int i = 0; i < _ignorePaths.length; i++)
_ignorePathMap.put(_ignorePaths[i], _ignorePaths[i]);
}
else
_ignorePathMap = null;
_writer = new OutputStreamWriter(_out);
_buffers = new ArrayList();
_copy = new char[1024];
super.doStart();
}
/* ------------------------------------------------------------ */
protected void doStop() throws Exception
{
super.doStop();
try {if (_writer != null) _writer.flush();} catch (IOException e) {Log.ignore(e);}
if (_out != null && _closeOut)
try {_out.close();} catch (IOException e) {Log.ignore(e);}
_out = null;
_fileOut = null;
_closeOut = false;
_logDateCache = null;
_writer = null;
_buffers = null;
_copy = null;
}
/* ------------------------------------------------------------ */
/**
* @return the log File Date Format
*/
public String getFilenameDateFormat()
{
return _filenameDateFormat;
}
/* ------------------------------------------------------------ */
/** Set the log file date format.
* see RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)
* @param logFileDateFormat the logFileDateFormat to pass to RolloverFileOutputStream
*/
public void setFilenameDateFormat(String logFileDateFormat)
{
_filenameDateFormat=logFileDateFormat;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,182 +0,0 @@
// ========================================================================
// $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.http;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Locale;
import java.util.TimeZone;
import javax.servlet.http.Cookie;
import org.apache.commons.logging.Log;
import org.mortbay.log.LogFactory;
import org.mortbay.util.DateCache;
import org.mortbay.util.LogSupport;
import org.mortbay.util.RolloverFileOutputStream;
import org.mortbay.util.StringUtil;
/* ------------------------------------------------------------ */
/** NCSA HTTP Request Log.
*
* Override log() to put in the requestor's destination hash,
* instead of 127.0.0.1,
* which is placed in the X-I2P-DestHash field in the request headers
* by I2PTunnelHTTPServer.
*
* NCSA common or NCSA extended (combined) request log.
* @version $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
* @author Tony Thompson
* @author Greg Wilkins
*/
public class I2PRequestLog extends NCSARequestLog
{
/* ------------------------------------------------------------ */
/** Constructor.
*/
public I2PRequestLog()
{
super();
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param filename Filename, which can be in
* rolloverFileOutputStream format
* @see org.mortbay.util.RolloverFileOutputStream
* @exception IOException
*/
public I2PRequestLog(String filename)
throws IOException
{
super(filename);
}
/* ------------------------------------------------------------ */
/** Log a request.
* @param request The request
* @param response The response to this request.
* @param responseLength The bytes written to the response.
*/
public void log(HttpRequest request,
HttpResponse response,
int responseLength)
{
try{
// ignore ignorables
if (_ignorePathMap != null &&
_ignorePathMap.getMatch(request.getPath()) != null)
return;
// log the rest
if (_fileOut==null)
return;
StringBuilder buf = new StringBuilder(160);
String addr = request.getField("X-I2P-DestHash");
if(addr != null)
buf.append(addr).append(".i2p");
else
buf.append(request.getRemoteAddr());
buf.append(" - ");
String user = request.getAuthUser();
buf.append((user==null)?"-":user);
buf.append(" [");
buf.append(_logDateCache.format(request.getTimeStamp()));
buf.append("] \"");
buf.append(request.getMethod());
buf.append(' ');
buf.append(request.getURI());
buf.append(' ');
buf.append(request.getVersion());
buf.append("\" ");
int status=response.getStatus();
buf.append((char)('0'+((status/100)%10)));
buf.append((char)('0'+((status/10)%10)));
buf.append((char)('0'+(status%10)));
if (responseLength>=0)
{
buf.append(' ');
if (responseLength>99999)
buf.append(Integer.toString(responseLength));
else
{
if (responseLength>9999)
buf.append((char)('0'+((responseLength/10000)%10)));
if (responseLength>999)
buf.append((char)('0'+((responseLength/1000)%10)));
if (responseLength>99)
buf.append((char)('0'+((responseLength/100)%10)));
if (responseLength>9)
buf.append((char)('0'+((responseLength/10)%10)));
buf.append((char)('0'+(responseLength%10)));
}
buf.append(' ');
}
else
buf.append(" - ");
String log =buf.toString();
synchronized(_writer)
{
_writer.write(log);
if (isExtended())
{
logExtended(request,response,_writer);
if (!getLogCookies())
_writer.write(" -");
}
if (getLogCookies())
{
Cookie[] cookies = request.getCookies();
if (cookies==null || cookies.length==0)
_writer.write(" -");
else
{
_writer.write(" \"");
for (int i=0;i<cookies.length;i++)
{
if (i!=0)
_writer.write(';');
_writer.write(cookies[i].getName());
_writer.write('=');
_writer.write(cookies[i].getValue());
}
_writer.write("\"");
}
}
if (getLogLatency())
_writer.write(" "+(System.currentTimeMillis()-request.getTimeStamp()));
_writer.write(StringUtil.__LINE_SEPARATOR);
_writer.flush();
}
}
catch(IOException e)
{
log.warn(LogSupport.EXCEPTION,e);
}
}
}

View File

@ -1,505 +0,0 @@
// ========================================================================
// $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.http;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Locale;
import java.util.TimeZone;
import javax.servlet.http.Cookie;
import org.apache.commons.logging.Log;
import org.mortbay.log.LogFactory;
import org.mortbay.util.DateCache;
import org.mortbay.util.LogSupport;
import org.mortbay.util.RolloverFileOutputStream;
import org.mortbay.util.StringUtil;
/* ------------------------------------------------------------ */
/** NCSA HTTP Request Log.
* NCSA common or NCSA extended (combined) request log.
*
* Taken from 5.1.12 source and modded to change some private vars to protected
* so we can extend it for I2P.
*
* @version $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
* @author Tony Thompson
* @author Greg Wilkins
*/
public class NCSARequestLog implements RequestLog
{
protected static Log log = LogFactory.getLog(NCSARequestLog.class);
private String _filename;
private boolean _extended;
private boolean _append;
private int _retainDays;
private boolean _closeOut;
private boolean _preferProxiedForAddress;
private String _logDateFormat="dd/MMM/yyyy:HH:mm:ss ZZZ";
private Locale _logLocale=Locale.getDefault();
private String _logTimeZone=TimeZone.getDefault().getID();
private String[] _ignorePaths;
private boolean _logLatency=false;
private boolean _logCookies=false;
protected transient OutputStream _out;
protected transient OutputStream _fileOut;
protected transient DateCache _logDateCache;
protected transient PathMap _ignorePathMap;
protected transient Writer _writer;
/* ------------------------------------------------------------ */
/** Constructor.
*/
public NCSARequestLog()
{
_extended=true;
_append=true;
_retainDays=31;
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param filename Filename, which can be in
* rolloverFileOutputStream format
* @see org.mortbay.util.RolloverFileOutputStream
* @exception IOException
*/
public NCSARequestLog(String filename)
throws IOException
{
_extended=true;
_append=true;
_retainDays=31;
setFilename(filename);
}
/* ------------------------------------------------------------ */
/** Set the log filename.
* @see NCSARequestLog#setRetainDays(int)
* @param filename The filename to use. If the filename contains the
* string "yyyy_mm_dd", then a RolloverFileOutputStream is used and the
* log is rolled over nightly and aged according setRetainDays. If no
* filename is set or a null filename
* passed, then requests are logged to System.err.
*/
public void setFilename(String filename)
{
if (filename!=null)
{
filename=filename.trim();
if (filename.length()==0)
filename=null;
}
_filename=filename;
}
/* ------------------------------------------------------------ */
/** Get the log filename.
* @see NCSARequestLog#getDatedFilename()
* @return The log filename without any date expansion.
*/
public String getFilename()
{
return _filename;
}
/* ------------------------------------------------------------ */
/** Get the dated log filename.
* @see NCSARequestLog#getFilename()
* @return The log filename with any date encoding expanded.
*/
public String getDatedFilename()
{
if (_fileOut instanceof RolloverFileOutputStream)
return ((RolloverFileOutputStream)_fileOut).getDatedFilename();
return null;
}
/* ------------------------------------------------------------ */
/**
* @param format The date format to use within the log file.
*/
public void setLogDateFormat(String format)
{
_logDateFormat=format;
}
/* ------------------------------------------------------------ */
/**
* @return The date format to use within the log file.
*/
public String getLogDateFormat()
{
return _logDateFormat;
}
/* ------------------------------------------------------------ */
/**
* @param tz The date format timezone to use within the log file.
*/
public void setLogTimeZone(String tz)
{
_logTimeZone=tz;
}
/* ------------------------------------------------------------ */
/**
* @return The date format timezone to use within the log file.
*/
public String getLogTimeZone()
{
return _logTimeZone;
}
/* ------------------------------------------------------------ */
/**
* @return The number of days to retain rollovered log files.
*/
public int getRetainDays()
{
return _retainDays;
}
/* ------------------------------------------------------------ */
/**
* @param retainDays The number of days to retain rollovered log files.
*/
public void setRetainDays(int retainDays)
{
_retainDays = retainDays;
}
/* ------------------------------------------------------------ */
/**
* @return True if NCSA extended format is to be used.
*/
public boolean isExtended()
{
return _extended;
}
/* ------------------------------------------------------------ */
/**
* @param e True if NCSA extended format is to be used.
*/
public void setExtended(boolean e)
{
_extended=e;
}
/* ------------------------------------------------------------ */
/**
* @return True if logs are appended to existing log files.
*/
public boolean isAppend()
{
return _append;
}
/* ------------------------------------------------------------ */
/**
* @param a True if logs are appended to existing log files.
*/
public void setAppend(boolean a)
{
_append=a;
}
/* ------------------------------------------------------------ */
/**
* @deprecated ignored
*/
public void setBuffered(boolean b)
{}
/* ------------------------------------------------------------ */
/** Set which paths to ignore.
*
* @param ignorePaths Array of path specifications to ignore
*/
public void setIgnorePaths(String[] ignorePaths)
{
// Contributed by Martin Vilcans (martin@jadestone.se)
_ignorePaths = ignorePaths;
}
/* ------------------------------------------------------------ */
public String[] getIgnorePaths()
{
return _ignorePaths;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the logCookies.
*/
public boolean getLogCookies()
{
return _logCookies;
}
/* ------------------------------------------------------------ */
/**
* @param logCookies The logCookies to set.
*/
public void setLogCookies(boolean logCookies)
{
_logCookies = logCookies;
}
/* ------------------------------------------------------------ */
/**
* @return Returns true if logging latency
*/
public boolean getLogLatency()
{
return _logLatency;
}
/* ------------------------------------------------------------ */
/**
* @param logLatency If true, latency is logged at the end of the log line
*/
public void setLogLatency(boolean logLatency)
{
_logLatency = logLatency;
}
/* ------------------------------------------------------------ */
/**
* Prefer to log the proxied-for IP address (if present in
* the request header) over the native requester IP address.
* Useful in reverse-proxy situations when you'd rather see
* the IP address of the host before the most recent proxy
* server, as opposed to your own proxy server(s) every time.
*
* jlrobins@socialserve.com, March 2004.
**/
public void setPreferProxiedForAddress(boolean value)
{
_preferProxiedForAddress = value;
}
/* ------------------------------------------------------------ */
public void start()
throws Exception
{
_logDateCache=new DateCache(_logDateFormat,_logLocale);
_logDateCache.setTimeZoneID(_logTimeZone);
if (_filename != null)
{
_fileOut=new RolloverFileOutputStream(_filename,_append,_retainDays);
_closeOut=true;
}
else
_fileOut=System.err;
_out=_fileOut;
if (_ignorePaths!=null && _ignorePaths.length>0)
{
_ignorePathMap=new PathMap();
for (int i=0;i<_ignorePaths.length;i++)
_ignorePathMap.put(_ignorePaths[i],_ignorePaths[i]);
}
else
_ignorePathMap=null;
_writer=new OutputStreamWriter(_out);
}
/* ------------------------------------------------------------ */
public boolean isStarted()
{
return _fileOut!=null;
}
/* ------------------------------------------------------------ */
public void stop()
{
try{if (_writer!=null)_writer.flush();} catch (IOException e){LogSupport.ignore(log,e);}
if (_out!=null && _closeOut)
try{_out.close();}catch(IOException e){LogSupport.ignore(log,e);}
_out=null;
_fileOut=null;
_closeOut=false;
_logDateCache=null;
_writer=null;
}
/* ------------------------------------------------------------ */
/** Log a request.
* @param request The request
* @param response The response to this request.
* @param responseLength The bytes written to the response.
*/
public void log(HttpRequest request,
HttpResponse response,
int responseLength)
{
try{
// ignore ignorables
if (_ignorePathMap != null &&
_ignorePathMap.getMatch(request.getPath()) != null)
return;
// log the rest
if (_fileOut==null)
return;
StringBuffer buf = new StringBuffer(160);
String addr = null;
if(_preferProxiedForAddress)
{
// If header is not present, addr will remain null ...
addr = request.getField(HttpFields.__XForwardedFor);
}
if(addr == null)
addr = request.getRemoteAddr();
buf.append(addr);
buf.append(" - ");
String user = request.getAuthUser();
buf.append((user==null)?"-":user);
buf.append(" [");
buf.append(_logDateCache.format(request.getTimeStamp()));
buf.append("] \"");
buf.append(request.getMethod());
buf.append(' ');
buf.append(request.getURI());
buf.append(' ');
buf.append(request.getVersion());
buf.append("\" ");
int status=response.getStatus();
buf.append((char)('0'+((status/100)%10)));
buf.append((char)('0'+((status/10)%10)));
buf.append((char)('0'+(status%10)));
if (responseLength>=0)
{
buf.append(' ');
if (responseLength>99999)
buf.append(Integer.toString(responseLength));
else
{
if (responseLength>9999)
buf.append((char)('0'+((responseLength/10000)%10)));
if (responseLength>999)
buf.append((char)('0'+((responseLength/1000)%10)));
if (responseLength>99)
buf.append((char)('0'+((responseLength/100)%10)));
if (responseLength>9)
buf.append((char)('0'+((responseLength/10)%10)));
buf.append((char)('0'+(responseLength%10)));
}
buf.append(' ');
}
else
buf.append(" - ");
String log =buf.toString();
synchronized(_writer)
{
_writer.write(log);
if (_extended)
{
logExtended(request,response,_writer);
if (!_logCookies)
_writer.write(" -");
}
if (_logCookies)
{
Cookie[] cookies = request.getCookies();
if (cookies==null || cookies.length==0)
_writer.write(" -");
else
{
_writer.write(" \"");
for (int i=0;i<cookies.length;i++)
{
if (i!=0)
_writer.write(';');
_writer.write(cookies[i].getName());
_writer.write('=');
_writer.write(cookies[i].getValue());
}
_writer.write("\"");
}
}
if (_logLatency)
_writer.write(" "+(System.currentTimeMillis()-request.getTimeStamp()));
_writer.write(StringUtil.__LINE_SEPARATOR);
_writer.flush();
}
}
catch(IOException e)
{
log.warn(LogSupport.EXCEPTION,e);
}
}
/* ------------------------------------------------------------ */
/** Log Extended fields.
* This method can be extended by a derived class to add extened fields to
* each log entry. It is called by the log method after all standard
* fields have been added, but before the line terminator.
* Derived implementations should write extra fields to the Writer
* provided.
* The default implementation writes the referer and user agent.
* @param request The request to log.
* @param response The response to log.
* @param log The writer to write the extra fields to.
* @exception IOException Problem writing log
*/
protected void logExtended(HttpRequest request,
HttpResponse response,
Writer log)
throws IOException
{
String referer = request.getField(HttpFields.__Referer);
if(referer==null)
log.write("\"-\" ");
else
{
log.write('"');
log.write(referer);
log.write("\" ");
}
String agent = request.getField(HttpFields.__UserAgent);
if(agent==null)
log.write("\"-\"");
else
{
log.write('"');
log.write(agent);
log.write('"');
}
}
}

View File

@ -1,809 +0,0 @@
// ========================================================================
// $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $
// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.http.handler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.List;
import org.apache.commons.logging.Log;
import org.mortbay.log.LogFactory;
import org.mortbay.http.HttpException;
import org.mortbay.http.HttpFields;
import org.mortbay.http.HttpRequest;
import org.mortbay.http.HttpResponse;
import org.mortbay.http.InclusiveByteRange;
import org.mortbay.http.MultiPartResponse;
import org.mortbay.http.ResourceCache;
import org.mortbay.util.CachedResource;
import org.mortbay.util.IO;
import org.mortbay.util.LogSupport;
import org.mortbay.util.Resource;
import org.mortbay.util.StringMap;
import org.mortbay.util.TypeUtil;
import org.mortbay.util.URI;
/* ------------------------------------------------------------ */
/** Handler to serve files and resources.
* Serves files from a given resource URL base and implements
* the GET, HEAD, DELETE, OPTIONS, PUT, MOVE methods and the
* IfModifiedSince and IfUnmodifiedSince header fields.
* A simple memory cache is also provided to reduce file I/O.
* HTTP/1.1 ranges are supported.
*
* @version $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $
* @author Nuno Pregui?a (sorry, wasn't UTF-8)
* @author Greg Wilkins
*/
public class ResourceHandler extends AbstractHttpHandler
{
private static Log log = LogFactory.getLog(ResourceHandler.class);
/* ----------------------------------------------------------------- */
private boolean _acceptRanges=true;
private boolean _redirectWelcomeFiles ;
private String[] _methods=null;
private String _allowed;
private boolean _dirAllowed=true;
private int _minGzipLength =-1;
private StringMap _methodMap = new StringMap();
{
setAllowedMethods(new String[]
{
HttpRequest.__GET,
HttpRequest.__POST,
HttpRequest.__HEAD,
HttpRequest.__OPTIONS,
HttpRequest.__TRACE
});
}
/* ----------------------------------------------------------------- */
/** Construct a ResourceHandler.
*/
public ResourceHandler()
{}
/* ----------------------------------------------------------------- */
public synchronized void start()
throws Exception
{
super.start();
}
/* ----------------------------------------------------------------- */
public void stop()
throws InterruptedException
{
super.stop();
}
/* ------------------------------------------------------------ */
public String[] getAllowedMethods()
{
return _methods;
}
/* ------------------------------------------------------------ */
public void setAllowedMethods(String[] methods)
{
StringBuffer b = new StringBuffer();
_methods=methods;
_methodMap.clear();
for (int i=0;i<methods.length;i++)
{
_methodMap.put(methods[i],methods[i]);
if (i>0)
b.append(',');
b.append(methods[i]);
}
_allowed=b.toString();
}
/* ------------------------------------------------------------ */
public boolean isMethodAllowed(String method)
{
return _methodMap.get(method)!=null;
}
/* ------------------------------------------------------------ */
public String getAllowedString()
{
return _allowed;
}
/* ------------------------------------------------------------ */
public boolean isDirAllowed()
{
return _dirAllowed;
}
/* ------------------------------------------------------------ */
public void setDirAllowed(boolean dirAllowed)
{
_dirAllowed = dirAllowed;
}
/* ------------------------------------------------------------ */
public boolean isAcceptRanges()
{
return _acceptRanges;
}
/* ------------------------------------------------------------ */
/**
* @return True if welcome files are redirected to. False if forward is used.
*/
public boolean getRedirectWelcome()
{
return _redirectWelcomeFiles;
}
/* ------------------------------------------------------------ */
/**
* @param redirectWelcome True if welcome files are redirected to. False
* if forward is used.
*/
public void setRedirectWelcome(boolean redirectWelcome)
{
_redirectWelcomeFiles = redirectWelcome;
}
/* ------------------------------------------------------------ */
/** Set if the handler accepts range requests.
* Default is false;
* @param ar True if the handler should accept ranges
*/
public void setAcceptRanges(boolean ar)
{
_acceptRanges=ar;
}
/* ------------------------------------------------------------ */
/** Get minimum content length for GZIP encoding.
* @return Minimum length of content for gzip encoding or -1 if disabled.
*/
public int getMinGzipLength()
{
return _minGzipLength;
}
/* ------------------------------------------------------------ */
/** Set minimum content length for GZIP encoding.
* @param minGzipLength If set to a positive integer, then static content
* larger than this will be served as gzip content encoded
* if a matching resource is found ending with ".gz"
*/
public void setMinGzipLength(int minGzipLength)
{
_minGzipLength = minGzipLength;
}
/* ------------------------------------------------------------ */
/** get Resource to serve.
* Map a path to a resource. The default implementation calls
* HttpContext.getResource but derived handers may provide
* their own mapping.
* @param pathInContext The path to find a resource for.
* @return The resource to serve.
*/
protected Resource getResource(String pathInContext)
throws IOException
{
return getHttpContext().getResource(pathInContext);
}
/* ------------------------------------------------------------ */
public void handle(String pathInContext,
String pathParams,
HttpRequest request,
HttpResponse response)
throws HttpException, IOException
{
Resource resource = getResource(pathInContext);
if (resource==null)
return;
// Is the method allowed?
if (!isMethodAllowed(request.getMethod()))
{
if(log.isDebugEnabled())log.debug("Method not allowed: "+request.getMethod());
if (resource.exists())
{
setAllowHeader(response);
response.sendError(HttpResponse.__405_Method_Not_Allowed);
}
return;
}
// Handle the request
try
{
if(log.isDebugEnabled())log.debug("PATH="+pathInContext+" RESOURCE="+resource);
// check filename
String method=request.getMethod();
if (method.equals(HttpRequest.__GET) ||
method.equals(HttpRequest.__POST) ||
method.equals(HttpRequest.__HEAD))
handleGet(request, response, pathInContext, pathParams, resource);
else if (method.equals(HttpRequest.__PUT))
handlePut(request, response, pathInContext, resource);
else if (method.equals(HttpRequest.__DELETE))
handleDelete(request, response, pathInContext, resource);
else if (method.equals(HttpRequest.__OPTIONS))
handleOptions(response, pathInContext);
else if (method.equals(HttpRequest.__MOVE))
handleMove(request, response, pathInContext, resource);
else if (method.equals(HttpRequest.__TRACE))
handleTrace(request, response);
else
{
if(log.isDebugEnabled())log.debug("Unknown action:"+method);
// anything else...
try{
if (resource.exists())
response.sendError(HttpResponse.__501_Not_Implemented);
}
catch(Exception e) {LogSupport.ignore(log,e);}
}
}
catch(IllegalArgumentException e)
{
LogSupport.ignore(log,e);
}
finally
{
if (resource!=null && !(resource instanceof CachedResource))
resource.release();
}
}
/* ------------------------------------------------------------------- */
public void handleGet(HttpRequest request,
HttpResponse response,
String pathInContext,
String pathParams,
Resource resource)
throws IOException
{
if(log.isDebugEnabled())log.debug("Looking for "+resource);
if (resource!=null && resource.exists())
{
// check if directory
if (resource.isDirectory())
{
if (!pathInContext.endsWith("/") && !pathInContext.equals("/"))
{
log.debug("Redirect to directory/");
String q=request.getQuery();
// Properly fix URI
URI urifix = new URI(request.getRequestURL().toString());
urifix.setPath(urifix.getPath());
StringBuffer buf = new StringBuffer(urifix.toString());
urifix = null;
if (q!=null&&q.length()!=0)
{
buf.append('?');
buf.append(q);
}
response.setField(HttpFields.__Location, URI.addPaths(buf.toString(),"/"));
response.setStatus(302);
request.setHandled(true);
return;
}
// See if index file exists
String welcome=getHttpContext().getWelcomeFile(resource);
if (welcome!=null)
{
// Forward to the index
String ipath=URI.addPaths(pathInContext,welcome);
if (_redirectWelcomeFiles)
{
// Redirect to the index
ipath=URI.addPaths(getHttpContext().getContextPath(),ipath);
response.setContentLength(0);
response.sendRedirect(ipath);
}
else
{
URI uri=request.getURI();
uri.setPath(URI.addPaths(uri.getPath(),welcome));
getHttpContext().handle(ipath,pathParams,request,response);
}
return;
}
// Check modified dates
if (!passConditionalHeaders(request,response,resource))
return;
// If we got here, no forward to index took place
sendDirectory(request,response,resource,pathInContext.length()>1);
}
// check if it is a file
else if (resource.exists())
{
// Check modified dates
if (!passConditionalHeaders(request,response,resource))
return;
sendData(request,response,pathInContext,resource,true);
}
else
// don't know what it is
log.warn("Unknown file type");
}
}
/* ------------------------------------------------------------ */
/* Check modification date headers.
*/
private boolean passConditionalHeaders(HttpRequest request,
HttpResponse response,
Resource resource)
throws IOException
{
if (!request.getMethod().equals(HttpRequest.__HEAD))
{
// If we have meta data for the file
// Try a direct match for most common requests. Avoids
// parsing the date.
ResourceCache.ResourceMetaData metaData =
(ResourceCache.ResourceMetaData)resource.getAssociate();
if (metaData!=null)
{
String ifms=request.getField(HttpFields.__IfModifiedSince);
String mdlm=metaData.getLastModified();
if (ifms!=null && mdlm!=null && ifms.equals(mdlm))
{
response.setStatus(HttpResponse.__304_Not_Modified);
request.setHandled(true);
return false;
}
}
long date=0;
// Parse the if[un]modified dates and compare to resource
if ((date=request.getDateField(HttpFields.__IfUnmodifiedSince))>0)
{
if (resource.lastModified()/1000 > date/1000)
{
response.sendError(HttpResponse.__412_Precondition_Failed);
return false;
}
}
if ((date=request.getDateField(HttpFields.__IfModifiedSince))>0)
{
if (resource.lastModified()/1000 <= date/1000)
{
response.setStatus(HttpResponse.__304_Not_Modified);
request.setHandled(true);
return false;
}
}
}
return true;
}
/* ------------------------------------------------------------ */
void handlePut(HttpRequest request,
HttpResponse response,
String pathInContext,
Resource resource)
throws IOException
{
if(log.isDebugEnabled())log.debug("PUT "+pathInContext+" in "+resource);
boolean exists=resource!=null && resource.exists();
if (exists &&
!passConditionalHeaders(request,response,resource))
return;
if (pathInContext.endsWith("/"))
{
if (!exists)
{
if (!resource.getFile().mkdirs())
response.sendError(HttpResponse.__403_Forbidden, "Directories could not be created");
else
{
request.setHandled(true);
response.setStatus(HttpResponse.__201_Created);
response.commit();
}
}
else
{
request.setHandled(true);
response.setStatus(HttpResponse.__200_OK);
response.commit();
}
}
else
{
try
{
int toRead = request.getContentLength();
InputStream in = request.getInputStream();
OutputStream out = resource.getOutputStream();
if (toRead>=0)
IO.copy(in,out,toRead);
else
IO.copy(in,out);
out.close();
request.setHandled(true);
response.setStatus(exists
?HttpResponse.__200_OK
:HttpResponse.__201_Created);
response.commit();
}
catch (Exception ex)
{
log.warn(LogSupport.EXCEPTION,ex);
response.sendError(HttpResponse.__403_Forbidden,
ex.getMessage());
}
}
}
/* ------------------------------------------------------------ */
void handleDelete(HttpRequest request,
HttpResponse response,
String pathInContext,
Resource resource)
throws IOException
{
if(log.isDebugEnabled())log.debug("DELETE "+pathInContext+" from "+resource);
if (!resource.exists() ||
!passConditionalHeaders(request,response,resource))
return;
try
{
// delete the file
if (resource.delete())
response.setStatus(HttpResponse.__204_No_Content);
else
response.sendError(HttpResponse.__403_Forbidden);
// Send response
request.setHandled(true);
}
catch (SecurityException sex)
{
log.warn(LogSupport.EXCEPTION,sex);
response.sendError(HttpResponse.__403_Forbidden, sex.getMessage());
}
}
/* ------------------------------------------------------------ */
void handleMove(HttpRequest request,
HttpResponse response,
String pathInContext,
Resource resource)
throws IOException
{
if (!resource.exists() || !passConditionalHeaders(request,response,resource))
return;
String newPath = URI.canonicalPath(request.getField("New-uri"));
if (newPath==null)
{
response.sendError(HttpResponse.__405_Method_Not_Allowed,
"Bad new uri");
return;
}
String contextPath = getHttpContext().getContextPath();
if (contextPath!=null && !newPath.startsWith(contextPath))
{
response.sendError(HttpResponse.__405_Method_Not_Allowed,
"Not in context");
return;
}
// Find path
try
{
// TODO - Check this
String newInfo=newPath;
if (contextPath!=null)
newInfo=newInfo.substring(contextPath.length());
Resource newFile = getHttpContext().getBaseResource().addPath(newInfo);
if(log.isDebugEnabled())log.debug("Moving "+resource+" to "+newFile);
resource.renameTo(newFile);
response.setStatus(HttpResponse.__204_No_Content);
request.setHandled(true);
}
catch (Exception ex)
{
log.warn(LogSupport.EXCEPTION,ex);
setAllowHeader(response);
response.sendError(HttpResponse.__405_Method_Not_Allowed,
"Error:"+ex);
return;
}
}
/* ------------------------------------------------------------ */
void handleOptions(HttpResponse response, String pathInContext)
throws IOException
{
if ("*".equals(pathInContext))
return;
setAllowHeader(response);
response.commit();
}
/* ------------------------------------------------------------ */
void setAllowHeader(HttpResponse response)
{
response.setField(HttpFields.__Allow, getAllowedString());
}
/* ------------------------------------------------------------ */
public void writeHeaders(HttpResponse response,Resource resource, long count)
throws IOException
{
ResourceCache.ResourceMetaData metaData =
(ResourceCache.ResourceMetaData)resource.getAssociate();
response.setContentType(metaData.getMimeType());
if (count != -1)
{
if (count==resource.length())
response.setField(HttpFields.__ContentLength,metaData.getLength());
else
response.setContentLength((int)count);
}
response.setField(HttpFields.__LastModified,metaData.getLastModified());
if (_acceptRanges && response.getHttpRequest().getDotVersion()>0)
response.setField(HttpFields.__AcceptRanges,"bytes");
}
/* ------------------------------------------------------------ */
public void sendData(HttpRequest request,
HttpResponse response,
String pathInContext,
Resource resource,
boolean writeHeaders)
throws IOException
{
long resLength=resource.length();
// see if there are any range headers
Enumeration reqRanges =
request.getDotVersion()>0
?request.getFieldValues(HttpFields.__Range)
:null;
if (!writeHeaders || reqRanges == null || !reqRanges.hasMoreElements())
{
// look for a gziped content.
Resource data=resource;
if (_minGzipLength>0)
{
String accept=request.getField(HttpFields.__AcceptEncoding);
if (accept!=null && resLength>_minGzipLength &&
!pathInContext.endsWith(".gz"))
{
Resource gz = getHttpContext().getResource(pathInContext+".gz");
if (gz.exists() && accept.indexOf("gzip")>=0)
{
if(log.isDebugEnabled())log.debug("gzip="+gz);
response.setField(HttpFields.__ContentEncoding,"gzip");
data=gz;
resLength=data.length();
}
}
}
writeHeaders(response,resource,resLength);
request.setHandled(true);
OutputStream out = response.getOutputStream();
data.writeTo(out,0,resLength);
return;
}
// Parse the satisfiable ranges
List ranges =InclusiveByteRange.satisfiableRanges(reqRanges,resLength);
if(log.isDebugEnabled())log.debug("ranges: " + reqRanges + " == " + ranges);
// if there are no satisfiable ranges, send 416 response
if (ranges==null || ranges.size()==0)
{
log.debug("no satisfiable ranges");
writeHeaders(response, resource, resLength);
response.setStatus(HttpResponse.__416_Requested_Range_Not_Satisfiable);
response.setReason((String)HttpResponse.__statusMsg
.get(TypeUtil.newInteger(HttpResponse.__416_Requested_Range_Not_Satisfiable)));
response.setField(HttpFields.__ContentRange,
InclusiveByteRange.to416HeaderRangeString(resLength));
OutputStream out = response.getOutputStream();
resource.writeTo(out,0,resLength);
request.setHandled(true);
return;
}
// if there is only a single valid range (must be satisfiable
// since were here now), send that range with a 216 response
if ( ranges.size()== 1)
{
InclusiveByteRange singleSatisfiableRange =
(InclusiveByteRange)ranges.get(0);
if(log.isDebugEnabled())log.debug("single satisfiable range: " + singleSatisfiableRange);
long singleLength = singleSatisfiableRange.getSize(resLength);
writeHeaders(response,resource,singleLength);
response.setStatus(HttpResponse.__206_Partial_Content);
response.setReason((String)HttpResponse.__statusMsg
.get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));
response.setField(HttpFields.__ContentRange,
singleSatisfiableRange.toHeaderRangeString(resLength));
OutputStream out = response.getOutputStream();
resource.writeTo(out,
singleSatisfiableRange.getFirst(resLength),
singleLength);
request.setHandled(true);
return;
}
// multiple non-overlapping valid ranges cause a multipart
// 216 response which does not require an overall
// content-length header
//
ResourceCache.ResourceMetaData metaData =
(ResourceCache.ResourceMetaData)resource.getAssociate();
String encoding = metaData.getMimeType();
MultiPartResponse multi = new MultiPartResponse(response);
response.setStatus(HttpResponse.__206_Partial_Content);
response.setReason((String)HttpResponse.__statusMsg
.get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));
// If the request has a "Request-Range" header then we need to
// send an old style multipart/x-byteranges Content-Type. This
// keeps Netscape and acrobat happy. This is what Apache does.
String ctp;
if (request.containsField(HttpFields.__RequestRange))
ctp = "multipart/x-byteranges; boundary=";
else
ctp = "multipart/byteranges; boundary=";
response.setContentType(ctp+multi.getBoundary());
InputStream in=(resource instanceof CachedResource)
?null:resource.getInputStream();
OutputStream out = response.getOutputStream();
long pos=0;
for (int i=0;i<ranges.size();i++)
{
InclusiveByteRange ibr = (InclusiveByteRange) ranges.get(i);
String header=HttpFields.__ContentRange+": "+
ibr.toHeaderRangeString(resLength);
if(log.isDebugEnabled())log.debug("multi range: "+encoding+" "+header);
multi.startPart(encoding,new String[]{header});
long start=ibr.getFirst(resLength);
long size=ibr.getSize(resLength);
if (in!=null)
{
// Handle non cached resource
if (start<pos)
{
in.close();
in=resource.getInputStream();
pos=0;
}
if (pos<start)
{
in.skip(start-pos);
pos=start;
}
IO.copy(in,out,size);
pos+=size;
}
else
// Handle cached resource
resource.writeTo(out,start,size);
}
if (in!=null)
in.close();
multi.close();
request.setHandled(true);
return;
}
/* ------------------------------------------------------------------- */
void sendDirectory(HttpRequest request,
HttpResponse response,
Resource resource,
boolean parent)
throws IOException
{
if (!_dirAllowed)
{
response.sendError(HttpResponse.__403_Forbidden);
return;
}
request.setHandled(true);
if(log.isDebugEnabled())log.debug("sendDirectory: "+resource);
byte[] data=null;
if (resource instanceof CachedResource)
data=((CachedResource)resource).getCachedData();
if (data==null)
{
String base = URI.addPaths(request.getPath(),"/");
String dir = resource.getListHTML(URI.encodePath(base),parent);
if (dir==null)
{
response.sendError(HttpResponse.__403_Forbidden,
"No directory");
return;
}
data=dir.getBytes("UTF8");
if (resource instanceof CachedResource)
((CachedResource)resource).setCachedData(data);
}
response.setContentType("text/html; charset=UTF8");
response.setContentLength(data.length);
if (request.getMethod().equals(HttpRequest.__HEAD))
{
response.commit();
return;
}
response.getOutputStream().write(data,0,data.length);
response.commit();
}
}

View File

@ -1,617 +0,0 @@
// ========================================================================
// $Id: Server.java,v 1.40 2005/10/21 13:52:11 gregwilkins Exp $
// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.jetty;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.mortbay.log.LogFactory;
import org.mortbay.http.HttpContext;
import org.mortbay.http.HttpServer;
import org.mortbay.jetty.servlet.ServletHttpContext;
import org.mortbay.jetty.servlet.WebApplicationContext;
import org.mortbay.util.LogSupport;
import org.mortbay.util.Resource;
import org.mortbay.xml.XmlConfiguration;
/* ------------------------------------------------------------ */
/** The Jetty HttpServer.
*
* This specialization of org.mortbay.http.HttpServer adds knowledge
* about servlets and their specialized contexts. It also included
* support for initialization from xml configuration files
* that follow the XmlConfiguration dtd.
*
* HttpContexts created by Server are of the type
* org.mortbay.jetty.servlet.ServletHttpContext unless otherwise
* specified.
*
* This class also provides a main() method which starts a server for
* each config file passed on the command line. If the system
* property JETTY_NO_SHUTDOWN_HOOK is not set to true, then a shutdown
* hook is thread is registered to stop these servers.
*
* @see org.mortbay.xml.XmlConfiguration
* @see org.mortbay.jetty.servlet.ServletHttpContext
* @version $Revision: 1.40 $
* @author Greg Wilkins (gregw)
*/
public class Server extends HttpServer
{
static Log log = LogFactory.getLog(Server.class);
private String[] _webAppConfigurationClassNames =
new String[]{"org.mortbay.jetty.servlet.XMLConfiguration", "org.mortbay.jetty.servlet.JettyWebConfiguration"};
private String _configuration;
private String _rootWebApp;
private static ShutdownHookThread hookThread = new ShutdownHookThread();
/* ------------------------------------------------------------ */
/** Constructor.
*/
public Server()
{
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param configuration The filename or URL of the XML
* configuration file.
*/
public Server(String configuration)
throws IOException
{
this(Resource.newResource(configuration).getURL());
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param configuration The filename or URL of the XML
* configuration file.
*/
public Server(Resource configuration)
throws IOException
{
this(configuration.getURL());
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param configuration The filename or URL of the XML
* configuration file.
*/
public Server(URL configuration)
throws IOException
{
_configuration=configuration.toString();
Server.hookThread.add(this);
try
{
XmlConfiguration config=new XmlConfiguration(configuration);
config.configure(this);
}
catch(IOException e)
{
throw e;
}
catch(InvocationTargetException e)
{
log.warn(LogSupport.EXCEPTION,e.getTargetException());
throw new IOException("Jetty configuration problem: "+e.getTargetException());
}
catch(Exception e)
{
log.warn(LogSupport.EXCEPTION,e);
throw new IOException("Jetty configuration problem: "+e);
}
}
/* ------------------------------------------------------------ */
public boolean getStopAtShutdown()
{
return hookThread.contains(this);
}
/* ------------------------------------------------------------ */
public void setStopAtShutdown(boolean stop)
{
if (stop)
hookThread.add(this);
else
hookThread.remove(this);
}
/* ------------------------------------------------------------ */
/** Get the root webapp name.
* @return The name of the root webapp (eg. "root" for root.war).
*/
public String getRootWebApp()
{
return _rootWebApp;
}
/* ------------------------------------------------------------ */
/** Set the root webapp name.
* @param rootWebApp The name of the root webapp (eg. "root" for root.war).
*/
public void setRootWebApp(String rootWebApp)
{
_rootWebApp = rootWebApp;
}
/* ------------------------------------------------------------ */
/** Configure the server from an XML file.
* @param configuration The filename or URL of the XML
* configuration file.
*/
public void configure(String configuration)
throws IOException
{
URL url=Resource.newResource(configuration).getURL();
if (_configuration!=null && _configuration.equals(url.toString()))
return;
if (_configuration!=null)
throw new IllegalStateException("Already configured with "+_configuration);
try
{
XmlConfiguration config=new XmlConfiguration(url);
_configuration=url.toString();
config.configure(this);
}
catch(IOException e)
{
throw e;
}
catch(Exception e)
{
log.warn(LogSupport.EXCEPTION,e);
throw new IOException("Jetty configuration problem: "+e);
}
}
/* ------------------------------------------------------------ */
public String getConfiguration()
{
return _configuration;
}
/* ------------------------------------------------------------ */
/** Create a new ServletHttpContext.
* Ths method is called by HttpServer to creat new contexts. Thus
* calls to addContext or getContext that result in a new Context
* being created will return an
* org.mortbay.jetty.servlet.ServletHttpContext instance.
* @return ServletHttpContext
*/
protected HttpContext newHttpContext()
{
return new ServletHttpContext();
}
/* ------------------------------------------------------------ */
/** Create a new WebApplicationContext.
* Ths method is called by Server to creat new contexts for web
* applications. Thus calls to addWebApplication that result in
* a new Context being created will return an correct class instance.
* Derived class can override this method to create instance of its
* own class derived from WebApplicationContext in case it needs more
* functionality.
* @param webApp The Web application directory or WAR file.
* @return WebApplicationContext
*/
protected WebApplicationContext newWebApplicationContext(
String webApp
)
{
return new WebApplicationContext(webApp);
}
/* ------------------------------------------------------------ */
/** Add Web Application.
* @param contextPathSpec The context path spec. Which must be of
* the form / or /path/*
* @param webApp The Web application directory or WAR file.
* @return The WebApplicationContext
* @exception IOException
*/
public WebApplicationContext addWebApplication(String contextPathSpec,
String webApp)
throws IOException
{
return addWebApplication(null,contextPathSpec,webApp);
}
/* ------------------------------------------------------------ */
/** Add Web Application.
* @param virtualHost Virtual host name or null
* @param contextPathSpec The context path spec. Which must be of
* the form / or /path/*
* @param webApp The Web application directory or WAR file.
* @return The WebApplicationContext
* @exception IOException
*/
public WebApplicationContext addWebApplication(String virtualHost,
String contextPathSpec,
String webApp)
throws IOException
{
WebApplicationContext appContext =
newWebApplicationContext(webApp);
appContext.setContextPath(contextPathSpec);
addContext(virtualHost,appContext);
if(log.isDebugEnabled())log.debug("Web Application "+appContext+" added");
return appContext;
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If a
* webapp is called "root" it is added at "/".
* @param webapps Directory file name or URL to look for auto webapplication.
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String webapps)
throws IOException
{
return addWebApplications(null,webapps,null,false);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto webapplication.
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps)
throws IOException
{
return addWebApplications(host,webapps,null,false);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto
* webapplication.
* @param extract If true, extract war files
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps,
boolean extract)
throws IOException
{
return addWebApplications(host,webapps,null,extract);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto
* webapplication.
* @param defaults The defaults xml filename or URL which is
* loaded before any in the web app. Must respect the web.dtd.
* If null the default defaults file is used. If the empty string, then
* no defaults file is used.
* @param extract If true, extract war files
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps,
String defaults,
boolean extract)
throws IOException
{
return addWebApplications(host,webapps,defaults,extract,true,null);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto
* webapplication.
* @param defaults The defaults xml filename or URL which is
* loaded before any in the web app. Must respect the web.dtd.
* If null the default defaults file is used. If the empty string, then
* no defaults file is used.
* @param extract If true, extract war files
* @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps,
String defaults,
boolean extract,
boolean java2CompliantClassLoader)
throws IOException
{
return addWebApplications(host,webapps,defaults,extract,java2CompliantClassLoader,null);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto
* webapplication.
* @param defaults The defaults xml filename or URL which is
* loaded before any in the web app. Must respect the web.dtd.
* If null the default defaults file is used. If the empty string, then
* no defaults file is used.
* @param extract If true, extract war files
* @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications
* @param Attributes[] A set of attributes to pass to setAttribute, format is first item is the key, second item is the value.
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps,
String defaults,
boolean extract,
boolean java2CompliantClassLoader,
String Attributes[])
throws IOException
{
ArrayList wacs = new ArrayList();
Resource r=Resource.newResource(webapps);
if (!r.exists())
throw new IllegalArgumentException("No such webapps resource "+r);
if (!r.isDirectory())
throw new IllegalArgumentException("Not directory webapps resource "+r);
if(Attributes != null) {
if(((Attributes.length / 2) * 2) != Attributes.length) {
throw new IllegalArgumentException("Attributes must be in pairs of key,value.");
}
}
String[] files=r.list();
for (int f=0;files!=null && f<files.length;f++)
{
String context=files[f];
if (context.equalsIgnoreCase("CVS/") ||
context.equalsIgnoreCase("CVS") ||
context.startsWith("."))
continue;
String app = r.addPath(r.encode(files[f])).toString();
if (context.toLowerCase().endsWith(".war") ||
context.toLowerCase().endsWith(".jar"))
{
context=context.substring(0,context.length()-4);
Resource unpacked=r.addPath(context);
if (unpacked!=null && unpacked.exists() && unpacked.isDirectory())
continue;
}
if (_rootWebApp!=null && (context.equals(_rootWebApp)||context.equals(_rootWebApp+"/")))
context="/";
else
context="/"+context;
WebApplicationContext wac= addWebApplication(host,
context,
app);
wac.setExtractWAR(extract);
wac.setClassLoaderJava2Compliant(java2CompliantClassLoader);
if (defaults!=null)
{
if (defaults.length()==0)
wac.setDefaultsDescriptor(null);
else
wac.setDefaultsDescriptor(defaults);
}
if(Attributes != null) {
for(int i = 0; i < Attributes.length; i++, i++) {
wac.setAttribute(Attributes[i],Attributes[i + 1]);
}
}
wacs.add(wac);
}
return (WebApplicationContext[])wacs.toArray(new WebApplicationContext[wacs.size()]);
}
/* ------------------------------------------------------------ */
/** setWebApplicationConfigurationClasses
* Set up the list of classnames of WebApplicationContext.Configuration
* implementations that will be applied to configure every webapp.
* The list can be overridden by individual WebApplicationContexts.
* @param configurationClasses
*/
public void setWebApplicationConfigurationClassNames (String[] configurationClassNames)
{
if (configurationClassNames != null)
{
_webAppConfigurationClassNames = new String[configurationClassNames.length];
System.arraycopy(configurationClassNames, 0, _webAppConfigurationClassNames, 0, configurationClassNames.length);
}
}
public String[] getWebApplicationConfigurationClassNames ()
{
return _webAppConfigurationClassNames;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
public static void main(String[] arg)
{
String[] dftConfig={"etc/jetty.xml"};
if (arg.length==0)
{
log.info("Using default configuration: etc/jetty.xml");
arg=dftConfig;
}
final Server[] servers=new Server[arg.length];
// create and start the servers.
for (int i=0;i<arg.length;i++)
{
try
{
servers[i] = new Server(arg[i]);
servers[i].setStopAtShutdown(true);
servers[i].start();
}
catch(Exception e)
{
log.warn(LogSupport.EXCEPTION,e);
}
}
// create and start the servers.
for (int i=0;i<arg.length;i++)
{
try{servers[i].join();}
catch (Exception e){LogSupport.ignore(log,e);}
}
}
/**
* ShutdownHook thread for stopping all servers.
*
* Thread is hooked first time list of servers is changed.
*/
private static class ShutdownHookThread extends Thread {
private boolean hooked = false;
private ArrayList servers = new ArrayList();
/**
* Hooks this thread for shutdown.
* @see java.lang.Runtime#addShutdownHook(java.lang.Thread)
*/
private void createShutdownHook() {
if (!Boolean.getBoolean("JETTY_NO_SHUTDOWN_HOOK") && !hooked) {
try {
Method shutdownHook = java.lang.Runtime.class.getMethod("addShutdownHook",
new Class[] { java.lang.Thread.class });
shutdownHook.invoke(Runtime.getRuntime(), new Object[] { this });
this.hooked = true;
} catch (Exception e) {
if (log.isDebugEnabled()) log.debug("No shutdown hook in JVM ", e);
}
}
}
/**
* Add Server to servers list.
*/
public boolean add(Server server) {
createShutdownHook();
return this.servers.add(server);
}
/**
* Contains Server in servers list?
*/
public boolean contains(Server server) {
return this.servers.contains(server);
}
/**
* Append all Servers from Collection
*/
public boolean addAll(Collection c) {
createShutdownHook();
return this.servers.addAll(c);
}
/**
* Clear list of Servers.
*/
public void clear() {
createShutdownHook();
this.servers.clear();
}
/**
* Remove Server from list.
*/
public boolean remove(Server server) {
createShutdownHook();
return this.servers.remove(server);
}
/**
* Remove all Servers in Collection from list.
*/
public boolean removeAll(Collection c) {
createShutdownHook();
return this.servers.removeAll(c);
}
/**
* Stop all Servers in list.
*/
public void run() {
setName("Shutdown");
log.info("Shutdown hook executing");
Iterator it = servers.iterator();
while (it.hasNext()) {
Server svr = (Server) it.next();
if (svr == null) continue;
try {
svr.stop();
} catch (Exception e) {
log.warn(LogSupport.EXCEPTION, e);
}
log.info("Shutdown hook complete");
// Try to avoid JVM crash
try {
Thread.sleep(1000);
} catch (Exception e) {
log.warn(LogSupport.EXCEPTION, e);
}
}
}
}
}

View File

@ -1,352 +0,0 @@
// ========================================================================
// $Id: FileResource.java,v 1.31 2006/01/04 13:55:31 gregwilkins Exp $
// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.security.Permission;
import org.apache.commons.logging.Log;
import org.mortbay.log.LogFactory;
/* ------------------------------------------------------------ */
/** File Resource.
*
* Handle resources of implied or explicit file type.
* This class can check for aliasing in the filesystem (eg case
* insensitivity). By default this is turned on if the platform does
* not have the "/" path separator, or it can be controlled with the
* "org.mortbay.util.FileResource.checkAliases" system parameter.
*
* If alias checking is turned on, then aliased resources are
* treated as if they do not exist, nor can they be created.
*
* @version $Revision: 1.31 $
* @author Greg Wilkins (gregw)
*/
public class FileResource extends URLResource
{
private static Log log = LogFactory.getLog(Credential.class);
private static boolean __checkAliases;
static
{
__checkAliases=
"true".equalsIgnoreCase
(System.getProperty("org.mortbay.util.FileResource.checkAliases","true"));
if (__checkAliases)
log.info("Checking Resource aliases");
}
/* ------------------------------------------------------------ */
private File _file;
private transient URL _alias=null;
private transient boolean _aliasChecked=false;
/* ------------------------------------------------------------------------------- */
/** setCheckAliases.
* @param checkAliases True of resource aliases are to be checked for (eg case insensitivity or 8.3 short names) and treated as not found.
*/
public static void setCheckAliases(boolean checkAliases)
{
__checkAliases=checkAliases;
}
/* ------------------------------------------------------------------------------- */
/** getCheckAliases.
* @return True of resource aliases are to be checked for (eg case insensitivity or 8.3 short names) and treated as not found.
*/
public static boolean getCheckAliases()
{
return __checkAliases;
}
/* -------------------------------------------------------- */
FileResource(URL url)
throws IOException, URISyntaxException
{
super(url,null);
try
{
// Try standard API to convert URL to file.
_file =new File(new URI(url.toString()));
}
catch (Exception e)
{
LogSupport.ignore(log,e);
try
{
// Assume that File.toURL produced unencoded chars. So try
// encoding them.
String urls=
"file:"+org.mortbay.util.URI.encodePath(url.toString().substring(5));
_file =new File(new URI(urls));
}
catch (Exception e2)
{
LogSupport.ignore(log,e2);
// Still can't get the file. Doh! try good old hack!
checkConnection();
Permission perm = _connection.getPermission();
_file = new File(perm==null?url.getFile():perm.getName());
}
}
if (_file.isDirectory() && !_urlString.endsWith("/"))
_urlString=_urlString+"/";
}
/* -------------------------------------------------------- */
FileResource(URL url, URLConnection connection, File file)
{
super(url,connection);
_file=file;
if (_file.isDirectory() && !_urlString.endsWith("/"))
_urlString=_urlString+"/";
}
/* -------------------------------------------------------- */
public Resource addPath(String path)
throws IOException,MalformedURLException
{
FileResource r=null;
if (!isDirectory())
{
r=(FileResource)super.addPath(path);
}
else
{
path = org.mortbay.util.URI.canonicalPath(path);
// treat all paths being added as relative
String rel=path;
if (path.startsWith("/"))
rel = path.substring(1);
File newFile = new File(_file,rel.replace('/', File.separatorChar));
r=new FileResource(newFile.toURI().toURL(),null,newFile);
}
String encoded=org.mortbay.util.URI.encodePath(path);
int expected=r._urlString.length()-encoded.length();
int index = r._urlString.lastIndexOf(encoded, expected);
if (expected!=index && ((expected-1)!=index || path.endsWith("/") || !r.isDirectory()))
{
r._alias=r._url;
r._aliasChecked=true;
}
return r;
}
/* ------------------------------------------------------------ */
public URL getAlias()
{
if (__checkAliases) {
if (!_aliasChecked)
{
try
{
String abs=_file.getAbsolutePath();
String can=_file.getCanonicalPath();
if (abs.length()!=can.length() || !abs.equals(can))
_alias=new File(can).toURI().toURL();
_aliasChecked=true;
if (_alias!=null && log.isDebugEnabled())
{
log.debug("ALIAS abs="+abs);
log.debug("ALIAS can="+can);
}
}
catch(Exception e)
{
log.warn(LogSupport.EXCEPTION,e);
return getURL();
}
}
} else return null;
return _alias;
}
/* -------------------------------------------------------- */
/**
* Returns true if the resource exists.
*/
public boolean exists()
{
return _file.exists();
}
/* -------------------------------------------------------- */
/**
* Returns the last modified time
*/
public long lastModified()
{
return _file.lastModified();
}
/* -------------------------------------------------------- */
/**
* Returns true if the respresenetd resource is a container/directory.
*/
public boolean isDirectory()
{
return _file.isDirectory();
}
/* --------------------------------------------------------- */
/**
* Return the length of the resource
*/
public long length()
{
return _file.length();
}
/* --------------------------------------------------------- */
/**
* Returns the name of the resource
*/
public String getName()
{
return _file.getAbsolutePath();
}
/* ------------------------------------------------------------ */
/**
* Returns an File representing the given resource or NULL if this
* is not possible.
*/
public File getFile()
{
return _file;
}
/* --------------------------------------------------------- */
/**
* Returns an input stream to the resource
*/
public InputStream getInputStream() throws IOException
{
return new FileInputStream(_file);
}
/* --------------------------------------------------------- */
/**
* Returns an output stream to the resource
*/
public OutputStream getOutputStream()
throws java.io.IOException, SecurityException
{
return new FileOutputStream(_file);
}
/* --------------------------------------------------------- */
/**
* Deletes the given resource
*/
public boolean delete()
throws SecurityException
{
return _file.delete();
}
/* --------------------------------------------------------- */
/**
* Rename the given resource
*/
public boolean renameTo( Resource dest)
throws SecurityException
{
if( dest instanceof FileResource)
return _file.renameTo( ((FileResource)dest)._file);
else
return false;
}
/* --------------------------------------------------------- */
/**
* Returns a list of resources contained in the given resource
*/
public String[] list()
{
String[] list =_file.list();
if (list==null)
return null;
for (int i=list.length;i-->0;)
{
if (new File(_file,list[i]).isDirectory() &&
!list[i].endsWith("/"))
list[i]+="/";
}
return list;
}
/* ------------------------------------------------------------ */
/** Encode according to this resource type.
* File URIs are encoded.
* @param uri URI to encode.
* @return The uri unchanged.
*/
public String encode(String uri)
{
return uri;
}
/* ------------------------------------------------------------ */
/**
* @param o
* @return
*/
public boolean equals( Object o)
{
if (this == o)
return true;
if (null == o || ! (o instanceof FileResource))
return false;
FileResource f=(FileResource)o;
return f._file == _file || (null != _file && _file.equals(f._file));
}
/* ------------------------------------------------------------ */
/**
* @return the hashcode.
*/
public int hashCode()
{
return null == _file ? super.hashCode() : _file.hashCode();
}
}

View File

@ -1,253 +0,0 @@
// ========================================================================
// $Id: InetAddrPort.java,v 1.7 2004/10/23 09:03:22 gregwilkins Exp $
// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.util;
import java.io.Serializable;
import java.net.InetAddress;
/* ======================================================================== */
/** InetAddress and Port.
*/
public class InetAddrPort implements Serializable
{
/* ------------------------------------------------------------ */
public final static String __0_0_0_0 = "0.0.0.0";
/* ------------------------------------------------------------ */
private InetAddress _addr=null;
private boolean _addrIsHost=false;
private int _port=0;
/* ------------------------------------------------------------------- */
public InetAddrPort()
{}
/* ------------------------------------------------------------ */
/** Constructor for a port on all local host address.
* @param port
*/
public InetAddrPort(int port)
{
_port=port;
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param addr
* @param port
*/
public InetAddrPort(InetAddress addr, int port)
{
_addr=addr;
_port=port;
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param host
* @param port
*/
public InetAddrPort(String host, int port)
throws java.net.UnknownHostException
{
setHost(host);
setPort(port);
}
/* ------------------------------------------------------------ */
/** Constructor.
* Patched to support [::1]:port for I2P
*
* @param inetAddrPort String of the form "addr:port"
*/
public InetAddrPort(String inetAddrPort)
throws java.net.UnknownHostException
{
int b = inetAddrPort.indexOf('[');
if (b>0)
throw new java.net.UnknownHostException("Bad [] syntax");
if (b==0) // IPV6
{
int b2 = inetAddrPort.indexOf(']');
if (b2<2)
throw new java.net.UnknownHostException("Bad [] syntax");
String addr=inetAddrPort.substring(1,b2);
if (addr.indexOf('/')>0)
addr=addr.substring(addr.indexOf('/')+1);
inetAddrPort=inetAddrPort.substring(b2+1);
int c = inetAddrPort.indexOf(':');
if (c>0)
throw new java.net.UnknownHostException("Bad [] syntax");
if (c==0)
inetAddrPort=inetAddrPort.substring(1);
if (addr.length()>0 && ! __0_0_0_0.equals(addr))
{
_addrIsHost=!Character.isDigit((addr.charAt(0)));
this._addr=InetAddress.getByName(addr);
}
} else { // IPV4
int c = inetAddrPort.indexOf(':');
if (c>=0)
{
String addr=inetAddrPort.substring(0,c);
if (addr.indexOf('/')>0)
addr=addr.substring(addr.indexOf('/')+1);
inetAddrPort=inetAddrPort.substring(c+1);
if (addr.length()>0 && ! __0_0_0_0.equals(addr))
{
_addrIsHost=!Character.isDigit((addr.charAt(0)));
this._addr=InetAddress.getByName(addr);
}
}
}
_port = Integer.parseInt(inetAddrPort);
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param address InetAddrPort top copy.
*/
public InetAddrPort(InetAddrPort address)
{
if (address!=null)
{
_addr=address._addr;
_port=address._port;
}
}
/* ------------------------------------------------------------ */
/** Get the Host.
* @return The IP address
*/
public String getHost()
{
if (_addr==null)
return __0_0_0_0;
return _addrIsHost?_addr.getHostName():_addr.getHostAddress();
}
/* ------------------------------------------------------------ */
/** Set the Host.
* @param host
* @exception java.net.UnknownHostException
*/
public void setHost(String host)
throws java.net.UnknownHostException
{
_addr=null;
if (host!=null)
{
if (host.indexOf('/')>0)
host=host.substring(0,host.indexOf('/'));
_addrIsHost=!Character.isDigit((host.charAt(0)));
_addr=InetAddress.getByName(host);
}
}
/* ------------------------------------------------------------ */
/** Get the IP address.
* @return The IP address
*/
public InetAddress getInetAddress()
{
return _addr;
}
/* ------------------------------------------------------------ */
/** Set the IP address.
* @param addr The IP address
*/
public void setInetAddress(InetAddress addr)
{
_addrIsHost=false;
_addr=addr;
}
/* ------------------------------------------------------------ */
/** Get the port.
* @return The port number
*/
public int getPort()
{
return _port;
}
/* ------------------------------------------------------------ */
/** Set the port.
* @param port The port number
*/
public void setPort(int port)
{
_port=port;
}
/* ------------------------------------------------------------------- */
public String toString()
{
return getHost()+':'+_port;
}
/* ------------------------------------------------------------ */
/** Clone the InetAddrPort.
* @return A new instance.
*/
public Object clone()
{
return new InetAddrPort(this);
}
/* ------------------------------------------------------------ */
/** Hash Code.
* @return hash Code.
*/
public int hashCode()
{
return _port+((_addr==null)?0:_addr.hashCode());
}
/* ------------------------------------------------------------ */
/** Equals.
* @param o
* @return True if is the same address and port.
*/
public boolean equals(Object o)
{
if (o==null)
return false;
if (o==this)
return true;
if (o instanceof InetAddrPort)
{
InetAddrPort addr=(InetAddrPort)o;
return addr._port==_port &&
( addr._addr==_addr ||
addr._addr!=null && addr._addr.equals(_addr));
}
return false;
}
}

View File

@ -1,431 +0,0 @@
// ========================================================================
// $Id: Resource.java,v 1.32 2009/05/16 01:53:36 gregwilkins Exp $
// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.mortbay.log.LogFactory;
/* ------------------------------------------------------------ */
/** Abstract resource class.
*
* @version $Id: Resource.java,v 1.32 2009/05/16 01:53:36 gregwilkins Exp $
* @author Nuno Preguica
* @author Greg Wilkins (gregw)
*/
public abstract class Resource implements Serializable
{
private static Log log = LogFactory.getLog(Resource.class);
Object _associate;
/* ------------------------------------------------------------ */
/** Construct a resource from a url.
* @param url A URL.
* @return A Resource object.
*/
public static Resource newResource(URL url)
throws IOException
{
if (url==null)
return null;
String urls=url.toExternalForm();
if( urls.startsWith( "file:"))
{
try
{
FileResource fileResource= new FileResource(url);
return fileResource;
}
catch(Exception e)
{
log.debug(LogSupport.EXCEPTION,e);
return new BadResource(url,e.toString());
}
}
else if( urls.startsWith( "jar:file:"))
{
return new JarFileResource(url);
}
else if( urls.startsWith( "jar:"))
{
return new JarResource(url);
}
return new URLResource(url,null);
}
/* ------------------------------------------------------------ */
/** Construct a resource from a string.
* @param resource A URL or filename.
* @return A Resource object.
*/
public static Resource newResource(String resource)
throws MalformedURLException, IOException
{
URL url=null;
try
{
// Try to format as a URL?
url = new URL(resource);
}
catch(MalformedURLException e)
{
if(!resource.startsWith("ftp:") &&
!resource.startsWith("file:") &&
!resource.startsWith("jar:"))
{
try
{
// It's a file.
if (resource.startsWith("./"))
resource=resource.substring(2);
File file=new File(resource).getCanonicalFile();
url=file.toURI().toURL();
URLConnection connection=url.openConnection();
FileResource fileResource= new FileResource(url,connection,file);
return fileResource;
}
catch(Exception e2)
{
log.debug(LogSupport.EXCEPTION,e2);
throw e;
}
}
else
{
log.warn("Bad Resource: "+resource);
throw e;
}
}
String nurl=url.toString();
if (nurl.length()>0 &&
nurl.charAt(nurl.length()-1)!=
resource.charAt(resource.length()-1))
{
if ((nurl.charAt(nurl.length()-1)!='/' ||
nurl.charAt(nurl.length()-2)!=resource.charAt(resource.length()-1))
&&
(resource.charAt(resource.length()-1)!='/' ||
resource.charAt(resource.length()-2)!=nurl.charAt(nurl.length()-1)
))
{
return new BadResource(url,"Trailing special characters stripped by URL in "+resource);
}
}
return newResource(url);
}
/* ------------------------------------------------------------ */
/** Construct a system resource from a string.
* The resource is tried as classloader resource before being
* treated as a normal resource.
*/
public static Resource newSystemResource(String resource)
throws IOException
{
URL url=null;
// Try to format as a URL?
ClassLoader
loader=Thread.currentThread().getContextClassLoader();
if (loader!=null)
{
url=loader.getResource(resource);
if (url==null && resource.startsWith("/"))
url=loader.getResource(resource.substring(1));
}
if (url==null)
{
loader=Resource.class.getClassLoader();
if (loader!=null)
{
url=loader.getResource(resource);
if (url==null && resource.startsWith("/"))
url=loader.getResource(resource.substring(1));
}
}
if (url==null)
{
url=ClassLoader.getSystemResource(resource);
if (url==null && resource.startsWith("/"))
url=loader.getResource(resource.substring(1));
}
if (url==null)
return null;
return newResource(url);
}
/* ------------------------------------------------------------ */
protected void finalize()
{
release();
}
/* ------------------------------------------------------------ */
/** Release any resources held by the resource.
*/
public abstract void release();
/* ------------------------------------------------------------ */
/**
* Returns true if the respresened resource exists.
*/
public abstract boolean exists();
/* ------------------------------------------------------------ */
/**
* Returns true if the respresenetd resource is a container/directory.
* If the resource is not a file, resources ending with "/" are
* considered directories.
*/
public abstract boolean isDirectory();
/* ------------------------------------------------------------ */
/**
* Returns the last modified time
*/
public abstract long lastModified();
/* ------------------------------------------------------------ */
/**
* Return the length of the resource
*/
public abstract long length();
/* ------------------------------------------------------------ */
/**
* Returns an URL representing the given resource
*/
public abstract URL getURL();
/* ------------------------------------------------------------ */
/**
* Returns an File representing the given resource or NULL if this
* is not possible.
*/
public abstract File getFile()
throws IOException;
/* ------------------------------------------------------------ */
/**
* Returns the name of the resource
*/
public abstract String getName();
/* ------------------------------------------------------------ */
/**
* Returns an input stream to the resource
*/
public abstract InputStream getInputStream()
throws java.io.IOException;
/* ------------------------------------------------------------ */
/**
* Returns an output stream to the resource
*/
public abstract OutputStream getOutputStream()
throws java.io.IOException, SecurityException;
/* ------------------------------------------------------------ */
/**
* Deletes the given resource
*/
public abstract boolean delete()
throws SecurityException;
/* ------------------------------------------------------------ */
/**
* Rename the given resource
*/
public abstract boolean renameTo( Resource dest)
throws SecurityException;
/* ------------------------------------------------------------ */
/**
* Returns a list of resource names contained in the given resource
* The resource names are not URL encoded.
*/
public abstract String[] list();
/* ------------------------------------------------------------ */
/**
* Returns the resource contained inside the current resource with the
* given name.
* @param path The path segment to add, which should be encoded by the
* encode method.
*/
public abstract Resource addPath(String path)
throws IOException,MalformedURLException;
/* ------------------------------------------------------------ */
/** Encode according to this resource type.
* The default implementation calls URI.encodePath(uri)
* @param uri
* @return String encoded for this resource type.
*/
public String encode(String uri)
{
return URI.encodePath(uri);
}
/* ------------------------------------------------------------ */
public Object getAssociate()
{
return _associate;
}
/* ------------------------------------------------------------ */
public void setAssociate(Object o)
{
_associate=o;
}
/* ------------------------------------------------------------ */
/**
* @return The canonical Alias of this resource or null if none.
*/
public URL getAlias()
{
return null;
}
/* ------------------------------------------------------------ */
public CachedResource cache()
throws IOException
{
return new CachedResource(this);
}
/* ------------------------------------------------------------ */
/** Get the resource list as a HTML directory listing.
* @param base The base URL
* @param parent True if the parent directory should be included
* @return String of HTML
*/
public String getListHTML(String base,
boolean parent)
throws IOException
{
if (!isDirectory())
return null;
String[] ls = list();
if (ls==null)
return null;
Arrays.sort(ls);
String title = "Directory: "+URI.decodePath(base);
title=StringUtil.replace(StringUtil.replace(title,"<","&lt;"),">","&gt;");
StringBuffer buf=new StringBuffer(4096);
buf.append("<HTML><HEAD><TITLE>");
buf.append(title);
buf.append("</TITLE></HEAD><BODY>\n<H1>");
buf.append(title);
buf.append("</H1><TABLE BORDER=0>");
if (parent)
{
buf.append("<TR><TD><A HREF=");
buf.append(URI.encodePath(URI.addPaths(base,"../")));
buf.append(">Parent Directory</A></TD><TD></TD><TD></TD></TR>\n");
}
DateFormat dfmt=DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
DateFormat.MEDIUM);
for (int i=0 ; i< ls.length ; i++)
{
String encoded=URI.encodePath(ls[i]);
// bugfix for I2P - Backport from Jetty 6 (zero file lengths and last-modified times)
// http://jira.codehaus.org/browse/JETTY-361?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel#issue-tabs
// See resource.diff attachment
//Resource item = addPath(encoded);
Resource item = addPath(ls[i]);
buf.append("<TR><TD><A HREF=\"");
String path=URI.addPaths(base,encoded);
if (item.isDirectory() && !path.endsWith("/"))
path=URI.addPaths(path,"/");
buf.append(path);
buf.append("\">");
buf.append(StringUtil.replace(StringUtil.replace(ls[i],"<","&lt;"),">","&gt;"));
buf.append("</A>&nbsp;");
buf.append("</TD><TD ALIGN=right>");
buf.append(item.length());
buf.append(" bytes&nbsp;</TD><TD>");
buf.append(dfmt.format(new Date(item.lastModified())));
buf.append("</TD></TR>\n");
}
buf.append("</TABLE>\n");
buf.append("</BODY></HTML>\n");
return buf.toString();
}
/* ------------------------------------------------------------ */
/**
* @param out
* @param start First byte to write
* @param count Bytes to write or -1 for all of them.
*/
public void writeTo(OutputStream out,long start,long count)
throws IOException
{
InputStream in = getInputStream();
try
{
in.skip(start);
if (count<0)
IO.copy(in,out);
else
IO.copy(in,out,(int)count);
}
finally
{
in.close();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
# This is not needed by Jetty - but it helps with many web apps.
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

View File

@ -21,7 +21,12 @@
<pathelement location="../../../core/java/build/obj" />
<pathelement location="../../../router/java/build/obj" />
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
<pathelement location="../../jetty/jettylib/jetty-sslengine.jar" />
<pathelement location="../../jetty/jettylib/jetty-java5-threadpool.jar" />
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
<pathelement location="../../systray/java/build/obj" />
<pathelement location="../../systray/java/lib/systray4j.jar" />
<pathelement location="../../desktopgui/build" />
@ -53,7 +58,12 @@
<pathelement location="../../../core/java/build/i2p.jar" />
<pathelement location="../../../router/java/build/router.jar" />
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
<pathelement location="../../jetty/jettylib/jetty-sslengine.jar" />
<pathelement location="../../jetty/jettylib/jetty-java5-threadpool.jar" />
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
<pathelement location="../../systray/java/build/systray.jar" />
<pathelement location="../../systray/java/lib/systray4j.jar" />
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
@ -233,7 +243,9 @@
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
<pathelement location="../../jetty/jettylib/commons-el.jar" />
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
<pathelement location="../../jetty/jettylib/ant.jar" />
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
<pathelement location="../../systray/java/build/obj" />
<pathelement location="../../systray/java/lib/systray4j.jar" />
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
@ -266,6 +278,11 @@
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
<pathelement location="../../jetty/jettylib/commons-el.jar" />
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
<pathelement location="../../jetty/jettylib/jetty-sslengine.jar" />
<pathelement location="../../jetty/jettylib/jetty-java5-threadpool.jar" />
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
<pathelement location="../../systray/java/build/obj" />
<pathelement location="../../systray/java/lib/systray4j.jar" />
<pathelement location="../../desktopgui/dist/desktopgui.jar" />

View File

@ -14,7 +14,7 @@ import net.i2p.router.client.ClientManagerFacadeImpl;
import net.i2p.router.startup.ClientAppConfig;
import net.i2p.router.startup.LoadClientAppsJob;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.ContextHandlerCollection;
/**
* Saves changes to clients.config or webapps.config
@ -286,7 +286,7 @@ public class ConfigClientsHandler extends FormHandler {
* requested and add the .war to that one
*/
private void startWebApp(String app) {
Server s = WebAppStarter.getConsoleServer();
ContextHandlerCollection s = WebAppStarter.getConsoleServer();
if (s != null) {
try {
File path = new File(_context.getBaseDir(), "webapps");

View File

@ -4,11 +4,13 @@ import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.i2p.I2PAppContext;
import org.mortbay.http.HttpRequest;
import org.mortbay.http.HttpResponse;
import org.mortbay.jetty.servlet.WebApplicationHandler;
import org.mortbay.jetty.webapp.WebAppContext;
/**
* Convert foo.jsp to foo_xx.jsp for language xx.
@ -19,12 +21,12 @@ import org.mortbay.jetty.servlet.WebApplicationHandler;
*
* @author zzz
*/
public class LocaleWebAppHandler extends WebApplicationHandler
public class LocaleWebAppHandler extends WebAppContext
{
private final I2PAppContext _context;
public LocaleWebAppHandler(I2PAppContext ctx) {
super();
public LocaleWebAppHandler(I2PAppContext ctx, String path, String warPath) {
super(warPath, path);
_context = ctx;
}
@ -36,13 +38,13 @@ public class LocaleWebAppHandler extends WebApplicationHandler
*/
@Override
public void handle(String pathInContext,
String pathParams,
HttpRequest httpRequest,
HttpResponse httpResponse)
throws IOException
HttpServletRequest httpRequest,
HttpServletResponse httpResponse,
int dispatch)
throws IOException, ServletException
{
// Handle OPTIONS (nothing to override)
if (HttpRequest.__OPTIONS.equals(httpRequest.getMethod()))
if ("OPTIONS".equals(httpRequest.getMethod()))
{
handleOptions(httpRequest, httpResponse);
return;
@ -74,7 +76,7 @@ public class LocaleWebAppHandler extends WebApplicationHandler
if (lang != null && lang.length() > 0 && !lang.equals("en")) {
String testPath = pathInContext.substring(0, len - 4) + '_' + lang + ".jsp";
// Do we have a servlet for the new path that isn't the catchall *.jsp?
Map.Entry servlet = getHolderEntry(testPath);
Map.Entry servlet = getServletHandler().getHolderEntry(testPath);
if (servlet != null) {
String servletPath = (String) servlet.getKey();
if (servletPath != null && !servletPath.startsWith("*")) {
@ -87,7 +89,7 @@ public class LocaleWebAppHandler extends WebApplicationHandler
}
}
//System.err.println("New path: " + newPath);
super.handle(newPath, pathParams, httpRequest, httpResponse);
super.handle(newPath, httpRequest, httpResponse, dispatch);
//System.err.println("Was handled? " + httpRequest.isHandled());
}
@ -95,22 +97,24 @@ public class LocaleWebAppHandler extends WebApplicationHandler
* Overrides method in ServletHandler
* @since 0.8
*/
/**** not in Jetty 6
@Override
public void handleTrace(HttpRequest request,
HttpResponse response)
public void handleTrace(HttpServletRequest request,
HttpServletResponse response)
throws IOException
{
response.sendError(HttpResponse.__405_Method_Not_Allowed);
response.sendError(405);
}
****/
/**
* Not an override
* @since 0.8
*/
public void handleOptions(HttpRequest request,
HttpResponse response)
public void handleOptions(HttpServletRequest request,
HttpServletResponse response)
throws IOException
{
response.sendError(HttpResponse.__405_Method_Not_Allowed);
response.sendError(405);
}
}

View File

@ -6,6 +6,7 @@ import java.util.List;
import net.i2p.util.FileUtil;
import net.i2p.util.VersionComparator;
import org.mortbay.jetty.Server;
import org.mortbay.http.Version;
import org.tanukisoftware.wrapper.WrapperManager;
@ -15,19 +16,12 @@ public class LogsHelper extends HelperBase {
/** @since 0.8.12 */
public String getJettyVersion() {
return jettyVersion();
return Server.getVersion();
}
/** @since 0.8.13 */
static String jettyVersion() {
try {
String rv = Version.getImplVersion();
if (rv.startsWith("Jetty/"))
rv = rv.substring(6);
return rv;
} catch (Throwable t) {
return "unknown";
}
return Server.getVersion();
}
public String getLogs() {

View File

@ -30,7 +30,7 @@ import net.i2p.util.Log;
import net.i2p.util.Translate;
import net.i2p.util.VersionComparator;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.ContextHandlerCollection;
/**
@ -157,7 +157,7 @@ public class PluginStarter implements Runnable {
}
// start console webapps in console/webapps
Server server = WebAppStarter.getConsoleServer();
ContextHandlerCollection server = WebAppStarter.getConsoleServer();
if (server != null) {
File consoleDir = new File(pluginDir, "console");
Properties wprops = RouterConsoleRunner.webAppProperties(consoleDir.getAbsolutePath());
@ -257,8 +257,8 @@ public class PluginStarter implements Runnable {
}
// stop console webapps in console/webapps
Server server = WebAppStarter.getConsoleServer();
if (server != null) {
//ContextHandlerCollection server = WebAppStarter.getConsoleServer();
//if (server != null) {
/*
File consoleDir = new File(pluginDir, "console");
Properties props = RouterConsoleRunner.webAppProperties(consoleDir.getAbsolutePath());
@ -278,11 +278,11 @@ public class PluginStarter implements Runnable {
Iterator <String> wars = pluginWars.get(appName).iterator();
while (wars.hasNext()) {
String warName = wars.next();
WebAppStarter.stopWebApp(server, warName);
WebAppStarter.stopWebApp(warName);
}
pluginWars.get(appName).clear();
}
}
//}
// remove summary bar link
Properties props = pluginProperties(ctx, appName);

View File

@ -9,12 +9,18 @@ import java.security.KeyStore;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import net.i2p.I2PAppContext;
import net.i2p.apps.systray.SysTray;
import net.i2p.data.Base32;
import net.i2p.data.DataHelper;
import net.i2p.desktopgui.Main;
import net.i2p.jetty.I2PLogger;
import net.i2p.router.RouterContext;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread;
@ -24,25 +30,41 @@ import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.ShellCommand;
import net.i2p.util.VersionComparator;
import org.mortbay.http.DigestAuthenticator;
import org.mortbay.http.HashUserRealm;
import org.mortbay.http.NCSARequestLog;
import org.mortbay.http.SecurityConstraint;
import org.mortbay.http.SocketListener;
import org.mortbay.http.SslListener;
import org.mortbay.http.handler.SecurityHandler;
import org.mortbay.jetty.AbstractConnector;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.NCSARequestLog;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.WebApplicationContext;
import org.mortbay.jetty.servlet.WebApplicationHandler;
import org.mortbay.util.InetAddrPort;
import org.mortbay.jetty.handler.ContextHandlerCollection;
import org.mortbay.jetty.handler.DefaultHandler;
import org.mortbay.jetty.handler.HandlerCollection;
import org.mortbay.jetty.handler.RequestLogHandler;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.security.DigestAuthenticator;
import org.mortbay.jetty.security.HashUserRealm;
import org.mortbay.jetty.security.Constraint;
import org.mortbay.jetty.security.ConstraintMapping;
import org.mortbay.jetty.security.SecurityHandler;
import org.mortbay.jetty.security.SslSelectChannelConnector;
import org.mortbay.jetty.servlet.ServletHandler;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.jetty.servlet.SessionHandler;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.log.Log;
import org.mortbay.thread.QueuedThreadPool;
import org.mortbay.thread.concurrent.ThreadPool;
/**
* Start the router console.
*/
public class RouterConsoleRunner {
private Server _server;
private static Server _server;
private String _listenPort;
private String _listenHost;
private String _sslListenPort;
private String _sslListenHost;
private String _webAppsDir;
private static final String PROP_WEBAPP_CONFIG_FILENAME = "router.webappsConfigFile";
private static final String DEFAULT_WEBAPP_CONFIG_FILENAME = "webapps.config";
private static final DigestAuthenticator authenticator = new DigestAuthenticator();
@ -58,6 +80,11 @@ public class RouterConsoleRunner {
private static final String USAGE = "Bad RouterConsoleRunner arguments, check clientApp.0.args in your clients.config file! " +
"Usage: [[port host[,host]] [-s sslPort [host[,host]]] [webAppsDir]]";
private static final int MIN_THREADS = 1;
private static final int MAX_THREADS = 24;
private static final int MAX_IDLE_TIME = 90*1000;
private static final String THREAD_NAME = "RouterConsole Jetty";
static {
System.setProperty("org.mortbay.http.Version.paranoid", "true");
}
@ -135,6 +162,15 @@ public class RouterConsoleRunner {
runner.startConsole();
}
/**
* SInce _server is now static
* @return may be null or stopped perhaps
* @since Jetty 6 since it doesn't have Server.getServers()
*/
static Server getConsoleServer() {
return _server;
}
private static void startTrayApp() {
try {
//TODO: move away from routerconsole into a separate application.
@ -158,6 +194,24 @@ public class RouterConsoleRunner {
}
}
/**
* http://irc.codehaus.org/display/JETTY/Porting+to+jetty6
*
*<pre>
* Server
* HandlerCollection
* ContextHandlerCollection
* WebAppContext (i.e. ContextHandler)
* SessionHandler
* SecurityHandler
* ServletHandler
* servlets...
* WebAppContext
* ...
* DefaultHandler
* RequestLogHandler (opt)
*</pre>
*/
public void startConsole() {
File workDir = new SecureDirectory(I2PAppContext.getGlobalContext().getTempDir(), "jetty-work");
boolean workDirRemoved = FileUtil.rmdir(workDir, false);
@ -167,9 +221,37 @@ public class RouterConsoleRunner {
if (!workDirCreated)
System.err.println("ERROR: Unable to create Jetty temporary work directory");
//try {
// Log.setLog(new I2PLogger(I2PAppContext.getGlobalContext()));
//} catch (Throwable t) {
// System.err.println("INFO: I2P Jetty logging class not found, logging to wrapper log");
//}
// This way it doesn't try to load Slf4jLog first
System.setProperty("org.mortbay.log.class", "net.i2p.jetty.I2PLogger");
// so Jetty can find WebAppConfiguration
System.setProperty("jetty.class.path", I2PAppContext.getGlobalContext().getBaseDir() + "/lib/routerconsole.jar");
_server = new Server();
_server.setGracefulShutdown(1000);
try {
ThreadPool ctp = new CustomThreadPoolExecutor();
ctp.prestartAllCoreThreads();
_server.setThreadPool(ctp);
} catch (Throwable t) {
// class not found...
System.out.println("INFO: Jetty concurrent ThreadPool unavailable, using QueuedThreadPool");
QueuedThreadPool qtp = new QueuedThreadPool(MAX_THREADS);
qtp.setMinThreads(MIN_THREADS);
qtp.setMaxIdleTimeMs(MAX_IDLE_TIME);
_server.setThreadPool(qtp);
}
HandlerCollection hColl = new HandlerCollection();
ContextHandlerCollection chColl = new ContextHandlerCollection();
_server.addHandler(hColl);
hColl.addHandler(chColl);
hColl.addHandler(new DefaultHandler());
String log = I2PAppContext.getGlobalContext().getProperty("routerconsole.log");
if (log != null) {
@ -177,8 +259,10 @@ public class RouterConsoleRunner {
if (!logFile.isAbsolute())
logFile = new File(I2PAppContext.getGlobalContext().getLogDir(), "logs/" + log);
try {
_server.setRequestLog(new NCSARequestLog(logFile.getAbsolutePath()));
} catch (IOException ioe) {
RequestLogHandler rhl = new RequestLogHandler();
rhl.setRequestLog(new NCSARequestLog(logFile.getAbsolutePath()));
hColl.addHandler(rhl);
} catch (Exception ioe) {
System.err.println("ERROR: Unable to create Jetty log: " + ioe);
}
}
@ -201,8 +285,8 @@ public class RouterConsoleRunner {
if (!_webAppsDir.endsWith("/"))
_webAppsDir += '/';
List<String> notStarted = new ArrayList();
WebApplicationHandler baseHandler = null;
WebAppContext rootWebApp = null;
ServletHandler rootServletHandler = null;
try {
int boundAddresses = 0;
@ -217,17 +301,17 @@ public class RouterConsoleRunner {
// _server.addListener('[' + host + "]:" + _listenPort);
//else
// _server.addListener(host + ':' + _listenPort);
InetAddrPort iap = new InetAddrPort(host, lport);
SocketListener lsnr = new SocketListener(iap);
lsnr.setMinThreads(1); // default 2
lsnr.setMaxThreads(24); // default 256
lsnr.setMaxIdleTimeMs(90*1000); // default 10 sec
// Use AbstractConnector instead of Connector so we can do setName()
AbstractConnector lsnr = new SelectChannelConnector();
lsnr.setHost(host);
lsnr.setPort(lport);
lsnr.setMaxIdleTime(90*1000); // default 10 sec
lsnr.setName("ConsoleSocket"); // all with same name will use the same thread pool
_server.addListener(lsnr);
_server.addConnector(lsnr);
boundAddresses++;
} catch (NumberFormatException nfe) {
System.err.println("Unable to bind routerconsole to " + host + " port " + _listenPort + ' ' + nfe);
} catch (IOException ioe) { // this doesn't seem to work, exceptions don't happen until start() below
} catch (Exception ioe) { // this doesn't seem to work, exceptions don't happen until start() below
System.err.println("Unable to bind routerconsole to " + host + " port " + _listenPort + ' ' + ioe);
}
}
@ -252,19 +336,20 @@ public class RouterConsoleRunner {
while (tok.hasMoreTokens()) {
String host = tok.nextToken().trim();
// doing it this way means we don't have to escape an IPv6 host with []
InetAddrPort iap = new InetAddrPort(host, sslPort);
try {
SslListener ssll = new SslListener(iap);
// TODO if class not found use SslChannelConnector
// Sadly there's no common base class with the ssl methods in it
SslSelectChannelConnector ssll = new SslSelectChannelConnector();
ssll.setHost(host);
ssll.setPort(sslPort);
// the keystore path and password
ssll.setKeystore(keyStore.getAbsolutePath());
ssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD));
// the X.509 cert password (if not present, verifyKeyStore() returned false)
ssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork"));
ssll.setMinThreads(1); // default 2
ssll.setMaxThreads(24); // default 256
ssll.setMaxIdleTimeMs(90*1000); // default 10 sec
ssll.setMaxIdleTime(90*1000); // default 10 sec
ssll.setName("ConsoleSocket"); // all with same name will use the same thread pool
_server.addListener(ssll);
_server.addConnector(ssll);
boundAddresses++;
} catch (Exception e) { // probably no exceptions at this point
System.err.println("Unable to bind routerconsole to " + host + " port " + sslPort + " for SSL: " + e);
@ -280,47 +365,25 @@ public class RouterConsoleRunner {
System.err.println("Unable to bind routerconsole to any address on port " + _listenPort + (sslPort > 0 ? (" or SSL port " + sslPort) : ""));
return;
}
_server.setRootWebApp(ROUTERCONSOLE);
WebApplicationContext wac = _server.addWebApplication("/", _webAppsDir + ROUTERCONSOLE + ".war");
rootWebApp = new LocaleWebAppHandler(I2PAppContext.getGlobalContext(),
"/", _webAppsDir + ROUTERCONSOLE + ".war");
File tmpdir = new SecureDirectory(workDir, ROUTERCONSOLE + "-" +
(_listenPort != null ? _listenPort : _sslListenPort));
tmpdir.mkdir();
wac.setTempDirectory(tmpdir);
baseHandler = new LocaleWebAppHandler(I2PAppContext.getGlobalContext());
wac.addHandler(0, baseHandler);
initialize(wac);
File dir = new File(_webAppsDir);
String fileNames[] = dir.list(WarFilenameFilter.instance());
if (fileNames != null) {
for (int i = 0; i < fileNames.length; i++) {
try {
String appName = fileNames[i].substring(0, fileNames[i].lastIndexOf(".war"));
String enabled = props.getProperty(PREFIX + appName + ENABLED);
if (! "false".equals(enabled)) {
String path = new File(dir, fileNames[i]).getCanonicalPath();
tmpdir = new SecureDirectory(workDir, appName + "-" +
(_listenPort != null ? _listenPort : _sslListenPort));
WebAppStarter.addWebApp(I2PAppContext.getGlobalContext(), _server, appName, path, tmpdir);
rootWebApp.setTempDirectory(tmpdir);
rootWebApp.setSessionHandler(new SessionHandler());
rootServletHandler = new ServletHandler();
rootWebApp.setServletHandler(rootServletHandler);
initialize(rootWebApp);
chColl.addHandler(rootWebApp);
if (enabled == null) {
// do this so configclients.jsp knows about all apps from reading the config
props.setProperty(PREFIX + appName + ENABLED, "true");
rewrite = true;
}
} else {
notStarted.add(appName);
}
} catch (IOException ioe) {
System.err.println("Error resolving '" + fileNames[i] + "' in '" + dir);
}
}
}
} catch (IOException ioe) {
} catch (Exception ioe) {
ioe.printStackTrace();
}
if (rewrite)
storeWebAppProperties(props);
try {
// start does a mapContexts()
_server.start();
} catch (Throwable me) {
// NoClassFoundDefError from a webapp is a throwable, not an exception
@ -333,14 +396,61 @@ public class RouterConsoleRunner {
me.printStackTrace();
}
if (baseHandler != null) {
// Start all the other webapps after the server is up,
// so things start faster.
// Jetty 6 starts the connector before the router console is ready
// This also prevents one webapp from breaking the whole thing
List<String> notStarted = new ArrayList();
if (_server.isRunning()) {
File dir = new File(_webAppsDir);
String fileNames[] = dir.list(WarFilenameFilter.instance());
if (fileNames != null) {
for (int i = 0; i < fileNames.length; i++) {
String appName = fileNames[i].substring(0, fileNames[i].lastIndexOf(".war"));
String enabled = props.getProperty(PREFIX + appName + ENABLED);
if (! "false".equals(enabled)) {
try {
String path = new File(dir, fileNames[i]).getCanonicalPath();
WebAppStarter.startWebApp(I2PAppContext.getGlobalContext(), chColl, appName, path);
if (enabled == null) {
// do this so configclients.jsp knows about all apps from reading the config
props.setProperty(PREFIX + appName + ENABLED, "true");
rewrite = true;
}
} catch (Throwable t) {
System.err.println("ERROR: Failed to start " + appName + ' ' + t);
t.printStackTrace();
notStarted.add(appName);
}
} else {
notStarted.add(appName);
}
}
}
} else {
System.err.println("ERROR: Router console did not start, not starting webapps");
}
if (rewrite)
storeWebAppProperties(props);
if (rootServletHandler != null && notStarted.size() > 0) {
// map each not-started webapp to the error page
ServletHolder noWebApp = rootServletHandler.getServlet("net.i2p.router.web.jsp.nowebapp_jsp");
for (int i = 0; i < notStarted.size(); i++) {
// we want a new handler for each one since if the webapp is started we remove the handler???
try {
baseHandler.mapPathToServlet('/' + notStarted.get(i) + "/*",
"net.i2p.router.web.jsp.nowebapp_jsp");
if (noWebApp != null) {
String path = '/' + notStarted.get(i);
// LocaleWebAppsHandler adds a .jsp
rootServletHandler.addServletWithMapping(noWebApp, path + ".jsp");
rootServletHandler.addServletWithMapping(noWebApp, path + "/*");
} else {
System.err.println("Can't find nowebapp.jsp?");
}
} catch (Throwable me) {
System.err.println(me);
me.printStackTrace();
}
}
}
@ -455,18 +565,22 @@ public class RouterConsoleRunner {
return success;
}
static void initialize(WebApplicationContext context) {
static void initialize(WebAppContext context) {
SecurityHandler sec = new SecurityHandler();
List<ConstraintMapping> constraints = new ArrayList(4);
String password = getPassword();
if (password != null) {
HashUserRealm realm = new HashUserRealm("i2prouter");
realm.put("admin", password);
realm.addUserToRole("admin", "routerAdmin");
context.setRealm(realm);
context.setAuthenticator(authenticator);
context.addHandler(0, new SecurityHandler());
SecurityConstraint constraint = new SecurityConstraint("admin", "routerAdmin");
sec.setUserRealm(realm);
sec.setAuthenticator(authenticator);
Constraint constraint = new Constraint("admin", "routerAdmin");
constraint.setAuthenticate(true);
context.addSecurityConstraint("/", constraint);
ConstraintMapping cm = new ConstraintMapping();
cm.setConstraint(constraint);
cm.setPathSpec("/");
constraints.add(cm);
}
// This forces a '403 Forbidden' response for TRACE and OPTIONS unless the
@ -478,12 +592,27 @@ public class RouterConsoleRunner {
// The other strange methods - PUT, DELETE, MOVE - are disabled by default
// See also:
// http://old.nabble.com/Disable-HTTP-TRACE-in-Jetty-5.x-td12412607.html
SecurityConstraint sc = new SecurityConstraint();
sc.setName("No trace or options");
sc.addMethod("TRACE");
sc.addMethod("OPTIONS");
sc.setAuthenticate(true);
context.addSecurityConstraint("/*", sc) ;
Constraint sc = new Constraint();
sc.setName("No trace");
ConstraintMapping cm = new ConstraintMapping();
cm.setMethod("TRACE");
cm.setConstraint(sc);
cm.setPathSpec("/");
constraints.add(cm);
sc = new Constraint();
sc.setName("No options");
cm = new ConstraintMapping();
cm.setMethod("OPTIONS");
cm.setConstraint(sc);
cm.setPathSpec("/");
constraints.add(cm);
ConstraintMapping cmarr[] = constraints.toArray(new ConstraintMapping[constraints.size()]);
sec.setConstraintMappings(cmarr);
context.setSecurityHandler(sec);
}
static String getPassword() {
@ -508,11 +637,11 @@ public class RouterConsoleRunner {
}
/** @since 0.8.8 */
private class ServerShutdown implements Runnable {
private static class ServerShutdown implements Runnable {
public void run() {
try {
_server.stop();
} catch (InterruptedException ie) {}
} catch (Exception ie) {}
}
}
@ -571,4 +700,31 @@ public class RouterConsoleRunner {
}
}
/**
* Just to set the name and set Daemon
* @since Jetty 6
*/
private static class CustomThreadPoolExecutor extends ThreadPool {
public CustomThreadPoolExecutor() {
super(MIN_THREADS, MAX_THREADS, MAX_IDLE_TIME, TimeUnit.MILLISECONDS,
new SynchronousQueue(), new CustomThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
}
}
/**
* Just to set the name and set Daemon
* @since Jetty 6
*/
private static class CustomThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread rv = Executors.defaultThreadFactory().newThread(r);
rv.setName(THREAD_NAME);
rv.setDaemon(true);
return rv;
}
}
}

View File

@ -6,7 +6,8 @@ import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import org.mortbay.jetty.servlet.WebApplicationContext;
import org.mortbay.jetty.webapp.Configuration;
import org.mortbay.jetty.webapp.WebAppContext;
/**
@ -31,16 +32,16 @@ import org.mortbay.jetty.servlet.WebApplicationContext;
* @since 0.7.12
* @author zzz
*/
public class WebAppConfiguration implements WebApplicationContext.Configuration {
private WebApplicationContext _wac;
public class WebAppConfiguration implements Configuration {
private WebAppContext _wac;
private static final String CLASSPATH = ".classpath";
public void setWebApplicationContext(WebApplicationContext context) {
public void setWebAppContext(WebAppContext context) {
_wac = context;
}
public WebApplicationContext getWebApplicationContext() {
public WebAppContext getWebAppContext() {
return _wac;
}
@ -87,10 +88,16 @@ public class WebAppConfiguration implements WebApplicationContext.Configuration
else
path = dir.getAbsolutePath() + '/' + elem;
System.err.println("Adding " + path + " to classpath for " + appName);
_wac.addClassPath(path);
_wac.setExtraClasspath(path);
}
}
public void configureDefaults() {}
public void configureWebApp() {}
/** @since Jetty 6 */
public void deconfigureWebApp() {}
/** @since Jetty 6 */
public void configureClassLoader() {}
}

View File

@ -14,10 +14,12 @@ import net.i2p.util.Log;
import net.i2p.util.SecureDirectory;
import net.i2p.util.PortMapper;
import org.mortbay.http.HttpContext;
import org.mortbay.http.HttpListener;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.WebApplicationContext;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.jetty.handler.ContextHandler;
import org.mortbay.jetty.handler.ContextHandlerCollection;
/**
@ -49,9 +51,10 @@ public class WebAppStarter {
* adds and starts
* @throws just about anything, caller would be wise to catch Throwable
*/
static void startWebApp(I2PAppContext ctx, Server server, String appName, String warPath) throws Exception {
static void startWebApp(I2PAppContext ctx, ContextHandlerCollection server,
String appName, String warPath) throws Exception {
File tmpdir = new SecureDirectory(ctx.getTempDir(), "jetty-work-" + appName + ctx.random().nextInt());
WebApplicationContext wac = addWebApp(ctx, server, appName, warPath, tmpdir);
WebAppContext wac = addWebApp(ctx, server, appName, warPath, tmpdir);
_log.debug("Loading war from: " + warPath);
wac.start();
}
@ -61,12 +64,13 @@ public class WebAppStarter {
* This is used only by RouterConsoleRunner, which adds all the webapps first
* and then starts all at once.
*/
static WebApplicationContext addWebApp(I2PAppContext ctx, Server server, String appName, String warPath, File tmpdir) throws IOException {
static WebAppContext addWebApp(I2PAppContext ctx, ContextHandlerCollection server,
String appName, String warPath, File tmpdir) throws IOException {
// Jetty will happily load one context on top of another without stopping
// the first one, so we remove any previous one here
try {
stopWebApp(server, appName);
stopWebApp(appName);
} catch (Throwable t) {}
// To avoid ZipErrors from JarURLConnetion caching,
@ -91,7 +95,7 @@ public class WebAppStarter {
warPath = tmpPath;
}
WebApplicationContext wac = server.addWebApplication("/"+ appName, warPath);
WebAppContext wac = new WebAppContext(warPath, "/"+ appName);
tmpdir.mkdir();
wac.setTempDirectory(tmpdir);
@ -101,12 +105,14 @@ public class WebAppStarter {
// see WebAppConfiguration for info
String[] classNames = server.getWebApplicationConfigurationClassNames();
String[] classNames = wac.getConfigurationClasses();
String[] newClassNames = new String[classNames.length + 1];
for (int j = 0; j < classNames.length; j++)
newClassNames[j] = classNames[j];
newClassNames[classNames.length] = WebAppConfiguration.class.getName();
wac.setConfigurationClassNames(newClassNames);
wac.setConfigurationClasses(newClassNames);
server.addHandler(wac);
server.mapContexts();
return wac;
}
@ -114,42 +120,55 @@ public class WebAppStarter {
* stop it and remove the context
* @throws just about anything, caller would be wise to catch Throwable
*/
static void stopWebApp(Server server, String appName) {
// this will return a new context if one does not exist
HttpContext wac = server.getContext('/' + appName);
static void stopWebApp(String appName) {
ContextHandler wac = getWebApp(appName);
if (wac == null)
return;
try {
// false -> not graceful
wac.stop(false);
} catch (InterruptedException ie) {}
// not graceful is default in Jetty 6?
wac.stop();
} catch (Exception ie) {}
ContextHandlerCollection server = getConsoleServer();
if (server == null)
return;
try {
server.removeContext(wac);
server.removeHandler(wac);
server.mapContexts();
} catch (IllegalStateException ise) {}
}
static boolean isWebAppRunning(String appName) {
Server server = WebAppStarter.getConsoleServer();
if (server == null)
ContextHandler wac = getWebApp(appName);
if (wac == null)
return false;
// this will return a new context if one does not exist
HttpContext wac = server.getContext('/' + appName);
return wac.isStarted();
}
/** see comments in ConfigClientsHandler */
static Server getConsoleServer() {
PortMapper pm = I2PAppContext.getGlobalContext().portMapper();
int p1 = pm.getPort(PortMapper.SVC_CONSOLE);
int p2 = pm.getPort(PortMapper.SVC_HTTPS_CONSOLE);
Collection c = Server.getHttpServers();
for (int i = 0; i < c.size(); i++) {
Server s = (Server) c.toArray()[i];
HttpListener[] hl = s.getListeners();
for (int j = 0; j < hl.length; j++) {
int port = hl[j].getPort();
if (port == p1 || port == p2)
return s;
}
/** @since Jetty 6 */
static ContextHandler getWebApp(String appName) {
ContextHandlerCollection server = getConsoleServer();
if (server == null)
return null;
Handler handlers[] = server.getHandlers();
if (handlers == null)
return null;
String path = '/'+ appName;
for (int i = 0; i < handlers.length; i++) {
ContextHandler ch = (ContextHandler) handlers[i];
if (path.equals(ch.getContextPath()))
return ch;
}
return null;
}
/** see comments in ConfigClientsHandler */
static ContextHandlerCollection getConsoleServer() {
Server s = RouterConsoleRunner.getConsoleServer();
if (s == null)
return null;
Handler h = s.getChildHandlerByClass(ContextHandlerCollection.class);
if (h == null)
return null;
return (ContextHandlerCollection) h;
}
}

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html" %>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -10,7 +11,7 @@
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigNetHelper" id="nethelper" scope="request" />
<jsp:setProperty name="nethelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="nethelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<h1><%=intl._("I2P Bandwidth Configuration")%></h1>
<div class="main" id="main">
<%@include file="confignav.jsi" %>
@ -18,7 +19,7 @@
<jsp:useBean class="net.i2p.router.web.ConfigNetHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure">
<form action="" method="POST">

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -10,7 +11,7 @@
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigAdvancedHelper" id="advancedhelper" scope="request" />
<jsp:setProperty name="advancedhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="advancedhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<h1><%=intl._("I2P Advanced Configuration")%></h1>
<div class="main" id="main">
@ -20,7 +21,7 @@
<jsp:useBean class="net.i2p.router.web.ConfigAdvancedHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure">
<div class="wideload">

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -14,17 +15,17 @@ button span.hide{
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigClientsHelper" id="clientshelper" scope="request" />
<jsp:setProperty name="clientshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="clientshelper" property="edit" value="<%=request.getParameter("edit")%>" />
<jsp:setProperty name="clientshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:setProperty name="clientshelper" property="edit" value="<%=request.getParameter(\"edit\")%>" />
<h1><%=intl._("I2P Client Configuration")%></h1>
<div class="main" id="main">
<%@include file="confignav.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigClientsHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter("action")%>" />
<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter(\"action\")%>" />
<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter(\"nonce\")%>" />
<jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure">

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -15,10 +16,10 @@
<jsp:useBean class="net.i2p.router.web.ConfigKeyringHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<jsp:useBean class="net.i2p.router.web.ConfigKeyringHelper" id="keyringhelper" scope="request" />
<jsp:setProperty name="keyringhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="keyringhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<div class="configure"><h2><%=intl._("Keyring")%></h2><p>
<%=intl._("The router keyring is used to decrypt encrypted leaseSets.")%>
<%=intl._("The keyring may contain keys for local or remote encrypted destinations.")%></p>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -7,7 +8,7 @@
<%=intl.title("config logging")%>
</head><body>
<jsp:useBean class="net.i2p.router.web.ConfigLoggingHelper" id="logginghelper" scope="request" />
<jsp:setProperty name="logginghelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="logginghelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<%@include file="summary.jsi" %>
<h1><%=intl._("I2P Logging Configuration")%></h1>
@ -17,7 +18,7 @@
<jsp:useBean class="net.i2p.router.web.ConfigLoggingHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure">
<form action="" method="POST">

View File

@ -4,7 +4,7 @@
*/
%>
<jsp:useBean class="net.i2p.router.web.ConfigNavHelper" id="navHelper" scope="request" />
<jsp:setProperty name="navHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="navHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% navHelper.storeWriter(out); %>
<div class="confignav" id="confignav">
<%

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html" %>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -10,7 +11,7 @@
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigNetHelper" id="nethelper" scope="request" />
<jsp:setProperty name="nethelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="nethelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<h1><%=intl._("I2P Network Configuration")%></h1>
<div class="main" id="main">
<%@include file="confignav.jsi" %>
@ -18,7 +19,7 @@
<jsp:useBean class="net.i2p.router.web.ConfigNetHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure">
<form action="" method="POST">

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -15,13 +16,13 @@
<jsp:useBean class="net.i2p.router.web.ConfigPeerHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<jsp:useBean class="net.i2p.router.web.ConfigPeerHelper" id="peerhelper" scope="request" />
<jsp:setProperty name="peerhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="peerhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% String peer = "";
if (request.getParameter("peer") != null)
@ -61,7 +62,7 @@
</form>
<a name="shitlist"> </a><h2><%=intl._("Banned Peers")%></h2>
<jsp:useBean class="net.i2p.router.web.ProfilesHelper" id="profilesHelper" scope="request" />
<jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% profilesHelper.storeWriter(out); %>
<jsp:getProperty name="profilesHelper" property="shitlistSummary" />
<div class="wideload"><h2><%=intl._("Banned IPs")%></h2>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -10,16 +11,16 @@
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigReseedHelper" id="reseedHelper" scope="request" />
<jsp:setProperty name="reseedHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="reseedHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<h1><%=intl._("I2P Reseeding Configuration")%></h1>
<div class="main" id="main">
<%@include file="confignav.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigReseedHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter("action")%>" />
<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter(\"action\")%>" />
<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter(\"nonce\")%>" />
<jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure"><form action="" method="POST">

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -15,7 +16,7 @@
<jsp:useBean class="net.i2p.router.web.ConfigServiceHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure">
<form action="" method="POST">

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -64,11 +65,11 @@ function toggleAll(category)
<jsp:useBean class="net.i2p.router.web.ConfigStatsHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<jsp:useBean class="net.i2p.router.web.ConfigStatsHelper" id="statshelper" scope="request" />
<jsp:setProperty name="statshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="statshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<div class="configure">
<form id="statsForm" name="statsForm" action="" method="POST">
<input type="hidden" name="action" value="foo" >

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -10,16 +11,16 @@
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigTunnelsHelper" id="tunnelshelper" scope="request" />
<jsp:setProperty name="tunnelshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="tunnelshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<h1><%=intl._("I2P Tunnel Configuration")%></h1>
<div class="main" id="main">
<%@include file="confignav.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigTunnelsHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="shouldsave" value="<%=request.getParameter("shouldsave")%>" />
<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter("action")%>" />
<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:setProperty name="formhandler" property="shouldsave" value="<%=request.getParameter(\"shouldsave\")%>" />
<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter(\"action\")%>" />
<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter(\"nonce\")%>" />
<jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure"><p>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -10,7 +11,7 @@
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigUIHelper" id="uihelper" scope="request" />
<jsp:setProperty name="uihelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="uihelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<h1><%=uihelper._("I2P UI Configuration")%></h1>
<div class="main" id="main">
@ -20,7 +21,7 @@
<jsp:useBean class="net.i2p.router.web.ConfigUIHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure"><div class="topshimten"><h3><%=uihelper._("Router Console Theme")%></h3></div>
<form action="" method="POST">

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -15,10 +16,10 @@
<jsp:useBean class="net.i2p.router.web.ConfigUpdateHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="*" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<jsp:useBean class="net.i2p.router.web.ConfigUpdateHelper" id="updatehelper" scope="request" />
<jsp:setProperty name="updatehelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="updatehelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<div class="messages">
<jsp:getProperty name="updatehelper" property="newsStatus" /></div>
<div class="configure">

View File

@ -27,7 +27,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="shortcut icon" href="/themes/console/images/favicon.ico">
<jsp:useBean class="net.i2p.router.web.CSSHelper" id="intl" scope="request" />
<jsp:setProperty name="intl" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="intl" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<%
String conNonceParam = request.getParameter("consoleNonce");
if (conNonceParam != null && conNonceParam.equals(System.getProperty("router.consoleNonce"))) {

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%

View File

@ -1,6 +1,6 @@
<%@page contentType="text/plain"
%><jsp:useBean id="helper" class="net.i2p.router.web.StatHelper"
/><jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>"
/><jsp:setProperty name="helper" property="peer" value="<%=net.i2p.data.DataHelper.stripHTML(request.getParameter("peer"))%>"
/><jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>"
/><jsp:setProperty name="helper" property="peer" value="<%=net.i2p.data.DataHelper.stripHTML(request.getParameter(\"peer\"))%>"
/><% helper.storeWriter(out);
%><jsp:getProperty name="helper" property="profile" />

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
@ -57,7 +58,7 @@
<b>Java version:</b> <%=System.getProperty("java.vendor")%> <%=System.getProperty("java.version")%> (<%=System.getProperty("java.runtime.name")%> <%=System.getProperty("java.runtime.version")%>)<br>
<b>Wrapper version:</b> <%=System.getProperty("wrapper.version", "none")%><br>
<jsp:useBean class="net.i2p.router.web.LogsHelper" id="logsHelper" scope="request" />
<jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<b>Server version:</b> <jsp:getProperty name="logsHelper" property="jettyVersion" /><br>
<b>Platform:</b> <%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%><br>
<b>Processor:</b> <%=net.i2p.util.NativeBigInteger.cpuModel()%> (<%=net.i2p.util.NativeBigInteger.cpuType()%>)<br>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -7,7 +8,7 @@
<%=intl.title("graphs")%>
<jsp:useBean class="net.i2p.router.web.GraphHelper" id="graphHelper" scope="request" />
<% graphHelper.storeMethod(request.getMethod()); %>
<jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %>
<jsp:setProperty name="graphHelper" property="*" />
<%

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%

View File

@ -1,8 +0,0 @@
<html><head><title>I2PSnark Anonymous BitTorrent Client Disabled</title>
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="pragma" content="no-cache" />
</head>
<body>
The I2PSnark Anonymous BitTorrent Client is not running. Please visit the <a href="/configclients#webapp">config clients page</a>
to start it.
</body></html>

View File

@ -1,7 +0,0 @@
<html><head><title>I2P Tunnel Manager Not Running</title>
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="pragma" content="no-cache" />
</head>
<body>
The I2P Tunnel Manager is not currently running. Please visit the <a href="/configclients#webapp">Client Configuration</a> page to start it.
</body></html>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -17,7 +18,7 @@
<%@include file="summary.jsi" %><h1><%=intl._("I2P Router Console")%></h1>
<div class="news" id="news">
<jsp:useBean class="net.i2p.router.web.NewsHelper" id="newshelper" scope="request" />
<jsp:setProperty name="newshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="newshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<%
if (newshelper.shouldShowNews()) {
java.io.File fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getRouterDir(), "docs/news.xml");
@ -30,7 +31,7 @@
} // shouldShowNews()
%>
<jsp:useBean class="net.i2p.router.web.ConfigUpdateHelper" id="updatehelper" scope="request" />
<jsp:setProperty name="updatehelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="updatehelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="updatehelper" property="newsStatus" /><br>
</div><div class="main" id="main">
<jsp:useBean class="net.i2p.router.web.ContentHelper" id="contenthelper" scope="request" />
@ -60,6 +61,6 @@
<% java.io.File fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getBaseDir(), "docs/readme.html"); %>
<jsp:setProperty name="contenthelper" property="page" value="<%=fpath.getAbsolutePath()%>" />
<jsp:setProperty name="contenthelper" property="maxLines" value="300" />
<jsp:setProperty name="contenthelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="contenthelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:getProperty name="contenthelper" property="content" />
</div></body></html>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -9,7 +10,7 @@
<%@include file="summary.jsi" %><h1><%=intl._("I2P Router Job Queue")%></h1>
<div class="main" id="main">
<jsp:useBean class="net.i2p.router.web.JobQueueHelper" id="jobQueueHelper" scope="request" />
<jsp:setProperty name="jobQueueHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="jobQueueHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% jobQueueHelper.storeWriter(out); %>
<jsp:getProperty name="jobQueueHelper" property="jobQueueSummary" />
<hr></div></body></html>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -22,7 +23,7 @@
<b>Java version:</b> <%=System.getProperty("java.vendor")%> <%=System.getProperty("java.version")%> (<%=System.getProperty("java.runtime.name")%> <%=System.getProperty("java.runtime.version")%>)<br>
<b>Wrapper version:</b> <%=System.getProperty("wrapper.version", "none")%><br>
<jsp:useBean class="net.i2p.router.web.LogsHelper" id="logsHelper" scope="request" />
<jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<b>Server version:</b> <jsp:getProperty name="logsHelper" property="jettyVersion" /><br>
<b>Platform:</b> <%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%><br>
<b>Processor:</b> <%=net.i2p.util.NativeBigInteger.cpuModel()%> (<%=net.i2p.util.NativeBigInteger.cpuType()%>)<br>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -11,10 +12,10 @@
<div class="main" id="main">
<div class="wideload">
<jsp:useBean class="net.i2p.router.web.NetDbHelper" id="netdbHelper" scope="request" />
<jsp:setProperty name="netdbHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="netdbHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% netdbHelper.storeWriter(out); %>
<jsp:setProperty name="netdbHelper" property="full" value="<%=request.getParameter("f")%>" />
<jsp:setProperty name="netdbHelper" property="router" value="<%=request.getParameter("r")%>" />
<jsp:setProperty name="netdbHelper" property="lease" value="<%=request.getParameter("l")%>" />
<jsp:setProperty name="netdbHelper" property="full" value="<%=request.getParameter(\"f\")%>" />
<jsp:setProperty name="netdbHelper" property="router" value="<%=request.getParameter(\"r\")%>" />
<jsp:setProperty name="netdbHelper" property="lease" value="<%=request.getParameter(\"l\")%>" />
<jsp:getProperty name="netdbHelper" property="netDbSummary" />
</div></div></body></html>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
@ -11,7 +12,7 @@
</head><body>
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="conhelper" scope="request" />
<jsp:setProperty name="conhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="conhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% conhelper.storeWriter(out); %>
<h1>I2P Router &raquo; Old Console</h1>
<div class="main" id="main">

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -10,9 +11,9 @@
<h1><%=intl._("I2P Network Peers")%></h1>
<div class="main" id="main"><div class="wideload">
<jsp:useBean class="net.i2p.router.web.PeerHelper" id="peerHelper" scope="request" />
<jsp:setProperty name="peerHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="peerHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% peerHelper.storeWriter(out); %>
<jsp:setProperty name="peerHelper" property="urlBase" value="peers.jsp" />
<jsp:setProperty name="peerHelper" property="sort" value="<%=request.getParameter("sort") != null ? request.getParameter("sort") : ""%>" />
<jsp:setProperty name="peerHelper" property="sort" value="<%=request.getParameter(\"sort\") != null ? request.getParameter(\"sort\") : \"\"%>" />
<jsp:getProperty name="peerHelper" property="peerSummary" />
</div></div></body></html>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -9,9 +10,9 @@
<h1><%=intl._("I2P Network Peer Profiles")%></h1>
<div class="main" id="main"><div class="wideload">
<jsp:useBean class="net.i2p.router.web.ProfilesHelper" id="profilesHelper" scope="request" />
<jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% profilesHelper.storeWriter(out); %>
<jsp:setProperty name="profilesHelper" property="full" value="<%=request.getParameter("f")%>" />
<jsp:setProperty name="profilesHelper" property="full" value="<%=request.getParameter(\"f\")%>" />
<jsp:getProperty name="profilesHelper" property="profileSummary" />
<a name="shitlist"> </a><h2><%=intl._("Banned Peers")%></h2>
<jsp:getProperty name="profilesHelper" property="shitlistSummary" />

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -8,9 +9,9 @@
</head><body>
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="oldhelper" scope="request" />
<jsp:setProperty name="oldhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="oldhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% oldhelper.storeWriter(out); %>
<jsp:setProperty name="oldhelper" property="full" value="<%=request.getParameter("f")%>" />
<jsp:setProperty name="oldhelper" property="full" value="<%=request.getParameter(\"f\")%>" />
<h1><%=intl._("I2P Router Statistics")%></h1>
<div class="main" id="main">
<jsp:getProperty name="oldhelper" property="stats" />

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%

View File

@ -6,10 +6,10 @@
*/
%>
<jsp:useBean class="net.i2p.router.web.SummaryHelper" id="helper" scope="request" />
<jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="helper" property="action" value="<%=request.getParameter("action")%>" />
<jsp:setProperty name="helper" property="updateNonce" value="<%=request.getParameter("updateNonce")%>" />
<jsp:setProperty name="helper" property="consoleNonce" value="<%=request.getParameter("consoleNonce")%>" />
<jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:setProperty name="helper" property="action" value="<%=request.getParameter(\"action\")%>" />
<jsp:setProperty name="helper" property="updateNonce" value="<%=request.getParameter(\"updateNonce\")%>" />
<jsp:setProperty name="helper" property="consoleNonce" value="<%=request.getParameter(\"consoleNonce\")%>" />
<jsp:setProperty name="helper" property="requestURI" value="<%=request.getRequestURI()%>" />
<% helper.storeWriter(out); %>
<%
@ -28,7 +28,7 @@
%>
<jsp:useBean class="net.i2p.router.web.UpdateHandler" id="update" scope="request" />
<jsp:setProperty name="update" property="*" />
<jsp:setProperty name="update" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="update" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<%
// moved to java for ease of translation and to avoid 30 copies
helper.renderSummaryBar();

View File

@ -1,8 +0,0 @@
<html><head><title>SusiDNS Disabled</title>
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="pragma" content="no-cache" />
</head>
<body>
SusiDNS is not running. Go to <a href="/configclients#webapp">the config clients page</a>
to start it.
</body></html>

View File

@ -1,8 +0,0 @@
<html><head><title>SusiMail Disabled</title>
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="pragma" content="no-cache" />
</head>
<body>
SusiMail is not running. Go to <a href="/configclients#webapp">the config clients page</a>
to start it.
</body></html>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -9,7 +10,7 @@
<%@include file="summary.jsi" %><h1><%=intl._("I2P Tunnel Summary")%></h1>
<div class="main" id="main">
<jsp:useBean class="net.i2p.router.web.TunnelHelper" id="tunnelHelper" scope="request" />
<jsp:setProperty name="tunnelHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="tunnelHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% tunnelHelper.storeWriter(out); %>
<jsp:getProperty name="tunnelHelper" property="tunnelSummary" />
</div></body></html>

View File

@ -1,4 +1,5 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
@ -17,7 +18,7 @@
peerB64 = net.i2p.data.DataHelper.stripHTML(peerB64); // XSS
%>
<jsp:useBean id="stathelper" class="net.i2p.router.web.StatHelper" />
<jsp:setProperty name="stathelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="stathelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<jsp:setProperty name="stathelper" property="peer" value="<%=peerB64%>" />
<% stathelper.storeWriter(out); %>
<h2><%=intl._("Profile for peer {0}", peerB64)%></h2>

View File

@ -0,0 +1,12 @@
These are 1.2 libs downloaded from http://jstl.java.net/download.html
Licenses: Common Development and Distribution License (CDDL) version 1.0 + GNU General Public License (GPL) version 2
https://glassfish.dev.java.net/public/CDDL+GPL.html
1.2 libs are compatible with JSP 2.1 containers.
See http://www.coderanch.com/how-to/java/JstlTagLibDefinitions for more info.
The previous files were version 1.1.2 for JSP 2.0.
Old names kept so they are overwritten in the update and are in the classpath.
jstl-api-1.2.jar -> jstl.jar
jstl-impl-1.2.jar -> standard.jar

View File

@ -17,6 +17,7 @@
<pathelement location="${lib}/jasper-compiler.jar" />
<pathelement location="${lib}/jasper-runtime.jar" />
<pathelement location="${lib}/javax.servlet.jar" />
<pathelement location="${lib}/jsp-api.jar" />
<pathelement location="${lib}/commons-logging.jar" />
<pathelement location="${lib}/commons-el.jar" />
<pathelement location="${lib}/ant.jar" />

View File

@ -29,6 +29,7 @@
%>
<%@page pageEncoding="UTF-8"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@ page contentType="text/html"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />

View File

@ -29,6 +29,7 @@
%>
<%@page pageEncoding="UTF-8"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application"/>

View File

@ -26,6 +26,7 @@
%>
<%@page pageEncoding="UTF-8"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@ page contentType="text/html"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />

View File

@ -29,6 +29,7 @@
%>
<%@page pageEncoding="UTF-8"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@ page contentType="text/html"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />

View File

@ -29,6 +29,7 @@
%>
<%@page pageEncoding="UTF-8"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@ page contentType="text/html"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />

View File

@ -19,6 +19,7 @@
<classpath>
<pathelement location="../jetty/jettylib/javax.servlet.jar" />
<pathelement location="../jetty/jettylib/org.mortbay.jetty.jar" />
<pathelement location="../jetty/jettylib/jetty-util.jar" />
<pathelement location="../../core/java/build/i2p.jar" />
</classpath>
</javac>

View File

@ -15,4 +15,26 @@
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
<!--
Jetty 6 mulipart form handling
See http://docs.codehaus.org/display/JETTY/File+Upload+in+jetty6
and RequestWrapper.java.
Unused because it doesn't support content-type until Jetty 8.
<filter>
<filter-name>fileuploadfilter</filter-name>
<filter-class>org.mortbay.servlet.MultiPartFilter</filter-class>
<init-param>
<param-name>deleteFiles</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>fileuploadfilter</filter-name>
<url-pattern>/susimail</url-pattern>
</filter-mapping>
-->
-</web-app>

View File

@ -35,6 +35,19 @@ import javax.servlet.http.HttpSession;
import org.mortbay.servlet.MultiPartRequest;
/**
* Required major changes for Jetty 6
* to support change from MultiPartRequest to MultiPartFilter.
* See http://docs.codehaus.org/display/JETTY/File+Upload+in+jetty6
* Unfortunately, Content-type not available until Jetty 8
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=349110
*
* So we could either extend and fix MultiPartFilter, and rewrite everything here,
* or copy MultiParRequest into our war and fix it so it compiles with Jetty 6.
* We do the latter.
*
* The filter would have been added in web.xml,
* see that file, where it's commented out.
*
* @author user
*/
public class RequestWrapper {

View File

@ -0,0 +1,447 @@
// ========================================================================
// $Id: MultiPartRequest.java,v 1.16 2005/12/02 20:13:52 gregwilkins Exp $
// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.servlet;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
//import org.apache.commons.logging.Log;
//import org.mortbay.log.LogFactory;
import org.mortbay.jetty.HttpHeaders;
import org.mortbay.util.LineInput;
import org.mortbay.util.MultiMap;
import org.mortbay.util.StringUtil;
/* ------------------------------------------------------------ */
/** Multipart Form Data request.
* <p>
* This class decodes the multipart/form-data stream sent by
* a HTML form that uses a file input item.
*
* <p><h4>Usage</h4>
* Each part of the form data is named from the HTML form and
* is available either via getString(name) or getInputStream(name).
* Furthermore the MIME parameters and filename can be requested for
* each part.
* <pre>
* </pre>
*
* Modded to compile with Jetty 6 for I2P
*
* @version $Id: MultiPartRequest.java,v 1.16 2005/12/02 20:13:52 gregwilkins Exp $
* @author Greg Wilkins
* @author Jim Crossley
*/
public class MultiPartRequest
{
//private static Log log = LogFactory.getLog(MultiPartRequest.class);
/* ------------------------------------------------------------ */
HttpServletRequest _request;
LineInput _in;
String _boundary;
String _encoding;
byte[] _byteBoundary;
MultiMap _partMap = new MultiMap(10);
int _char=-2;
boolean _lastPart=false;
/* ------------------------------------------------------------ */
/** Constructor.
* @param request The request containing a multipart/form-data
* request
* @exception IOException IOException
*/
public MultiPartRequest(HttpServletRequest request)
throws IOException
{
_request=request;
String content_type = request.getHeader(HttpHeaders.CONTENT_TYPE);
if (!content_type.startsWith("multipart/form-data"))
throw new IOException("Not multipart/form-data request");
//if(log.isDebugEnabled())log.debug("Multipart content type = "+content_type);
_encoding = request.getCharacterEncoding();
if (_encoding != null)
_in = new LineInput(request.getInputStream(), 2048, _encoding);
else
_in = new LineInput(request.getInputStream());
// Extract boundary string
_boundary="--"+
value(content_type.substring(content_type.indexOf("boundary=")));
//if(log.isDebugEnabled())log.debug("Boundary="+_boundary);
_byteBoundary= (_boundary+"--").getBytes(StringUtil.__ISO_8859_1);
loadAllParts();
}
/* ------------------------------------------------------------ */
/** Get the part names.
* @return an array of part names
*/
public String[] getPartNames()
{
Set s = _partMap.keySet();
return (String[]) s.toArray(new String[s.size()]);
}
/* ------------------------------------------------------------ */
/** Check if a named part is present
* @param name The part
* @return true if it was included
*/
public boolean contains(String name)
{
Part part = (Part)_partMap.get(name);
return (part!=null);
}
/* ------------------------------------------------------------ */
/** Get the data of a part as a string.
* @param name The part name
* @return The part data
*/
public String getString(String name)
{
List part = _partMap.getValues(name);
if (part==null)
return null;
if (_encoding != null)
{
try
{
return new String(((Part)part.get(0))._data, _encoding);
}
catch (UnsupportedEncodingException uee)
{
//if (log.isDebugEnabled())log.debug("Invalid character set: " + uee);
return null;
}
}
else
return new String(((Part)part.get(0))._data);
}
/* ------------------------------------------------------------ */
/**
* @param name The part name
* @return The parts data
*/
public String[] getStrings(String name)
{
List parts = _partMap.getValues(name);
if (parts==null)
return null;
String[] strings = new String[parts.size()];
if (_encoding == null)
{
for (int i=0; i<strings.length; i++)
strings[i] = new String(((Part)parts.get(i))._data);
}
else
{
try
{
for (int i=0; i<strings.length; i++)
strings[i] = new String(((Part)parts.get(i))._data, _encoding);
}
catch (UnsupportedEncodingException uee)
{
//if (log.isDebugEnabled())log.debug("Invalid character set: " + uee);
return null;
}
}
return strings;
}
/* ------------------------------------------------------------ */
/** Get the data of a part as a stream.
* @param name The part name
* @return Stream providing the part data
*/
public InputStream getInputStream(String name)
{
List part = (List)_partMap.getValues(name);
if (part==null)
return null;
return new ByteArrayInputStream(((Part)part.get(0))._data);
}
/* ------------------------------------------------------------ */
public InputStream[] getInputStreams(String name)
{
List parts = (List)_partMap.getValues(name);
if (parts==null)
return null;
InputStream[] streams = new InputStream[parts.size()];
for (int i=0; i<streams.length; i++) {
streams[i] = new ByteArrayInputStream(((Part)parts.get(i))._data);
}
return streams;
}
/* ------------------------------------------------------------ */
/** Get the MIME parameters associated with a part.
* @param name The part name
* @return Hashtable of parameters
*/
public Hashtable getParams(String name)
{
List part = (List)_partMap.getValues(name);
if (part==null)
return null;
return ((Part)part.get(0))._headers;
}
/* ------------------------------------------------------------ */
public Hashtable[] getMultipleParams(String name)
{
List parts = (List)_partMap.getValues(name);
if (parts==null)
return null;
Hashtable[] params = new Hashtable[parts.size()];
for (int i=0; i<params.length; i++) {
params[i] = ((Part)parts.get(i))._headers;
}
return params;
}
/* ------------------------------------------------------------ */
/** Get any file name associated with a part.
* @param name The part name
* @return The filename
*/
public String getFilename(String name)
{
List part = (List)_partMap.getValues(name);
if (part==null)
return null;
return ((Part)part.get(0))._filename;
}
/* ------------------------------------------------------------ */
public String[] getFilenames(String name)
{
List parts = (List)_partMap.getValues(name);
if (parts==null)
return null;
String[] filenames = new String[parts.size()];
for (int i=0; i<filenames.length; i++) {
filenames[i] = ((Part)parts.get(i))._filename;
}
return filenames;
}
/* ------------------------------------------------------------ */
private void loadAllParts()
throws IOException
{
// Get first boundary
String line = _in.readLine();
if (!line.equals(_boundary))
{
//log.warn(line);
throw new IOException("Missing initial multi part boundary");
}
// Read each part
while (!_lastPart)
{
// Read Part headers
Part part = new Part();
String content_disposition=null;
while ((line=_in.readLine())!=null)
{
// If blank line, end of part headers
if (line.length()==0)
break;
//if(log.isDebugEnabled())log.debug("LINE="+line);
// place part header key and value in map
int c = line.indexOf(':',0);
if (c>0)
{
String key = line.substring(0,c).trim().toLowerCase();
String value = line.substring(c+1,line.length()).trim();
String ev = (String) part._headers.get(key);
part._headers.put(key,(ev!=null)?(ev+';'+value):value);
//if(log.isDebugEnabled())log.debug(key+": "+value);
if (key.equals("content-disposition"))
content_disposition=value;
}
}
// Extract content-disposition
boolean form_data=false;
if (content_disposition==null)
{
throw new IOException("Missing content-disposition");
}
StringTokenizer tok =
new StringTokenizer(content_disposition,";");
while (tok.hasMoreTokens())
{
String t = tok.nextToken().trim();
String tl = t.toLowerCase();
if (t.startsWith("form-data"))
form_data=true;
else if (tl.startsWith("name="))
part._name=value(t);
else if (tl.startsWith("filename="))
part._filename=value(t);
}
// Check disposition
if (!form_data)
{
//log.warn("Non form-data part in multipart/form-data");
continue;
}
if (part._name==null || part._name.length()==0)
{
//log.warn("Part with no name in multipart/form-data");
continue;
}
//if(log.isDebugEnabled())log.debug("name="+part._name);
//if(log.isDebugEnabled())log.debug("filename="+part._filename);
_partMap.add(part._name,part);
part._data=readBytes();
}
}
/* ------------------------------------------------------------ */
private byte[] readBytes()
throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c;
boolean cr=false;
boolean lf=false;
// loop for all lines`
while (true)
{
int b=0;
while ((c=(_char!=-2)?_char:_in.read())!=-1)
{
_char=-2;
// look for CR and/or LF
if (c==13 || c==10)
{
if (c==13) _char=_in.read();
break;
}
// look for boundary
if (b>=0 && b<_byteBoundary.length && c==_byteBoundary[b])
b++;
else
{
// this is not a boundary
if (cr) baos.write(13);
if (lf) baos.write(10);
cr=lf=false;
if (b>0)
baos.write(_byteBoundary,0,b);
b=-1;
baos.write(c);
}
}
// check partial boundary
if ((b>0 && b<_byteBoundary.length-2) ||
(b==_byteBoundary.length-1))
{
if (cr) baos.write(13);
if (lf) baos.write(10);
cr=lf=false;
baos.write(_byteBoundary,0,b);
b=-1;
}
// boundary match
if (b>0 || c==-1)
{
if (b==_byteBoundary.length)
_lastPart=true;
if (_char==10) _char=-2;
break;
}
// handle CR LF
if (cr) baos.write(13);
if (lf) baos.write(10);
cr=(c==13);
lf=(c==10 || _char==10);
if (_char==10) _char=-2;
}
//if(log.isTraceEnabled())log.trace(baos.toString());
return baos.toByteArray();
}
/* ------------------------------------------------------------ */
private String value(String nameEqualsValue)
{
String value =
nameEqualsValue.substring(nameEqualsValue.indexOf('=')+1).trim();
int i=value.indexOf(';');
if (i>0)
value=value.substring(0,i);
if (value.startsWith("\""))
{
value=value.substring(1,value.indexOf('"',1));
}
else
{
i=value.indexOf(' ');
if (i>0)
value=value.substring(0,i);
}
return value;
}
/* ------------------------------------------------------------ */
private class Part
{
String _name=null;
String _filename=null;
Hashtable _headers= new Hashtable(10);
byte[] _data=null;
}
};

View File

@ -0,0 +1,112 @@
// ========================================================================
// $Id: ByteArrayPool.java,v 1.9 2004/05/09 20:32:49 gregwilkins Exp $
// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.util;
/* ------------------------------------------------------------ */
/** Byte Array Pool
* Simple pool for recycling byte arrays of a fixed size.
*
* @version $Id: ByteArrayPool.java,v 1.9 2004/05/09 20:32:49 gregwilkins Exp $
* @author Greg Wilkins (gregw)
*/
public class ByteArrayPool
{
public static final int __POOL_SIZE=
Integer.getInteger("org.mortbay.util.ByteArrayPool.pool_size",8).intValue();
public static final ThreadLocal __pools=new BAThreadLocal();
public static int __slot;
/* ------------------------------------------------------------ */
/** Get a byte array from the pool of known size.
* @param size Size of the byte array.
* @return Byte array of known size.
*/
public static byte[] getByteArray(int size)
{
byte[][] pool = (byte[][])__pools.get();
boolean full=true;
for (int i=pool.length;i-->0;)
{
if (pool[i]!=null && pool[i].length==size)
{
byte[]b = pool[i];
pool[i]=null;
return b;
}
else
full=false;
}
if (full)
for (int i=pool.length;i-->0;)
pool[i]=null;
return new byte[size];
}
/* ------------------------------------------------------------ */
public static byte[] getByteArrayAtLeast(int minSize)
{
byte[][] pool = (byte[][])__pools.get();
for (int i=pool.length;i-->0;)
{
if (pool[i]!=null && pool[i].length>=minSize)
{
byte[]b = pool[i];
pool[i]=null;
return b;
}
}
return new byte[minSize];
}
/* ------------------------------------------------------------ */
public static void returnByteArray(final byte[] b)
{
if (b==null)
return;
byte[][] pool = (byte[][])__pools.get();
for (int i=pool.length;i-->0;)
{
if (pool[i]==null)
{
pool[i]=b;
return;
}
}
// slot.
int s = __slot++;
if (s<0)s=-s;
pool[s%pool.length]=b;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private static final class BAThreadLocal extends ThreadLocal
{
protected Object initialValue()
{
return new byte[__POOL_SIZE][];
}
}
}

View File

@ -0,0 +1,719 @@
// ========================================================================
// $Id: LineInput.java,v 1.17 2005/10/05 11:32:40 gregwilkins Exp $
// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.mortbay.util;
import java.io.ByteArrayInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
//import org.apache.commons.logging.Log;
//import org.mortbay.log.LogFactory;
/* ------------------------------------------------------------ */
/** Fast LineInput InputStream.
* This buffered InputStream provides methods for reading lines
* of bytes. The lines can be converted to String or character
* arrays either using the default encoding or a user supplied
* encoding.
*
* Buffering and data copying are highly optimized, making this
* an ideal class for protocols that mix character encoding lines
* with arbitrary byte data (eg HTTP).
*
* The buffer size is also the maximum line length in bytes and/or
* characters. If the byte length of a line is less than the max,
* but the character length is greater, than then trailing characters
* are lost.
*
* Line termination is forgiving and accepts CR, LF, CRLF or EOF.
* Line input uses the mark/reset mechanism, so any marks set
* prior to a readLine call are lost.
*
* @version $Id: LineInput.java,v 1.17 2005/10/05 11:32:40 gregwilkins Exp $
* @author Greg Wilkins (gregw)
*/
public class LineInput extends FilterInputStream
{
//private static Log log = LogFactory.getLog(LineInput.class);
/* ------------------------------------------------------------ */
private byte _buf[];
private ByteBuffer _byteBuffer;
private InputStreamReader _reader;
private int _mark=-1; // reset marker
private int _pos; // Start marker
private int _avail; // Available back marker, may be byte limited
private int _contents; // Absolute back marker of buffer
private int _byteLimit=-1;
private boolean _newByteLimit;
private LineBuffer _lineBuffer;
private String _encoding;
private boolean _eof=false;
private boolean _lastCr=false;
private boolean _seenCrLf=false;
private final static int LF=10;
private final static int CR=13;
/* ------------------------------------------------------------ */
/** Constructor.
* Default buffer and maximum line size is 2048.
* @param in The underlying input stream.
*/
public LineInput(InputStream in)
{
this(in,0);
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param in The underlying input stream.
* @param bufferSize The buffer size and maximum line length.
*/
public LineInput(InputStream in, int bufferSize)
{
super(in);
_mark=-1;
if (bufferSize==0)
bufferSize=8192;
_buf=ByteArrayPool.getByteArray(bufferSize);
_byteBuffer=new ByteBuffer(_buf);
_lineBuffer=new LineBuffer(bufferSize);
try
{
_reader=new InputStreamReader(_byteBuffer,"UTF-8");
}
catch (UnsupportedEncodingException e)
{
_reader=new InputStreamReader(_byteBuffer);
}
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param in The underlying input stream.
* @param bufferSize The buffer size and maximum line length.
* @param encoding the character encoding to use for readLine methods.
* @exception UnsupportedEncodingException
*/
public LineInput(InputStream in, int bufferSize, String encoding)
throws UnsupportedEncodingException
{
super(in);
_mark=-1;
if (bufferSize==0)
bufferSize=2048;
_buf=ByteArrayPool.getByteArray(bufferSize);
_byteBuffer=new ByteBuffer(_buf);
_lineBuffer=new LineBuffer(bufferSize);
_reader=new InputStreamReader(_byteBuffer,encoding);
_encoding=encoding;
}
/* ------------------------------------------------------------ */
public InputStream getInputStream()
{
return in;
}
/* ------------------------------------------------------------ */
/** Set the byte limit.
* If set, only this number of bytes are read before EOF.
* @param bytes Limit number of bytes, or -1 for no limit.
*/
public void setByteLimit(int bytes)
{
_byteLimit=bytes;
if (bytes>=0)
{
_newByteLimit=true;
_byteLimit-=_contents-_pos;
if (_byteLimit<0)
{
_avail+=_byteLimit;
_byteLimit=0;
}
}
else
{
_newByteLimit=false;
_avail=_contents;
_eof=false;
}
}
/* ------------------------------------------------------------ */
/** Get the byte limit.
* @return Number of bytes until EOF is returned or -1 for no limit.
*/
public int getByteLimit()
{
if (_byteLimit<0)
return _byteLimit;
return _byteLimit+_avail-_pos;
}
/* ------------------------------------------------------------ */
/** Read a line ended by CR, LF or CRLF.
* The default or supplied encoding is used to convert bytes to
* characters.
* @return The line as a String or null for EOF.
* @exception IOException
*/
public synchronized String readLine()
throws IOException
{
int len=fillLine(_buf.length);
if (len<0)
return null;
String s=null;
if (_encoding==null)
s=new String(_buf,_mark,len);
else
{
try
{
s=new String(_buf,_mark,len,_encoding);
}
catch(UnsupportedEncodingException e)
{
//log.warn(LogSupport.EXCEPTION,e);
}
}
_mark=-1;
return s;
}
/* ------------------------------------------------------------ */
/** Read a line ended by CR, LF or CRLF.
* The default or supplied encoding is used to convert bytes to
* characters.
* @param c Character buffer to place the line into.
* @param off Offset into the buffer.
* @param len Maximum length of line.
* @return The length of the line or -1 for EOF.
* @exception IOException
*/
public int readLine(char[] c,int off,int len)
throws IOException
{
int blen=fillLine(len);
if (blen<0)
return -1;
if (blen==0)
return 0;
_byteBuffer.setStream(_mark,blen);
int read=0;
while(read<len && _reader.ready())
{
int r = _reader.read(c,off+read,len-read);
if (r<=0)
break;
read+=r;
}
_mark=-1;
return read;
}
/* ------------------------------------------------------------ */
/** Read a line ended by CR, LF or CRLF.
* @param b Byte array to place the line into.
* @param off Offset into the buffer.
* @param len Maximum length of line.
* @return The length of the line or -1 for EOF.
* @exception IOException
*/
public int readLine(byte[] b,int off,int len)
throws IOException
{
len=fillLine(len);
if (len<0)
return -1;
if (len==0)
return 0;
System.arraycopy(_buf,_mark, b, off, len);
_mark=-1;
return len;
}
/* ------------------------------------------------------------ */
/** Read a Line ended by CR, LF or CRLF.
* Read a line into a shared LineBuffer instance. The LineBuffer is
* resused between calls and should not be held by the caller.
* The default or supplied encoding is used to convert bytes to
* characters.
* @return LineBuffer instance or null for EOF.
* @exception IOException
*/
public LineBuffer readLineBuffer()
throws IOException
{
return readLineBuffer(_buf.length);
}
/* ------------------------------------------------------------ */
/** Read a Line ended by CR, LF or CRLF.
* Read a line into a shared LineBuffer instance. The LineBuffer is
* resused between calls and should not be held by the caller.
* The default or supplied encoding is used to convert bytes to
* characters.
* @param len Maximum length of a line, or 0 for default
* @return LineBuffer instance or null for EOF.
* @exception IOException
*/
public LineBuffer readLineBuffer(int len)
throws IOException
{
len=fillLine(len>0?len:_buf.length);
if (len<0)
return null;
if (len==0)
{
_lineBuffer.size=0;
return _lineBuffer;
}
_byteBuffer.setStream(_mark,len);
_lineBuffer.size=0;
int read=0;
while(read<len && _reader.ready())
{
int r = _reader.read(_lineBuffer.buffer,
read,
len-read);
if (r<=0)
break;
read+=r;
}
_lineBuffer.size=read;
_mark=-1;
return _lineBuffer;
}
/* ------------------------------------------------------------ */
public synchronized int read() throws IOException
{
int b;
if (_pos >=_avail)
fill();
if (_pos >=_avail)
b=-1;
else
b=_buf[_pos++]&255;
return b;
}
/* ------------------------------------------------------------ */
public synchronized int read(byte b[], int off, int len) throws IOException
{
int avail=_avail-_pos;
if (avail <=0)
{
fill();
avail=_avail-_pos;
}
if (avail <=0)
len=-1;
else
{
len=(avail < len) ? avail : len;
System.arraycopy(_buf,_pos,b,off,len);
_pos +=len;
}
return len;
}
/* ------------------------------------------------------------ */
public long skip(long n) throws IOException
{
int avail=_avail-_pos;
if (avail <=0)
{
fill();
avail=_avail-_pos;
}
if (avail <=0)
n=0;
else
{
n=(avail < n) ? avail : n;
_pos +=n;
}
return n;
}
/* ------------------------------------------------------------ */
public synchronized int available()
throws IOException
{
int in_stream=in.available();
if (_byteLimit>=0 && in_stream>_byteLimit)
in_stream=_byteLimit;
return _avail - _pos + in_stream;
}
/* ------------------------------------------------------------ */
public synchronized void mark(int limit)
throws IllegalArgumentException
{
if (limit>_buf.length)
{
byte[] new_buf=new byte[limit];
System.arraycopy(_buf,_pos,new_buf,_pos,_avail-_pos);
_buf=new_buf;
if (_byteBuffer!=null)
_byteBuffer.setBuffer(_buf);
}
_mark=_pos;
}
/* ------------------------------------------------------------ */
public synchronized void reset()
throws IOException
{
if (_mark < 0)
throw new IOException("Resetting to invalid mark");
_pos=_mark;
_mark=-1;
}
/* ------------------------------------------------------------ */
public boolean markSupported()
{
return true;
}
/* ------------------------------------------------------------ */
private void fill()
throws IOException
{
// if the mark is in the middle of the buffer
if (_mark > 0)
{
// moved saved bytes to start of buffer
int saved=_contents - _mark;
System.arraycopy(_buf, _mark, _buf, 0, saved);
_pos-=_mark;
_avail-=_mark;
_contents=saved;
_mark=0;
}
else if (_mark<0 && _pos>0)
{
// move remaining bytes to start of buffer
int saved=_contents-_pos;
System.arraycopy(_buf,_pos, _buf, 0, saved);
_avail-=_pos;
_contents=saved;
_pos=0;
}
else if (_mark==0 && _pos>0 && _contents==_buf.length)
{
// Discard the mark as we need the space.
_mark=-1;
fill();
return;
}
// Get ready to top up the buffer
int n=0;
_eof=false;
// Handle byte limited EOF
if (_byteLimit==0)
_eof=true;
// else loop until something is read.
else while (!_eof && n==0 && _buf.length>_contents)
{
// try to read as much as will fit.
int space=_buf.length-_contents;
n=in.read(_buf,_contents,space);
if (n<=0)
{
// If no bytes - we could be NBIO, so we want to avoid
// a busy loop.
if (n==0)
{
// Yield to give a chance for some bytes to turn up
Thread.yield();
// Do a byte read as that is blocking
int b = in.read();
if (b>=0)
{
n=1;
_buf[_contents++]=(byte)b;
}
else
_eof=true;
}
else
_eof=true;
}
else
_contents+=n;
_avail=_contents;
// If we have a byte limit
if (_byteLimit>0)
{
// adjust the bytes available
if (_contents-_pos >=_byteLimit)
_avail=_byteLimit+_pos;
if (n>_byteLimit)
_byteLimit=0;
else if (n>=0)
_byteLimit-=n;
else if (n==-1)
throw new IOException("Premature EOF");
}
}
// If we have some characters and the last read was a CR and
// the first char is a LF, skip it
if (_avail-_pos>0 && _lastCr && _buf[_pos]==LF)
{
_seenCrLf=true;
_pos++;
if (_mark>=0)
_mark++;
_lastCr=false;
// If the byte limit has just been imposed, dont count
// LF as content.
if(_byteLimit>=0 && _newByteLimit)
{
if (_avail<_contents)
_avail++;
else
_byteLimit++;
}
// If we ate all that ws filled, fill some more
if (_pos==_avail)
fill();
}
_newByteLimit=false;
}
/* ------------------------------------------------------------ */
private int fillLine(int maxLen)
throws IOException
{
_mark=_pos;
if (_pos>=_avail)
fill();
if (_pos>=_avail)
return -1;
byte b;
boolean cr=_lastCr;
boolean lf=false;
_lastCr=false;
int len=0;
LineLoop:
while (_pos<=_avail)
{
// if we have gone past the end of the buffer
while (_pos==_avail)
{
// If EOF or no more space in the buffer,
// return a line.
if (_eof || (_mark==0 && _contents==_buf.length))
{
_lastCr=!_eof && _buf[_avail-1]==CR;
cr=true;
lf=true;
break LineLoop;
}
// If we have a CR and no more characters are available
if (cr && in.available()==0 && !_seenCrLf)
{
_lastCr=true;
cr=true;
lf=true;
break LineLoop;
}
else
{
// Else just wait for more...
_pos=_mark;
fill();
_pos=len;
cr=false;
}
}
// Get the byte
b=_buf[_pos++];
switch(b)
{
case LF:
if (cr) _seenCrLf=true;
lf=true;
break LineLoop;
case CR:
if (cr)
{
// Double CR
if (_pos>1)
{
_pos--;
break LineLoop;
}
}
cr=true;
break;
default:
if(cr)
{
if (_pos==1)
cr=false;
else
{
_pos--;
break LineLoop;
}
}
len++;
if (len==maxLen)
{
// look for EOL
if (_mark!=0 && _pos+2>=_avail && _avail<_buf.length)
fill();
if (_pos<_avail && _buf[_pos]==CR)
{
cr=true;
_pos++;
}
if (_pos<_avail && _buf[_pos]==LF)
{
lf=true;
_pos++;
}
if (!cr && !lf)
{
// fake EOL
lf=true;
cr=true;
}
break LineLoop;
}
break;
}
}
if (!cr && !lf && len==0)
len=-1;
return len;
}
/* ------------------------------------------------------------ */
private static class ByteBuffer extends ByteArrayInputStream
{
ByteBuffer(byte[] buffer)
{
super(buffer);
}
void setBuffer(byte[] buffer)
{
buf=buffer;
}
void setStream(int offset,int length)
{
pos=offset;
count=offset+length;
mark=-1;
}
}
/* ------------------------------------------------------------ */
/** Reusable LineBuffer.
* Externalized LineBuffer for fast line parsing.
*/
public static class LineBuffer
{
public char[] buffer;
public int size;
public LineBuffer(int maxLineLength)
{buffer=new char[maxLineLength];}
public String toString(){return new String(buffer,0,size);}
}
/* ------------------------------------------------------------ */
public void destroy()
{
ByteArrayPool.returnByteArray(_buf);
_byteBuffer=null;
_reader=null;
_lineBuffer=null;
_encoding=null;
}
}

View File

@ -77,6 +77,11 @@ public class UrlLauncher {
try {
test.close();
} catch (IOException ioe) {}
// Jetty 6 seems to start the Connector before the
// webapp is completely ready
try {
Thread.sleep(2*1000);
} catch (InterruptedException ie) {}
return true;
} catch (Exception e) {}
if (System.currentTimeMillis() > done)

View File

@ -10,6 +10,6 @@
# Javadocs
# Note: Include the trailing slash! Don't surround the URL in quotes!
javasedocs.url=http://docs.oracle.com/javase/6/docs/api/
jettydocs.url=http://docs.i2p2.de/jetty/javadoc/
jettydocs.url=http://jetty.codehaus.org/jetty/jetty-6/apidocs/
jrobindocs.url=http://docs.i2p-projekt.de/jrobin/javadoc/
wrapperdocs.url=http://wrapper.tanukisoftware.com/jdoc/

157
build.xml
View File

@ -36,6 +36,7 @@
<echo message=" updaterWithJavadoc: updater including the javadocs, for display in the console" />
<echo message=" updater200WithJavadoc: updater including the javadocs, for display in the console (creates i2pupdate200.zip)" />
<echo message=" updaterWithJetty: Updater including Jetty" />
<echo message=" updater200withJetty: Updater including Jetty" />
<echo message=" updaterWithJettyFixes: updater including local jetty patches" />
<echo message=" updaterWithGeoIP: updater including GeoIP Files" />
<echo message=" updaterWithJettyFixesAndGeoIP" />
@ -50,26 +51,28 @@
<echo message=" javadoc: generate javadoc for the entire project into ./build/javadoc" />
<echo message=" slackpkg: generate Slackware packages in ./Slackware/i2p and ./Slackware/i2p-base" />
<echo message=" debianhowto: instructions on building Debian packages" />
<echo message=" debian: generate Debian packages in ../" />
<echo message=" run &quot;ant debianhowto&quot; for instructions" />
<echo message=" debian-clean: rollback debian specific patches and run the &quot;distclean&quot; target (done automatically at the end of the &quot;debian&quot; target)" />
<!-- <echo message=" debianrepo: build a Debian repository (reprepro required)" /> -->
<echo message=" debian: generate Debian packages in ../" />
<echo message=" run &quot;ant debianhowto&quot; for instructions" />
<echo message=" debian-clean: rollback debian specific patches and run the &quot;distclean&quot; target (done automatically at the end of the &quot;debian&quot; target)" />
<!-- <echo message=" debianrepo: build a Debian repository (reprepro required)" /> -->
<echo message=" poupdate: update the .po files for translators" />
<echo message=" pkg-portable-win32: build a minimum portable version for win32" />
</target>
<target name="debianhowto">
<echo message="To build debian packages, you must make sure that you have" />
<echo message="the necessary build-dependencies installed." />
<echo message="The packages required to build can be found in the file "/>
<echo message="&quot;debian/control&quot; in both the Build-Depends and Build-Depends-Indep fields."/>
<echo message="In addition to those packages, be sure to install &quot;fakeroot&quot;,"/>
<echo message="&quot;quilt&quot; and &quot;build-essential&quot;!" />
<echo message="" />
<echo message="The following command will install all dependencies for you:" />
<echo message="apt-get install debhelper ant debconf default-jdk gettext libgmp3-dev po-debconf fakeroot build-essential quilt" />
<echo message=" " />
<echo message="Once the dependencies are installed, run &quot;ant debian&quot;"/>
<echo message="to patch the source and build the packages." />
<echo message="To build debian packages, you must make sure that you have" />
<echo message="the necessary build-dependencies installed." />
<echo message="The packages required to build can be found in the file "/>
<echo message="&quot;debian/control&quot; in the &quot;Build-Depends&quot; field."/>
<echo message="In addition to those packages, be sure to install &quot;fakeroot&quot;,"/>
<echo message="&quot;quilt&quot; and &quot;build-essential&quot;!" />
<echo message="" />
<echo message="The following command will install all of the dependencies for you:" />
<echo message=" " />
<echo message="apt-get install debhelper ant debconf default-jdk gettext libgmp3-dev po-debconf fakeroot build-essential \" />
<echo message=" quilt libcommons-el-java libcommons-logging-java libjetty-extra-java libjetty-java" />
<echo message=" " />
<echo message="Once the dependencies are installed, run &quot;ant debian&quot;"/>
<echo message="to patch the source and build the packages." />
</target>
<target name="dist" depends="pkg, javadoc">
</target>
@ -132,7 +135,7 @@
<ant dir="apps/routerconsole/java/" target="jar" />
</target>
<target name="buildJetty" depends="buildProperties" >
<target name="buildJetty" depends="buildCore" >
<ant dir="apps/jetty" target="build" />
</target>
@ -195,12 +198,9 @@
<target name="buildWEB" depends="buildRouterConsole" >
<copy file="apps/routerconsole/java/build/routerconsole.jar" todir="build/" />
<copy file="apps/routerconsole/java/build/routerconsole.war" todir="build/" />
<copy file="apps/jetty/jettylib/org.mortbay.jetty.jar" todir="build/" />
<copy file="apps/jetty/jettylib/jasper-compiler.jar" todir="build/" />
<copy file="apps/jetty/jettylib/jasper-runtime.jar" todir="build/" />
<copy file="apps/jetty/jettylib/commons-logging.jar" todir="build/" />
<copy file="apps/jetty/jettylib/commons-el.jar" todir="build/" />
<copy file="apps/jetty/jettylib/javax.servlet.jar" todir="build/" />
<copy todir="build/" >
<fileset dir="apps/jetty/jettylib" excludes="ant.jar" />
</copy>
</target>
<target name="buildexe">
@ -400,9 +400,10 @@
<group title="Desktopgui Application" packages="net.i2p.desktopgui:net.i2p.desktopgui.*" />
<group title="I2PSnark Application" packages="org.klomp.snark:org.klomp.snark.*" />
<group title="I2PTunnel Application" packages="net.i2p.i2ptunnel:net.i2p.i2ptunnel.*" />
<group title="Jetty Logging" packages="org.mortbay.http" />
<group title="SAM Bridge" packages="net.i2p.sam:net.i2p.sam.client" />
<group title="SusiDNS Application" packages="i2p.susi.dns" />
<group title="SusiMail Application" packages="i2p.susi.webmail:i2p.susi.webmail.*:i2p.susi.debug:i2p.susi.util" />
<group title="SusiMail Application" packages="i2p.susi.webmail:i2p.susi.webmail.*:i2p.susi.debug:i2p.susi.util:org.mortbay.servlet:org.mortbay.util" />
<group title="Systray Application" packages="net.i2p.apps.systray" />
<sourcepath>
<pathelement location="core/java/src" />
@ -421,10 +422,16 @@
<pathelement location="apps/BOB/src" />
<pathelement location="apps/susidns/src/java/src" />
<pathelement location="apps/susimail/src/src" />
<pathelement location="apps/jetty/java/src" />
</sourcepath>
<classpath>
<pathelement location="apps/jetty/jettylib/org.mortbay.jetty.jar" />
<pathelement location="apps/jetty/jettylib/javax.servlet.jar" />
<pathelement location="apps/jetty/jettylib/jetty-sslengine.jar" />
<pathelement location="apps/jetty/jettylib/jetty-start.jar" />
<pathelement location="apps/jetty/jettylib/jetty-java5-threadpool.jar" />
<pathelement location="apps/jetty/jettylib/jetty-util.jar" />
<pathelement location="apps/jetty/jettylib/jsp-api.jar" />
<pathelement location="apps/systray/java/lib/systray4j.jar" />
<pathelement location="apps/jrobin/jrobin-1.5.9.1.jar" />
<pathelement location="installer/lib/wrapper/all/wrapper.jar" />
@ -569,6 +576,15 @@
<defaultexcludes default="true"/>
</target>
<target name="webappDistclean">
<ant dir="apps/i2ptunnel/java/" target="distclean" />
<ant dir="apps/routerconsole/java/" target="distclean" />
<ant dir="apps/addressbook/" target="distclean" />
<ant dir="apps/susimail/" target="distclean" />
<ant dir="apps/susidns/src/" target="distclean" />
<ant dir="apps/i2psnark/java/" target="distclean" />
</target>
<target name="pkg" depends="distclean, updater, preppkg, installer" />
<target name="pkgclean" depends="deletepkg-temp">
@ -688,14 +704,12 @@
</delete>
<copy file="build/i2p.jar" todir="pkg-temp/lib/" />
<copy file="build/i2ptunnel.jar" todir="pkg-temp/lib/" />
<copy file="build/jasper-compiler.jar" todir="pkg-temp/lib/" />
<copy file="build/jasper-runtime.jar" todir="pkg-temp/lib/" />
<copy file="build/commons-logging.jar" todir="pkg-temp/lib/" />
<copy file="build/commons-el.jar" todir="pkg-temp/lib/" />
<copy file="build/javax.servlet.jar" todir="pkg-temp/lib/" />
<!-- all jetty stuff -->
<copy todir="pkg-temp/lib" >
<fileset dir="build" includes="commons*.jar jasper*.jar javax*.jar jetty*.jar jsp*.jar org.mortbay.jetty.jar" />
</copy>
<copy file="build/mstreaming.jar" todir="pkg-temp/lib/" />
<copy file="build/streaming.jar" todir="pkg-temp/lib/" />
<copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" />
<copy file="build/router.jar" todir="pkg-temp/lib/" />
<copy file="build/desktopgui.jar" todir="pkg-temp/lib/" />
<copy file="build/routerconsole.jar" todir="pkg-temp/lib/" />
@ -742,20 +756,13 @@
<copy file="installer/resources/uninstall.ico" todir="pkg-temp/docs/" />
<!-- Eepsite stuff here -->
<mkdir dir="pkg-temp/eepsite" />
<mkdir dir="pkg-temp/eepsite/webapps" />
<mkdir dir="pkg-temp/eepsite/logs" />
<mkdir dir="pkg-temp/eepsite/cgi-bin" />
<mkdir dir="pkg-temp/eepsite/docroot" />
<mkdir dir="pkg-temp/eepsite/docroot/help" />
<mkdir dir="pkg-temp/eepsite/docroot/help/lib" />
<copy todir="pkg-temp/eepsite/docroot/" >
<fileset dir="installer/resources/eepsite.help/" />
<copy todir="pkg-temp/eepsite/" >
<fileset dir="installer/resources/eepsite/" />
</copy>
<copy todir="pkg-temp/eepsite/docroot/help/lib/" >
<fileset dir="installer/resources/icons/flags/" includes="cn.png de.png es.png fr.png ir.png it.png jp.png nl.png ru.png se.png us.png" />
</copy>
<copy file="installer/resources/themes/console/images/favicon.ico" tofile="pkg-temp/eepsite/docroot/favicon.ico" />
<copy file="installer/resources/jetty.xml" tofile="pkg-temp/eepsite/jetty.xml" />
</target>
<target name="preplicenses">
@ -769,6 +776,7 @@
So we include the MIT one in our binary package
-->
<copy file="installer/lib/launch4j/head/LICENSE.txt" tofile="pkg-temp/licenses/LICENSE-Launch4j.txt" />
<copy file="apps/jetty/apache-tomcat-deployer/NOTICE" tofile="pkg-temp/licenses/NOTICE-Tomcat.txt" />
<!-- Not sure if these are used or should be included -->
<copy file="installer/lib/launch4j/lib/foxtrot.LICENSE.txt" tofile="pkg-temp/licenses/LICENSE-Foxtrot.txt" />
<copy file="installer/lib/launch4j/lib/JGoodies.Forms.LICENSE.txt" tofile="pkg-temp/licenses/LICENSE-JGoodies-Forms.txt" />
@ -835,6 +843,7 @@
<target name="updater200WithJavadoc" depends="prepupdate, preplicenses, copyJavadoc, pack200, zipit200" />
<target name="updaterWithGeoIP" depends="prepupdate, prepgeoupdate, preplicenses, zipit" />
<target name="updaterWithJetty" depends="prepjupdate, preplicenses, zipit" />
<target name="updater200WithJetty" depends="prepjupdate, preplicenses, pack200, zipit200" />
<target name="updaterWithJettyFixes" depends="prepjupdatefixes, preplicenses, zipit" />
<target name="updaterWithJettyFixesAndJbigi" depends="prepjupdatefixes, prepjbigiupdate, preplicenses, zipit" />
<target name="updaterWithJettyFixesAndGeoIP" depends="prepjupdatefixes, prepgeoupdate, preplicenses, zipit" />
@ -951,16 +960,26 @@
</copy>
</target>
<!-- All jetty jars required for update.
We don't need commons-el or commons-logging, they haven't changed.
TODO do we need to bother updating jasper?
TODO where is JMX? We don't need it I hope.
-->
<target name="prepjupdate" depends="prepupdate, buildWEB">
<copy file="build/jasper-compiler.jar" todir="pkg-temp/lib/" />
<copy file="build/jasper-runtime.jar" todir="pkg-temp/lib/" />
<copy file="build/commons-logging.jar" todir="pkg-temp/lib/" />
<copy file="build/commons-el.jar" todir="pkg-temp/lib/" />
<copy file="build/javax.servlet.jar" todir="pkg-temp/lib/" />
<copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" />
<copy todir="pkg-temp/lib" >
<fileset dir="build" includes="commons*.jar jasper*.jar javax*.jar jetty*.jar jsp*.jar org.mortbay.jetty.jar" />
</copy>
<!-- We have to package the new eepsite files for MigrateJetty.java, but we
can't overwrite an existing eepsite dir in a non-split configuration.
-->
<copy todir="pkg-temp/eepsite-jetty6" >
<fileset dir="installer/resources/eepsite" includes="*.xml contexts/* etc/*" />
</copy>
</target>
<!-- Jetty 6 I2P logging addons, not really fixes -->
<target name="prepjupdatefixes" depends="prepupdate, buildWEB">
<copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" />
<copy file="build/jetty-i2p.jar" todir="pkg-temp/lib/" />
</target>
<target name="util-list-changes" depends="checkForMtn" if="mtn.available" >
@ -1392,33 +1411,33 @@
<target name="debian-binary" >
<echo message="Did you update the version using dch -i?" />
<echo message=" " />
<echo message="If the changelog was not updated with dch -i, press" />
<echo message="press CTRL+C to abort building this Debian package." />
<echo message="" />
<echo message="Pausing build for ten seconds to give enough time to read this notice." />
<exec executable="sleep" failonerror="true">
<arg value="10" />
</exec>
<echo message="====================" />
<!-- bundle the jetty 5 lib since there isn't a deb for it -->
<ant dir="apps/jetty" target="ensureJettylib" />
<exec executable="fakeroot" failonerror="true">
<arg value="debian/rules" />
<arg value="patch" />
<arg value="binary" />
<arg value="clean" />
<echo message=" " />
<echo message="If the changelog was not updated with dch -i, press" />
<echo message="press CTRL+C to abort building this Debian package." />
<echo message="" />
<echo message="Pausing build for ten seconds to give enough time to read this notice." />
<exec executable="sleep" failonerror="true">
<arg value="10" />
</exec>
<delete dir=".pc" />
<echo message="====================" />
<exec executable="fakeroot" failonerror="true">
<arg value="debian/rules" />
<arg value="patch" />
<arg value="binary" />
<arg value="clean" />
</exec>
<delete dir=".pc" />
</target>
<target name="debian-clean" depends="buildProperties" >
<exec executable="fakeroot" failonerror="true">
<arg value="debian/rules" />
<arg value="clean" />
<arg value="debian/rules" />
<arg value="clean" />
</exec>
<delete dir="./.pc" />
<delete dir="./.pc" />
</target>
<target name="debian-patch" depends="buildProperties" >
<exec executable="quilt" failonerror="true">
<arg value="-a" />
@ -1428,8 +1447,8 @@
</target>
<target name="debian-unpatch" depends="buildProperties">
<exec executable="quilt" failonerror="false">
<arg value="-a" />
<arg value="pop" />
<arg value="-a" />
<arg value="pop" />
</exec>
</target>

11
debian/control vendored
View File

@ -10,9 +10,12 @@ Build-Depends: debhelper (>= 7.0.50~),
debconf,
default-jdk,
gettext,
libcommons-el-java,
libcommons-logging-java,
libgmp3-dev,
libjetty-extra-java,
libjetty-java,
po-debconf
##Build-Depends-Indep: tor-geoipdb
Package: i2p
Architecture: all
@ -65,7 +68,11 @@ Package: i2p-router
Architecture: all
Section: net
Priority: optional
Depends: ${misc:Depends}, ${java:Depends}, ${shlibs:Depends}, default-jre-headless | java5-runtime-headless | java6-runtime-headless
Depends: ${misc:Depends}, ${java:Depends}, ${shlibs:Depends},
default-jre-headless | java5-runtime-headless | java6-runtime-headless,
libcommons-logging-java,
libjetty-java,
libtomcat6-java
Replaces: i2p ( << 0.8.6-5)
Breaks: i2p (<< 0.8.6-5)
Recommends: libjbigi-jni (>= ${source:Version}), libjbigi-jni (<< ${source:Version}.1~), ttf-dejavu

Some files were not shown because too many files have changed in this diff Show More