fsockopen - how to detect end of message? - php

I have code:
$f = fsockopen('mail.myserver.com', 110); //POP3
echo fgets($f, 4096) . '<hr>';
fputs($f, "USER login#myserver.com\r\n");
echo fgets($f) . '<br>';
fputs($f, "PASS mypass\r\n");
echo fgets($f) . '<br>';
fputs($f, "LIST\r\n");
echo fgets($f) . '<br>';
fputs($f, "RETR 1\r\n");
So far so good, but then I have a loop to receive the whole message:
while (!feof($f))
{
echo fgets($f, 1280);
}
and it takes forever because the script waits for timeouts to kick in—it NEVER detects EOF by itself.
How can I detect EOF and break the loop before it times out? If I use telnet then everything works—somehow telnet clients know when to stop receiving.

See:
Warning If a connection opened by fsockopen() wasn't closed by the server, feof() will hang. To workaround this, see below example:
On: feof
The workaround essentially waits default_socket_timeout and then terminates the while-loop.

Sockets may provide a better alternative to handling timeouts/hangs.

Related

stream_select(), signals and Stdin in PHP

I am trying to write a native PHP CLI application which reads data (log data) from stdin and does some handling after.
I got a first working version with a simple while-Loop:
while ($line = fgets(STDIN)) {
// Do my stuff here
}
When installing signal handling via
function signal_handler(int $signo, mixed $siginfo) {
// ...
}
pcntl_async_signals(TRUE);
pcntl_signal(SIGHUP, 'signal_handler');
this works partly: The signals are only processed after each fgets().
I tried to use stream_select() with NULL as timeout and some other stuff, but this lead to a massive system load :-)
Is there any best practice to use stream_select() and fgets() on stdin to read data until it's "ready" and wait/pause indefinitely else but let signals being processed?
You can use stream_set_blocking(STDIN, 0); to remove the blocking.
Example:
function signal_handler(int $signo, $siginfo) {
exit("signal caught\n");
}
stream_set_blocking(STDIN, 0);
pcntl_async_signals(TRUE);
pcntl_signal(SIGHUP, 'signal_handler');
echo "pid=" . posix_getpid() . "\n";
echo "Listening input...\n";
while (true) {
while ($line = fgets(STDIN)) {
echo "Input: '$line'\n";
}
}
Possible output:
Pid=46834
Listening input...
Input: 'test'
signal caught
See stream_set_blocking()

popened process never dies

I am using this neat code that tails a logfile live on the browser (thanks SO!)
The problem is that tail remains running even after user closes the tab/browser/pc
any ideas?
logs are still being written while window is closed, so I know that the server is trying to send something and fails, but the if connection_status()​!=0 seems to never fire
<?php
$files = scandir('somefile', SCANDIR_SORT_DESCENDING);
$newestfile = $files[0];
echo "$newestfile<br/>\n";
$handle = popen("tail -fn +1 ./somedir/" . $newestfile . " 2>&1", 'r');
while(!feof($handle)) {
if (connection_status()​!=0){
exec("killall tail");
pclose($handle);
}
$buffer = fgets($handle);
echo "$buffer<br/>\n";
ob_flush();
flush();
}
pclose($handle);
?>
Update:
I ended up using a modified version of this:
https://github.com/richardvk/web_file_tail
KUDOS to this guy!

shell_exec in PHP returns empty string

shell_exec and exec are not returning any content. I can't figure out what's wrong.
Here's some code:
echo 'test: ';
$output = shell_exec('whoami');
var_export($output, TRUE);
echo PHP_EOL . '<br>' . PHP_EOL;
And here's the source of the output
test 2:
<br>
I do not have control over the host, but I believe they're running SuPHP. According to phpinfo, safe_mode is off. Running whoami from SSH outputs the expected value.
I'm at a loss. Any idea how to debug this?
You're never printing the $output variable. The var_export() call returns the content of the variable when you call it with a true second parameter, it does not print it directly.
If you want the output from a shell command read back into PHP, you're probably going to need popen(). For example:
if( ($fp = popen("some shell command", "r")) ) {
while( !feof($fp) ) {
echo fread($fp, 1024);
flush(); // input will be buffered
}
fclose($fp);
}

Reading data from fsockopen using fgets/fread hangs

Here is the code that I am using:
if (!($fp = fsockopen('ssl://imap.gmail.com', '993', $errno, $errstr, 15)))
echo "Could not connect to host";
$server_response = fread($fp, 256);
echo $server_response;
fwrite($fp, "C01 CAPABILITY"."\r\n");
while (!feof($fp)) {
echo fgets($fp, 256);
}
I get the first response:
OK Gimap ready for requests from xx.xx.xx.xx v3if9968808ibd.15
but then the page times out. I have searched through stream_set_blocking, stream_set_timeout, stream_select, fread, etc. but could not get it to work. I need to read all the data that the server sends and then proceed with other commands (I would be retrieving emails using imap).
Thanks
Your script is hanging in the while loop at the end. This is because you have used !feof() as the condition for the loop, and the server is not closing the connection. This means the feof() will always return false and the loop will continue forever.
This will not be problem when your write a full implementation, as you will be looking for response codes and can break out of the loop accordingly, for example:
<?php
// Open a socket
if (!($fp = fsockopen('ssl://imap.gmail.com', 993, $errno, $errstr, 15))) {
die("Could not connect to host");
}
// Set timout to 1 second
if (!stream_set_timeout($fp, 1)) die("Could not set timeout");
// Fetch first line of response and echo it
echo fgets($fp);
// Send data to server
echo "Writing data...";
fwrite($fp, "C01 CAPABILITY\r\n");
echo " Done\r\n";
// Keep fetching lines until response code is correct
while ($line = fgets($fp)) {
echo $line;
$line = preg_split('/\s+/', $line, 0, PREG_SPLIT_NO_EMPTY);
$code = $line[0];
if (strtoupper($code) == 'C01') {
break;
}
}
echo "I've finished!";
Your script should be working. In fact, it is working.
See the results below on my pc when I ran your code:
* OK Gimap ready for requests from xx.xx.xx.xx l5if4585958ebb.20
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH
C01 OK Thats all she wrote! l5if4585958ebb.20
Since gmail doesn't disconnect you. No end of file occurs. And the page loading simply times out.
In other words: Your script will just keep waiting and waiting until gmail does disconnect, which unfortunately happens after your page load has already timed out.

php shell_exec with realtime updating

I have this shell program that I want to execute by php. The problem is that it can potentially take a long time, and as of that I need it to have real-time updating to the user's browser.
I read that I may need to use popen() to do that, but I am sort of (ok, I really am :P) a PHP noob and can't figure out how I may be able to do it.
Would appreciate any help!
if( ($fp = popen("your command", "r")) ) {
while( !feof($fp) ){
echo fread($fp, 1024);
flush(); // you have to flush buffer
}
fclose($fp);
}
there is a dirty easy option
`yourcommand 1>&2`;
redirecting the stdout to the stderr.
there are two possible behaviors:
Non Block, where you need to do something else between flushs (#GameBit show how to do it).
With Block, where you wait until the called command finish, in this case look passthru function
I used this solution. It works fine for me.
$commandString = "myexe";
# Uncomment this line if you want to execute the command in background on Windows
# $commandString = "start /b $commandString";
$exec = popen($commandString, "r");
# echo "Async Code Test";
while($output = fgets($exec, 2048))
{
echo "$output <br>\n";
ob_flush();
flush();
}
pclose($exec);
try this code (tested on Windows machine + wamp server)
header('Content-Encoding: none;');
set_time_limit(0);
$handle = popen("<<< Your Shell Command >>>", "r");
if (ob_get_level() == 0)
ob_start();
while(!feof($handle)) {
$buffer = fgets($handle);
$buffer = trim(htmlspecialchars($buffer));
echo $buffer . "<br />";
echo str_pad('', 4096);
ob_flush();
flush();
sleep(1);
}
pclose($handle);
ob_end_flush();

Categories