Using php-cgi with webserver in android - java

I found that we can run Phpcgi on android by going to this site.I have created a web server in android it works fine and i have installed Php cgi and want to ask that how can i link both so that i can run php scripts as well as HTML pages.Any help will be appreciated.
Update:
In my Request Processor the out is sent like this:
contentType = guessContentTypeFromName(filename);
Date now = new Date( );
out.write("Date: " + now + "\r\n");
out.write("Server: JHTTP/1.0\r\n");
out.write("Content-length: " + theData.length + "\r\n");
out.write("Content-type: " + contentType + "\r\n\r\n");
out.flush( );
guessConte....()
if (name.endsWith(".php")) {
String pathToPhpExecutable = Environment.getExternalStorageDirectory() + "/data" + "/php-cgi";
String phpFile ="" + "/php/myPhpFile.php";
Process process = null;
try {
process = new ProcessBuilder()
.command(pathToPhpExecutable, phpFile)
.redirectErrorStream(true)
.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
} finally {
process.destroy();
}

You can use the Process and ProcessBuilder classes to create and execute an command. Keep in mind that depending on the process you want to execute, you may require root permissions and it won't work on non-rooted Android devices.
String pathToPhpExecutable = getFileDir() + "/php-cgi";
String phpFile = getFileDir() + "/php/myPhpFile.php";
Process process = new ProcessBuilder()
.command(pathToPhpExecutable, phpFile)
.redirectErrorStream(true)
.start();
try {
InputStream in = process.getInputStream();
// Read the input stream and i.e. display the results in a WebView
} finally {
process.destroy();
}
Don't be confused by the naming. According to the Process documentation getInputStream() returns the output of the stream connected to the std::out. This will return Code (Json, HTML, plain text) generated by the PHP.
However, chances are you will need root for it to work. Or that the files won't have execution permission (x in Linux) when you unpack them from your APK. But calling chmod or chown (if it's assigned to the wrong user name) will most likely require an rooted Android devices.
Process | Android Developers

Related

ProcessBuilder failing when calling a system command where Runtime exec works

I'm having trouble with ProcessBuilder not running a command on the server.
Early in my project I use Runtime.exec() just to retrieve output from a program which works fine:
private List<SatelliteCode> getSatelliteCodes() {
List<SatelliteCode> codes = new ArrayList<>();
Runtime runtime = Runtime.getRuntime();
String[] commands = { "w_scan", "-s?" };
Process process;
try {
process = runtime.exec(commands);
BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String s = error.readLine(); // discard first line
while ((s = error.readLine()) != null) {
s = s.trim();
int i = s.indexOf('\t'); // separated by a tab!?!?
codes.add(new SatelliteCode(s.substring(0, i), s.substring(i)));
}
} catch (IOException e) {
e.printStackTrace();
}
return codes;
}
Running this in the terminal works fine and I get all the output I need:
w_scan -fs -cGB -sS19E2 > channels.conf
However, the server needs to grab the ongoing output from the 'process.getErrorStream()' to display in the web interface. What is actually happening is the ProcessBuilder is failing and returning an exit code of 1.
The function that initialises the ProcessBuilder and to start the scan running is [EDIT 1]:
private static StringBuilder scan_error_output = null;
#Override
public boolean startSatelliteScan(String user, String country_code, String satellite_code) {
UserAccountPermissions perm = validateUserEdit(user);
if (perm == null) return false;
Shared.writeUserLog(user, Shared.getTimeStamp() +
": DVB satellite scan started " +
country_code + " - " + satellite_code +
System.lineSeparator() + System.lineSeparator());
scan_error_output = new StringBuilder();
new ScanThread(country_code, satellite_code).start();
// write out country code and satellite code to prefs file
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(satellite_last_scan_codes));
bw.write(country_code); bw.newLine();
bw.write(satellite_code); bw.newLine();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
That will then run two other threads on the server, one that will run the scan itself and wait for it to finish so that it can get the final scan data. And the other which constantly updates the output from the std error stream which is then polled at intervals from the clients browser. This is much like showing the ongoing output from the terminal.
The scan thread (which fails to start the process) [EDIT 1]:
private static class ScanThread extends Thread {
private String cc, sc;
public ScanThread(String country_code, String satellite_code) {
cc = country_code;
sc = satellite_code;
}
public void run() {
ProcessBuilder pb = new ProcessBuilder("/usr/bin/w_scan",
"-fs", "-c" + cc, "-s" + sc);
pb.redirectOutput(new File(satellite_scan_file));
Process process;
try {
System.out.println("Scan thread started");
process = pb.start();
IOScanErrorOutputHandler error_output_handler = new IOScanErrorOutputHandler(process.getErrorStream());
error_output_handler.start();
int result = process.waitFor();
System.out.println(cc + " - " + sc + " - " +
"Process.waitFor() result " + result);
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
System.out.println("Scan thread finished");
}
}
The error output stream thread which captures the output which obviously doesn't start due to the scan thread failing:
private static class IOScanErrorOutputHandler extends Thread {
private InputStream inputStream;
IOScanErrorOutputHandler(InputStream inputStream) {
this.inputStream = inputStream;
}
public void run() {
Scanner br = null;
try {
System.out.println("Scan thread Error IO capture running");
br = new Scanner(new InputStreamReader(inputStream));
String line = null;
while (br.hasNextLine()) {
line = br.nextLine();
scan_error_output.append(line + System.getProperty("line.separator"));
}
} finally {
br.close();
}
System.out.println("Scan thread Error IO capture finished");
scan_error_output = null;
}
}
And the server function which returns the std error output progress:
#Override
public String pollScanResult(String user) {
if (validateUserEdit(user) == null) return null;
StringBuilder sb = scan_error_output; // grab instance
if (sb == null) return null;
return sb.toString();
}
As mentioned above, Runtime.exec() works fine, but the ProcessBuilder is failing.
NB: I'm on Linux Mint 18.1, using Apache Tomcat 8 as the server, linux default JDK 8 and GWT 2.7 [Correction from 2.8] in Eclipse Neon.
Can anyone see what I am doing wrong?
Many thanks in advance...
[EDIT 1]
Whilst developing this on another machine, Linux Mint 17.2, JDK 8 and Apache Tomcat 7, for DVB-T, this method worked fine and polling for the scan output showed up in the client's browser.
The ProcessBuilder.start still returns 1 and an empty file is created for the output scan file.
[EDIT 2]
It appears that the reason the ProcessBuilder is failing is because the user 'tomcat8' doesn't have permissions to run 'w_scan'. 'w_scan' works from the terminal, but not from the tomcat server. Somehow I've got to fix that now.
[SOLUTIONS]
After being put in the right direction by VGR for getting the error stream from the ProcessBuilder, I started digging further and found I was getting:
main:3909: FATAL: failed to open '/dev/dvb/adapter0/frontend0': 13 Permission denied
Apache tomcat 8 didn't have permission to access the DVB-S frontend to run a scan. This was fixed in two ways:
1 - 03catalina.policy I added the extra permissions (whether they made a difference I do not know).
grant codeBase "file:/dev/dvb/-" {
permission java.io.FilePermission "file:/dev/dvb/-", "read, write";
permission java.security.AllPermission;
};
2 - The dvb frontends belong to the 'video' group. So I needed to add the user tomcat8 to that group.
usermod -a -G video tomcat8
All works for now...
You are not doing the same thing with ProcessBuilder that you’re doing with Runtime.exec, so I don't know why you think ProcessBuilder is the problem.
You have a few problems with how you’re writing the command’s output to a file.
First, the presence of ">", satellite_scan_temp_file in your ProcessBuilder command is incorrect. Output redirection is not part of any command; it is handled by a shell. But when you run with Runtime.exec or ProcessBuilder, you are not running in a shell, you are executing the process directly. Neither w_scan nor any other command considers > a special character.
The correct way to redirect to a file is with the redirectOutput method:
ProcessBuilder pb = new ProcessBuilder(
"/usr/bin/w_scan", "-fs", "-s" + satellite_code, "-c" + country_code);
pb.redirectOutput(new File(satellite_scan_temp_file));
Second, your ScanThread code is ignoring the (currently incorrect) redirect, and is attempting to read the command’s output. But there is no output, because you are redirecting it all to a file.
Once you are properly redirecting output to a file, you can remove your BufferedReader and BufferedWriter loops completely.
Finally, it is worth noting that the error output you captured probably told you that > is not a valid argument to the w_scan process.

Compiling Java program with VBScripts? (NetBeans)

I have a Java program created that runs VBSscripts after button clicks.
examplescript.vbs
How do I compile these vbs files and then call them to run in the program code? I've been troubleshooting for several days and can't find an answer. Once again I need to be able to run these scripts, at one point I had an input stream created to it but couldn't get it as a vbs file. Hopefully I'm overlooking something here
Edit:
This is what I currently have. With this code I receive the error "Windows Script Host. There is no script extension for file extension ".BufferedInputStream#4e34904""
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("hello.vbs");
try {
Runtime.getRuntime().exec("wscript " + is);
}
catch( IOException e ) {
System.out.println(e);
System.exit(0);
}
System.out.print(is);
You can run your VBScript as below.
Runtime.getRuntime().exec( "wscript path/to/examplescript.vbs" );
As already mentioned, VBScript is a script and doesn't need compiling. If you want to run code written in VBScript then you can do it this way:
This example uses VBScript to get the Motherboard Serial Number of a computer that is running Microsoft Windows:
try {
// Create a temporary script file named MBSerialxxxxxxxx.vbs
File file = File.createTempFile("MBSerial",".vbs");
// Delete the temporary file when virtual machines terminates
file.deleteOnExit();
try (FileWriter fw = new java.io.FileWriter(file)) {
String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+ "Set colItems = objWMIService.ExecQuery _ \n"
+ " (\"Select * from Win32_BaseBoard\") \n"
+ "For Each objItem in colItems \n"
+ " Wscript.Echo objItem.SerialNumber \n"
+ " exit for ' do the first cpu only! \n"
+ "Next \n";
fw.write(vbs);
}
// Run the VBScript file....
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
// Read in any output to the command window.
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
// display the output...
System.out.println(line.trim());
}
input.close();
}
catch(IOException e){
e.printStackTrace();
}

How to run application with parameters from within java application on mac osx

I am writing a small java application to load ZDoom with custom wad files on mac osx and am having trouble executing the command.
I have generated a string within the application that will run ZDoom and load the custom wad, I have tested this by copy-pasting the string from the netbeans breakline debugger and running it directly in terminal.
When I run the code through my application ZDoom does load up but it does so without the custom wad so I believe it is executing without it's arguments.
I have tried two different techniques to run the command:
private void loadZdoom() {
// get selected wad
String wad = (String) wadListComboBox.getSelectedItem();
ProcessBuilder builder = new ProcessBuilder(defaultZdoomInstallPath + "/Contents/MacOS/zdoom", "-file", defaultZdoomWadsPath.replace(" ", "\\ ") + "/" + wad);
builder.redirectErrorStream(true);
try {
Process p = builder.start();
} catch (IOException ex) {
}
}
And
private void loadZdoom() {
// get selected wad
String wad = (String) wadListComboBox.getSelectedItem();
String runCommand = defaultZdoomInstallPath + "/Contents/MacOS/zdoom " + "-file " + defaultZdoomWadsPath.replace(" ", "\\ ") + "/" + wad;
try {
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec(runCommand);
} catch (IOException e) {
}
}
What am I doing wrong here?
I figured out what the problem was, I was escaping the space in the path to the wad file as you need to do this in terminal but it seems this is unnecessary in JAVA. All is working as expected now :)

Java's System.getRuntime().exec not behaving as if the shell user called it

I am running a java application from the console on an HP-UX machine. In it, I generate some reports, zip them, and then email them. Everything is working, except the email.
I am using the mail binary to send mail from the command line. Since it's HP-UX, it's a bit different than the standard GNU sendmail.
This is the code I'm using to send the mail:
public static void EmailReports(String[] recipients, String reportArchive, String subject){
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
String today = dateFormat.format(new Date());
File tempEmailFile;
BufferedWriter emailWriter;
try {
tempEmailFile = File.createTempFile("report_email_" + today, "msg");
emailWriter = new BufferedWriter(new FileWriter(tempEmailFile));
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not create temporary file.");
return;
}
try {
emailWriter.write("SUBJECT: " + subject + "\n");
emailWriter.write("FROM: " + FROM + "\n");
emailWriter.write(BODY + "\n");
emailWriter.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not write to temporary file.");
}
//read the archive in
try {
FileInputStream archiveIS = new FileInputStream(new File(reportArchive));
OutputStream archiveEncoder = MimeUtility.encode(new FileOutputStream(tempEmailFile, true), "uuencode", Zipper.getArchiveName(reportArchive));
//read archive
byte[] buffer = new byte[archiveIS.available()]; //these should never be more than a megabyte or two, so storing it in memory is no big deal.
archiveIS.read(buffer);
//encode archive
archiveEncoder.write(buffer);
//close both
archiveIS.close();
archiveEncoder.close();
} catch (FileNotFoundException e) {
System.out.println("Failed to send email. Could not find archive to email.");
e.printStackTrace();
} catch (MessagingException e) {
System.out.println("Failed to send email. Could not encode archive.");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not encode archive.");
}
System.out.println("Sending '" + subject + "' email.");
try {
Process p = Runtime.getRuntime().exec("mail me#example.com < " + tempEmailFile.getAbsolutePath());
System.out.println("mail me#example.com < " + tempEmailFile.getAbsolutePath());
StringBuffer buffer = new StringBuffer();
while(p.getErrorStream().available() > 0){
buffer.append((char) p.getErrorStream().read());
}
System.out.println("STDERR: " + buffer.toString());
buffer = new StringBuffer();
while(p.getInputStream().available() > 0){
buffer.append((char) p.getInputStream().read());
}
System.out.println("STDOUT: " + buffer.toString());
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not get access to the shell.");
}
}
When I run the program, and it sends the email, I get a blank email, no subject, no body, no attachment, and it's from the user#hostname from the HP-UX box instead of from the email specified in FROM.
However, when I run the same line that it runs (see the command printed out after I call exec), I get the correct email, from the correct user, with a subject, body, and attachment.
STDOUT and STDERR are both empty. It's almost as if I'm sending mail a blank file, but when I print the file before I call the exec, it's there.
What's going on here?
Edit: Attempts made:
Using Ksh:
try {
String cmd = "mail me#example.com.com < " + tempEmailFile.getAbsolutePath();
Runtime.getRuntime().exec(new String[] {"/usr/bin/ksh", cmd});
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not get access to the shell.");
}
Using STDIN:
try {
System.out.println("mail me#example.com < " + tempEmailFile.getAbsolutePath());
Process p = Runtime.getRuntime().exec("mail me#example.com ");
FileInputStream inFile = new FileInputStream(tempEmailFile);
byte[] byteBuffer = new byte[inFile.available()];
inFile.read(byteBuffer);
p.getOutputStream().write(byteBuffer);
inFile.close();
p.getOutputStream().close();
StringBuffer buffer = new StringBuffer();
while(p.getErrorStream().available() > 0){
buffer.append((char) p.getErrorStream().read());
}
System.out.println("STDERR: " + buffer.toString());
buffer = new StringBuffer();
while(p.getInputStream().available() > 0){
buffer.append((char) p.getInputStream().read());
}
System.out.println("STDOUT: " + buffer.toString());
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not get access to the shell.");
}
I strongly suspect the problem is the redirection. That's normally handled by the shell - and there's no shell here.
Either you need to execute the process normally and then get the process's standard input stream and write to it from Java, or (probably simpler) run /bin/sh (or whatever) to get the shell to do the redirection.
Try exec'ing { "ksh", "-c", "mail me#example.com < " + etc }. The -c option tells the shell specifically to parse the next argument as a shell command with possible redirection and so on. Without the -c, ksh follows a heuristic to decide what to do with its command line, and it may not be running the command in the way you want it to.
Split into two lines, just to get better readability:
String cmd = "mail me#example.com < " + tempEmailFile.getAbsolutePath () ;
Process p = Runtime.getRuntime().exec (cmd);
This will look for a program named "mail me#example.com < " + tempEmailFile.getAbsolutePath (). It will not do redirection - for that to do you have to read the output of that process yourself.
Furtermore it will not lookup the path, so you might have to specify the whole path /usr/bin/mail or whatever it is.
And you have to split command and parameters; use an Array of String instead: ("/path/to/prg", "param1", "param2", "foo=bar");
You can use redirection, if you call as program a script, like
String cmd = "/usr/bin/mail me#example.com < " + tempEmailFile.getAbsolutePath () ;
String cmdarr = new String [] {"/bin/bash", "-c", cmd};
Process p = Runtime.getRuntime().exec (cmdarr);
It is shorter than invoking file redirection from Java yourself, more simple but you lose the ability to react sensible on different errors.

How to realize "mklink /H" (hardlinking) in Java?

i want to create a hardlink from a file "C:\xxx.log" to "C:\mklink\xxx.log" .
In cmd it works of course, but i want to write a software for this usecase.
So have to locate the existing file
Then make a hardlink
Then delete the old file
I started to implement but, i just know how to create a file. On google i found nothing about mklink \H for Java.
public void createFile() {
boolean flag = false;
// create File object
File stockFile = new File("c://mklink/test.txt");
try {
flag = stockFile.createNewFile();
} catch (IOException ioe) {
System.out.println("Error while Creating File in Java" + ioe);
}
System.out.println("stock file" + stockFile.getPath() + " created ");
}
There are 3 ways to create a hard link in JAVA.
JAVA 1.7 Supports hardlinks.
http://docs.oracle.com/javase/tutorial/essential/io/links.html#hardLink
JNA, The JNA allows you to make native system calls.
https://github.com/twall/jna
JNI, you could use C++ to create a hardlink and then call it through JAVA.
Hope this helps.
Link (soft or hard) is a OS feature that is not exposed to standard java API. I'd suggest you to run command mklink /h from java using Runitme.exec() or ProcessBuilder.
Or alternatively try to find 3rd party API that wraps this. Also check what's new in Java 7. Unfortunately I am not familiar with it but I know that they added rich file system API.
For posterity, I use the following method to create links on *nix/OSX or Windows. On windows mklink /j creates a "junction" which seems to be similar to a symlink.
protected void makeLink(File existingFile, File linkFile) throws IOException {
Process process;
String unixLnPath = "/bin/ln";
if (new File(unixLnPath).canExecute()) {
process =
Runtime.getRuntime().exec(
new String[] { unixLnPath, "-s", existingFile.getPath(), linkFile.getPath() });
} else {
process =
Runtime.getRuntime().exec(
new String[] { "cmd", "/c", "mklink", "/j", linkFile.getPath(), existingFile.getPath() });
}
int errorCode;
try {
errorCode = process.waitFor();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Link operation was interrupted", e);
}
if (errorCode != 0) {
logAndThrow("Could not create symlink from " + linkFile + " to " + existingFile, null);
}
}

Categories

Resources