Source Code Cross Referenced for CGIServlet.java in  » Web-Server » Rimfaxe-Web-Server » org » apache » catalina » servlets » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Rimfaxe Web Server » org.apache.catalina.servlets 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * CGIServlet.java $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/CGIServlet.java,v 1.7 2001/09/20 23:48:13 remm Exp $
0003:         * $Revision: 1.7 $, $Date: 2001/09/20 23:48:13 $
0004:         *
0005:         * ====================================================================
0006:         *
0007:         * The Apache Software License, Version 1.1
0008:         *
0009:         * Copyright (c) 1999 The Apache Software Foundation.  All rights
0010:         * reserved.
0011:         *
0012:         * Redistribution and use in source and binary forms, with or without
0013:         * modification, are permitted provided that the following conditions
0014:         * are met:
0015:         *
0016:         * 1. Redistributions of source code must retain the above copyright
0017:         *    notice, this list of conditions and the following disclaimer.
0018:         *
0019:         * 2. Redistributions in binary form must reproduce the above copyright
0020:         *    notice, this list of conditions and the following disclaimer in
0021:         *    the documentation and/or other materials provided with the
0022:         *    distribution.
0023:         *
0024:         * 3. The end-user documentation included with the redistribution, if
0025:         *    any, must include the following acknowlegement:
0026:         *       "This product includes software developed by the
0027:         *        Apache Software Foundation (http://www.apache.org/)."
0028:         *    Alternately, this acknowlegement may appear in the software itself,
0029:         *    if and wherever such third-party acknowlegements normally appear.
0030:         *
0031:         * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
0032:         *    Foundation" must not be used to endorse or promote products derived
0033:         *    from this software without prior written permission. For written
0034:         *    permission, please contact apache@apache.org.
0035:         *
0036:         * 5. Products derived from this software may not be called "Apache"
0037:         *    nor may "Apache" appear in their names without prior written
0038:         *    permission of the Apache Group.
0039:         *
0040:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0041:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0042:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0043:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0044:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0045:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0046:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0047:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0048:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0049:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0050:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0051:         * SUCH DAMAGE.
0052:         * ====================================================================
0053:         *
0054:         * This software consists of voluntary contributions made by many
0055:         * individuals on behalf of the Apache Software Foundation.  For more
0056:         * information on the Apache Software Foundation, please see
0057:         * <http://www.apache.org/>.
0058:         *
0059:         *
0060:         */
0061:
0062:        package org.apache.catalina.servlets;
0063:
0064:        import java.lang.Process;
0065:        import java.io.File;
0066:        import java.io.Writer;
0067:        import java.io.Reader;
0068:        import java.io.PrintWriter;
0069:        import java.io.BufferedWriter;
0070:        import java.io.BufferedReader;
0071:        import java.io.InputStream;
0072:        import java.io.OutputStream;
0073:        import java.io.InputStreamReader;
0074:        import java.io.OutputStreamWriter;
0075:        import java.io.BufferedInputStream;
0076:        import java.io.BufferedOutputStream;
0077:        import java.io.IOException;
0078:        import java.net.URLEncoder;
0079:        import java.util.Hashtable;
0080:        import java.util.Vector;
0081:        import java.util.Enumeration;
0082:        import java.util.StringTokenizer;
0083:        import java.util.Locale;
0084:        import java.util.Date;
0085:        import javax.servlet.ServletException;
0086:        import javax.servlet.ServletOutputStream;
0087:        import javax.servlet.ServletContext;
0088:        import javax.servlet.ServletConfig;
0089:        import javax.servlet.UnavailableException;
0090:        import javax.servlet.http.HttpServlet;
0091:        import javax.servlet.http.HttpServletRequest;
0092:        import javax.servlet.http.HttpServletResponse;
0093:        import javax.servlet.http.HttpSession;
0094:        import javax.servlet.http.Cookie;
0095:        import org.apache.catalina.Context;
0096:        import org.apache.catalina.Globals;
0097:        import org.apache.catalina.Wrapper;
0098:
0099:        // import org.apache.catalina.util.StringManager;
0100:
0101:        /**
0102:         *  CGI-invoking servlet for web applications, used to execute scripts which
0103:         *  comply to the Common Gateway Interface (CGI) specification and are named
0104:         *  in the path-info used to invoke this servlet.
0105:         *
0106:         * <p>
0107:         * <i>Note: This code compiles and even works for simple CGI cases.
0108:         *          Exhaustive testing has not been done.  Please consider it beta
0109:         *          quality.  Feedback is appreciated to the author (see below).</i>
0110:         * </p>
0111:         * <p>
0112:         *
0113:         * <b>Example</b>:<br>
0114:         * If an instance of this servlet was mapped (using
0115:         *       <code>&lt;web-app&gt;/WEB-INF/web.xml</code>) to:
0116:         * </p>
0117:         * <p>
0118:         * <code>
0119:         * &lt;web-app&gt;/cgi-bin/*
0120:         * </code>
0121:         * </p>
0122:         * <p>
0123:         * then the following request:
0124:         * </p>
0125:         * <p>
0126:         * <code>
0127:         * http://localhost:8080/&lt;web-app&gt;/cgi-bin/dir1/script/pathinfo1
0128:         * </code>
0129:         * </p>
0130:         * <p>
0131:         * would result in the execution of the script
0132:         * </p>
0133:         * <p>
0134:         * <code>
0135:         * &lt;web-app-root&gt;/WEB-INF/cgi/dir1/script
0136:         * </code>
0137:         * </p>
0138:         * <p>
0139:         * with the script's <code>PATH_INFO</code> set to <code>/pathinfo1</code>.
0140:         * </p>
0141:         * <p>
0142:         * Recommendation:  House all your CGI scripts under
0143:         * <code>&lt;webapp&gt;/WEB-INF/cgi</code>.  This will ensure that you do not
0144:         * accidentally expose your cgi scripts' code to the outside world and that
0145:         * your cgis will be cleanly ensconced underneath the WEB-INF (i.e.,
0146:         * non-content) area.
0147:         * </p>
0148:         * <p>
0149:         * The default CGI location is mentioned above.  You have the flexibility to
0150:         * put CGIs wherever you want, however:
0151:         * </p>
0152:         * <p>
0153:         *   The CGI search path will start at
0154:         *   webAppRootDir + File.separator + cgiPathPrefix
0155:         *   (or webAppRootDir alone if cgiPathPrefix is
0156:         *   null).
0157:         * </p>
0158:         * <p>
0159:         *   cgiPathPrefix is defined by setting
0160:         *   this servlet's cgiPathPrefix init parameter
0161:         * </p>
0162:         *
0163:         * <p>
0164:         *
0165:         * <B>CGI Specification</B>:<br> derived from
0166:         * <a href="http://cgi-spec.golux.com">http://cgi-spec.golux.com</a>.
0167:         * A work-in-progress & expired Internet Draft.  Note no actual RFC describing
0168:         * the CGI specification exists.  Where the behavior of this servlet differs
0169:         * from the specification cited above, it is either documented here, a bug,
0170:         * or an instance where the specification cited differs from Best
0171:         * Community Practice (BCP).
0172:         * Such instances should be well-documented here.  Please email the
0173:         * <a href="mailto:tomcat-dev@jakarta.apache.org">Jakarta Tomcat group [tomcat-dev@jakarta.apache.org]</a>
0174:         * with amendments.
0175:         *
0176:         * </p>
0177:         * <p>
0178:         *
0179:         * <b>Canonical metavariables</b>:<br>
0180:         * The CGI specification defines the following canonical metavariables:
0181:         * <br>
0182:         * [excerpt from CGI specification]
0183:         * <PRE>
0184:         *  AUTH_TYPE
0185:         *  CONTENT_LENGTH
0186:         *  CONTENT_TYPE
0187:         *  GATEWAY_INTERFACE
0188:         *  PATH_INFO
0189:         *  PATH_TRANSLATED
0190:         *  QUERY_STRING
0191:         *  REMOTE_ADDR
0192:         *  REMOTE_HOST
0193:         *  REMOTE_IDENT
0194:         *  REMOTE_USER
0195:         *  REQUEST_METHOD
0196:         *  SCRIPT_NAME
0197:         *  SERVER_NAME
0198:         *  SERVER_PORT
0199:         *  SERVER_PROTOCOL
0200:         *  SERVER_SOFTWARE
0201:         * </PRE>
0202:         * <p>
0203:         * Metavariables with names beginning with the protocol name (<EM>e.g.</EM>,
0204:         * "HTTP_ACCEPT") are also canonical in their description of request header
0205:         * fields.  The number and meaning of these fields may change independently
0206:         * of this specification.  (See also section 6.1.5 [of the CGI specification].)
0207:         * </p>
0208:         * [end excerpt]
0209:         *
0210:         * </p>
0211:         * <h2> Implementation notes</h2>
0212:         * <p>
0213:         *
0214:         * <b>standard input handling</b>: If your script accepts standard input,
0215:         * then the client must start sending input within a certain timeout period,
0216:         * otherwise the servlet will assume no input is coming and carry on running
0217:         * the script.  The script's the standard input will be closed and handling of
0218:         * any further input from the client is undefined.  Most likely it will be
0219:         * ignored.  If this behavior becomes undesirable, then this servlet needs
0220:         * to be enhanced to handle threading of the spawned process' stdin, stdout,
0221:         * and stderr (which should not be too hard).
0222:         * <br>
0223:         * If you find your cgi scripts are timing out receiving input, you can set
0224:         * the init parameter <code></code> of your webapps' cgi-handling servlet
0225:         * to be
0226:         * </p>
0227:         * <p>
0228:         *
0229:         * <b>Metavariable Values</b>: According to the CGI specificion,
0230:         * implementations may choose to represent both null or missing values in an
0231:         * implementation-specific manner, but must define that manner.  This
0232:         * implementation chooses to always define all required metavariables, but
0233:         * set the value to "" for all metavariables whose value is either null or
0234:         * undefined.  PATH_TRANSLATED is the sole exception to this rule, as per the
0235:         * CGI Specification.
0236:         *
0237:         * </p>
0238:         * <p>
0239:         *
0240:         * <b>NPH --  Non-parsed-header implementation</b>:  This implementation does
0241:         * not support the CGI NPH concept, whereby server ensures that the data
0242:         * supplied to the script are preceisely as supplied by the client and
0243:         * unaltered by the server.
0244:         * </p>
0245:         * <p>
0246:         * The function of a servlet container (including Tomcat) is specifically
0247:         * designed to parse and possible alter CGI-specific variables, and as
0248:         * such makes NPH functionality difficult to support.
0249:         * </p>
0250:         * <p>
0251:         * The CGI specification states that compliant servers MAY support NPH output.
0252:         * It does not state servers MUST support NPH output to be unconditionally
0253:         * compliant.  Thus, this implementation maintains unconditional compliance
0254:         * with the specification though NPH support is not present.
0255:         * </p>
0256:         * <p>
0257:         *
0258:         * The CGI specification is located at
0259:         * <a href="http://cgi-spec.golux.com">http://cgi-spec.golux.com</a>.
0260:         *
0261:         * </p>
0262:         * <p>
0263:         * <h3>TODO:</h3>
0264:         * <ul>
0265:         * <li> Support for setting headers (for example, Location headers don't work)
0266:         * <li> Support for collapsing multiple header lines (per RFC 2616)
0267:         * <li> Ensure handling of POST method does not interfere with 2.3 Filters
0268:         * <li> Refactor some debug code out of core
0269:         * <li> Ensure header handling preserves encoding
0270:         * <li> Possibly rewrite CGIRunner.run()?
0271:         * <li> Possibly refactor CGIRunner and CGIEnvironment as non-inner classes?
0272:         * <li> Document handling of cgi stdin when there is no stdin
0273:         * <li> Revisit IOException handling in CGIRunner.run()
0274:         * <li> Better documentation
0275:         * <li> Confirm use of ServletInputStream.available() in CGIRunner.run() is
0276:         *      not needed
0277:         * <li> Make checking for "." and ".." in servlet & cgi PATH_INFO less
0278:         *      draconian
0279:         * <li> [add more to this TODO list]
0280:         * </ul>
0281:         * </p>
0282:         *
0283:         * @author Martin T Dengler [root@martindengler.com]
0284:         * @author Amy Roh
0285:         * @version $Revision: 1.7 $, $Date: 2001/09/20 23:48:13 $
0286:         * @since Tomcat 4.0
0287:         *
0288:         */
0289:
0290:        public class CGIServlet extends HttpServlet {
0291:
0292:            /* some vars below copied from Craig R. McClanahan's InvokerServlet */
0293:
0294:            /** the string manager for this package. */
0295:            /* YAGNI
0296:            private static StringManager sm =
0297:                StringManager.getManager(Constants.Package);
0298:             */
0299:
0300:            /** the Context container associated with our web application. */
0301:            private ServletContext context = null;
0302:
0303:            /** the debugging detail level for this servlet. */
0304:            private int debug = 0;
0305:
0306:            /** the time in ms to wait for the client to send us CGI input data */
0307:            private int iClientInputTimeout = 100;
0308:
0309:            /**
0310:             *  The CGI search path will start at
0311:             *    webAppRootDir + File.separator + cgiPathPrefix
0312:             *    (or webAppRootDir alone if cgiPathPrefix is
0313:             *    null)
0314:             */
0315:            private String cgiPathPrefix = null;
0316:
0317:            /**
0318:             * Sets instance variables.
0319:             * <P>
0320:             * Modified from Craig R. McClanahan's InvokerServlet
0321:             * </P>
0322:             *
0323:             * @param config                    a <code>ServletConfig</code> object
0324:             *                                  containing the servlet's
0325:             *                                  configuration and initialization
0326:             *                                  parameters
0327:             *
0328:             * @exception ServletException      if an exception has occurred that
0329:             *                                  interferes with the servlet's normal
0330:             *                                  operation
0331:             */
0332:            public void init(ServletConfig config) throws ServletException {
0333:
0334:                super .init(config);
0335:
0336:                // Verify that we were not accessed using the invoker servlet
0337:                String servletName = getServletConfig().getServletName();
0338:                if (servletName == null)
0339:                    servletName = "";
0340:                if (servletName.startsWith("org.apache.catalina.INVOKER."))
0341:                    throw new UnavailableException(
0342:                            "Cannot invoke CGIServlet through the invoker");
0343:
0344:                // Set our properties from the initialization parameters
0345:                String value = null;
0346:                try {
0347:                    value = getServletConfig().getInitParameter("debug");
0348:                    debug = Integer.parseInt(value);
0349:                    cgiPathPrefix = getServletConfig().getInitParameter(
0350:                            "cgiPathPrefix");
0351:                    value = getServletConfig().getInitParameter(
0352:                            "iClientInputTimeout");
0353:                    iClientInputTimeout = Integer.parseInt(value);
0354:                } catch (Throwable t) {
0355:                    //NOOP
0356:                }
0357:                log("init: loglevel set to " + debug);
0358:
0359:                // Identify the internal container resources we need
0360:                //Wrapper wrapper = (Wrapper) getServletConfig();
0361:                //context = (Context) wrapper.getParent();
0362:
0363:                context = config.getServletContext();
0364:                if (debug >= 1) {
0365:                    //log("init: Associated with Context '" + context.getPath() + "'");
0366:                }
0367:
0368:            }
0369:
0370:            /**
0371:             * Prints out important Servlet API and container information
0372:             *
0373:             * <p>
0374:             * Copied from SnoopAllServlet by Craig R. McClanahan
0375:             * </p>
0376:             *
0377:             * @param  out    ServletOutputStream as target of the information
0378:             * @param  req    HttpServletRequest object used as source of information
0379:             * @param  res    HttpServletResponse object currently not used but could
0380:             *                provide future information
0381:             *
0382:             * @exception  IOException  if a write operation exception occurs
0383:             *
0384:             */
0385:            protected void printServletEnvironment(ServletOutputStream out,
0386:                    HttpServletRequest req, HttpServletResponse res)
0387:                    throws IOException {
0388:
0389:                // Document the properties from ServletRequest
0390:                out.println("<h1>ServletRequest Properties</h1>");
0391:                out.println("<ul>");
0392:                Enumeration attrs = req.getAttributeNames();
0393:                while (attrs.hasMoreElements()) {
0394:                    String attr = (String) attrs.nextElement();
0395:                    out.println("<li><b>attribute</b> " + attr + " = "
0396:                            + req.getAttribute(attr));
0397:                }
0398:                out.println("<li><b>characterEncoding</b> = "
0399:                        + req.getCharacterEncoding());
0400:                out.println("<li><b>contentLength</b> = "
0401:                        + req.getContentLength());
0402:                out.println("<li><b>contentType</b> = " + req.getContentType());
0403:                Enumeration locales = req.getLocales();
0404:                while (locales.hasMoreElements()) {
0405:                    Locale locale = (Locale) locales.nextElement();
0406:                    out.println("<li><b>locale</b> = " + locale);
0407:                }
0408:                Enumeration params = req.getParameterNames();
0409:                while (params.hasMoreElements()) {
0410:                    String param = (String) params.nextElement();
0411:                    String values[] = req.getParameterValues(param);
0412:                    for (int i = 0; i < values.length; i++)
0413:                        out.println("<li><b>parameter</b> " + param + " = "
0414:                                + values[i]);
0415:                }
0416:                out.println("<li><b>protocol</b> = " + req.getProtocol());
0417:                out.println("<li><b>remoteAddr</b> = " + req.getRemoteAddr());
0418:                out.println("<li><b>remoteHost</b> = " + req.getRemoteHost());
0419:                out.println("<li><b>scheme</b> = " + req.getScheme());
0420:                out.println("<li><b>secure</b> = " + req.isSecure());
0421:                out.println("<li><b>serverName</b> = " + req.getServerName());
0422:                out.println("<li><b>serverPort</b> = " + req.getServerPort());
0423:                out.println("</ul>");
0424:                out.println("<hr>");
0425:
0426:                // Document the properties from HttpServletRequest
0427:                out.println("<h1>HttpServletRequest Properties</h1>");
0428:                out.println("<ul>");
0429:                out.println("<li><b>authType</b> = " + req.getAuthType());
0430:                out.println("<li><b>contextPath</b> = " + req.getContextPath());
0431:                Cookie cookies[] = req.getCookies();
0432:                if (cookies != null) {
0433:                    for (int i = 0; i < cookies.length; i++)
0434:                        out.println("<li><b>cookie</b> " + cookies[i].getName()
0435:                                + " = " + cookies[i].getValue());
0436:                }
0437:                Enumeration headers = req.getHeaderNames();
0438:                while (headers.hasMoreElements()) {
0439:                    String header = (String) headers.nextElement();
0440:                    out.println("<li><b>header</b> " + header + " = "
0441:                            + req.getHeader(header));
0442:                }
0443:                out.println("<li><b>method</b> = " + req.getMethod());
0444:                out.println("<li><a name=\"pathInfo\"><b>pathInfo</b></a> = "
0445:                        + req.getPathInfo());
0446:                out.println("<li><b>pathTranslated</b> = "
0447:                        + req.getPathTranslated());
0448:                out.println("<li><b>queryString</b> = " + req.getQueryString());
0449:                out.println("<li><b>remoteUser</b> = " + req.getRemoteUser());
0450:                out.println("<li><b>requestedSessionId</b> = "
0451:                        + req.getRequestedSessionId());
0452:                out.println("<li><b>requestedSessionIdFromCookie</b> = "
0453:                        + req.isRequestedSessionIdFromCookie());
0454:                out.println("<li><b>requestedSessionIdFromURL</b> = "
0455:                        + req.isRequestedSessionIdFromURL());
0456:                out.println("<li><b>requestedSessionIdValid</b> = "
0457:                        + req.isRequestedSessionIdValid());
0458:                out.println("<li><b>requestURI</b> = " + req.getRequestURI());
0459:                out.println("<li><b>servletPath</b> = " + req.getServletPath());
0460:                out.println("<li><b>userPrincipal</b> = "
0461:                        + req.getUserPrincipal());
0462:                out.println("</ul>");
0463:                out.println("<hr>");
0464:
0465:                // Document the servlet request attributes
0466:                out.println("<h1>ServletRequest Attributes</h1>");
0467:                out.println("<ul>");
0468:                attrs = req.getAttributeNames();
0469:                while (attrs.hasMoreElements()) {
0470:                    String attr = (String) attrs.nextElement();
0471:                    out.println("<li><b>" + attr + "</b> = "
0472:                            + req.getAttribute(attr));
0473:                }
0474:                out.println("</ul>");
0475:                out.println("<hr>");
0476:
0477:                // Process the current session (if there is one)
0478:                HttpSession session = req.getSession(false);
0479:                if (session != null) {
0480:
0481:                    // Document the session properties
0482:                    out.println("<h1>HttpSession Properties</h1>");
0483:                    out.println("<ul>");
0484:                    out.println("<li><b>id</b> = " + session.getId());
0485:                    out.println("<li><b>creationTime</b> = "
0486:                            + new Date(session.getCreationTime()));
0487:                    out.println("<li><b>lastAccessedTime</b> = "
0488:                            + new Date(session.getLastAccessedTime()));
0489:                    out.println("<li><b>maxInactiveInterval</b> = "
0490:                            + session.getMaxInactiveInterval());
0491:                    out.println("</ul>");
0492:                    out.println("<hr>");
0493:
0494:                    // Document the session attributes
0495:                    out.println("<h1>HttpSession Attributes</h1>");
0496:                    out.println("<ul>");
0497:                    attrs = session.getAttributeNames();
0498:                    while (attrs.hasMoreElements()) {
0499:                        String attr = (String) attrs.nextElement();
0500:                        out.println("<li><b>" + attr + "</b> = "
0501:                                + session.getAttribute(attr));
0502:                    }
0503:                    out.println("</ul>");
0504:                    out.println("<hr>");
0505:
0506:                }
0507:
0508:                // Document the servlet configuration properties
0509:                out.println("<h1>ServletConfig Properties</h1>");
0510:                out.println("<ul>");
0511:                out.println("<li><b>servletName</b> = "
0512:                        + getServletConfig().getServletName());
0513:                out.println("</ul>");
0514:                out.println("<hr>");
0515:
0516:                // Document the servlet configuration initialization parameters
0517:                out.println("<h1>ServletConfig Initialization Parameters</h1>");
0518:                out.println("<ul>");
0519:                params = getServletConfig().getInitParameterNames();
0520:                while (params.hasMoreElements()) {
0521:                    String param = (String) params.nextElement();
0522:                    String value = getServletConfig().getInitParameter(param);
0523:                    out.println("<li><b>" + param + "</b> = " + value);
0524:                }
0525:                out.println("</ul>");
0526:                out.println("<hr>");
0527:
0528:                // Document the servlet context properties
0529:                out.println("<h1>ServletContext Properties</h1>");
0530:                out.println("<ul>");
0531:                out.println("<li><b>majorVersion</b> = "
0532:                        + getServletContext().getMajorVersion());
0533:                out.println("<li><b>minorVersion</b> = "
0534:                        + getServletContext().getMinorVersion());
0535:                out.println("<li><b>realPath('/')</b> = "
0536:                        + getServletContext().getRealPath("/"));
0537:                out.println("<li><b>serverInfo</b> = "
0538:                        + getServletContext().getServerInfo());
0539:                out.println("</ul>");
0540:                out.println("<hr>");
0541:
0542:                // Document the servlet context initialization parameters
0543:                out
0544:                        .println("<h1>ServletContext Initialization Parameters</h1>");
0545:                out.println("<ul>");
0546:                params = getServletContext().getInitParameterNames();
0547:                while (params.hasMoreElements()) {
0548:                    String param = (String) params.nextElement();
0549:                    String value = getServletContext().getInitParameter(param);
0550:                    out.println("<li><b>" + param + "</b> = " + value);
0551:                }
0552:                out.println("</ul>");
0553:                out.println("<hr>");
0554:
0555:                // Document the servlet context attributes
0556:                out.println("<h1>ServletContext Attributes</h1>");
0557:                out.println("<ul>");
0558:                attrs = getServletContext().getAttributeNames();
0559:                while (attrs.hasMoreElements()) {
0560:                    String attr = (String) attrs.nextElement();
0561:                    out.println("<li><b>" + attr + "</b> = "
0562:                            + getServletContext().getAttribute(attr));
0563:                }
0564:                out.println("</ul>");
0565:                out.println("<hr>");
0566:
0567:            }
0568:
0569:            /**
0570:             * Provides CGI Gateway service -- delegates to <code>doGet</code>
0571:             *
0572:             * @param  req   HttpServletRequest passed in by servlet container
0573:             * @param  res   HttpServletResponse passed in by servlet container
0574:             *
0575:             * @exception  ServletException  if a servlet-specific exception occurs
0576:             * @exception  IOException  if a read/write exception occurs
0577:             *
0578:             * @see javax.servlet.http.HttpServlet
0579:             *
0580:             */
0581:            protected void doPost(HttpServletRequest req,
0582:                    HttpServletResponse res) throws IOException,
0583:                    ServletException {
0584:                doGet(req, res);
0585:            }
0586:
0587:            /**
0588:             * Provides CGI Gateway service
0589:             *
0590:             * @param  req   HttpServletRequest passed in by servlet container
0591:             * @param  res   HttpServletResponse passed in by servlet container
0592:             *
0593:             * @exception  ServletException  if a servlet-specific exception occurs
0594:             * @exception  IOException  if a read/write exception occurs
0595:             *
0596:             * @see javax.servlet.http.HttpServlet
0597:             *
0598:             */
0599:            protected void doGet(HttpServletRequest req, HttpServletResponse res)
0600:                    throws ServletException, IOException {
0601:
0602:                // Verify that we were not accessed using the invoker servlet
0603:                if (req.getAttribute(Globals.INVOKED_ATTR) != null)
0604:                    throw new UnavailableException(
0605:                            "Cannot invoke CGIServlet through the invoker");
0606:
0607:                CGIEnvironment cgiEnv = new CGIEnvironment(req,
0608:                        getServletContext());
0609:
0610:                if (cgiEnv.isValid()) {
0611:                    CGIRunner cgi = new CGIRunner(cgiEnv.getCommand(), cgiEnv
0612:                            .getEnvironment(), cgiEnv.getWorkingDirectory(),
0613:                            cgiEnv.getParameters());
0614:                    //if POST, we need to cgi.setInput
0615:                    //REMIND: how does this interact with Servlet API 2.3's Filters?!
0616:                    if ("POST".equals(req.getMethod())) {
0617:                        cgi.setInput(req.getInputStream());
0618:                    }
0619:                    cgi.setResponse(res);
0620:                    cgi.run();
0621:                }
0622:
0623:                //REMIND: change to debug method or something
0624:                if ((req.getParameter("X_TOMCAT_CGI_DEBUG") != null)
0625:                        || (!cgiEnv.isValid())) {
0626:                    try {
0627:                        ServletOutputStream out = res.getOutputStream();
0628:                        out
0629:                                .println("<HTML><HEAD><TITLE>$Name:  $</TITLE></HEAD>");
0630:                        out
0631:                                .println("<BODY>$Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/CGIServlet.java,v 1.7 2001/09/20 23:48:13 remm Exp $<p>");
0632:
0633:                        if (cgiEnv.isValid()) {
0634:                            out.println(cgiEnv.toString());
0635:                        } else {
0636:                            res.setStatus(404);
0637:                            out.println("<H3>");
0638:                            out
0639:                                    .println("CGI script not found or not specified.");
0640:                            out.println("</H3>");
0641:                            out.println("<H4>");
0642:                            out.println("Check the <b>HttpServletRequest ");
0643:                            out
0644:                                    .println("<a href=\"#pathInfo\">pathInfo</a></b> ");
0645:                            out
0646:                                    .println("property to see if it is what you meant ");
0647:                            out
0648:                                    .println("it to be.  You must specify an existant ");
0649:                            out.println("and executable file as part of the ");
0650:                            out.println("path-info.");
0651:                            out.println("</H4>");
0652:                            out.println("<H4>");
0653:                            out
0654:                                    .println("For a good discussion of how CGI scripts ");
0655:                            out
0656:                                    .println("work and what their environment variables ");
0657:                            out.println("mean, please visit the <a ");
0658:                            out
0659:                                    .println("href=\"http://cgi-spec.golux.com\">CGI ");
0660:                            out.println("Specification page</a>.");
0661:                            out.println("</H4>");
0662:
0663:                        }
0664:
0665:                        printServletEnvironment(out, req, res);
0666:
0667:                        out.println("</BODY></HTML>");
0668:
0669:                    } catch (IOException ignored) {
0670:                    }
0671:
0672:                } //debugging
0673:
0674:            } //doGet
0675:
0676:            /** For future testing use only; does nothing right now */
0677:            public static void main(String[] args) {
0678:                System.out
0679:                        .println("$Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/CGIServlet.java,v 1.7 2001/09/20 23:48:13 remm Exp $");
0680:            }
0681:
0682:            /**
0683:             * Encapsulates the CGI environment and rules to derive
0684:             * that environment from the servlet container and request information.
0685:             *
0686:             * <p>
0687:             * </p>
0688:             *
0689:             * @author   Martin Dengler [root@martindengler.com]
0690:             * @version  $Revision: 1.7 $, $Date: 2001/09/20 23:48:13 $
0691:             * @since    Tomcat 4.0
0692:             *
0693:             */
0694:            protected class CGIEnvironment {
0695:
0696:                /** context of the enclosing servlet */
0697:                private ServletContext context = null;
0698:
0699:                /** context path of enclosing servlet */
0700:                private String contextPath = null;
0701:
0702:                /** servlet URI of the enclosing servlet */
0703:                private String servletPath = null;
0704:
0705:                /** pathInfo for the current request */
0706:                private String pathInfo = null;
0707:
0708:                /** real file system directory of the enclosing servlet's web app */
0709:                private String webAppRootDir = null;
0710:
0711:                /** derived cgi environment */
0712:                private Hashtable env = null;
0713:
0714:                /** cgi command to be invoked */
0715:                private String command = null;
0716:
0717:                /** cgi command's desired working directory */
0718:                private File workingDirectory = null;
0719:
0720:                /** cgi command's query parameters */
0721:                private Hashtable queryParameters = null;
0722:
0723:                /** whether or not this object is valid or not */
0724:                private boolean valid = false;
0725:
0726:                /**
0727:                 * Creates a CGIEnvironment and derives the necessary environment,
0728:                 * query parameters, working directory, cgi command, etc.
0729:                 *
0730:                 * @param  req       HttpServletRequest for information provided by
0731:                 *                   the Servlet API
0732:                 * @param  context   ServletContext for information provided by the
0733:                 *                   Servlet API
0734:                 *
0735:                 */
0736:                protected CGIEnvironment(HttpServletRequest req,
0737:                        ServletContext context) {
0738:                    setupFromContext(context);
0739:                    setupFromRequest(req);
0740:
0741:                    queryParameters = new Hashtable();
0742:                    Enumeration paramNames = req.getParameterNames();
0743:                    while (paramNames != null && paramNames.hasMoreElements()) {
0744:                        String param = paramNames.nextElement().toString();
0745:                        if (param != null) {
0746:                            queryParameters.put(param, URLEncoder.encode(req
0747:                                    .getParameter(param)));
0748:                        }
0749:                    }
0750:
0751:                    this .valid = setCGIEnvironment(req);
0752:
0753:                    if (this .valid) {
0754:                        workingDirectory = new File(command.substring(0,
0755:                                command.lastIndexOf(File.separator)));
0756:                    }
0757:
0758:                }
0759:
0760:                /**
0761:                 * Uses the ServletContext to set some CGI variables
0762:                 *
0763:                 * @param  context   ServletContext for information provided by the
0764:                 *                   Servlet API
0765:                 */
0766:                protected void setupFromContext(ServletContext context) {
0767:                    this .context = context;
0768:                    this .webAppRootDir = context.getRealPath("/");
0769:                }
0770:
0771:                /**
0772:                 * Uses the HttpServletRequest to set most CGI variables
0773:                 *
0774:                 * @param  req   HttpServletRequest for information provided by
0775:                 *               the Servlet API
0776:                 */
0777:                protected void setupFromRequest(HttpServletRequest req) {
0778:                    this .contextPath = req.getContextPath();
0779:                    this .pathInfo = req.getPathInfo();
0780:                    this .servletPath = req.getServletPath();
0781:                }
0782:
0783:                /**
0784:                 * Resolves core information about the cgi script.
0785:                 *
0786:                 * <p>
0787:                 * Example URI:
0788:                 * <PRE> /servlet/cgigateway/dir1/realCGIscript/pathinfo1 </PRE>
0789:                 * <ul>
0790:                 * <LI><b>path</b> = $CATALINA_HOME/mywebapp/dir1/realCGIscript
0791:                 * <LI><b>scriptName</b> = /servlet/cgigateway/dir1/realCGIscript
0792:                 * <LI><b>cgiName</b> = /dir1/realCGIscript
0793:                 * <LI><b>name</b> = realCGIscript
0794:                 * </ul>
0795:                 * </p>
0796:                 * <p>
0797:                 * CGI search algorithm: search the real path below
0798:                 *    &lt;my-webapp-root&gt; and find the first non-directory in
0799:                 *    the getPathTranslated("/"), reading/searching from left-to-right.
0800:                 *</p>
0801:                 *<p>
0802:                 *   The CGI search path will start at
0803:                 *   webAppRootDir + File.separator + cgiPathPrefix
0804:                 *   (or webAppRootDir alone if cgiPathPrefix is
0805:                 *   null).
0806:                 *</p>
0807:                 *<p>
0808:                 *   cgiPathPrefix is defined by setting
0809:                 *   this servlet's cgiPathPrefix init parameter
0810:                 *
0811:                 *</p>
0812:                 *
0813:                 * @param pathInfo       String from HttpServletRequest.getPathInfo()
0814:                 * @param webAppRootDir  String from context.getRealPath("/")
0815:                 * @param contextPath    String as from
0816:                 *                       HttpServletRequest.getContextPath()
0817:                 * @param servletPath    String as from
0818:                 *                       HttpServletRequest.getServletPath()
0819:                 * @param cgiPathPrefix  subdirectory of webAppRootDir below which
0820:                 *                       the web app's CGIs may be stored; can be null.
0821:                 *                       The CGI search path will start at
0822:                 *                       webAppRootDir + File.separator + cgiPathPrefix
0823:                 *                       (or webAppRootDir alone if cgiPathPrefix is
0824:                 *                       null).  cgiPathPrefix is defined by setting
0825:                 *                       the servlet's cgiPathPrefix init parameter.
0826:                 *
0827:                 *
0828:                 * @return
0829:                 * <ul>
0830:                 * <li>
0831:                 * <code>path</code> -    full file-system path to valid cgi script,
0832:                 *                        or null if no cgi was found
0833:                 * <li>
0834:                 * <code>scriptName</code> -
0835:                 *                        CGI variable SCRIPT_NAME; the full URL path
0836:                 *                        to valid cgi script or null if no cgi was
0837:                 *                        found
0838:                 * <li>
0839:                 * <code>cgiName</code> - servlet pathInfo fragment corresponding to
0840:                 *                        the cgi script itself, or null if not found
0841:                 * <li>
0842:                 * <code>name</code> -    simple name (no directories) of the
0843:                 *                        cgi script, or null if no cgi was found
0844:                 * </ul>
0845:                 *
0846:                 * @author Martin Dengler [root@martindengler.com]
0847:                 * @since Tomcat 4.0
0848:                 */
0849:                protected String[] findCGI(String pathInfo,
0850:                        String webAppRootDir, String contextPath,
0851:                        String servletPath, String cgiPathPrefix) {
0852:                    String path = null;
0853:                    String name = null;
0854:                    String scriptname = null;
0855:                    String cginame = null;
0856:
0857:                    if ((webAppRootDir != null)
0858:                            && (webAppRootDir.lastIndexOf(File.separator) == (webAppRootDir
0859:                                    .length() - 1))) {
0860:                        //strip the trailing "/" from the webAppRootDir
0861:                        webAppRootDir = webAppRootDir.substring(0,
0862:                                (webAppRootDir.length() - 1));
0863:                    }
0864:
0865:                    if (cgiPathPrefix != null) {
0866:                        webAppRootDir = webAppRootDir + File.separator
0867:                                + cgiPathPrefix;
0868:                    }
0869:
0870:                    if (debug >= 2) {
0871:                        log("findCGI: path=" + pathInfo + ", " + webAppRootDir);
0872:                    }
0873:
0874:                    File currentLocation = new File(webAppRootDir);
0875:                    StringTokenizer dirWalker = new StringTokenizer(pathInfo,
0876:                            File.separator);
0877:                    if (debug >= 3) {
0878:                        log("findCGI: currentLoc=" + currentLocation);
0879:                    }
0880:                    while (!currentLocation.isFile()
0881:                            && dirWalker.hasMoreElements()) {
0882:                        if (debug >= 3) {
0883:                            log("findCGI: currentLoc=" + currentLocation);
0884:                        }
0885:                        currentLocation = new File(currentLocation,
0886:                                (String) dirWalker.nextElement());
0887:                    }
0888:                    if (!currentLocation.isFile()) {
0889:                        return new String[] { null, null, null, null };
0890:                    } else {
0891:                        if (debug >= 2) {
0892:                            log("findCGI: FOUND cgi at " + currentLocation);
0893:                        }
0894:                        path = currentLocation.getAbsolutePath();
0895:                        name = currentLocation.getName();
0896:                        cginame = currentLocation.getParent().substring(
0897:                                webAppRootDir.length())
0898:                                + File.separator + name;
0899:
0900:                        if (".".equals(contextPath)) {
0901:                            scriptname = servletPath + cginame;
0902:                        } else {
0903:                            scriptname = contextPath + servletPath + cginame;
0904:                        }
0905:                    }
0906:
0907:                    if (debug >= 1) {
0908:                        log("findCGI calc: name=" + name + ", path=" + path
0909:                                + ", scriptname=" + scriptname + ", cginame="
0910:                                + cginame);
0911:                    }
0912:                    return new String[] { path, scriptname, cginame, name };
0913:
0914:                }
0915:
0916:                /**
0917:                 * Constructs the CGI environment to be supplied to the invoked CGI
0918:                 * script; relies heavliy on Servlet API methods and findCGI
0919:                 *
0920:                 * @param    HttpServletRequest request associated with the CGI
0921:                 *           invokation
0922:                 *
0923:                 * @return   true if environment was set OK, false if there
0924:                 *           was a problem and no environment was set
0925:                 */
0926:                protected boolean setCGIEnvironment(HttpServletRequest req) {
0927:
0928:                    /*
0929:                     * This method is slightly ugly; c'est la vie.
0930:                     * "You cannot stop [ugliness], you can only hope to contain [it]"
0931:                     * (apologies to Marv Albert regarding MJ)
0932:                     */
0933:
0934:                    Hashtable envp = new Hashtable();
0935:
0936:                    String sPathInfoOrig = null;
0937:                    String sPathTranslatedOrig = null;
0938:                    String sPathInfoCGI = null;
0939:                    String sPathTranslatedCGI = null;
0940:                    String sCGIFullPath = null;
0941:                    String sCGIScriptName = null;
0942:                    String sCGIFullName = null;
0943:                    String sCGIName = null;
0944:                    String[] sCGINames;
0945:
0946:                    sPathInfoOrig = this .pathInfo;
0947:                    sPathInfoOrig = sPathInfoOrig == null ? "" : sPathInfoOrig;
0948:
0949:                    sPathTranslatedOrig = req.getPathTranslated();
0950:                    sPathTranslatedOrig = sPathTranslatedOrig == null ? ""
0951:                            : sPathTranslatedOrig;
0952:
0953:                    sCGINames = findCGI(sPathInfoOrig, webAppRootDir,
0954:                            contextPath, servletPath, cgiPathPrefix);
0955:
0956:                    sCGIFullPath = sCGINames[0];
0957:                    sCGIScriptName = sCGINames[1];
0958:                    sCGIFullName = sCGINames[2];
0959:                    sCGIName = sCGINames[3];
0960:
0961:                    if (sCGIFullPath == null || sCGIScriptName == null
0962:                            || sCGIFullName == null || sCGIName == null) {
0963:                        return false;
0964:                    }
0965:
0966:                    envp.put("SERVER_SOFTWARE", "TOMCAT");
0967:
0968:                    envp.put("SERVER_NAME", nullsToBlanks(req.getServerName()));
0969:
0970:                    envp.put("GATEWAY_INTERFACE", "CGI/1.1");
0971:
0972:                    envp.put("SERVER_PROTOCOL",
0973:                            nullsToBlanks(req.getProtocol()));
0974:
0975:                    int port = req.getServerPort();
0976:                    Integer iPort = (port == 0 ? new Integer(-1) : new Integer(
0977:                            port));
0978:                    envp.put("SERVER_PORT", iPort.toString());
0979:
0980:                    envp.put("REQUEST_METHOD", nullsToBlanks(req.getMethod()));
0981:
0982:                    /*-
0983:                     * PATH_INFO should be determined by using sCGIFullName:
0984:                     * 1) Let sCGIFullName not end in a "/" (see method findCGI)
0985:                     * 2) Let sCGIFullName equal the pathInfo fragment which
0986:                     *    corresponds to the actual cgi script.
0987:                     * 3) Thus, PATH_INFO = request.getPathInfo().substring(
0988:                     *                      sCGIFullName.length())
0989:                     *
0990:                     * (see method findCGI, where the real work is done)
0991:                     *
0992:                     */
0993:                    if (pathInfo == null
0994:                            || (pathInfo.substring(sCGIFullName.length())
0995:                                    .length() <= 0)) {
0996:                        sPathInfoCGI = "";
0997:                    } else {
0998:                        sPathInfoCGI = pathInfo
0999:                                .substring(sCGIFullName.length());
1000:                    }
1001:                    envp.put("PATH_INFO", sPathInfoCGI);
1002:
1003:                    /*-
1004:                     * PATH_TRANSLATED must be determined after PATH_INFO (and the
1005:                     * implied real cgi-script) has been taken into account.
1006:                     *
1007:                     * The following example demonstrates:
1008:                     *
1009:                     * servlet info   = /servlet/cgigw/dir1/dir2/cgi1/trans1/trans2
1010:                     * cgifullpath    = /servlet/cgigw/dir1/dir2/cgi1
1011:                     * path_info      = /trans1/trans2
1012:                     * webAppRootDir  = servletContext.getRealPath("/")
1013:                     *
1014:                     * path_translated = servletContext.getRealPath("/trans1/trans2")
1015:                     *
1016:                     * That is, PATH_TRANSLATED = webAppRootDir + sPathInfoCGI
1017:                     * (unless sPathInfoCGI is null or blank, then the CGI
1018:                     * specification dictates that the PATH_TRANSLATED metavariable
1019:                     * SHOULD NOT be defined.
1020:                     *
1021:                     */
1022:                    if (sPathInfoCGI != null && !("".equals(sPathInfoCGI))) {
1023:                        sPathTranslatedCGI = context.getRealPath(sPathInfoCGI);
1024:                    } else {
1025:                        sPathTranslatedCGI = null;
1026:                    }
1027:                    if (sPathTranslatedCGI == null
1028:                            || "".equals(sPathTranslatedCGI)) {
1029:                        //NOOP
1030:                    } else {
1031:                        envp.put("PATH_TRANSLATED",
1032:                                nullsToBlanks(sPathTranslatedCGI));
1033:                    }
1034:
1035:                    envp.put("SCRIPT_NAME", nullsToBlanks(sCGIScriptName));
1036:
1037:                    envp.put("QUERY_STRING",
1038:                            nullsToBlanks(req.getQueryString()));
1039:
1040:                    envp.put("REMOTE_HOST", nullsToBlanks(req.getRemoteHost()));
1041:
1042:                    envp.put("REMOTE_ADDR", nullsToBlanks(req.getRemoteAddr()));
1043:
1044:                    envp.put("AUTH_TYPE", nullsToBlanks(req.getAuthType()));
1045:
1046:                    envp.put("REMOTE_USER", nullsToBlanks(req.getRemoteUser()));
1047:
1048:                    envp.put("REMOTE_IDENT", ""); //not necessary for full compliance
1049:
1050:                    envp.put("CONTENT_TYPE",
1051:                            nullsToBlanks(req.getContentType()));
1052:
1053:                    /* Note CGI spec says CONTENT_LENGTH must be NULL ("") or undefined
1054:                     * if there is no content, so we cannot put 0 or -1 in as per the
1055:                     * Servlet API spec.
1056:                     */
1057:                    int contentLength = req.getContentLength();
1058:                    String sContentLength = (contentLength <= 0 ? ""
1059:                            : (new Integer(contentLength)).toString());
1060:                    envp.put("CONTENT_LENGTH", sContentLength);
1061:
1062:                    Enumeration headers = req.getHeaderNames();
1063:                    String header = null;
1064:                    while (headers.hasMoreElements()) {
1065:                        header = null;
1066:                        header = ((String) headers.nextElement()).toUpperCase();
1067:                        //REMIND: rewrite multiple headers as if received as single
1068:                        //REMIND: change character set
1069:                        //REMIND: I forgot what the previous REMIND means
1070:                        if ("AUTHORIZATION".equalsIgnoreCase(header)
1071:                                || "PROXY_AUTHORIZATION"
1072:                                        .equalsIgnoreCase(header)) {
1073:                            //NOOP per CGI specification section 11.2
1074:                        } else if ("HOST".equalsIgnoreCase(header)) {
1075:                            String host = req.getHeader(header);
1076:                            int idx = host.indexOf(":");
1077:                            if (idx < 0)
1078:                                idx = host.length();
1079:                            envp.put("HTTP_" + header.replace('-', '_'), host
1080:                                    .substring(0, idx));
1081:                        } else {
1082:                            envp.put("HTTP_" + header.replace('-', '_'), req
1083:                                    .getHeader(header));
1084:                        }
1085:                    }
1086:
1087:                    command = sCGIFullPath;
1088:                    envp.put("X_TOMCAT_SCRIPT_PATH", command); //for kicks
1089:
1090:                    this .env = envp;
1091:
1092:                    return true;
1093:
1094:                }
1095:
1096:                /**
1097:                 * Print important CGI environment information in a easy-to-read HTML
1098:                 * table
1099:                 *
1100:                 * @return  HTML string containing CGI environment info
1101:                 *
1102:                 */
1103:                public String toString() {
1104:
1105:                    StringBuffer sb = new StringBuffer();
1106:
1107:                    sb.append("<TABLE border=2>");
1108:
1109:                    sb.append("<tr><th colspan=2 bgcolor=grey>");
1110:                    sb.append("CGIEnvironment Info</th></tr>");
1111:
1112:                    sb.append("<tr><td>Debug Level</td><td>");
1113:                    sb.append(debug);
1114:                    sb.append("</td></tr>");
1115:
1116:                    sb.append("<tr><td>Validity:</td><td>");
1117:                    sb.append(isValid());
1118:                    sb.append("</td></tr>");
1119:
1120:                    if (isValid()) {
1121:                        Enumeration envk = env.keys();
1122:                        while (envk.hasMoreElements()) {
1123:                            String s = (String) envk.nextElement();
1124:                            sb.append("<tr><td>");
1125:                            sb.append(s);
1126:                            sb.append("</td><td>");
1127:                            sb.append(blanksToString((String) env.get(s),
1128:                                    "[will be set to blank]"));
1129:                            sb.append("</td></tr>");
1130:                        }
1131:                    }
1132:
1133:                    sb.append("<tr><td colspan=2><HR></td></tr>");
1134:
1135:                    sb.append("<tr><td>Derived Command</td><td>");
1136:                    sb.append(nullsToBlanks(command));
1137:                    sb.append("</td></tr>");
1138:
1139:                    sb.append("<tr><td>Working Directory</td><td>");
1140:                    if (workingDirectory != null) {
1141:                        sb.append(workingDirectory.toString());
1142:                    }
1143:                    sb.append("</td></tr>");
1144:
1145:                    sb.append("<tr><td colspan=2>Query Params</td></tr>");
1146:                    Enumeration paramk = queryParameters.keys();
1147:                    while (paramk.hasMoreElements()) {
1148:                        String s = paramk.nextElement().toString();
1149:                        sb.append("<tr><td>");
1150:                        sb.append(s);
1151:                        sb.append("</td><td>");
1152:                        sb.append(queryParameters.get(s).toString());
1153:                        sb.append("</td></tr>");
1154:                    }
1155:
1156:                    sb.append("</TABLE><p>end.");
1157:
1158:                    return sb.toString();
1159:                }
1160:
1161:                /**
1162:                 * Gets derived command string
1163:                 *
1164:                 * @return  command string
1165:                 *
1166:                 */
1167:                protected String getCommand() {
1168:                    return command;
1169:                }
1170:
1171:                /**
1172:                 * Gets derived CGI working directory
1173:                 *
1174:                 * @return  working directory
1175:                 *
1176:                 */
1177:                protected File getWorkingDirectory() {
1178:                    return workingDirectory;
1179:                }
1180:
1181:                /**
1182:                 * Gets derived CGI environment
1183:                 *
1184:                 * @return   CGI environment
1185:                 *
1186:                 */
1187:                protected Hashtable getEnvironment() {
1188:                    return env;
1189:                }
1190:
1191:                /**
1192:                 * Gets derived CGI query parameters
1193:                 *
1194:                 * @return   CGI query parameters
1195:                 *
1196:                 */
1197:                protected Hashtable getParameters() {
1198:                    return queryParameters;
1199:                }
1200:
1201:                /**
1202:                 * Gets validity status
1203:                 *
1204:                 * @return   true if this environment is valid, false
1205:                 *           otherwise
1206:                 *
1207:                 */
1208:                protected boolean isValid() {
1209:                    return valid;
1210:                }
1211:
1212:                /**
1213:                 * Converts null strings to blank strings ("")
1214:                 *
1215:                 * @param    string to be converted if necessary
1216:                 * @return   a non-null string, either the original or the empty string
1217:                 *           ("") if the original was <code>null</code>
1218:                 */
1219:                protected String nullsToBlanks(String s) {
1220:                    return nullsToString(s, "");
1221:                }
1222:
1223:                /**
1224:                 * Converts null strings to another string
1225:                 *
1226:                 * @param    string to be converted if necessary
1227:                 * @param    string to return instead of a null string
1228:                 * @return   a non-null string, either the original or the substitute
1229:                 *           string if the original was <code>null</code>
1230:                 */
1231:                protected String nullsToString(String couldBeNull,
1232:                        String subForNulls) {
1233:                    return (couldBeNull == null ? subForNulls : couldBeNull);
1234:                }
1235:
1236:                /**
1237:                 * Converts blank strings to another string
1238:                 *
1239:                 * @param    string to be converted if necessary
1240:                 * @param    string to return instead of a blank string
1241:                 * @return   a non-null string, either the original or the substitute
1242:                 *           string if the original was <code>null</code> or empty ("")
1243:                 */
1244:                protected String blanksToString(String couldBeBlank,
1245:                        String subForBlanks) {
1246:                    return (("".equals(couldBeBlank) || couldBeBlank == null) ? subForBlanks
1247:                            : couldBeBlank);
1248:                }
1249:
1250:            } //class CGIEnvironment
1251:
1252:            /**
1253:             * Encapsulates the knowledge of how to run a CGI script, given the
1254:             * script's desired environment and (optionally) input/output streams
1255:             *
1256:             * <p>
1257:             *
1258:             * Exposes a <code>run</code> method used to actually invoke the
1259:             * CGI.
1260:             *
1261:             * </p>
1262:             * <p>
1263:             *
1264:             * The CGI environment and settings are derived from the information
1265:             * passed to the constuctor.
1266:             *
1267:             * </p>
1268:             * <p>
1269:             *
1270:             * The input and output streams can be set by the <code>setInput</code>
1271:             * and <code>setResponse</code> methods, respectively.
1272:             * </p>
1273:             *
1274:             * @author    Martin Dengler [root@martindengler.com]
1275:             * @version   $Revision: 1.7 $, $Date: 2001/09/20 23:48:13 $
1276:             */
1277:
1278:            protected class CGIRunner {
1279:
1280:                /** script/command to be executed */
1281:                private String command = null;
1282:
1283:                /** environment used when invoking the cgi script */
1284:                private Hashtable env = null;
1285:
1286:                /** working directory used when invoking the cgi script */
1287:                private File wd = null;
1288:
1289:                /** query parameters to be passed to the invoked script */
1290:                private Hashtable params = null;
1291:
1292:                /** stdin to be passed to cgi script */
1293:                private InputStream stdin = null;
1294:
1295:                /** response object used to set headers & get output stream */
1296:                private HttpServletResponse response = null;
1297:
1298:                /** boolean tracking whether this object has enough info to run() */
1299:                private boolean readyToRun = false;
1300:
1301:                /**
1302:                 *  Creates a CGIRunner and initializes its environment, working
1303:                 *  directory, and query parameters.
1304:                 *  <BR>
1305:                 *  Input/output streams (optional) are set using the
1306:                 *  <code>setInput</code> and <code>setResponse</code> methods,
1307:                 *  respectively.
1308:                 *
1309:                 * @param  command  string full path to command to be executed
1310:                 * @param  env      Hashtable with the desired script environment
1311:                 * @param  wd       File with the script's desired working directory
1312:                 * @param  params   Hashtable with the script's query parameters
1313:                 *
1314:                 * @param  res       HttpServletResponse object for setting headers
1315:                 *                   based on CGI script output
1316:                 *
1317:                 */
1318:                protected CGIRunner(String command, Hashtable env, File wd,
1319:                        Hashtable params) {
1320:                    this .command = command;
1321:                    this .env = env;
1322:                    this .wd = wd;
1323:                    this .params = params;
1324:                    updateReadyStatus();
1325:                }
1326:
1327:                /**
1328:                 * Checks & sets ready status
1329:                 */
1330:                protected void updateReadyStatus() {
1331:                    if (command != null && env != null && wd != null
1332:                            && params != null && response != null) {
1333:                        readyToRun = true;
1334:                    } else {
1335:                        readyToRun = false;
1336:                    }
1337:                }
1338:
1339:                /**
1340:                 * Gets ready status
1341:                 *
1342:                 * @return   false if not ready (<code>run</code> will throw
1343:                 *           an exception), true if ready
1344:                 */
1345:                protected boolean isReady() {
1346:                    return readyToRun;
1347:                }
1348:
1349:                /**
1350:                 * Sets HttpServletResponse object used to set headers and send
1351:                 * output to
1352:                 *
1353:                 * @param  response   HttpServletResponse to be used
1354:                 *
1355:                 */
1356:                protected void setResponse(HttpServletResponse response) {
1357:                    this .response = response;
1358:                    updateReadyStatus();
1359:                }
1360:
1361:                /**
1362:                 * Sets standard input to be passed on to the invoked cgi script
1363:                 *
1364:                 * @param  stdin   InputStream to be used
1365:                 *
1366:                 */
1367:                protected void setInput(InputStream stdin) {
1368:                    this .stdin = stdin;
1369:                    updateReadyStatus();
1370:                }
1371:
1372:                /**
1373:                 * Converts a Hashtable to a String array by converting each
1374:                 * key/value pair in the Hashtable to a String in the form
1375:                 * "key=value" (hashkey + "=" + hash.get(hashkey).toString())
1376:                 *
1377:                 * @param  h   Hashtable to convert
1378:                 *
1379:                 * @return     converted string array
1380:                 *
1381:                 * @exception  NullPointerException   if a hash key has a null value
1382:                 *
1383:                 */
1384:                protected String[] hashToStringArray(Hashtable h)
1385:                        throws NullPointerException {
1386:                    Vector v = new Vector();
1387:                    Enumeration e = h.keys();
1388:                    while (e.hasMoreElements()) {
1389:                        String k = e.nextElement().toString();
1390:                        v.add(k + "=" + h.get(k));
1391:                    }
1392:                    String[] strArr = new String[v.size()];
1393:                    v.copyInto(strArr);
1394:                    return strArr;
1395:                }
1396:
1397:                /**
1398:                 * Executes a CGI script with the desired environment, current working
1399:                 * directory, and input/output streams
1400:                 *
1401:                 * <p>
1402:                 * This implements the following CGI specification recommedations:
1403:                 * <UL>
1404:                 * <LI> Servers SHOULD provide the "<code>query</code>" component of
1405:                 *      the script-URI as command-line arguments to scripts if it
1406:                 *      does not contain any unencoded "=" characters and the
1407:                 *      command-line arguments can be generated in an unambiguous
1408:                 *      manner.
1409:                 * <LI> Servers SHOULD set the AUTH_TYPE metavariable to the value
1410:                 *      of the "<code>auth-scheme</code>" token of the
1411:                 *      "<code>Authorization</code>" if it was supplied as part of the
1412:                 *      request header.  See <code>getCGIEnvironment</code> method.
1413:                 * <LI> Where applicable, servers SHOULD set the current working
1414:                 *      directory to the directory in which the script is located
1415:                 *      before invoking it.
1416:                 * <LI> Server implementations SHOULD define their behavior for the
1417:                 *      following cases:
1418:                 *     <ul>
1419:                 *     <LI> <u>Allowed characters in pathInfo</u>:  This implementation
1420:                 *             does not allow ASCII NUL nor any character which cannot
1421:                 *             be URL-encoded according to internet standards;
1422:                 *     <LI> <u>Allowed characters in path segments</u>: This
1423:                 *             implementation does not allow non-terminal NULL
1424:                 *             segments in the the path -- IOExceptions may be thrown;
1425:                 *     <LI> <u>"<code>.</code>" and "<code>..</code>" path
1426:                 *             segments</u>:
1427:                 *             This implementation does not allow "<code>.</code>" and
1428:                 *             "<code>..</code>" in the the path, and such characters
1429:                 *             will result in an IOException being thrown;
1430:                 *     <LI> <u>Implementation limitations</u>: This implementation
1431:                 *             does not impose any limitations except as documented
1432:                 *             above.  This implementation may be limited by the
1433:                 *             servlet container used to house this implementation.
1434:                 *             In particular, all the primary CGI variable values
1435:                 *             are derived either directly or indirectly from the
1436:                 *             container's implementation of the Servlet API methods.
1437:                 *     </ul>
1438:                 * </UL>
1439:                 * </p>
1440:                 *
1441:                 * For more information, see java.lang.Runtime#exec(String command, 
1442:                 * String[] envp, File dir)
1443:                 * 
1444:                 * @exception IOException if problems during reading/writing occur
1445:                 *
1446:                 */
1447:                protected void run() throws IOException {
1448:
1449:                    /*
1450:                     * REMIND:  this method feels too big; should it be re-written?
1451:                     */
1452:
1453:                    if (!isReady()) {
1454:                        throw new IOException(this .getClass().getName()
1455:                                + ": not ready to run.");
1456:                    }
1457:
1458:                    if (debug >= 1) {
1459:                        log("runCGI(envp=[" + env + "], command=" + command
1460:                                + ")");
1461:                    }
1462:
1463:                    if ((command.indexOf(File.separator + "." + File.separator) >= 0)
1464:                            || (command.indexOf(File.separator + "..") >= 0)
1465:                            || (command.indexOf(".." + File.separator) >= 0)) {
1466:                        throw new IOException(this .getClass().getName()
1467:                                + "Illegal Character in CGI command "
1468:                                + "path ('.' or '..') detected.  Not "
1469:                                + "running CGI [" + command + "].");
1470:                    }
1471:
1472:                    /* original content/structure of this section taken from
1473:                     * http://developer.java.sun.com/developer/
1474:                     *                               bugParade/bugs/4216884.html
1475:                     * with major modifications by Martin Dengler
1476:                     */
1477:                    Runtime rt = null;
1478:                    BufferedReader commandsStdOut = null;
1479:                    BufferedReader commandsStdErr = null;
1480:                    BufferedOutputStream commandsStdIn = null;
1481:                    Process proc = null;
1482:                    byte[] bBuf = new byte[1024];
1483:                    char[] cBuf = new char[1024];
1484:                    int bufRead = -1;
1485:
1486:                    //create query arguments
1487:                    Enumeration paramNames = params.keys();
1488:                    StringBuffer cmdAndArgs = new StringBuffer(command);
1489:                    if (paramNames != null && paramNames.hasMoreElements()) {
1490:                        cmdAndArgs.append(" ");
1491:                        while (paramNames.hasMoreElements()) {
1492:                            String k = (String) paramNames.nextElement();
1493:                            String v = params.get(k).toString();
1494:                            if ((k.indexOf("=") < 0) && (v.indexOf("=") < 0)) {
1495:                                cmdAndArgs.append(k);
1496:                                cmdAndArgs.append("=");
1497:                                v = java.net.URLEncoder.encode(v);
1498:                                cmdAndArgs.append(v);
1499:                                cmdAndArgs.append(" ");
1500:                            }
1501:                        }
1502:                    }
1503:
1504:                    /*String postIn = getPostInput(params);
1505:                    int contentLength = (postIn.length()
1506:                            + System.getProperty("line.separator").length());
1507:                    if ("POST".equals(env.get("REQUEST_METHOD"))) {
1508:                        env.put("CONTENT_LENGTH", new Integer(contentLength));
1509:                    }*/
1510:
1511:                    StringBuffer perlCommand = new StringBuffer("perl ");
1512:                    if (command.endsWith(".pl") || command.endsWith(".cgi")) {
1513:                        perlCommand.append(cmdAndArgs.toString());
1514:                        cmdAndArgs = perlCommand;
1515:                    }
1516:
1517:                    rt = Runtime.getRuntime();
1518:                    proc = rt.exec(cmdAndArgs.toString(),
1519:                            hashToStringArray(env), wd);
1520:
1521:                    /*
1522:                     * provide input to cgi
1523:                     * First  -- parameters
1524:                     * Second -- any remaining input
1525:                     */
1526:                    /*commandsStdIn = new BufferedOutputStream(proc.getOutputStream());
1527:                    if (debug >= 2 ) {
1528:                        log("runCGI stdin=[" + stdin + "], qs="
1529:                            + env.get("QUERY_STRING"));
1530:                    }
1531:                    if ("POST".equals(env.get("REQUEST_METHOD"))) {
1532:                        if (debug >= 2) {
1533:                            log("runCGI: writing ---------------\n");
1534:                            log(postIn);
1535:                            log("runCGI: new content_length=" + contentLength
1536:                                + "---------------\n");
1537:                        }
1538:                        commandsStdIn.write(postIn.getBytes());
1539:                    }
1540:                    if (stdin != null) {
1541:                        //REMIND: document this
1542:                        /* assume if nothing is available after a time, that nothing is
1543:                     * coming...
1544:                     */
1545:                    /*if (stdin.available() <= 0) {
1546:                        if (debug >= 2 ) {
1547:                            log("runCGI stdin is NOT available ["
1548:                                + stdin.available() + "]");
1549:                        }
1550:                        try {
1551:                            Thread.currentThread().sleep(iClientInputTimeout);
1552:                        } catch (InterruptedException ignored) {
1553:                        }
1554:                    }
1555:                    if (stdin.available() > 0) {
1556:                        if (debug >= 2 ) {
1557:                            log("runCGI stdin IS available ["
1558:                                + stdin.available() + "]");
1559:                        }
1560:                        bBuf = new byte[1024];
1561:                        bufRead = -1;
1562:                        try {
1563:                            while ((bufRead = stdin.read(bBuf)) != -1) {
1564:                                if (debug >= 2 ) {
1565:                                    log("runCGI: read [" + bufRead
1566:                                        + "] bytes from stdin");
1567:                                }
1568:                                commandsStdIn.write(bBuf, 0, bufRead);
1569:                            }
1570:                            if (debug >= 2 ) {
1571:                                log("runCGI: DONE READING from stdin");
1572:                            }
1573:                        } catch (IOException ioe) {
1574:                            //REMIND: replace with logging
1575:                            //REMIND: should I throw this exception?
1576:                            log("runCGI: couldn't write all bytes.");
1577:                            ioe.printStackTrace();
1578:                        }
1579:                    }
1580:                    }
1581:                    commandsStdIn.flush();
1582:                    commandsStdIn.close();*/
1583:                    String sContentLength = (String) env.get("CONTENT_LENGTH");
1584:                    if (!"".equals(sContentLength)) {
1585:                        commandsStdIn = new BufferedOutputStream(proc
1586:                                .getOutputStream());
1587:                        byte[] content = new byte[Integer
1588:                                .parseInt(sContentLength)];
1589:                        stdin.read(content);
1590:                        commandsStdIn.write(content);
1591:                        commandsStdIn.flush();
1592:                        commandsStdIn.close();
1593:                    }
1594:
1595:                    /* we want to wait for the process to exit,  Process.waitFor()
1596:                     * is useless in our situation; see
1597:                     * http://developer.java.sun.com/developer/
1598:                     *                               bugParade/bugs/4223650.html
1599:                     */
1600:
1601:                    boolean isRunning = true;
1602:                    commandsStdOut = new BufferedReader(new InputStreamReader(
1603:                            proc.getInputStream()));
1604:                    commandsStdErr = new BufferedReader(new InputStreamReader(
1605:                            proc.getErrorStream()));
1606:                    BufferedWriter servletContainerStdout = null;
1607:
1608:                    try {
1609:                        if (response.getOutputStream() != null) {
1610:                            servletContainerStdout = new BufferedWriter(
1611:                                    new OutputStreamWriter(response
1612:                                            .getOutputStream()));
1613:                        }
1614:                    } catch (IOException ignored) {
1615:                        //NOOP: no output will be written
1616:                    }
1617:
1618:                    while (isRunning) {
1619:
1620:                        try {
1621:                            //read stderr first
1622:                            cBuf = new char[1024];
1623:                            while ((bufRead = commandsStdErr.read(cBuf)) != -1) {
1624:                                if (servletContainerStdout != null) {
1625:                                    servletContainerStdout.write(cBuf, 0,
1626:                                            bufRead);
1627:                                }
1628:                            }
1629:
1630:                            //set headers
1631:                            String line = null;
1632:                            while (((line = commandsStdOut.readLine()) != null)
1633:                                    && !("".equals(line))) {
1634:                                if (debug >= 2) {
1635:                                    log("runCGI: addHeader(\"" + line + "\")");
1636:                                }
1637:                                if (line.startsWith("HTTP")) {
1638:                                    //TODO: should set status codes (NPH support)
1639:                                    /*
1640:                                     * response.setStatus(getStatusCode(line));
1641:                                     */
1642:                                } else {
1643:                                    response.addHeader(line.substring(0,
1644:                                            line.indexOf(":")).trim(), line
1645:                                            .substring(line.indexOf(":") + 1)
1646:                                            .trim());
1647:                                }
1648:                            }
1649:
1650:                            //write output
1651:                            cBuf = new char[1024];
1652:                            while ((bufRead = commandsStdOut.read(cBuf)) != -1) {
1653:                                if (servletContainerStdout != null) {
1654:                                    if (debug >= 4) {
1655:                                        log("runCGI: write(\"" + cBuf + "\")");
1656:                                    }
1657:                                    servletContainerStdout.write(cBuf, 0,
1658:                                            bufRead);
1659:                                }
1660:                            }
1661:
1662:                            if (servletContainerStdout != null) {
1663:                                servletContainerStdout.flush();
1664:                            }
1665:
1666:                            proc.exitValue(); // Throws exception if alive
1667:
1668:                            isRunning = false;
1669:
1670:                        } catch (IllegalThreadStateException e) {
1671:                            try {
1672:                                Thread.currentThread().sleep(500);
1673:                            } catch (InterruptedException ignored) {
1674:                            }
1675:                        }
1676:                    } //replacement for Process.waitFor()
1677:
1678:                }
1679:
1680:                /**
1681:                 * Gets a string for input to a POST cgi script
1682:                 *
1683:                 * @param  params   Hashtable of query parameters to be passed to
1684:                 *                  the CGI script
1685:                 * @return          for use as input to the CGI script
1686:                 */
1687:
1688:                protected String getPostInput(Hashtable params) {
1689:                    String lineSeparator = System.getProperty("line.separator");
1690:                    Enumeration paramNames = params.keys();
1691:                    StringBuffer postInput = new StringBuffer("");
1692:                    StringBuffer qs = new StringBuffer("");
1693:                    if (paramNames != null && paramNames.hasMoreElements()) {
1694:                        while (paramNames.hasMoreElements()) {
1695:                            String k = (String) paramNames.nextElement();
1696:                            String v = params.get(k).toString();
1697:                            if ((k.indexOf("=") < 0) && (v.indexOf("=") < 0)) {
1698:                                postInput.append(k);
1699:                                qs.append(k);
1700:                                postInput.append("=");
1701:                                qs.append("=");
1702:                                postInput.append(v);
1703:                                qs.append(v);
1704:                                postInput.append(lineSeparator);
1705:                                qs.append("&");
1706:                            }
1707:                        }
1708:                    }
1709:                    qs.append(lineSeparator);
1710:                    return qs.append(postInput).toString();
1711:                }
1712:
1713:            } //class CGIRunner
1714:
1715:        } //class CGIServlet
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.