Source Code Cross Referenced for CGIServlet.java in  » Sevlet-Container » tomcat-catalina » 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 » Sevlet Container » tomcat catalina » org.apache.catalina.servlets 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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