1 9 15 package org.mortbay.servlet; 16 17 import java.io.File ; 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.io.OutputStream ; 21 import java.util.Enumeration ; 22 import java.util.HashMap ; 23 import java.util.Iterator ; 24 import java.util.Map ; 25 26 import javax.servlet.ServletException ; 27 import javax.servlet.http.HttpServlet ; 28 import javax.servlet.http.HttpServletRequest ; 29 import javax.servlet.http.HttpServletResponse ; 30 31 import org.apache.commons.logging.Log; 32 import org.mortbay.log.LogFactory; 33 import org.mortbay.http.HttpFields; 34 import org.mortbay.util.IO; 35 import org.mortbay.util.LineInput; 36 import org.mortbay.util.LogSupport; 37 import org.mortbay.util.StringUtil; 38 39 60 public class CGI extends HttpServlet 61 { 62 private static Log log = LogFactory.getLog(CGI.class); 63 64 protected File _docRoot; 65 protected String _path; 66 protected String _cmdPrefix; 67 protected EnvList _env; 68 69 70 public void init() 71 throws ServletException 72 { 73 _env= new EnvList(); 74 _cmdPrefix=getInitParameter("commandPrefix"); 75 76 String tmp = getInitParameter("cgibinResourceBase"); 77 if (tmp==null) 78 tmp = getServletContext().getRealPath("/"); 79 80 if(log.isDebugEnabled())log.debug("CGI: CGI bin "+tmp); 81 82 if (tmp==null) 83 { 84 log.warn("CGI: no CGI bin !"); 85 throw new ServletException (); 86 } 87 88 File dir = new File (tmp); 89 if (!dir.exists()) 90 { 91 log.warn("CGI: CGI bin does not exist - "+dir); 92 throw new ServletException (); 93 } 94 95 if (!dir.canRead()) 96 { 97 log.warn("CGI: CGI bin is not readable - "+dir); 98 throw new ServletException (); 99 } 100 101 if (!dir.isDirectory()) 102 { 103 log.warn("CGI: CGI bin is not a directory - "+dir); 104 throw new ServletException (); 105 } 106 107 try 108 { 109 _docRoot=dir.getCanonicalFile(); 110 if(log.isDebugEnabled())log.debug("CGI: CGI bin accepted - "+_docRoot); 111 } 112 catch (IOException e) 113 { 114 log.warn("CGI: CGI bin failed - "+dir); 115 e.printStackTrace(); 116 throw new ServletException (); 117 } 118 119 _path=getInitParameter("Path"); 120 if(log.isDebugEnabled())log.debug("CGI: PATH accepted - "+_path); 121 if (_path != null) 122 _env.set("PATH", _path); 123 124 Enumeration e= getInitParameterNames(); 125 while (e.hasMoreElements()) 126 { 127 String n= (String )e.nextElement(); 128 if (n != null && n.startsWith("ENV_")) 129 _env.set(n.substring(4),getInitParameter(n)); 130 } 131 } 132 133 134 public void service(HttpServletRequest req, HttpServletResponse res) 135 throws ServletException , IOException 136 { 137 String pathInContext = 138 StringUtil.nonNull(req.getServletPath()) + 139 StringUtil.nonNull(req.getPathInfo()); 140 141 if(log.isDebugEnabled())log.debug("CGI: req.getContextPath() : "+req.getContextPath()); 142 if(log.isDebugEnabled())log.debug("CGI: req.getServletPath() : "+req.getServletPath()); 143 if(log.isDebugEnabled())log.debug("CGI: req.getPathInfo() : "+req.getPathInfo()); 144 if(log.isDebugEnabled())log.debug("CGI: _docRoot : "+_docRoot); 145 146 147 151 String both=pathInContext; 152 String first=both; 153 String last=""; 154 155 File exe=new File (_docRoot, first); 156 157 while ((first.endsWith("/") || !exe.exists()) && first.length()>=0) 158 { 159 int index=first.lastIndexOf('/'); 160 161 first=first.substring(0, index); 162 last=both.substring(index, both.length()); 163 exe=new File (_docRoot, first); 164 } 165 166 if (first.length()==0 || 167 !exe.exists() || 168 !exe.getCanonicalPath().equals(exe.getAbsolutePath()) || 169 exe.isDirectory()) 170 res.sendError(404); 171 else 172 { 173 if(log.isDebugEnabled())log.debug("CGI: script is "+exe); 174 if(log.isDebugEnabled())log.debug("CGI: pathInfo is "+last); 175 176 exec(exe, last, req, res); 177 } 178 } 179 180 181 188 private void exec(File command, 189 String pathInfo, 190 HttpServletRequest req, 191 HttpServletResponse res) 192 throws IOException 193 { 194 String path=command.toString(); 195 File dir=command.getParentFile(); 196 if(log.isDebugEnabled())log.debug("CGI: execing: "+path); 197 198 EnvList env = new EnvList(_env); 199 200 env.set("AUTH_TYPE", req.getAuthType()); 203 env.set("CONTENT_LENGTH", Integer.toString(req.getContentLength())); 204 env.set("CONTENT_TYPE", req.getContentType()); 205 env.set("GATEWAY_INTERFACE", "CGI/1.1"); 206 env.set("PATH_INFO", pathInfo); 207 env.set("PATH_TRANSLATED", req.getPathTranslated()); 208 env.set("QUERY_STRING", req.getQueryString()); 209 env.set("REMOTE_ADDR", req.getRemoteAddr()); 210 env.set("REMOTE_HOST", req.getRemoteHost()); 211 env.set("REMOTE_USER", req.getRemoteUser()); 217 env.set("REQUEST_METHOD", req.getMethod()); 218 String scriptName = req.getRequestURI().substring(0,req.getRequestURI().length() - pathInfo.length()); 219 env.set("SCRIPT_NAME",scriptName); 220 env.set("SCRIPT_FILENAME",getServletContext().getRealPath(scriptName)); 221 env.set("SERVER_NAME", req.getServerName()); 222 env.set("SERVER_PORT", Integer.toString(req.getServerPort())); 223 env.set("SERVER_PROTOCOL", req.getProtocol()); 224 env.set("SERVER_SOFTWARE", getServletContext().getServerInfo()); 225 Enumeration enm = req.getHeaderNames(); 226 while (enm.hasMoreElements()) 227 { 228 String name = (String ) enm.nextElement(); 229 String value = req.getHeader(name); 230 env.set("HTTP_" + name.toUpperCase().replace( '-', '_' ), value); 231 } 232 233 env.set("HTTPS", (req.isSecure()?"ON":"OFF")); 235 239 243 String execCmd=path; 244 if (execCmd.indexOf(" ")>=0) 245 execCmd="\""+execCmd+"\""; 246 if (_cmdPrefix!=null) 247 execCmd=_cmdPrefix+" "+execCmd; 248 249 Process p=dir==null 250 ?Runtime.getRuntime().exec(execCmd, env.getEnvArray()) 251 :Runtime.getRuntime().exec(execCmd, env.getEnvArray(),dir); 252 253 final InputStream inFromReq=req.getInputStream(); 255 final OutputStream outToCgi=p.getOutputStream(); 256 final int inputLength = req.getContentLength(); 257 258 new Thread (new Runnable () 259 { 260 public void run() 261 { 262 try{ 263 if (inputLength>0) 264 IO.copy(inFromReq,outToCgi,inputLength); 265 outToCgi.close(); 266 } 267 catch(IOException e){LogSupport.ignore(log,e);} 268 } 269 }).start(); 270 271 272 try 275 { 276 LineInput li = new LineInput(p.getInputStream()); 278 HttpFields fields=new HttpFields(); 279 fields.read(li); 280 281 String ContentStatus = "Status"; 282 String redirect = fields.get(HttpFields.__Location); 283 String status = fields.get(ContentStatus); 284 285 if (status!=null) 286 { 287 log.debug("Found a Status header - setting status on response"); 288 fields.remove(ContentStatus); 289 290 int i = status.indexOf(' '); 293 if (i>0) 294 status = status.substring(0,i); 295 296 res.setStatus(Integer.parseInt(status)); 297 } 298 299 for (Iterator i=fields.iterator(); i.hasNext();) 301 { 302 HttpFields.Entry e=(HttpFields.Entry)i.next(); 303 res.addHeader(e.getKey(),e.getValue()); 304 } 305 306 if (status==null && redirect != null) 307 { 308 if (!redirect.startsWith("http:/")&&!redirect.startsWith("https:/")) 311 res.sendRedirect(redirect); 312 else 313 res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); 314 } 315 316 IO.copy(li, res.getOutputStream()); 318 319 p.waitFor(); 320 int exitValue = p.exitValue(); 321 if(log.isDebugEnabled())log.debug("CGI: p.exitValue(): " + exitValue); 322 if (0 != exitValue) 323 { 324 log.warn("Non-zero exit status ("+exitValue+ 325 ") from CGI program: "+path); 326 if (!res.isCommitted()) 327 res.sendError(500, "Failed to exec CGI"); 328 } 329 } 330 catch (IOException e) 331 { 332 log.debug("CGI: Client closed connection!"); 335 } 336 catch (InterruptedException ie) 337 { 338 log.debug("CGI: interrupted!"); 339 } 340 finally 341 { 342 p.destroy(); 343 } 344 345 if(log.isDebugEnabled())log.debug("CGI: Finished exec: " + p); 346 } 347 348 349 350 353 private static class EnvList 354 { 355 private Map envMap; 356 357 EnvList() 358 { 359 envMap= new HashMap (); 360 } 361 362 EnvList(EnvList l) 363 { 364 envMap= new HashMap (l.envMap); 365 } 366 367 369 public void set(String name, String value) { 370 envMap.put(name, name + "=" + StringUtil.nonNull(value)); 371 } 372 373 374 public String [] getEnvArray() 375 { 376 return (String [])envMap.values().toArray(new String [envMap.size()]); 377 } 378 } 379 } 380 | Popular Tags |