1 package com.quadcap.http.servlets.cgi; 2 3 40 41 import java.io.ByteArrayOutputStream ; 42 import java.io.File ; 43 import java.io.FileOutputStream ; 44 import java.io.InputStream ; 45 import java.io.IOException ; 46 import java.io.OutputStream ; 47 48 import java.util.Hashtable ; 49 import java.util.Enumeration ; 50 import java.util.Vector ; 51 52 import java.net.URLEncoder ; 53 54 import javax.servlet.ServletException ; 55 56 import javax.servlet.http.HttpServletRequest ; 57 import javax.servlet.http.HttpServletResponse ; 58 59 import com.quadcap.http.util.HeaderParser; 60 61 import com.quadcap.io.LogInputStream; 62 63 import com.quadcap.util.text.Scanner; 64 65 import com.quadcap.util.Debug; 66 67 72 public class CgiScript { 73 CgiServlet servlet; 74 File script; 75 String interp; 76 77 static final String FORM_ENCODED = "application/x-www-form-urlencoded"; 78 79 public CgiScript(CgiServlet servlet, String interp, File script) { 80 this.servlet = servlet; 81 this.interp = interp; 82 this.script = script; 83 } 84 85 final String ns(String s) { 86 return s == null ? "" : s; 87 } 88 89 public synchronized void service(HttpServletRequest req, 90 HttpServletResponse res) 91 throws IOException , ServletException 92 { 93 boolean form = false; 94 byte[] formData = null; 95 if (req.getMethod().equalsIgnoreCase("POST") && 96 req.getContentType().equalsIgnoreCase(FORM_ENCODED)) { 97 form = true; 98 ByteArrayOutputStream bos = new ByteArrayOutputStream (); 99 Enumeration ed = req.getParameterNames(); 100 boolean first = true; 101 while (ed.hasMoreElements()) { 102 String name = ed.nextElement().toString(); 103 String [] vals = req.getParameterValues(name); 104 for (int i = 0; i < vals.length; i++) { 105 if (!first) bos.write('&'); 106 first = false; 107 bos.write(URLEncoder.encode(name).getBytes()); 108 bos.write('='); 109 bos.write(URLEncoder.encode(vals[i]).getBytes()); 110 } 111 } 112 formData = bos.toByteArray(); 113 } else { 114 formData = new byte[0]; 115 } 116 if (Trace.bit(2)) { 118 Debug.println("formData = " + new String (formData)); 119 } 120 122 123 Vector env = new Vector (); 124 if (form) { 125 env.addElement("CONTENT_LENGTH=" + formData.length); 126 } else { 127 env.addElement("CONTENT_LENGTH=" + req.getContentLength()); 128 } 129 env.addElement("CONTENT_TYPE=" + req.getContentType()); 130 env.addElement("DOCUMENT_ROOT=" + 131 servlet.getServletConfig().getServletContext().getRealPath(".")); 132 env.addElement("GATEWAY_INTERFACE=1.1"); 133 env.addElement("HTTP_ACCEPT=" + req.getHeader("Http-Accept")); 134 env.addElement("HTTP_USER_AGENT=" + req.getHeader("User-Agent")); 135 env.addElement("PATH_INFO=" + ns(req.getPathInfo())); 136 env.addElement("QUERY_STRING=" + req.getQueryString()); 137 env.addElement("REQUEST_METHOD=" + req.getMethod()); 138 env.addElement("SCRIPT_NAME=" + req.getServletPath()); 139 env.addElement("SERVER_NAME=" + req.getServerName()); 140 env.addElement("SERVER_PORT=" + req.getServerPort()); 141 env.addElement("SERVER_PROTOCOL=" + req.getProtocol()); 142 143 String [] envp = new String [env.size()]; 144 for (int i = 0; i < env.size(); i++) { 145 envp[i] = env.elementAt(i).toString(); 146 if (Trace.bit(2)) { 148 Debug.println(" " + envp[i]); 149 } 150 } 152 153 String [] cmdp = new String [2]; 154 155 cmdp[0] = interp; 156 cmdp[1] = script.getAbsolutePath(); 157 158 res.setContentType("text/html"); 159 160 if (Trace.bit(0)) { 162 Debug.println("Invoking: " + cmdp[0] + " " + cmdp[1]); 163 } 164 Process cgi = Runtime.getRuntime().exec(cmdp, envp); 166 InputStream pi = cgi.getInputStream(); 167 168 172 OutputStream po = cgi.getOutputStream(); 173 InputStream pe = cgi.getErrorStream(); 174 175 OutputStream so = res.getOutputStream(); 176 ByteArrayOutputStream se = new ByteArrayOutputStream (); 177 178 Thread t1 = makeInputThread(formData, po); 179 Thread t2 = makeOutputThread(pi, so, res); 180 Thread t3 = makeCopyThread(pe, se); 181 182 t1.start(); 183 t2.start(); 184 t3.start(); 185 int ret = 0; 186 187 try { ret = cgi.waitFor(); } catch (Exception e) {} 188 try { t1.join(); } catch (Exception e) {} 189 try { t2.join(); } catch (Exception e) {} 190 try { t3.join(); } catch (Exception e) {} 191 192 if (Trace.bit(1)) { 194 Debug.println("stderr: " + se.toString()); 195 } 196 198 if (ret != 0) { 200 throw new ServletException ("Script failed: " + se.toString()); 201 } 202 } 203 204 208 public static Thread makeInputThread(final byte[] formData, 209 final OutputStream out) { 210 Thread t = new Thread () { 211 public void run() { 212 int c; 213 try { 214 out.write(formData); 215 out.close(); 216 } catch (IOException e) { 217 Debug.print(e); 218 } 219 } 220 }; 221 return t; 222 } 223 224 public static Thread makeOutputThread(final InputStream in, 225 final OutputStream out, 226 final HttpServletResponse res) { 227 Thread t = new Thread () { 228 Hashtable headers = new Hashtable (); 229 Scanner scanner = new Scanner(in); 230 boolean terminate = false; 231 public void run() { 232 int c; 233 try { 234 try { 235 HeaderParser.parseHeaders(scanner, headers); 236 } catch (Throwable e) { 237 Debug.print(e); 238 Debug.println("scanner = " + scanner.getLog()); 240 } 242 Enumeration e = headers.keys(); 243 while (e.hasMoreElements()) { 244 String hdr = (String )e.nextElement(); 245 String val = (String )headers.get(hdr); 246 if (hdr.equals("status")) { 247 int code = Integer.parseInt(val.substring(0,3)); 248 String reason = val.substring(4); 249 if (code == 303) { 250 res.sendRedirect(reason); 251 return; 252 } else { 253 res.setStatus(code, reason); 254 } 255 } else if (hdr.equals("content-type")) { 256 res.setContentType(val); 257 } else if (hdr.equals("location")) { 258 res.sendRedirect(val); 259 } else { 260 res.setHeader(hdr, val); 261 } 262 } 263 264 while (!terminate && (c = in.read()) >= 0) { 265 out.write(c); 266 } 267 } catch (IOException e) { 268 Debug.print(e); 269 } 270 } 271 public void terminate() { 272 this.terminate = true; 273 } 274 }; 275 return t; 276 } 277 278 282 public static Thread makeCopyThread(final InputStream in, 283 final OutputStream out) { 284 Thread t = new Thread () { 285 boolean terminate = false; 286 public void run() { 287 int c; 288 try { 289 while (!terminate && (c = in.read()) >= 0) out.write(c); 290 } catch (IOException e) { 291 Debug.print(e); 292 } 293 } 294 public void terminate() { 295 this.terminate = true; 296 } 297 }; 298 return t; 299 } 300 301 } 302 303 | Popular Tags |