Coverage Report - org.webslinger.types.cgi
 
Classes in this File Line Coverage Branch Coverage Complexity
cgi
0%
0/131
0%
0/25
0
 
 1  
 package org.webslinger.types;
 2  
 
 3  
 import java.io.File;
 4  
 import java.io.InputStream;
 5  
 import java.io.IOException;
 6  
 import java.io.OutputStream;
 7  
 import java.util.Collection;
 8  
 import java.util.Enumeration;
 9  
 import java.util.Map;
 10  
 import java.util.Vector;
 11  
 import javax.servlet.ServletException;
 12  
 import javax.servlet.ServletRequest;
 13  
 import javax.servlet.ServletResponse;
 14  
 import javax.servlet.http.HttpServletRequest;
 15  
 import javax.servlet.http.HttpServletResponse;
 16  
 
 17  
 import org.apache.bsf.BSFException;
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 
 20  
 import org.webslinger.PathContext;
 21  
 import org.webslinger.TypeHandler;
 22  
 import org.webslinger.Webslinger;
 23  
 import org.webslinger.WebslingerServletContext;
 24  
 import org.webslinger.bsf.LanguageManager;
 25  
 import org.webslinger.commons.vfs.VFSUtil;
 26  
 import org.webslinger.io.IOUtil;
 27  
 
 28  0
 public class cgi extends TypeHandler {
 29  0
     private static final String[][] headerNames = new String[][] {
 30  
         {"Cookie",      "HTTP_COOKIE"},
 31  
         {"Host",        "HTTP_HOST"},
 32  
         {"Referer",     "HTTP_REFERER"},
 33  
         {"User-Agent",  "HTTP_USER_AGENT"},
 34  
     };
 35  0
     private static final File ROOT = new File("/");
 36  0
     private static final File CGI_BIN = new File("/usr/lib/cgi-bin");
 37  
 
 38  
 
 39  
     private static void setEnv(Map<String, String> env, String name, boolean value) {
 40  0
         env.put(name, value ? "on" : "off");
 41  0
     }
 42  
     static void setEnv(Map<String, String> env, String name, int value) {
 43  0
         if (value == -1) return;
 44  0
         env.put(name, Integer.toString(value));
 45  0
     }
 46  
 
 47  
     static void setEnv(Map<String, String> env, String name, Object value) {
 48  0
         if (value == null) return;
 49  0
         if (value instanceof Number) {
 50  0
             value = value.toString();
 51  0
         } else if (value instanceof Boolean) {
 52  0
             value = ((Boolean) value).booleanValue() ? "on" : "off";
 53  0
         } else if (!(value instanceof String)) {
 54  0
             throw new InternalError();
 55  
         }
 56  0
         env.put(name, (String) value);
 57  0
     }
 58  
 
 59  
     public Object run(Webslinger webslinger) throws IOException, ServletException {
 60  0
         HttpServletResponse response = webslinger.getResponse();
 61  0
         HttpServletRequest request = webslinger.getRequest();
 62  
 
 63  0
         String programName = (String) webslinger.getAttribute("program-name");
 64  0
         if (programName == null) {
 65  0
             response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "No program specified.");
 66  0
             return null;
 67  
         }
 68  0
         programName = StringUtils.chomp(programName);
 69  0
         if (programName.indexOf("/") != -1) {
 70  0
             response.sendError(HttpServletResponse.SC_FORBIDDEN, "Can't specify relative program.");
 71  0
             return null;
 72  
         }
 73  0
         File cgiProgram = new File(CGI_BIN, programName);
 74  0
         if (!cgiProgram.exists()) {
 75  0
             response.sendError(HttpServletResponse.SC_NOT_FOUND, "Script not found.");
 76  0
             return null;
 77  
         }
 78  
 
 79  0
         ProcessBuilder builder = new ProcessBuilder(cgiProgram.toString());
 80  0
         Map<String, String> env = builder.environment();
 81  
 
 82  0
         Enumeration<String> en = request.getHeaderNames();
 83  0
         while (en.hasMoreElements()) {
 84  0
             String headerName = en.nextElement();
 85  0
             setEnv(env, headerName.toUpperCase().replaceAll("-", "_"), request.getHeader(headerName));
 86  0
         }
 87  
 
 88  
         //SERVER_SOFTWARE
 89  
         //GATEWAY_INTERFACE
 90  
 
 91  
         //REMOTE_IDENT
 92  
 
 93  0
         if (request.getContentLength() >= 0) {
 94  0
             setEnv(env, "CONTENT_LENGTH", request.getContentLength());
 95  0
             setEnv(env, "CONTENT_TYPE", request.getContentType());
 96  
         }
 97  0
         setEnv(env, "AUTH_TYPE", request.getAuthType());
 98  0
         setEnv(env, "HTTPS", request.isSecure());
 99  0
         setEnv(env, "LOCAL_ADDR", request.getLocalAddr());
 100  0
         setEnv(env, "LOCAL_NAME", request.getLocalName());
 101  0
         setEnv(env, "LOCAL_PORT", request.getLocalPort());
 102  0
         setEnv(env, "PATH_INFO", request.getPathInfo());
 103  
         //setEnv(env, "PATH_TRANSLATED", request.getPathTranslated());
 104  0
         setEnv(env, "SERVER_PROTOCOL", request.getProtocol());
 105  0
         setEnv(env, "QUERY_STRING", request.getQueryString());
 106  0
         setEnv(env, "REMOTE_ADDR", request.getRemoteAddr());
 107  0
         setEnv(env, "REMOTE_HOST", request.getRemoteHost());
 108  0
         setEnv(env, "REMOTE_PORT", request.getRemotePort());
 109  0
         setEnv(env, "REMOTE_USER", request.getRemoteUser());
 110  0
         setEnv(env, "REQUEST_METHOD", request.getMethod());
 111  0
         setEnv(env, "SERVER_NAME", request.getServerName());
 112  0
         setEnv(env, "SERVER_PORT", request.getServerPort());
 113  0
         setEnv(env, "SCRIPT_NAME", webslinger.getServletPath());
 114  0
         builder.redirectErrorStream();
 115  0
         builder.directory(ROOT);
 116  0
         Process process = builder.start();
 117  0
         if (request.getContentLength() >= 0) {
 118  0
             IOUtil.copy(request.getInputStream(), true, process.getOutputStream(), true);
 119  
         }
 120  0
         InputStream input = process.getInputStream();
 121  0
         StringBuilder headerName = new StringBuilder();
 122  0
         StringBuilder headerValue = new StringBuilder();
 123  
 
 124  0
         int mode = 0;
 125  
         int c;
 126  
 READ_LOOP:
 127  0
         while ((c = input.read()) != -1) {
 128  0
             switch (mode) {
 129  
                 case 0:
 130  
                 case 1:
 131  0
                     switch (c) {
 132  
                         case ':':
 133  0
                             if (mode == 0) break READ_LOOP;
 134  0
                             mode = 2;
 135  0
                             break;
 136  
                         case 'a': case 'b': case 'c': case 'd': case 'e':
 137  
                         case 'f': case 'g': case 'h': case 'i': case 'j':
 138  
                         case 'k': case 'l': case 'm': case 'n': case 'o':
 139  
                         case 'p': case 'q': case 'r': case 's': case 't':
 140  
                         case 'u': case 'v': case 'w': case 'x': case 'y':
 141  
                         case 'z':
 142  
                         case 'A': case 'B': case 'C': case 'D': case 'E':
 143  
                         case 'F': case 'G': case 'H': case 'I': case 'J':
 144  
                         case 'K': case 'L': case 'M': case 'N': case 'O':
 145  
                         case 'P': case 'Q': case 'R': case 'S': case 'T':
 146  
                         case 'U': case 'V': case 'W': case 'X': case 'Y':
 147  
                         case 'Z':
 148  0
                             headerName.append((char) c);
 149  0
                             mode = 1;
 150  0
                             break;
 151  
                         case '-':
 152  
                         case '_':
 153  0
                             if (mode == 0) break READ_LOOP;
 154  0
                             headerName.append((char) c);
 155  0
                             mode = 1;
 156  0
                             break;
 157  
                         default:
 158  0
                             break READ_LOOP;
 159  
                     }
 160  
                     break;
 161  
                 case 2: case 3:
 162  0
                     switch (c) {
 163  
                         case ' ':
 164  0
                             if (mode == 2) {
 165  0
                                 mode = 3;
 166  0
                                 break;
 167  
                             }
 168  0
                             headerValue.append((char) c);
 169  0
                             break;
 170  
                         case '\r':
 171  0
                             mode = 4;
 172  0
                             break;
 173  
                         case '\n':
 174  0
                             mode = 5;
 175  0
                             break;
 176  
                         default:
 177  0
                             headerValue.append((char) c);
 178  0
                             break;
 179  
                     }
 180  
                     break;
 181  
                 case 4:
 182  0
                     mode = 5;
 183  0
                     if (c != '\n') continue;
 184  
                     break;
 185  
                 case 5:
 186  0
                     switch (c) {
 187  
                         case ' ':
 188  0
                             mode = 6;
 189  0
                             headerValue.append("\r\n ");
 190  0
                             break;
 191  
                         case 'a': case 'b': case 'c': case 'd': case 'e':
 192  
                         case 'f': case 'g': case 'h': case 'i': case 'j':
 193  
                         case 'k': case 'l': case 'm': case 'n': case 'o':
 194  
                         case 'p': case 'q': case 'r': case 's': case 't':
 195  
                         case 'u': case 'v': case 'w': case 'x': case 'y':
 196  
                         case 'z':
 197  
                         case 'A': case 'B': case 'C': case 'D': case 'E':
 198  
                         case 'F': case 'G': case 'H': case 'I': case 'J':
 199  
                         case 'K': case 'L': case 'M': case 'N': case 'O':
 200  
                         case 'P': case 'Q': case 'R': case 'S': case 'T':
 201  
                         case 'U': case 'V': case 'W': case 'X': case 'Y':
 202  
                         case 'Z':
 203  
                         case '\r':
 204  
                         case '\n':
 205  0
                             response.setHeader(headerName.toString(), headerValue.toString());
 206  0
                             headerName.setLength(0);
 207  0
                             headerValue.setLength(0);
 208  0
                             headerName.append((char) c);
 209  0
                             if (c == '\r') {
 210  0
                                 mode = 7;
 211  0
                             } else if (c == '\n') {
 212  0
                                 break READ_LOOP;
 213  
                             } else {
 214  0
                                 mode = 0;
 215  
                             }
 216  0
                             break;
 217  
                         default:
 218  0
                             break READ_LOOP;
 219  
                     }
 220  
                     break;
 221  
                 case 6:
 222  0
                     switch (c) {
 223  
                         case '\r':
 224  0
                             mode = 4;
 225  0
                             break;
 226  
                         case '\n':
 227  0
                             mode = 5;
 228  0
                             break;
 229  
                         default:
 230  0
                             headerValue.append((char) c);
 231  
                     }
 232  0
                     break;
 233  
                 case 7:
 234  0
                     if (c == '\n') mode = 8;
 235  0
                     break READ_LOOP;
 236  
             }
 237  
         }
 238  0
         OutputStream out = response.getOutputStream();
 239  0
         switch (mode) {
 240  
             case 0:
 241  0
                 if (c != -1) out.write((char) c);
 242  
                 break;
 243  
             case 1:
 244  0
                 out.write(headerName.toString().getBytes());
 245  0
                 if (c != -1) out.write((char) c);
 246  
                 break;
 247  
             case 2: case 3: case 4: case 5: case 6:
 248  0
                 out.write(headerName.toString().getBytes());
 249  0
                 out.write(headerValue.toString().getBytes());
 250  0
                 break;
 251  
             case 7:
 252  0
                 out.write((char) c);
 253  0
                 break;
 254  
             case 8:
 255  
                 break;
 256  
         }
 257  0
         IOUtil.copy(input, true, out, true);
 258  0
         return null;
 259  
     }
 260  
 }