Index: src/com/caucho/quercus/env/ServerArrayValue.java =================================================================== --- src/com/caucho/quercus/env/ServerArrayValue.java (revision 4183) +++ src/com/caucho/quercus/env/ServerArrayValue.java (working copy) @@ -30,17 +30,27 @@ package com.caucho.quercus.env; import com.caucho.quercus.QuercusRequestAdapter; +import com.caucho.util.LruCache; import javax.servlet.http.HttpServletRequest; +import java.net.InetAddress; +import java.net.NetworkInterface; import java.util.Enumeration; import java.util.Map; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Represents the server */ public class ServerArrayValue extends ArrayValueImpl { + private static final Logger log + = Logger.getLogger(ServerArrayValue.class.getName()); + + private static final StringValue SERVER_ADDR_V + = new StringBuilderValue("SERVER_ADDR"); private static final StringValue SERVER_NAME_V = new StringBuilderValue("SERVER_NAME"); private static final StringValue SERVER_PORT_V @@ -75,6 +85,8 @@ = new StringBuilderValue("PATH_INFO"); private static final StringValue PATH_TRANSLATED_V = new StringBuilderValue("PATH_TRANSLATED"); + private static final StringValue PATH_AUTH_USER_V + = new StringBuilderValue("PATH_AUTH_USER_V"); private static final StringValue PHP_SELF_V = new StringBuilderValue("PHP_SELF"); @@ -84,6 +96,11 @@ private static final StringValue HTTP_HOST_V = new StringBuilderValue("HTTP_HOST"); + + private static final + LruCache _hostAddressCache + = new LruCache(200); + private final Env _env; @@ -211,6 +228,112 @@ HttpServletRequest request = _env.getRequest(); if (request != null) { + + // check DNS for server address. We use the first IP that matches one of our interfaces + String hostAddress = _hostAddressCache.get(request.getServerName()); + if (hostAddress == null) + { + InetAddress[] allAddresses = null; + try { + allAddresses = InetAddress.getAllByName(request.getServerName()); + } catch(Exception e) { + log.log(Level.FINE, L.l("failed to resolve hostname '{0}' to an IP address.", request.getServerName()), e); + } + + for (int addrIdx = 0; allAddresses != null && addrIdx < allAddresses.length; addrIdx++) + { + NetworkInterface ni = null; + if (allAddresses[addrIdx] != null) + { + try { + ni = NetworkInterface.getByInetAddress(allAddresses[addrIdx]); + } + catch(Exception e) { + log.log(Level.SEVERE, L.l("failed to read local interface."), e); + } + } // if valid address + + + if (ni != null) { + hostAddress = allAddresses[addrIdx].getHostAddress(); + break; + } + } // for all addresses + + + // if there are no valid addresses get all interfaces and try to use the first one with its IP + if (hostAddress == null) { + + Enumeration niEnum = null; + try {niEnum = NetworkInterface.getNetworkInterfaces();} catch(Exception e) {log.log(Level.SEVERE,e.getMessage(), e);} + if (niEnum != null && niEnum.hasMoreElements()) { + + // try non loopback interfaces first + NetworkInterface ni = niEnum.nextElement(); + boolean isUp = false; + boolean isLoopback = true; + try {isUp = ni.isUp();isLoopback = ni.isLoopback();} catch(Exception e) {log.log(Level.SEVERE,e.getMessage(), e);} + while (niEnum.hasMoreElements() && (isLoopback || !isUp)) { + ni = niEnum.nextElement(); + try {isUp = ni.isUp();isLoopback = ni.isLoopback();} catch(Exception e) {log.log(Level.SEVERE,e.getMessage(), e);} + } + + if (ni != null && !isLoopback && isUp) { + InetAddress niAddress = null; + Enumeration addresses = ni.getInetAddresses(); + if (addresses != null && addresses.hasMoreElements()) { + niAddress = addresses.nextElement(); + } + + if (niAddress != null) + hostAddress = niAddress.getHostAddress(); + } // iff network interface is no loopback and is up + } // iff valid network interface enumeration + + } + + // if there are no valid addresses yet, try all loopback interfaces + if (hostAddress == null) { + Enumeration niEnum = null; + try {niEnum = NetworkInterface.getNetworkInterfaces();} catch(Exception e) {log.log(Level.SEVERE,e.getMessage(), e);} + if (niEnum != null && niEnum.hasMoreElements()) { + // try loopback interfaces first + NetworkInterface ni = niEnum.nextElement(); + boolean isUp = false; + boolean isLoopback = false; + try {isUp = ni.isUp();isLoopback = ni.isLoopback();} catch(Exception e) {log.log(Level.SEVERE,e.getMessage(), e);} + while (niEnum.hasMoreElements() && (!isLoopback || !isUp) ) { + ni = niEnum.nextElement(); + try {isUp = ni.isUp();isLoopback = ni.isLoopback();} catch(Exception e) {log.log(Level.SEVERE,e.getMessage(), e);} + } + + if (ni != null && isLoopback && isUp) { + InetAddress niAddress = null; + Enumeration addresses = ni.getInetAddresses(); + if (addresses != null && addresses.hasMoreElements()) { + niAddress = addresses.nextElement(); + } + + if (niAddress != null) + hostAddress = niAddress.getHostAddress(); + } // iff network interface is loopback + } // iff valid network interface enumeration + } + + + + if (hostAddress != null) // found new host address + _hostAddressCache.put(request.getServerName(), hostAddress); + } // if nost address not in cache + + if (hostAddress != null) { + super.put(SERVER_ADDR_V, + _env.createString(hostAddress)); + } else { + super.put(SERVER_ADDR_V, + _env.createString("127.0.0.1")); // use loop back interface address as default + } + super.put(SERVER_NAME_V, _env.createString(request.getServerName())); @@ -277,6 +400,12 @@ _env.createString(request.getRealPath(pathInfo))); } + String remoteUser = request.getRemoteUser(); + if (remoteUser != null) { + super.put(PATH_AUTH_USER_V, + _env.createString(remoteUser)); + } + if (request.isSecure()) super.put(HTTPS_V, _env.createString("on"));