1 17 18 19 package org.apache.catalina.servlets; 20 21 import java.io.BufferedOutputStream ; 22 import java.io.BufferedReader ; 23 import java.io.File ; 24 import java.io.FileOutputStream ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.InputStreamReader ; 28 import java.io.OutputStream ; 29 import java.io.UnsupportedEncodingException ; 30 import java.net.URLDecoder ; 31 import java.util.ArrayList ; 32 import java.util.Date ; 33 import java.util.Enumeration ; 34 import java.util.Hashtable ; 35 import java.util.Locale ; 36 import java.util.StringTokenizer ; 37 import java.util.Vector ; 38 39 import javax.servlet.ServletConfig ; 40 import javax.servlet.ServletContext ; 41 import javax.servlet.ServletException ; 42 import javax.servlet.ServletOutputStream ; 43 import javax.servlet.UnavailableException ; 44 import javax.servlet.http.Cookie ; 45 import javax.servlet.http.HttpServlet ; 46 import javax.servlet.http.HttpServletRequest ; 47 import javax.servlet.http.HttpServletResponse ; 48 import javax.servlet.http.HttpSession ; 49 50 import org.apache.catalina.Globals; 51 import org.apache.catalina.util.IOTools; 52 53 54 242 243 244 public final class CGIServlet extends HttpServlet { 245 246 247 248 249 private int debug = 0; 250 251 257 private String cgiPathPrefix = null; 258 259 260 private String cgiExecutable = "perl"; 261 262 263 private String parameterEncoding = System.getProperty("file.encoding", 264 "UTF-8"); 265 266 267 static Object expandFileLock = new Object (); 268 269 270 static Hashtable shellEnv = new Hashtable (); 271 272 287 public void init(ServletConfig config) throws ServletException { 288 289 super.init(config); 290 291 String servletName = getServletConfig().getServletName(); 293 if (servletName == null) 294 servletName = ""; 295 if (servletName.startsWith("org.apache.catalina.INVOKER.")) 296 throw new UnavailableException 297 ("Cannot invoke CGIServlet through the invoker"); 298 299 if (getServletConfig().getInitParameter("debug") != null) 301 debug = Integer.parseInt(getServletConfig().getInitParameter("debug")); 302 cgiPathPrefix = getServletConfig().getInitParameter("cgiPathPrefix"); 303 boolean passShellEnvironment = 304 Boolean.valueOf(getServletConfig().getInitParameter("passShellEnvironment")).booleanValue(); 305 306 if (passShellEnvironment) { 307 try { 308 shellEnv.putAll(getShellEnvironment()); 309 } catch (IOException ioe) { 310 ServletException e = new ServletException ( 311 "Unable to read shell environment variables", ioe); 312 throw e; 313 } 314 } 315 316 if (getServletConfig().getInitParameter("executable") != null) { 317 cgiExecutable = getServletConfig().getInitParameter("executable"); 318 } 319 320 if (getServletConfig().getInitParameter("parameterEncoding") != null) { 321 parameterEncoding = getServletConfig().getInitParameter("parameterEncoding"); 322 } 323 324 } 325 326 327 328 343 protected void printServletEnvironment(ServletOutputStream out, 344 HttpServletRequest req, HttpServletResponse res) throws IOException { 345 346 out.println("<h1>ServletRequest Properties</h1>"); 348 out.println("<ul>"); 349 Enumeration attrs = req.getAttributeNames(); 350 while (attrs.hasMoreElements()) { 351 String attr = (String ) attrs.nextElement(); 352 out.println("<li><b>attribute</b> " + attr + " = " + 353 req.getAttribute(attr)); 354 } 355 out.println("<li><b>characterEncoding</b> = " + 356 req.getCharacterEncoding()); 357 out.println("<li><b>contentLength</b> = " + 358 req.getContentLength()); 359 out.println("<li><b>contentType</b> = " + 360 req.getContentType()); 361 Enumeration locales = req.getLocales(); 362 while (locales.hasMoreElements()) { 363 Locale locale = (Locale ) locales.nextElement(); 364 out.println("<li><b>locale</b> = " + locale); 365 } 366 Enumeration params = req.getParameterNames(); 367 while (params.hasMoreElements()) { 368 String param = (String ) params.nextElement(); 369 String values[] = req.getParameterValues(param); 370 for (int i = 0; i < values.length; i++) 371 out.println("<li><b>parameter</b> " + param + " = " + 372 values[i]); 373 } 374 out.println("<li><b>protocol</b> = " + req.getProtocol()); 375 out.println("<li><b>remoteAddr</b> = " + req.getRemoteAddr()); 376 out.println("<li><b>remoteHost</b> = " + req.getRemoteHost()); 377 out.println("<li><b>scheme</b> = " + req.getScheme()); 378 out.println("<li><b>secure</b> = " + req.isSecure()); 379 out.println("<li><b>serverName</b> = " + req.getServerName()); 380 out.println("<li><b>serverPort</b> = " + req.getServerPort()); 381 out.println("</ul>"); 382 out.println("<hr>"); 383 384 out.println("<h1>HttpServletRequest Properties</h1>"); 386 out.println("<ul>"); 387 out.println("<li><b>authType</b> = " + req.getAuthType()); 388 out.println("<li><b>contextPath</b> = " + 389 req.getContextPath()); 390 Cookie cookies[] = req.getCookies(); 391 if (cookies!=null) { 392 for (int i = 0; i < cookies.length; i++) 393 out.println("<li><b>cookie</b> " + cookies[i].getName() +" = " +cookies[i].getValue()); 394 } 395 Enumeration headers = req.getHeaderNames(); 396 while (headers.hasMoreElements()) { 397 String header = (String ) headers.nextElement(); 398 out.println("<li><b>header</b> " + header + " = " + 399 req.getHeader(header)); 400 } 401 out.println("<li><b>method</b> = " + req.getMethod()); 402 out.println("<li><a name=\"pathInfo\"><b>pathInfo</b></a> = " 403 + req.getPathInfo()); 404 out.println("<li><b>pathTranslated</b> = " + 405 req.getPathTranslated()); 406 out.println("<li><b>queryString</b> = " + 407 req.getQueryString()); 408 out.println("<li><b>remoteUser</b> = " + 409 req.getRemoteUser()); 410 out.println("<li><b>requestedSessionId</b> = " + 411 req.getRequestedSessionId()); 412 out.println("<li><b>requestedSessionIdFromCookie</b> = " + 413 req.isRequestedSessionIdFromCookie()); 414 out.println("<li><b>requestedSessionIdFromURL</b> = " + 415 req.isRequestedSessionIdFromURL()); 416 out.println("<li><b>requestedSessionIdValid</b> = " + 417 req.isRequestedSessionIdValid()); 418 out.println("<li><b>requestURI</b> = " + 419 req.getRequestURI()); 420 out.println("<li><b>servletPath</b> = " + 421 req.getServletPath()); 422 out.println("<li><b>userPrincipal</b> = " + 423 req.getUserPrincipal()); 424 out.println("</ul>"); 425 out.println("<hr>"); 426 427 out.println("<h1>ServletRequest Attributes</h1>"); 429 out.println("<ul>"); 430 attrs = req.getAttributeNames(); 431 while (attrs.hasMoreElements()) { 432 String attr = (String ) attrs.nextElement(); 433 out.println("<li><b>" + attr + "</b> = " + 434 req.getAttribute(attr)); 435 } 436 out.println("</ul>"); 437 out.println("<hr>"); 438 439 HttpSession session = req.getSession(false); 441 if (session != null) { 442 443 out.println("<h1>HttpSession Properties</h1>"); 445 out.println("<ul>"); 446 out.println("<li><b>id</b> = " + 447 session.getId()); 448 out.println("<li><b>creationTime</b> = " + 449 new Date (session.getCreationTime())); 450 out.println("<li><b>lastAccessedTime</b> = " + 451 new Date (session.getLastAccessedTime())); 452 out.println("<li><b>maxInactiveInterval</b> = " + 453 session.getMaxInactiveInterval()); 454 out.println("</ul>"); 455 out.println("<hr>"); 456 457 out.println("<h1>HttpSession Attributes</h1>"); 459 out.println("<ul>"); 460 attrs = session.getAttributeNames(); 461 while (attrs.hasMoreElements()) { 462 String attr = (String ) attrs.nextElement(); 463 out.println("<li><b>" + attr + "</b> = " + 464 session.getAttribute(attr)); 465 } 466 out.println("</ul>"); 467 out.println("<hr>"); 468 469 } 470 471 out.println("<h1>ServletConfig Properties</h1>"); 473 out.println("<ul>"); 474 out.println("<li><b>servletName</b> = " + 475 getServletConfig().getServletName()); 476 out.println("</ul>"); 477 out.println("<hr>"); 478 479 out.println("<h1>ServletConfig Initialization Parameters</h1>"); 481 out.println("<ul>"); 482 params = getServletConfig().getInitParameterNames(); 483 while (params.hasMoreElements()) { 484 String param = (String ) params.nextElement(); 485 String value = getServletConfig().getInitParameter(param); 486 out.println("<li><b>" + param + "</b> = " + value); 487 } 488 out.println("</ul>"); 489 out.println("<hr>"); 490 491 out.println("<h1>ServletContext Properties</h1>"); 493 out.println("<ul>"); 494 out.println("<li><b>majorVersion</b> = " + 495 getServletContext().getMajorVersion()); 496 out.println("<li><b>minorVersion</b> = " + 497 getServletContext().getMinorVersion()); 498 out.println("<li><b>realPath('/')</b> = " + 499 getServletContext().getRealPath("/")); 500 out.println("<li><b>serverInfo</b> = " + 501 getServletContext().getServerInfo()); 502 out.println("</ul>"); 503 out.println("<hr>"); 504 505 out.println("<h1>ServletContext Initialization Parameters</h1>"); 507 out.println("<ul>"); 508 params = getServletContext().getInitParameterNames(); 509 while (params.hasMoreElements()) { 510 String param = (String ) params.nextElement(); 511 String value = getServletContext().getInitParameter(param); 512 out.println("<li><b>" + param + "</b> = " + value); 513 } 514 out.println("</ul>"); 515 out.println("<hr>"); 516 517 out.println("<h1>ServletContext Attributes</h1>"); 519 out.println("<ul>"); 520 attrs = getServletContext().getAttributeNames(); 521 while (attrs.hasMoreElements()) { 522 String attr = (String ) attrs.nextElement(); 523 out.println("<li><b>" + attr + "</b> = " + 524 getServletContext().getAttribute(attr)); 525 } 526 out.println("</ul>"); 527 out.println("<hr>"); 528 529 530 531 } 532 533 534 535 547 protected void doPost(HttpServletRequest req, HttpServletResponse res) 548 throws IOException , ServletException { 549 doGet(req, res); 550 } 551 552 553 554 566 protected void doGet(HttpServletRequest req, HttpServletResponse res) 567 throws ServletException , IOException { 568 569 if (req.getAttribute(Globals.INVOKED_ATTR) != null) 571 throw new UnavailableException 572 ("Cannot invoke CGIServlet through the invoker"); 573 574 CGIEnvironment cgiEnv = new CGIEnvironment(req, getServletContext()); 575 576 if (cgiEnv.isValid()) { 577 CGIRunner cgi = new CGIRunner(cgiEnv.getCommand(), 578 cgiEnv.getEnvironment(), 579 cgiEnv.getWorkingDirectory(), 580 cgiEnv.getParameters()); 581 if ("POST".equals(req.getMethod())) { 584 cgi.setInput(req.getInputStream()); 585 } 586 cgi.setResponse(res); 587 cgi.run(); 588 } 589 590 if (!cgiEnv.isValid()) { 591 res.setStatus(404); 592 } 593 594 if (debug >= 10) { 595 596 ServletOutputStream out = res.getOutputStream(); 597 out.println("<HTML><HEAD><TITLE>$Name$</TITLE></HEAD>"); 598 out.println("<BODY>$Header$<p>"); 599 600 if (cgiEnv.isValid()) { 601 out.println(cgiEnv.toString()); 602 } else { 603 out.println("<H3>"); 604 out.println("CGI script not found or not specified."); 605 out.println("</H3>"); 606 out.println("<H4>"); 607 out.println("Check the <b>HttpServletRequest "); 608 out.println("<a HREF=\"#pathInfo\">pathInfo</a></b> "); 609 out.println("property to see if it is what you meant "); 610 out.println("it to be. You must specify an existant "); 611 out.println("and executable file as part of the "); 612 out.println("path-info."); 613 out.println("</H4>"); 614 out.println("<H4>"); 615 out.println("For a good discussion of how CGI scripts "); 616 out.println("work and what their environment variables "); 617 out.println("mean, please visit the <a "); 618 out.println("href=\"http://cgi-spec.golux.com\">CGI "); 619 out.println("Specification page</a>."); 620 out.println("</H4>"); 621 622 } 623 624 printServletEnvironment(out, req, res); 625 626 out.println("</BODY></HTML>"); 627 628 } 629 630 631 } 633 634 635 636 public static void main(String [] args) { 637 System.out.println("$Header$"); 638 } 639 640 647 private Hashtable getShellEnvironment() throws IOException { 648 Hashtable envVars = new Hashtable (); 649 Process p = null; 650 Runtime r = Runtime.getRuntime(); 651 String OS = System.getProperty("os.name").toLowerCase(); 652 boolean ignoreCase; 653 654 if (OS.indexOf("windows 9") > -1) { 655 p = r.exec( "command.com /c set" ); 656 ignoreCase = true; 657 } else if ( (OS.indexOf("nt") > -1) 658 || (OS.indexOf("windows 20") > -1) 659 || (OS.indexOf("windows xp") > -1) ) { 660 p = r.exec( "cmd.exe /c set" ); 662 ignoreCase = true; 663 } else { 664 p = r.exec( "env" ); 666 ignoreCase = false; 667 } 668 669 BufferedReader br = new BufferedReader 670 ( new InputStreamReader ( p.getInputStream() ) ); 671 String line; 672 while( (line = br.readLine()) != null ) { 673 int idx = line.indexOf( '=' ); 674 String key = line.substring( 0, idx ); 675 String value = line.substring( idx+1 ); 676 if (ignoreCase) { 677 key = key.toUpperCase(); 678 } 679 envVars.put(key, value); 680 } 681 return envVars; 682 } 683 684 685 686 687 688 689 690 701 protected class CGIEnvironment { 702 703 704 705 private ServletContext context = null; 706 707 708 private String contextPath = null; 709 710 711 private String servletPath = null; 712 713 714 private String pathInfo = null; 715 716 717 private String webAppRootDir = null; 718 719 720 private File tmpDir = null; 721 722 723 private Hashtable env = null; 724 725 726 private String command = null; 727 728 729 private File workingDirectory = null; 730 731 732 private ArrayList cmdLineParameters = new ArrayList (); 733 734 735 private boolean valid = false; 736 737 738 748 protected CGIEnvironment(HttpServletRequest req, 749 ServletContext context) throws IOException { 750 setupFromContext(context); 751 setupFromRequest(req); 752 753 this.valid = setCGIEnvironment(req); 754 755 if (this.valid) { 756 workingDirectory = new File (command.substring(0, 757 command.lastIndexOf(File.separator))); 758 } 759 760 } 761 762 763 764 770 protected void setupFromContext(ServletContext context) { 771 this.context = context; 772 this.webAppRootDir = context.getRealPath("/"); 773 this.tmpDir = (File ) context.getAttribute(Globals.WORK_DIR_ATTR); 774 } 775 776 777 778 785 protected void setupFromRequest(HttpServletRequest req) 786 throws UnsupportedEncodingException { 787 788 this.contextPath = req.getContextPath(); 789 this.servletPath = req.getServletPath(); 790 this.pathInfo = req.getPathInfo(); 791 if (this.pathInfo == null) { 794 this.pathInfo = this.servletPath; 795 } 796 797 if (!"GET".equals(req.getMethod()) && 801 !"HEAD".equals(req.getMethod())) 802 return; 803 804 String qs = req.getQueryString(); 805 806 if (qs == null || qs.indexOf("=")>0) 807 return; 808 809 int delimIndex = 0; 810 int lastDelimIndex = 0; 811 delimIndex = qs.indexOf("+"); 812 813 while (delimIndex >0) { 814 cmdLineParameters.add(URLDecoder.decode(qs.substring( 815 lastDelimIndex,delimIndex),parameterEncoding)); 816 lastDelimIndex = delimIndex + 1; 817 delimIndex = qs.indexOf("+",lastDelimIndex); 818 } 819 cmdLineParameters.add(URLDecoder.decode(qs.substring( 820 lastDelimIndex),parameterEncoding)); 821 } 822 823 824 889 protected String [] findCGI(String pathInfo, String webAppRootDir, 890 String contextPath, String servletPath, 891 String cgiPathPrefix) { 892 String path = null; 893 String name = null; 894 String scriptname = null; 895 String cginame = null; 896 897 if ((webAppRootDir != null) 898 && (webAppRootDir.lastIndexOf(File.separator) == 899 (webAppRootDir.length() - 1))) { 900 webAppRootDir = 902 webAppRootDir.substring(0, (webAppRootDir.length() - 1)); 903 } 904 905 if (cgiPathPrefix != null) { 906 webAppRootDir = webAppRootDir + File.separator 907 + cgiPathPrefix; 908 } 909 910 if (debug >= 2) { 911 log("findCGI: path=" + pathInfo + ", " + webAppRootDir); 912 } 913 914 File currentLocation = new File (webAppRootDir); 915 StringTokenizer dirWalker = 916 new StringTokenizer (pathInfo, "/"); 917 if (debug >= 3) { 918 log("findCGI: currentLoc=" + currentLocation); 919 } 920 while (!currentLocation.isFile() && dirWalker.hasMoreElements()) { 921 if (debug >= 3) { 922 log("findCGI: currentLoc=" + currentLocation); 923 } 924 currentLocation = new File (currentLocation, 925 (String ) dirWalker.nextElement()); 926 } 927 if (!currentLocation.isFile()) { 928 return new String [] { null, null, null, null }; 929 } else { 930 if (debug >= 2) { 931 log("findCGI: FOUND cgi at " + currentLocation); 932 } 933 path = currentLocation.getAbsolutePath(); 934 name = currentLocation.getName(); 935 cginame = (currentLocation.getParent() + File.separator). 936 substring(webAppRootDir.length()) + name; 937 938 if (".".equals(contextPath)) { 939 scriptname = servletPath + cginame; 940 } else { 941 scriptname = contextPath + servletPath + cginame; 942 } 943 } 944 945 if (debug >= 1) { 946 log("findCGI calc: name=" + name + ", path=" + path 947 + ", scriptname=" + scriptname + ", cginame=" + cginame); 948 } 949 return new String [] { path, scriptname, cginame, name }; 950 } 951 952 962 protected boolean setCGIEnvironment(HttpServletRequest req) throws IOException { 963 964 969 970 Hashtable envp = new Hashtable (); 971 972 envp.putAll(shellEnv); 974 975 String sPathInfoOrig = null; 977 String sPathTranslatedOrig = null; 978 String sPathInfoCGI = null; 979 String sPathTranslatedCGI = null; 980 String sCGIFullPath = null; 981 String sCGIScriptName = null; 982 String sCGIFullName = null; 983 String sCGIName = null; 984 String [] sCGINames; 985 986 987 sPathInfoOrig = this.pathInfo; 988 sPathInfoOrig = sPathInfoOrig == null ? "" : sPathInfoOrig; 989 990 sPathTranslatedOrig = req.getPathTranslated(); 991 sPathTranslatedOrig = 992 sPathTranslatedOrig == null ? "" : sPathTranslatedOrig; 993 994 if (webAppRootDir == null ) { 995 webAppRootDir = tmpDir.toString(); 997 expandCGIScript(); 998 } 999 1000 sCGINames = findCGI(sPathInfoOrig, 1001 webAppRootDir, 1002 contextPath, 1003 servletPath, 1004 cgiPathPrefix); 1005 1006 sCGIFullPath = sCGINames[0]; 1007 sCGIScriptName = sCGINames[1]; 1008 sCGIFullName = sCGINames[2]; 1009 sCGIName = sCGINames[3]; 1010 1011 if (sCGIFullPath == null 1012 || sCGIScriptName == null 1013 || sCGIFullName == null 1014 || sCGIName == null) { 1015 return false; 1016 } 1017 1018 envp.put("SERVER_SOFTWARE", "TOMCAT"); 1019 1020 envp.put("SERVER_NAME", nullsToBlanks(req.getServerName())); 1021 1022 envp.put("GATEWAY_INTERFACE", "CGI/1.1"); 1023 1024 envp.put("SERVER_PROTOCOL", nullsToBlanks(req.getProtocol())); 1025 1026 int port = req.getServerPort(); 1027 Integer iPort = (port == 0 ? new Integer (-1) : new Integer (port)); 1028 envp.put("SERVER_PORT", iPort.toString()); 1029 1030 envp.put("REQUEST_METHOD", nullsToBlanks(req.getMethod())); 1031 1032 envp.put("REQUEST_URI", nullsToBlanks(req.getRequestURI())); 1033 1034 1035 1046 if (pathInfo == null 1047 || (pathInfo.substring(sCGIFullName.length()).length() <= 0)) { 1048 sPathInfoCGI = ""; 1049 } else { 1050 sPathInfoCGI = pathInfo.substring(sCGIFullName.length()); 1051 } 1052 envp.put("PATH_INFO", sPathInfoCGI); 1053 1054 1055 1074 if (sPathInfoCGI != null && !("".equals(sPathInfoCGI))) { 1075 sPathTranslatedCGI = context.getRealPath(sPathInfoCGI); 1076 } else { 1077 sPathTranslatedCGI = null; 1078 } 1079 if (sPathTranslatedCGI == null || "".equals(sPathTranslatedCGI)) { 1080 } else { 1082 envp.put("PATH_TRANSLATED", nullsToBlanks(sPathTranslatedCGI)); 1083 } 1084 1085 1086 envp.put("SCRIPT_NAME", nullsToBlanks(sCGIScriptName)); 1087 1088 envp.put("QUERY_STRING", nullsToBlanks(req.getQueryString())); 1089 1090 envp.put("REMOTE_HOST", nullsToBlanks(req.getRemoteHost())); 1091 1092 envp.put("REMOTE_ADDR", nullsToBlanks(req.getRemoteAddr())); 1093 1094 envp.put("AUTH_TYPE", nullsToBlanks(req.getAuthType())); 1095 1096 envp.put("REMOTE_USER", nullsToBlanks(req.getRemoteUser())); 1097 1098 envp.put("REMOTE_IDENT", ""); 1100 envp.put("CONTENT_TYPE", nullsToBlanks(req.getContentType())); 1101 1102 1103 1107 int contentLength = req.getContentLength(); 1108 String sContentLength = (contentLength <= 0 ? "" : 1109 (new Integer (contentLength)).toString()); 1110 envp.put("CONTENT_LENGTH", sContentLength); 1111 1112 1113 Enumeration headers = req.getHeaderNames(); 1114 String header = null; 1115 while (headers.hasMoreElements()) { 1116 header = null; 1117 header = ((String ) headers.nextElement()).toUpperCase(); 1118 if ("AUTHORIZATION".equalsIgnoreCase(header) || 1122 "PROXY_AUTHORIZATION".equalsIgnoreCase(header)) { 1123 } else { 1125 envp.put("HTTP_" + header.replace('-', '_'), 1126 req.getHeader(header)); 1127 } 1128 } 1129 1130 File fCGIFullPath = new File (sCGIFullPath); 1131 command = fCGIFullPath.getCanonicalPath(); 1132 1133 envp.put("X_TOMCAT_SCRIPT_PATH", command); 1135 envp.put("SCRIPT_FILENAME", command); 1137 this.env = envp; 1138 1139 return true; 1140 1141 } 1142 1143 1147 protected void expandCGIScript() { 1148 StringBuffer srcPath = new StringBuffer (); 1149 StringBuffer destPath = new StringBuffer (); 1150 InputStream is = null; 1151 1152 if (cgiPathPrefix == null ) { 1154 srcPath.append(pathInfo); 1155 is = context.getResourceAsStream(srcPath.toString()); 1156 destPath.append(tmpDir); 1157 destPath.append(pathInfo); 1158 } else { 1159 srcPath.append(cgiPathPrefix); 1161 StringTokenizer pathWalker = 1162 new StringTokenizer (pathInfo, "/"); 1163 while (pathWalker.hasMoreElements() && (is == null)) { 1165 srcPath.append("/"); 1166 srcPath.append(pathWalker.nextElement()); 1167 is = context.getResourceAsStream(srcPath.toString()); 1168 } 1169 destPath.append(tmpDir); 1170 destPath.append("/"); 1171 destPath.append(srcPath); 1172 } 1173 1174 if (is == null) { 1175 if (debug >= 2) { 1177 log("expandCGIScript: source '" + srcPath + "' not found"); 1178 } 1179 return; 1180 } 1181 1182 File f = new File (destPath.toString()); 1183 if (f.exists()) { 1184 return; 1186 } 1187 1188 String dirPath = new String (destPath.toString().substring( 1190 0,destPath.toString().lastIndexOf("/"))); 1191 File dir = new File (dirPath); 1192 dir.mkdirs(); 1193 1194 try { 1195 synchronized (expandFileLock) { 1196 if (f.exists()) { 1198 return; 1199 } 1200 1201 if (!f.createNewFile()) { 1203 return; 1204 } 1205 FileOutputStream fos = new FileOutputStream (f); 1206 1207 IOTools.flow(is, fos); 1209 is.close(); 1210 fos.close(); 1211 if (debug >= 2) { 1212 log("expandCGIScript: expanded '" + srcPath + "' to '" + destPath + "'"); 1213 } 1214 } 1215 } catch (IOException ioe) { 1216 if (f.exists()) { 1218 f.delete(); 1219 } 1220 } 1221 } 1222 1223 1224 1231 public String toString() { 1232 1233 StringBuffer sb = new StringBuffer (); 1234 1235 sb.append("<TABLE border=2>"); 1236 1237 sb.append("<tr><th colspan=2 bgcolor=grey>"); 1238 sb.append("CGIEnvironment Info</th></tr>"); 1239 1240 sb.append("<tr><td>Debug Level</td><td>"); 1241 sb.append(debug); 1242 sb.append("</td></tr>"); 1243 1244 sb.append("<tr><td>Validity:</td><td>"); 1245 sb.append(isValid()); 1246 sb.append("</td></tr>"); 1247 1248 if (isValid()) { 1249 Enumeration envk = env.keys(); 1250 while (envk.hasMoreElements()) { 1251 String s = (String ) envk.nextElement(); 1252 sb.append("<tr><td>"); 1253 sb.append(s); 1254 sb.append("</td><td>"); 1255 sb.append(blanksToString((String ) env.get(s), 1256 "[will be set to blank]")); 1257 sb.append("</td></tr>"); 1258 } 1259 } 1260 1261 sb.append("<tr><td colspan=2><HR></td></tr>"); 1262 1263 sb.append("<tr><td>Derived Command</td><td>"); 1264 sb.append(nullsToBlanks(command)); 1265 sb.append("</td></tr>"); 1266 1267 sb.append("<tr><td>Working Directory</td><td>"); 1268 if (workingDirectory != null) { 1269 sb.append(workingDirectory.toString()); 1270 } 1271 sb.append("</td></tr>"); 1272 1273 sb.append("<tr><td>Command Line Params</td><td>"); 1274 for (int i=0; i < cmdLineParameters.size(); i++) { 1275 String param = (String ) cmdLineParameters.get(i); 1276 sb.append("<p>"); 1277 sb.append(param); 1278 sb.append("</p>"); 1279 } 1280 sb.append("</td></tr>"); 1281 1282 sb.append("</TABLE><p>end."); 1283 1284 return sb.toString(); 1285 } 1286 1287 1288 1289 1295 protected String getCommand() { 1296 return command; 1297 } 1298 1299 1300 1301 1307 protected File getWorkingDirectory() { 1308 return workingDirectory; 1309 } 1310 1311 1312 1313 1319 protected Hashtable getEnvironment() { 1320 return env; 1321 } 1322 1323 1324 1325 1331 protected ArrayList getParameters() { 1332 return cmdLineParameters; 1333 } 1334 1335 1336 1337 1344 protected boolean isValid() { 1345 return valid; 1346 } 1347 1348 1349 1350 1357 protected String nullsToBlanks(String s) { 1358 return nullsToString(s, ""); 1359 } 1360 1361 1362 1363 1371 protected String nullsToString(String couldBeNull, 1372 String subForNulls) { 1373 return (couldBeNull == null ? subForNulls : couldBeNull); 1374 } 1375 1376 1377 1378 1386 protected String blanksToString(String couldBeBlank, 1387 String subForBlanks) { 1388 return (("".equals(couldBeBlank) || couldBeBlank == null) 1389 ? subForBlanks 1390 : couldBeBlank); 1391 } 1392 1393 1394 1395 } 1397 1398 1399 1400 1401 1402 1426 1427 protected class CGIRunner { 1428 1429 1430 private String command = null; 1431 1432 1433 private Hashtable env = null; 1434 1435 1436 private File wd = null; 1437 1438 1439 private ArrayList params = null; 1440 1441 1442 private InputStream stdin = null; 1443 1444 1445 private HttpServletResponse response = null; 1446 1447 1448 private boolean readyToRun = false; 1449 1450 1451 1452 1453 1467 protected CGIRunner(String command, Hashtable env, File wd, 1468 ArrayList params) { 1469 this.command = command; 1470 this.env = env; 1471 this.wd = wd; 1472 this.params = params; 1473 updateReadyStatus(); 1474 } 1475 1476 1477 1478 1481 protected void updateReadyStatus() { 1482 if (command != null 1483 && env != null 1484 && wd != null 1485 && params != null 1486 && response != null) { 1487 readyToRun = true; 1488 } else { 1489 readyToRun = false; 1490 } 1491 } 1492 1493 1494 1495 1501 protected boolean isReady() { 1502 return readyToRun; 1503 } 1504 1505 1506 1507 1514 protected void setResponse(HttpServletResponse response) { 1515 this.response = response; 1516 updateReadyStatus(); 1517 } 1518 1519 1520 1521 1527 protected void setInput(InputStream stdin) { 1528 this.stdin = stdin; 1529 updateReadyStatus(); 1530 } 1531 1532 1533 1534 1546 protected String [] hashToStringArray(Hashtable h) 1547 throws NullPointerException { 1548 Vector v = new Vector (); 1549 Enumeration e = h.keys(); 1550 while (e.hasMoreElements()) { 1551 String k = e.nextElement().toString(); 1552 v.add(k + "=" + h.get(k)); 1553 } 1554 String [] strArr = new String [v.size()]; 1555 v.copyInto(strArr); 1556 return strArr; 1557 } 1558 1559 1560 1561 1610 protected void run() throws IOException { 1611 1612 1615 1616 if (!isReady()) { 1617 throw new IOException (this.getClass().getName() 1618 + ": not ready to run."); 1619 } 1620 1621 if (debug >= 1 ) { 1622 log("runCGI(envp=[" + env + "], command=" + command + ")"); 1623 } 1624 1625 if ((command.indexOf(File.separator + "." + File.separator) >= 0) 1626 || (command.indexOf(File.separator + "..") >= 0) 1627 || (command.indexOf(".." + File.separator) >= 0)) { 1628 throw new IOException (this.getClass().getName() 1629 + "Illegal Character in CGI command " 1630 + "path ('.' or '..') detected. Not " 1631 + "running CGI [" + command + "]."); 1632 } 1633 1634 1639 Runtime rt = null; 1640 InputStream cgiOutput = null; 1641 BufferedReader commandsStdErr = null; 1642 BufferedOutputStream commandsStdIn = null; 1643 Process proc = null; 1644 int bufRead = -1; 1645 1646 StringBuffer cmdAndArgs = new StringBuffer (); 1648 if (command.indexOf(" ") < 0) { 1649 cmdAndArgs.append(command); 1650 } else { 1651 cmdAndArgs.append("\""); 1653 cmdAndArgs.append(command); 1654 cmdAndArgs.append("\""); 1655 } 1656 1657 for (int i=0; i < params.size(); i++) { 1658 cmdAndArgs.append(" "); 1659 String param = (String ) params.get(i); 1660 if (param.indexOf(" ") < 0) { 1661 cmdAndArgs.append(param); 1662 } else { 1663 cmdAndArgs.append("\""); 1665 cmdAndArgs.append(param); 1666 cmdAndArgs.append("\""); 1667 } 1668 } 1669 1670 StringBuffer command = new StringBuffer (cgiExecutable); 1671 command.append(" "); 1672 command.append(cmdAndArgs.toString()); 1673 cmdAndArgs = command; 1674 1675 try { 1676 rt = Runtime.getRuntime(); 1677 proc = rt.exec(cmdAndArgs.toString(), hashToStringArray(env), wd); 1678 1679 String sContentLength = (String ) env.get("CONTENT_LENGTH"); 1680 1681 if(!"".equals(sContentLength)) { 1682 commandsStdIn = new BufferedOutputStream (proc.getOutputStream()); 1683 IOTools.flow(stdin, commandsStdIn); 1684 commandsStdIn.flush(); 1685 commandsStdIn.close(); 1686 } 1687 1688 1693 1694 boolean isRunning = true; 1695 commandsStdErr = new BufferedReader 1696 (new InputStreamReader (proc.getErrorStream())); 1697 final BufferedReader stdErrRdr = commandsStdErr ; 1698 1699 new Thread () { 1700 public void run () { 1701 sendToLog(stdErrRdr) ; 1702 } ; 1703 }.start() ; 1704 1705 InputStream cgiHeaderStream = 1706 new HTTPHeaderInputStream(proc.getInputStream()); 1707 BufferedReader cgiHeaderReader = 1708 new BufferedReader (new InputStreamReader (cgiHeaderStream)); 1709 1710 while (isRunning) { 1711 try { 1712 String line = null; 1714 while (((line = cgiHeaderReader.readLine()) != null) 1715 && !("".equals(line))) { 1716 if (debug >= 2) { 1717 log("runCGI: addHeader(\"" + line + "\")"); 1718 } 1719 if (line.startsWith("HTTP")) { 1720 response.setStatus(getSCFromHttpStatusLine(line)); 1721 } else if (line.indexOf(":") >= 0) { 1722 String header = 1723 line.substring(0, line.indexOf(":")).trim(); 1724 String value = 1725 line.substring(line.indexOf(":") + 1).trim(); 1726 if (header.equalsIgnoreCase("status")) { 1727 response.setStatus(getSCFromCGIStatusHeader(value)); 1728 } else { 1729 response.addHeader(header , value); 1730 } 1731 } else { 1732 log("runCGI: bad header line \"" + line + "\""); 1733 } 1734 } 1735 1736 byte[] bBuf = new byte[2048]; 1738 1739 OutputStream out = response.getOutputStream(); 1740 cgiOutput = proc.getInputStream(); 1741 1742 try { 1743 while ((bufRead = cgiOutput.read(bBuf)) != -1) { 1744 if (debug >= 4) { 1745 log("runCGI: output " + bufRead + 1746 " bytes of data"); 1747 } 1748 out.write(bBuf, 0, bufRead); 1749 } 1750 } finally { 1751 if (bufRead != -1) { 1755 while ((bufRead = cgiOutput.read(bBuf)) != -1) {} 1756 } 1757 } 1758 1759 proc.exitValue(); 1761 isRunning = false; 1762 1763 } catch (IllegalThreadStateException e) { 1764 try { 1765 Thread.sleep(500); 1766 } catch (InterruptedException ignored) { 1767 } 1768 } 1769 } 1771 cgiOutput.close(); 1773 } 1774 catch (IOException e){ 1775 log ("Caught exception " + e); 1776 throw e; 1777 } 1778 finally{ 1779 if (debug > 4) { 1780 log ("Running finally block"); 1781 } 1782 if (proc != null){ 1783 proc.destroy(); 1784 proc = null; 1785 } 1786 } 1787 } 1788 1789 1796 private int getSCFromHttpStatusLine(String line) { 1797 int statusStart = line.indexOf(' ') + 1; 1798 1799 if (statusStart < 1 || line.length() < statusStart + 3) { 1800 log ("runCGI: invalid HTTP Status-Line:" + line); 1802 return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 1803 } 1804 1805 String status = line.substring(statusStart, statusStart + 3); 1806 1807 int statusCode; 1808 try { 1809 statusCode = Integer.parseInt(status); 1810 } catch (NumberFormatException nfe) { 1811 log ("runCGI: invalid status code:" + status); 1813 return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 1814 } 1815 1816 return statusCode; 1817 } 1818 1819 1827 private int getSCFromCGIStatusHeader(String value) { 1828 if (value.length() < 3) { 1829 log ("runCGI: invalid status value:" + value); 1831 return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 1832 } 1833 1834 String status = value.substring(0, 3); 1835 1836 int statusCode; 1837 try { 1838 statusCode = Integer.parseInt(status); 1839 } catch (NumberFormatException nfe) { 1840 log ("runCGI: invalid status code:" + status); 1842 return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 1843 } 1844 1845 return statusCode; 1846 } 1847 1848 private void sendToLog(BufferedReader rdr) { 1849 String line = null; 1850 int lineCount = 0 ; 1851 try { 1852 while ((line = rdr.readLine()) != null) { 1853 log("runCGI (stderr):" + line) ; 1854 lineCount++ ; 1855 } 1856 } catch (IOException e) { 1857 log("sendToLog error", e) ; 1858 } finally { 1859 try { 1860 rdr.close() ; 1861 } catch (IOException ce) { 1862 log("sendToLog error", ce) ; 1863 } ; 1864 } ; 1865 if ( lineCount > 0 && debug > 2) { 1866 log("runCGI: " + lineCount + " lines received on stderr") ; 1867 } ; 1868 } 1869 } 1871 1876 protected class HTTPHeaderInputStream extends InputStream { 1877 private static final int STATE_CHARACTER = 0; 1878 private static final int STATE_FIRST_CR = 1; 1879 private static final int STATE_FIRST_LF = 2; 1880 private static final int STATE_SECOND_CR = 3; 1881 private static final int STATE_HEADER_END = 4; 1882 1883 private InputStream input; 1884 private int state; 1885 1886 HTTPHeaderInputStream(InputStream theInput) { 1887 input = theInput; 1888 state = STATE_CHARACTER; 1889 } 1890 1891 1894 public int read() throws IOException { 1895 if (state == STATE_HEADER_END) { 1896 return -1; 1897 } 1898 1899 int i = input.read(); 1900 1901 1917 if (i == 10) { 1918 switch(state) { 1920 case STATE_CHARACTER: 1921 state = STATE_FIRST_LF; 1922 break; 1923 case STATE_FIRST_CR: 1924 state = STATE_FIRST_LF; 1925 break; 1926 case STATE_FIRST_LF: 1927 case STATE_SECOND_CR: 1928 state = STATE_HEADER_END; 1929 break; 1930 } 1931 1932 } else if (i == 13) { 1933 switch(state) { 1935 case STATE_CHARACTER: 1936 state = STATE_FIRST_CR; 1937 break; 1938 case STATE_FIRST_CR: 1939 state = STATE_HEADER_END; 1940 break; 1941 case STATE_FIRST_LF: 1942 state = STATE_SECOND_CR; 1943 break; 1944 } 1945 1946 } else { 1947 state = STATE_CHARACTER; 1948 } 1949 1950 return i; 1951 } 1952 } 1954} | Popular Tags |