blob: 371fa4fb0260f62e59dcbab54d74ff3117e04679 [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* 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.apache.ajp.tomcat4;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;
import java.util.TreeMap;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.Globals;
import org.apache.catalina.connector.HttpRequestBase;
import org.apache.catalina.util.StringParser;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.BaseRequest;
import org.apache.tomcat.util.http.Cookies;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.http.ServerCookie;
public class Ajp13Request extends HttpRequestBase {
private static final String match =
";" + Globals.SESSION_PARAMETER_NAME + "=";
private static int id = 1;
private Ajp13Logger logger = new Ajp13Logger();
private int debug;
public Ajp13Request(Ajp13Connector connector) {
super();
this.debug = connector.getDebug();
this.logger.setConnector(connector);
this.logger.setName("Ajp13Request[" + (id++) + "]");
}
public void recycle() {
super.recycle();
}
void setAjpRequest(BaseRequest ajp) throws UnsupportedEncodingException {
// XXX make this guy wrap AjpRequest so
// we're more efficient (that's the whole point of
// all of the MessageBytes in AjpRequest)
setMethod(ajp.method().toString());
setProtocol(ajp.protocol().toString());
setRequestURI(ajp.requestURI().toString());
setRemoteAddr(ajp.remoteAddr().toString());
setRemoteHost(ajp.remoteHost().toString());
setServerName(ajp.serverName().toString());
setServerPort(ajp.getServerPort());
if ((!(((Ajp13Connector) connector).getTomcatAuthentication()))
&& (ajp.remoteUser() != null)) {
setUserPrincipal(new Ajp13Principal(ajp.remoteUser().toString()));
} else {
setUserPrincipal(null);
}
setAuthType(ajp.authType().toString());
setAuthorization(ajp.authorization().toString());
setQueryString(ajp.queryString().toString());
setScheme(ajp.getScheme());
setSecure(ajp.getSecure());
setContentLength(ajp.getContentLength());
String contentType = ajp.contentType().toString();
if (contentType != null) {
setContentType(contentType);
}
MimeHeaders mheaders = ajp.headers();
int nheaders = mheaders.size();
for (int i = 0; i < nheaders; ++i) {
MessageBytes name = mheaders.getName(i);
MessageBytes value = mheaders.getValue(i);
addHeader(name.toString(), value.toString());
if ("accept-language".equals(name.toString()))
parseLocalesHeader(value.toString());
}
Iterator itr = ajp.getAttributeNames();
while (itr.hasNext()) {
String name = (String)itr.next();
setAttribute(name, ajp.getAttribute(name));
}
addCookies(ajp.cookies());
}
// public Object getAttribute(String name) {
// return ajp.getAttribute(name);
// }
// public Enumeration getAttributeNames() {
// return new Enumerator(ajp.getAttributeNames());
// }
public void setRequestURI(String uri) {
int semicolon = uri.indexOf(match);
if (semicolon >= 0) {
String rest = uri.substring(semicolon + match.length());
int semicolon2 = rest.indexOf(";");
if (semicolon2 >= 0) {
setRequestedSessionId(rest.substring(0, semicolon2));
rest = rest.substring(semicolon2);
} else {
setRequestedSessionId(rest);
rest = "";
}
setRequestedSessionURL(true);
uri = uri.substring(0, semicolon) + rest;
if (debug >= 1)
logger.log(" Requested URL session id is " +
((HttpServletRequest) getRequest())
.getRequestedSessionId());
} else {
setRequestedSessionId(null);
setRequestedSessionURL(false);
}
super.setRequestURI(uri);
}
private void addCookies(Cookies cookies) {
int ncookies = cookies.getCookieCount();
for (int j = 0; j < ncookies; j++) {
ServerCookie scookie = cookies.getCookie(j);
Cookie cookie = new Cookie(scookie.getName().toString(),
scookie.getValue().toString());
if (cookie.getName().equals(Globals.SESSION_COOKIE_NAME)) {
// Override anything requested in the URL
if (!isRequestedSessionIdFromCookie()) {
// Accept only the first session id cookie
setRequestedSessionId(cookie.getValue());
setRequestedSessionCookie(true);
setRequestedSessionURL(false);
if (debug > 0) {
logger.log(" Requested cookie session id is " +
((HttpServletRequest) getRequest())
.getRequestedSessionId());
}
}
}
if (debug > 0) {
logger.log(" Adding cookie " + cookie.getName() + "=" +
cookie.getValue());
}
addCookie(cookie);
}
}
public ServletInputStream createInputStream() throws IOException {
return (ServletInputStream)getStream();
}
/**
* Parse accept-language header value.
*/
protected void parseLocalesHeader(String value) {
// Store the accumulated languages that have been requested in
// a local collection, sorted by the quality value (so we can
// add Locales in descending order). The values will be ArrayLists
// containing the corresponding Locales to be added
TreeMap locales = new TreeMap();
// Preprocess the value to remove all whitespace
int white = value.indexOf(' ');
if (white < 0)
white = value.indexOf('\t');
if (white >= 0) {
StringBuffer sb = new StringBuffer();
int len = value.length();
for (int i = 0; i < len; i++) {
char ch = value.charAt(i);
if ((ch != ' ') && (ch != '\t'))
sb.append(ch);
}
value = sb.toString();
}
// Process each comma-delimited language specification
StringParser parser = new StringParser();
parser.setString(value);
int length = parser.getLength();
while (true) {
// Extract the next comma-delimited entry
int start = parser.getIndex();
if (start >= length)
break;
int end = parser.findChar(',');
String entry = parser.extract(start, end).trim();
parser.advance(); // For the following entry
// Extract the quality factor for this entry
double quality = 1.0;
int semi = entry.indexOf(";q=");
if (semi >= 0) {
try {
quality = Double.parseDouble(entry.substring(semi + 3));
} catch (NumberFormatException e) {
quality = 0.0;
}
entry = entry.substring(0, semi);
}
// Skip entries we are not going to keep track of
if (quality < 0.00005)
continue; // Zero (or effectively zero) quality factors
if ("*".equals(entry))
continue; // FIXME - "*" entries are not handled
// Extract the language and country for this entry
String language = null;
String country = null;
String variant = null;
int dash = entry.indexOf('-');
if (dash < 0) {
language = entry;
country = "";
variant = "";
} else {
language = entry.substring(0, dash);
country = entry.substring(dash + 1);
int vDash = country.indexOf('-');
if (vDash > 0) {
String cTemp = country.substring(0, vDash);
variant = country.substring(vDash + 1);
country = cTemp;
} else {
variant = "";
}
}
// Add a new Locale to the list of Locales for this quality level
Locale locale = new Locale(language, country, variant);
Double key = new Double(-quality); // Reverse the order
ArrayList values = (ArrayList) locales.get(key);
if (values == null) {
values = new ArrayList();
locales.put(key, values);
}
values.add(locale);
}
// Process the quality values in highest->lowest order (due to
// negating the Double value when creating the key)
Iterator keys = locales.keySet().iterator();
while (keys.hasNext()) {
Double key = (Double) keys.next();
ArrayList list = (ArrayList) locales.get(key);
Iterator values = list.iterator();
while (values.hasNext()) {
Locale locale = (Locale) values.next();
addLocale(locale);
}
}
}
}
class Ajp13Principal implements java.security.Principal {
String user;
Ajp13Principal(String user) {
this.user = user;
}
public boolean equals(Object o) {
if (o == null) {
return false;
} else if (!(o instanceof Ajp13Principal)) {
return false;
} else if (o == this) {
return true;
} else if (this.user == null && ((Ajp13Principal)o).user == null) {
return true;
} else if (user != null) {
return user.equals( ((Ajp13Principal)o).user);
} else {
return false;
}
}
public String getName() {
return user;
}
public int hashCode() {
if (user == null) return 0;
else return user.hashCode();
}
public String toString() {
return getName();
}
}