FileDocCategorySizeDatePackage
CGIProcessEnvironment.javaAPI DocGlassfish v2 API20369Fri May 04 22:32:30 BST 2007org.apache.catalina.util

CGIProcessEnvironment

public class CGIProcessEnvironment extends ProcessEnvironment
Encapsulates the CGI Process' environment and rules to derive that environment from the servlet container and request information.
author
Martin Dengler [root@martindengler.com]
version
$Revision: 1.5 $, $Date: 2007/05/05 05:32:30 $
since
Tomcat 4.0

Fields Summary
private static com.sun.org.apache.commons.logging.Log
log
private Hashtable
queryParameters
cgi command's query parameters
private String
cgiPathPrefix
The CGI search path will start at webAppRootDir + File.separator + cgiPathPrefix (or webAppRootDir alone if cgiPathPrefix is null)
Constructors Summary
public CGIProcessEnvironment(HttpServletRequest req, ServletContext context)
Creates a ProcessEnvironment and derives the necessary environment, working directory, command, etc. The cgi path prefix is initialized to "" (the empty string).

param
req HttpServletRequest for information provided by the Servlet API
param
context ServletContext for information provided by the Servlet API



                                                                                                   
      
          
            this(req, context, "");
    
public CGIProcessEnvironment(HttpServletRequest req, ServletContext context, String cgiPathPrefix)
Creates a ProcessEnvironment and derives the necessary environment, working directory, command, etc.

param
req HttpServletRequest for information provided by the Servlet API
param
context ServletContext for information provided by the Servlet API
param
cgiPathPrefix subdirectory of webAppRootDir below which the web app's CGIs may be stored; can be null or "".

            this(req, context, cgiPathPrefix, 0);
    
public CGIProcessEnvironment(HttpServletRequest req, ServletContext context, int debug)
Creates a ProcessEnvironment and derives the necessary environment, working directory, command, etc.

param
req HttpServletRequest for information provided by the Servlet API
param
context ServletContext for information provided by the Servlet API
param
debug int debug level (0 == none, 6 == lots)

            this(req, context, "", 0);
    
public CGIProcessEnvironment(HttpServletRequest req, ServletContext context, String cgiPathPrefix, int debug)
Creates a ProcessEnvironment and derives the necessary environment, working directory, command, etc.

param
req HttpServletRequest for information provided by the Servlet API
param
context ServletContext for information provided by the Servlet API
param
cgiPathPrefix subdirectory of webAppRootDir below which the web app's CGIs may be stored; can be null or "".
param
debug int debug level (0 == none, 6 == lots)

            super(req, context, debug);
            this.cgiPathPrefix = cgiPathPrefix;
            queryParameters = new Hashtable();
            Enumeration paramNames = req.getParameterNames();
            while (paramNames != null && paramNames.hasMoreElements()) {
                String param = paramNames.nextElement().toString();
                if (param != null) {
                    queryParameters.put(param,
                        URLEncoder.encode(req.getParameter(param)));
                }
            }
            this.valid = deriveProcessEnvironment(req);
    
Methods Summary
protected booleanderiveProcessEnvironment(javax.servlet.http.HttpServletRequest req)
Constructs the CGI environment to be supplied to the invoked CGI script; relies heavliy on Servlet API methods and findCGI

param
HttpServletRequest request associated with the CGI invokation
return
true if environment was set OK, false if there was a problem and no environment was set

        /*
         * This method is slightly ugly; c'est la vie.
         * "You cannot stop [ugliness], you can only hope to contain [it]"
         * (apologies to Marv Albert regarding MJ)
         */

        Hashtable envp;
        super.deriveProcessEnvironment(req);
        envp = getEnvironment();

        String sPathInfoOrig = null;
        String sPathTranslatedOrig = null;
        String sPathInfoCGI = null;
        String sPathTranslatedCGI = null;
        String sCGIFullPath = null;
        String sCGIScriptName = null;
        String sCGIFullName = null;
        String sCGIName = null;
        String[] sCGINames;
        sPathInfoOrig = this.pathInfo;
        sPathInfoOrig = sPathInfoOrig == null ? "" : sPathInfoOrig;
        sPathTranslatedOrig = req.getPathTranslated();
        sPathTranslatedOrig = sPathTranslatedOrig == null ? "" :
            sPathTranslatedOrig;
            sCGINames =
                findCGI(sPathInfoOrig, getWebAppRootDir(), getContextPath(),
                getServletPath(), cgiPathPrefix);
        sCGIFullPath = sCGINames[0];
        sCGIScriptName = sCGINames[1];
        sCGIFullName = sCGINames[2];
        sCGIName = sCGINames[3];
        if (sCGIFullPath == null || sCGIScriptName == null
            || sCGIFullName == null || sCGIName == null) {
                return false;
        }
        envp.put("SERVER_SOFTWARE", "TOMCAT");
        envp.put("SERVER_NAME", nullsToBlanks(req.getServerName()));
        envp.put("GATEWAY_INTERFACE", "CGI/1.1");
        envp.put("SERVER_PROTOCOL", nullsToBlanks(req.getProtocol()));
        int port = req.getServerPort();
        Integer iPort = (port == 0 ? Integer.valueOf(-1) : Integer.valueOf(port));
        envp.put("SERVER_PORT", iPort.toString());
        envp.put("REQUEST_METHOD", nullsToBlanks(req.getMethod()));

        /*-
        * PATH_INFO should be determined by using sCGIFullName:
        * 1) Let sCGIFullName not end in a "/" (see method findCGI)
        * 2) Let sCGIFullName equal the pathInfo fragment which
        *    corresponds to the actual cgi script.
        * 3) Thus, PATH_INFO = request.getPathInfo().substring(
        *                      sCGIFullName.length())
        *
        * (see method findCGI, where the real work is done)
        *
        */

        if (pathInfo == null ||
            (pathInfo.substring(sCGIFullName.length()).length() <= 0)) {
                sPathInfoCGI = "";
        } else {
            sPathInfoCGI = pathInfo.substring(sCGIFullName.length());
        }
        envp.put("PATH_INFO", sPathInfoCGI);

        /*-
        * PATH_TRANSLATED must be determined after PATH_INFO (and the
        * implied real cgi-script) has been taken into account.
        *
        * The following example demonstrates:
        *
        * servlet info   = /servlet/cgigw/dir1/dir2/cgi1/trans1/trans2
        * cgifullpath    = /servlet/cgigw/dir1/dir2/cgi1
        * path_info      = /trans1/trans2
        * webAppRootDir  = servletContext.getRealPath("/")
        *
        * path_translated = servletContext.getRealPath("/trans1/trans2")
        *
        * That is, PATH_TRANSLATED = webAppRootDir + sPathInfoCGI
        * (unless sPathInfoCGI is null or blank, then the CGI
        * specification dictates that the PATH_TRANSLATED metavariable
        * SHOULD NOT be defined.
        *
        */

        if (sPathInfoCGI != null && !("".equals(sPathInfoCGI))) {
            sPathTranslatedCGI = getContext().getRealPath(sPathInfoCGI);
        } else {
            sPathTranslatedCGI = null;
        }
        if (sPathTranslatedCGI == null || "".equals(sPathTranslatedCGI)) {
            //NOOP
        } else {
            envp.put("PATH_TRANSLATED", nullsToBlanks(sPathTranslatedCGI));
        }
        envp.put("SCRIPT_NAME", nullsToBlanks(sCGIScriptName));
        envp.put("QUERY_STRING", nullsToBlanks(req.getQueryString()));
        envp.put("REMOTE_HOST", nullsToBlanks(req.getRemoteHost()));
        envp.put("REMOTE_ADDR", nullsToBlanks(req.getRemoteAddr()));
        envp.put("AUTH_TYPE", nullsToBlanks(req.getAuthType()));
        envp.put("REMOTE_USER", nullsToBlanks(req.getRemoteUser()));
        envp.put("REMOTE_IDENT", ""); //not necessary for full compliance
        envp.put("CONTENT_TYPE", nullsToBlanks(req.getContentType()));

        /* Note CGI spec says CONTENT_LENGTH must be NULL ("") or undefined
        * if there is no content, so we cannot put 0 or -1 in as per the
        * Servlet API spec.
        */

        int contentLength = req.getContentLength();
        String sContentLength = (contentLength <= 0 ? "" : (Integer.valueOf(contentLength)).toString());
        envp.put("CONTENT_LENGTH", sContentLength);
        Enumeration headers = req.getHeaderNames();
        String header = null;
        while (headers.hasMoreElements()) {
            header = null;
            header = ((String)headers.nextElement()).toUpperCase();
            //REMIND: rewrite multiple headers as if received as single
            //REMIND: change character set
            //REMIND: I forgot what the previous REMIND means
            if ("AUTHORIZATION".equalsIgnoreCase(header)
                || "PROXY_AUTHORIZATION".equalsIgnoreCase(header)) {
                    //NOOP per CGI specification section 11.2
            } else if ("HOST".equalsIgnoreCase(header)) {
                String host = req.getHeader(header);
                envp.put("HTTP_" + header.replace('-", '_"),
                    host.substring(0, host.indexOf(":")));
            } else {
                envp.put("HTTP_" + header.replace('-", '_"),
                    req.getHeader(header));
            }
        }
        command = sCGIFullPath;
        workingDirectory = new File(command.substring(0,
            command.lastIndexOf(File.separator)));
        envp.put("X_TOMCAT_COMMAND_PATH", command); //for kicks
        this.setEnvironment(envp);
        return true;
    
protected java.lang.String[]findCGI(java.lang.String pathInfo, java.lang.String webAppRootDir, java.lang.String contextPath, java.lang.String servletPath, java.lang.String cgiPathPrefix)
Resolves core information about the cgi script.

Example URI:

 /servlet/cgigateway/dir1/realCGIscript/pathinfo1 
  • path = $CATALINA_HOME/mywebapp/dir1/realCGIscript
  • scriptName = /servlet/cgigateway/dir1/realCGIscript
  • cgiName = /dir1/realCGIscript
  • name = realCGIscript

CGI search algorithm: search the real path below <my-webapp-root> and find the first non-directory in the getPathTranslated("/"), reading/searching from left-to-right.

The CGI search path will start at webAppRootDir + File.separator + cgiPathPrefix (or webAppRootDir alone if cgiPathPrefix is null).

cgiPathPrefix is usually set by the calling servlet to the servlet's cgiPathPrefix init parameter

param
pathInfo String from HttpServletRequest.getPathInfo()
param
webAppRootDir String from context.getRealPath("/")
param
contextPath String as from HttpServletRequest.getContextPath()
param
servletPath String as from HttpServletRequest.getServletPath()
param
cgiPathPrefix subdirectory of webAppRootDir below which the web app's CGIs may be stored; can be null.
return
  • path - full file-system path to valid cgi script, or null if no cgi was found
  • scriptName - CGI variable SCRIPT_NAME; the full URL path to valid cgi script or null if no cgi was found
  • cgiName - servlet pathInfo fragment corresponding to the cgi script itself, or null if not found
  • name - simple name (no directories) of the cgi script, or null if no cgi was found
author
Martin Dengler [root@martindengler.com]
since
Tomcat 4.0

            String path = null;
            String name = null;
            String scriptname = null;
            String cginame = null;
            if ((webAppRootDir != null)
                && (webAppRootDir.lastIndexOf("/")
                == (webAppRootDir.length() - 1))) {
                    //strip the trailing "/" from the webAppRootDir
                    webAppRootDir =
                        webAppRootDir.substring(0,
                        (webAppRootDir.length() - 1));
            }
            if (cgiPathPrefix != null) {
                webAppRootDir = webAppRootDir + File.separator
                    + cgiPathPrefix;
            }
            if (debug >= 2) {
                log("findCGI: start = [" + webAppRootDir
                    + "], pathInfo = [" + pathInfo + "] ");
            }
            File currentLocation = new File(webAppRootDir);
            StringTokenizer dirWalker = new StringTokenizer(pathInfo, "/");
            while (!currentLocation.isFile() && dirWalker.hasMoreElements()) {
                currentLocation = new
                    File(currentLocation, (String) dirWalker.nextElement());
                if (debug >= 3) {
                    log("findCGI: traversing to [" + currentLocation + "]");
                }
            }
            if (!currentLocation.isFile()) {
                return new String[] { null, null, null, null };
            } else {
                if (debug >= 2) {
                    log("findCGI: FOUND cgi at [" + currentLocation + "]");
                }
                path = currentLocation.getAbsolutePath();
                name = currentLocation.getName();
                cginame = currentLocation.getParent()
                    .substring(webAppRootDir.length())
                    + File.separator + name;
                    if (".".equals(contextPath)) {
                        scriptname = servletPath + cginame;
                } else {
                    scriptname = contextPath + servletPath + cginame;
                }
            }
            if (debug >= 1) {
                log("findCGI calc: name=" + name + ", path=" + path
                    + ", scriptname=" + scriptname + ", cginame=" + cginame);
            }
            return new String[] { path, scriptname, cginame, name };
    
public java.util.HashtablegetParameters()
Gets process' derived query parameters

return
process' query parameters

        return queryParameters;
    
public java.lang.StringtoString()
Print important CGI environment information in an easy-to-read HTML table

return
HTML string containing CGI environment info

        StringBuffer sb = new StringBuffer();
        sb.append("<TABLE border=2>");
        sb.append("<tr><th colspan=2 bgcolor=grey>");
        sb.append("ProcessEnvironment Info</th></tr>");
        sb.append("<tr><td>Debug Level</td><td>");
        sb.append(debug);
        sb.append("</td></tr>");
        sb.append("<tr><td>Validity:</td><td>");
        sb.append(isValid());
        sb.append("</td></tr>");
        if (isValid()) {
            Enumeration envk = env.keys();
            while (envk.hasMoreElements()) {
                String s = (String)envk.nextElement();
                sb.append("<tr><td>");
                sb.append(s);
                sb.append("</td><td>");
                sb.append(blanksToString((String)env.get(s),
                    "[will be set to blank]"));
                    sb.append("</td></tr>");
            }
        }
        sb.append("<tr><td colspan=2><HR></td></tr>");
        sb.append("<tr><td>Derived Command</td><td>");
        sb.append(nullsToBlanks(command));
        sb.append("</td></tr>");
        sb.append("<tr><td>Working Directory</td><td>");
        if (workingDirectory != null) {
            sb.append(workingDirectory.toString());
        }
        sb.append("</td></tr>");
        sb.append("<tr><td colspan=2>Query Params</td></tr>");
        Enumeration paramk = queryParameters.keys();
        while (paramk.hasMoreElements()) {
            String s = paramk.nextElement().toString();
            sb.append("<tr><td>");
            sb.append(s);
            sb.append("</td><td>");
            sb.append(queryParameters.get(s).toString());
            sb.append("</td></tr>");
        }

        sb.append("</TABLE><p>end.");
        return sb.toString();