File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Servlets and the fly likes Can you execute CGI From a Servlet? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Servlets
Bookmark "Can you execute CGI From a Servlet?" Watch "Can you execute CGI From a Servlet?" New topic
Author

Can you execute CGI From a Servlet?

Brian Podolny
Ranch Hand

Joined: Aug 29, 2000
Posts: 32
I have a commercial cgi program (read as blackbox) which, for security reasons, I cannot expose directly to web users.
What I want to do is receive the request for the program and reroute it to a servlet which would perform authorization checking on the user. If the user is authorized then the java servlet would execute the cgi program directly and return the output to the user.
A call to the cgi program using Runtime.exec(program) doesn't work because the cgi program needs to be running in the web server environment.
I can accomplish what I want by running a batch file (this on Windows2K) as a cgi and then running the cgi program from the batch file but this an inelegant solution.
Any ideas? Thanks a bunch!
[ December 06, 2002: Message edited by: Brian Podolny ]
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12675
    
    5
How much of the server environment does the CGI really need? You might be able to fake it using the form of exec that includes environment string values.
Bill


Java Resources at www.wbrogden.com
Bruce Jin
Ranch Hand

Joined: Sep 20, 2001
Posts: 666
You can hide your CGI in a protected area and have a servlet to call it. I think in your servlet you need to use URL class to do this.


BJ - SCJP and SCWCD
We love Java programming. It is contagious, very cool, and lot of fun. - Peter Coad, Java Design

Crazy Bikes created by m-Power
Brian Podolny
Ranch Hand

Joined: Aug 29, 2000
Posts: 32
William,
Unfortunately, I can't just pass the environment variables to the commercial CGI program directly because the company that wrote it won't reveal what information it requires.
Bruce,
Could you elaborate a little more on what you mean by a protected area and what you would be using the URL class for?
Thanks to both of you for your help.
[ December 06, 2002: Message edited by: Brian Podolny ]
Randy Motluck
Greenhorn

Joined: Jul 19, 2002
Posts: 10
You could try this:
I found some code on:
http://www.webdeveloper.com/java/java_jj_read_write.html .
Combining that with a servlet, I was able to call a script that prints out the junk from the CGI environment (local Apache httpd w/ Perl).
Your idea sparked my interest and I can use it.
Here is the doGet() from my servlet CGIHandler.
Hope this helps.
-Randy
*************************************
public void doGet(
javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
boolean isValid = false;
//get theCgiUrl from Request URL or just set it to a static dest.
String theCgiUrl = "http://localhost/cgi-bin/printenv.pl";
String errorUrl = "http://127.0.0.1/"; //probably a local JSP like cgiError.jsp or something

ServletContext ctx = getServletContext();

//do some authorization, I will just set to true
isValid = true;

URL myUrl = null;
if(isValid)
{
myUrl = new URL(theCgiUrl);
}
else // isValid == false <=> not authorized
{
myUrl = new URL(errorUrl);
}
//log which URK
ctx.log(this.getClass().getName() + " -> using URL: " + myUrl);
//capture the URL's ctxtent
URLConnection conn = myUrl.openConnection();
conn.connect();
ctx.log(this.getClass().getName() + " -> connected..." );
//now get the content into a buffer.
DataInputStream data = null;
String line;
String content = "";
StringBuffer buf = new StringBuffer();
data = new DataInputStream(new BufferedInputStream(conn.getInputStream()));
while ((line = data.readLine()) != null)
{
buf.append(line + "\n");
content += line;
}
data.close();
//print it out
PrintWriter out = response.getWriter();
out.print(content);
}//end doGet()
Bruce Jin
Ranch Hand

Joined: Sep 20, 2001
Posts: 666
Because you don�t want your CGI to be accessed by browser directly you have to put it in a location that can�t be seen by browser. See <security-constraint> tag in web.xml file.
URL class can be used to retrieve resource from web. You can use it to get response from your CGI and resend that response to browser.
I have not done this myself. Just guess this might be one of the ways to do it.
Thanks.
Brian Podolny
Ranch Hand

Joined: Aug 29, 2000
Posts: 32
Sorry if this sounds a bit lame-brained but if the CGI has been placed in a directory that is not directly accessible via the webserver then how is a URL, even a local one, going to resolve to CGI program which, if I understand your suggestion correctly, is not accessible via direct URL.
Bruce Jin
Ranch Hand

Joined: Sep 20, 2001
Posts: 666
Brian:
I tried hard and I could not find a way to implement what I proposed above. Sorry.
Another thing to try is to add a simple interface to the CGI so that it can be called from an application rather than browser and have it output to some other stream instead of the browser. For example I added the following code to a servlet (servlet is just a special CGI) then this servlet can be called from an application (even from command line) and output to a file.
public static void main(String[] str) {

ServeltA aa = new ServletA();

try {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(�out.txt�)));
aa.start(out,sapplnp, satype);
out.close();
} catch(IOException e){
System.err.println( e);
}

}
}
Randy Motluck
Greenhorn

Joined: Jul 19, 2002
Posts: 10
In my example, I called a Perl CGI script on my own computer. I think your answer is the setup in the machine. You could restrict access to the web server that hosts your CGI. If you restrict it such that the only requests it answers are the ones coming from your machine where the Java app server runs, you are done. You just need to make sure the Servlet has the security you desire.
This would work for a GET Method. The Servlet can pick up the form data from the URL and pass it along. I did not try this for any POST method forms, but I would imagine that you could just rip off the encoded arguments and shoot them over the socket to the CGI server.
-Randy
-Randy
 
 
subject: Can you execute CGI From a Servlet?
 
Similar Threads
Interacting with Windows command prompt
runnning a java program via a batch file
calling batch files
invoke batch file on a remote machine
Create a process from Servlet