This is the error log, and i have no idea how to solve this.
[Thu Jan 25 10:39:42.689306 2018] [:error] [pid 21084]
PHP Warning: fgets(): SSL operation failed with code 1.
OpenSSL Error messages:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypterror:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypterror:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypterror:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt in ../vendor/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Connection/Socket.php on line 156
public function read($size = null)
{
$got_data = false;
$literal_len = null;
$token = new Horde_Imap_Client_Tokenize();
do {
if (feof($this->_stream)) {
$this->close();
$this->_params['debug']->info(
'ERROR: Server closed the connection.'
);
throw new Horde_Imap_Client_Exception(
Horde_Imap_Client_Translation::r("Mail server closed the connection unexpectedly."),
Horde_Imap_Client_Exception::DISCONNECT
);
}
if (is_null($literal_len)) {
$buffer = '';
while (($in = fgets($this->_stream)) !== false) {
$got_data = true;
if (substr($in, -1) === "\n") {
$in = rtrim($in);
$this->_params['debug']->server($buffer . $in);
$token->add($in);
break;
}
$buffer .= $in;
$token->add($in);
}
/* Check for literal data. */
if (is_null($len = $token->getLiteralLength())) {
break;
}
// Skip 0-length literal data.
if ($len['length']) {
$binary = $len['binary'];
$literal_len = $len['length'];
}
continue;
}
$old_len = $literal_len;
while (($literal_len > 0) && !feof($this->_stream)) {
$in = fread($this->_stream, min($literal_len, 8192));
/* Only store in stream if this is something more than a
* nominal number of bytes. */
if ($old_len > 256) {
$token->addLiteralStream($in);
} else {
$token->add($in);
}
if (!empty($this->_params['debugliteral'])) {
$this->_params['debug']->raw($in);
}
$got_data = true;
$literal_len -= strlen($in);
}
$literal_len = null;
if (empty($this->_params['debugliteral'])) {
$this->_params['debug']->server('[' . ($binary ? 'BINARY' : 'LITERAL') . ' DATA: ' . $old_len . ' bytes]');
}
} while (true);
if (!$got_data) {
$this->_params['debug']->info('ERROR: read/timeout error.');
throw new Horde_Imap_Client_Exception(
Horde_Imap_Client_Translation::r("Error when communicating with the mail server."),
Horde_Imap_Client_Exception::SERVER_READERROR
);
}
return $token;
}
The error appears at
while (($in = fgets($this->_stream)) !== false) {
I have another Instance of my application on the same server with the same settings just different database and domain name.
The other Instance seems to work just fine without having problems with this error.
Note: Horde is a kind of PHP library for sending Emails.
Can anyone help me?
Please try to change your setting as below:
<?php
$yourArrayOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
)
$response = file_get_contents("fileName", false,
stream_context_create($yourArrayOptions));
echo $response; ?>
please click here for better explanation file_get_contents(): SSL operation failed with code 1. And more
Related
Is it possible to have PHP scripts send data through to a Node.js server through websockets?
I'm planning a side project that would have PHP scripts running in the background working some magic and the front end application that end users would use would be in Node.js. There would be some socket.io interaction just in Node.js but I'd like the ability to push data into socket.io from the PHP scripts.
I am also working on this.
My implementation is a little different than others.
Most people use php & curl + nodejs & express & socketio
I've done it the following way:
memcache in both php and nodejs (to share the userid and cookie) (you can also use redis)
a custom PHP class to send a request via websocket to localhost, where the nodejs server broadcasts to a user room (all sessions from the same user).
Here is the class I used to communicate from php to socketio (sends only data to nodejs and not the way around!)
When I connect to socket.io, my script reads my php cookie and sends it to the node server, where it accesses the memcache json sessions and identifies the user, joining him to a room.
Here is a php json-serialized memcached session handler class. It is similar to the one I used.
To make a request in php --> socket.io i do the following:
$s = new SocketIO('127.0.0.1', 8088);
$adata = "On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain.";
$msg = json_encode(array('event'=> 'passdata','data'=> $adata, 'to'=> 1));
$tr = 0;
$fl = 0;
for ($i = 0 ; $i < 1000; $i++) {
$s->send( 'broadcast', $msg ) ? $tr++ : $fl++;
}
echo "HIT : " . $tr . PHP_EOL;
echo "MISS: " . $fl;
When a (socket.io) request from localhost goes to the server, i run this code:
var is_local = (this_ip === '127.0.0.1' ? true : false);
socket.on('broadcast', function(data) {
if (data.length === 0 ) return;
if (is_local && typeof data === 'string') {
try {
var j = JSON.parse(data);
} catch (e) {
console.log("invalid json # broadcast".red);
return false;
}
if (!j.hasOwnProperty('to') && !j.hasOwnProperty('event')) return false;
io.to(j.to).emit(j.event, j.data);
console.log('brc'.blue + ' to: ' + j.to + ' evt: ' + j.event);
/** #todo remove disconnect & try to create permanent connection */
socket.disconnect();
} else { console.log('brc ' + 'error'.red ); }
});
If i want to pass data from node to php, I simply exec php code on my nodejs server.
like this:
socket.on('php', function(func, data, callback) {
/* some functions */
if (check_usr(session) === false) return;
console.log('php'.green + ' act:' + func);
var cmd = 'php -r \'$_COOKIE["MONSTER"]="' + session + '"; require(\"' + __dirname + '/' + php_[func].exec + '\");\'';
console.log(cmd);
cp.exec(cmd ,
function(err, stdout, stderr) {
if (err == null) {
console.log(typeof callback);
console.log(JSON.parse(callback));
if (callback != null) callback(stdout);
console.log(stdout);
//socket.emit('php', {uid: uid, o: stdout});
console.log('emitted');
} else {
console.log('err '.red + stdout + ' ' + stderr);
}
});
});
The answer is yes, but exact implementation depends on your environment / requirements.
Here is one example I've hacked from a recent project: it sends a message, then waits for a response to end in chr(10) ("\n"). That response must be received within 0.5 seconds otherwise it assumes failure (see the timing loop). You can fiddle with those bits as needed.
Note: $ip and $port need to be passed in.
$retval = false; // final return value will conatin something if it all works
$socket = #socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false || !is_resource($socket)) {
$socket = false;
$this->lastErrorNum = socket_last_error();
$this->lastErrorMsg = 'Unable to create socket: ' . socket_strerror(socket_last_error());
} elseif (!#socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
$this->lastErrorNum = socket_last_error($socket);
$this->lastErrorMsg = 'Unable to set options on socket: ' . socket_strerror($this->lastErrorNum);
#socket_clear_error ( $socket );
} elseif (!#socket_connect($socket, $ip, $port)) {
$this->lastErrorNum = socket_last_error($socket);
$this->lastErrorMsg = 'Unable to connect socket: ' . socket_strerror($this->lastErrorNum);
#socket_clear_error ( $socket );
} else {
// Socket connected - send message
if (!#socket_write($socket, $message, strlen($message))) {
$this->lastErrorNum = socket_last_error($socket);
$this->lastErrorMsg = 'Unable to write to socket: ' . socket_strerror($this->lastErrorNum);
#socket_clear_error ( $socket );
} else {
// Read a response
$receiveStartTime = microtime(true);
$response = '';
socket_set_nonblock ($socket);
while(microtime(true) - $receiveStartTime < 0.5) {
$n = #socket_recv($socket, $dataIn, 1024, 0); // Assume max return value is 1024 bytes.
if ($n) {
$response .= $dataIn;
}
if (strpos($dataIn, "\n") !== false) {
#socket_clear_error ( $socket );
$response = str_replace("\n", '', $response);
break;
}
}
if (socket_last_error($socket) > 0) {
$this->lastErrorNum = socket_last_error($socket);
$this->lastErrorMsg = 'Unable to read from socket: ' . socket_strerror($this->lastErrorNum);
#socket_clear_error ( $socket );
} else {
$retval = $response;
}
}
#socket_close($socket);
}
I'm trying to extract song title from live mp3 streams using SC protocol. The php script works fine with some IPs and ports, however with some IPs and ports I cannot get required headers from the response to determine the meta-block frequency, therefore I cannot find the location of the song title in the stream. Here's my code:
<?php
while(true)
{
//close warning messages (re-open for debugging)
error_reporting(E_ERROR | E_PARSE);
//create and connect socket with the parameters entered by the user
$sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
echo "Establishing connection to the given adress...\n";
$fp = fsockopen($argv[1], $argv[2], $errno, $errstr, 10);
if($fp)
{
echo "Connection established.\n";
$result = socket_connect($sock, $argv[1], $argv[2]);
//prepare request
$request = "GET / HTTP/1.1\r\n";
$request .= "Icy-MetaData: 1\r\n\r\n";
//send request
socket_write($sock,$request,strlen($request));
//set sentinel boolean value's initial value
$headers = true;
//put the segment to be parsed into a string variable
$l = socket_read($sock,2048);
$meta = "";
$streamurl = "";
$checkContentType = false;
//Parsing metadata frequency and streamurl from response's headers.
foreach(preg_split("/((\r?\n)|(\r\n?))/", $l) as $line)
{
if(!(strpos($line, "metaint:") === false))
{
$meta = $line;
}
if(!(strpos($line, "icy-url:") === false))
{
$streamurl = $line;
}
if(!strpos($line, "audio/mpeg") === false)
{
$checkContentType = true;
}
}
echo $l;
//Checking if the content of the stream is mpeg or not
if($checkContentType)
{
$pos = strpos($meta, ":");
$interval = intval(substr($meta,$pos+1));
$pos = strpos($streamurl, ":");
$streamurl = substr($streamurl, $pos+1);
$flag = false;
//initialize bytecount to 0
$bytecount = 0;
//Extracting song title using SC protocol
while($headers)
{
$l = socket_read($sock,PHP_NORMAL_READ);
$bytecount++;
if($bytecount == $interval )
{
$headers = false;
$flag = true;
}
if($flag)
{
$len = ord($l);
}
}
//Determining length variable
$len = $len * 16;
$string = socket_read($sock,$len);
$pos2 = strpos($string, "'") + 1;
$pos3 = strpos($string, ";",$pos2) -1;
$songtitle = substr($string, $pos2, ($pos3-$pos2));
//Formatting the log entry
$finalstr = "[".date("c")."]"."[".$streamurl."]".$songtitle."\n";
echo "logged".$finalstr;
//finalize connection
socket_close($sock);
//Writing the requested info to a log file
file_put_contents("log.txt", $finalstr,FILE_APPEND | LOCK_EX);
//waiting 5 minutes
echo "Logging next entry in five minutes. \n";
sleep(300);
}
else
{
echo "Content of the stream is not suitable.\n";
exit;
}
}
else
{
echo "Unable to connect to the given ip and port.\n Exiting...\n";
socket_close($sock);
exit;
}
}
?>
I've never tried to access shoutcast programatically but I've run streaming audio servers in the past. There are actually two different flavours of shoutcast server and I would guess your program is trying to talk to one and these broken servers are the other type.
From the post READING SHOUTCAST METADATA FROM A STREAM:
Turns out that SHOUTcast and Icecast (two of the most popular server
applications for streaming radio) are supposed to be compatible, but
the response message from each server is slightly different.
Full details about the shoutcast protocol: Shoutcast Metadata Protocol
I'm trying to set up a WebSocket application, but I'm stuck at the following.
After accepting the socket I received the client's headers as expected, but when I try to send the upgrade back socket_write() throws a warning:
Warning: socket_write(): unable to write to socket [10038]: An operation was attempted on something that is not a socket
This happens in the following piece of code:
var_dump($this->socket); //output: resource(2) of type (Socket)
socket_write($this->socket, $upgrade);
This happens inside a pthreads context.
What are possible reasons PHP is throwing me this warning?
The full code:
public function handshake($headers)
{
Main::console($headers);
Main::console("Getting client WebSocket version...");
Main::console("Headers: \r\n\r\n".$headers);
if(preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $headers, $match))
$version = $match[1];
else {
Main::console("The client doesn't support WebSocket");
return false;
}
Main::console("Client WebSocket version is {$version}, (required: 13)");
if($version == 13) {
// Extract header variables
Main::console("Getting headers...");
if(preg_match("/GET (.*) HTTP/", $headers, $match))
$root = $match[1];
if(preg_match("/Host: (.*)\r\n/", $headers, $match))
$host = $match[1];
if(preg_match("/Origin: (.*)\r\n/", $headers, $match))
$origin = $match[1];
if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $headers, $match))
$key = $match[1];
Main::console("Client headers are:\r\n\r\n".
"- Root: ".$root."\r\n".
"- Host: ".$host."\r\n".
"- Origin: ".$origin."\r\n".
"- Sec-WebSocket-Key: ".$key."\n");
Main::console("Generating Sec-WebSocket-Accept key...");
$acceptKey = $key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
$acceptKey = base64_encode(sha1($acceptKey, true));
$upgrade = "HTTP/1.1 101 Switching Protocols\r\n".
"Upgrade: websocket\r\n".
"Connection: Upgrade\r\n".
"Sec-WebSocket-Accept: $acceptKey".
"\r\n\r\n";
Main::console("Sending this response to the client #{$this->getId()}:\r\n\r\n".$upgrade);
var_dump($this->socket);
socket_write($this->socket, $upgrade, strlen($upgrade));
$this->setHandshake(true);
Main::console("Handshake is successfully done!");
return true;
}
else {
Main::console("WebSocket version 13 required (the client supports version {$version})");
return false;
}
}
public function run()
{
while($this->alive)
{
$bytes = #socket_recv($this->socket, $buffer, 4096, MSG_WAITALL);
if ($buffer)
{
if(!$this->handshake)
{
$this->handshake($buffer);
} else {
Main::console("Client {$this->getID()} says {$buffer}");
}
}
}
}
Try socket_last_error() and socket_strerror() for more information. If that doesn't help, show us how the socket is created. Source: http://www.php.net/manual/en/function.socket-last-error.php
I'm trying to code a C# UDP server. It receives a specific ID from the client, and return the song associated with it. The client is a PHP webpage, and stocks the bytes received into a file. Right now I'm doing some tests, trying to simply start a fake lecture of the song (just a javascript alert) when the transfer is at 2048 bytes. But I have plenty of bugs... The PHP page seems to finish the transfer into the file BEFORE having received all the data... The server continue to send bytes but the file is complete, with the good weight and all...
I know I don't have a very good english, so if you don't undersood something, just ask !
Here is the C# code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Data.SQLite;
namespace cdCollector
{
public partial class Streaming : Form
{
private static List<IPAddress> clients_ = new List<IPAddress>();
public Streaming()
{
InitializeComponent();
listen();
}
public class ThreadClient
{
private static UdpClient socket_;
private static IPEndPoint ipepClient_;
private static int noChanson_;
private static SQLiteConnection connexion_;
public void setSocket(ref UdpClient socket) { socket_ = socket; }
public void setIpepClient(ref IPEndPoint ipepClient) { ipepClient_ = ipepClient; }
public void setNoChanson(int noChanson) { noChanson_ = noChanson; }
public void setConnexion(ref SQLiteConnection connexion) { connexion_ = connexion; }
public static void send()
{
try
{
while (Thread.CurrentThread.IsAlive)
{
Chanson uneChanson;
FileStream stream;
byte[] buffer = new byte[1024];
int read;
uneChanson = new Chanson(noChanson_);
uneChanson.load(ref connexion_);
stream = new FileStream("C:\\Users\\Julie\\Documents\\toune.flac", FileMode.Open, FileAccess.Read);
socket_.Send(Encoding.ASCII.GetBytes(stream.Length.ToString()), stream.Length.ToString().Length, ipepClient_);
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
socket_.Send(buffer, buffer.Length, ipepClient_);
Console.WriteLine("finished");
}
}
catch (ThreadAbortException tae)
{ }
catch (Exception)
{
Thread.CurrentThread.Abort();
}
}
}
public static void listen()
{
byte[] data = new byte[1024];
IPEndPoint ipepServer = new IPEndPoint(IPAddress.Any, 7575); // IP du serveur
IPEndPoint ipepClient = new IPEndPoint(IPAddress.Any, 0); // IP du client;
UdpClient socket = new UdpClient(ipepServer); // socket serveur
int noChanson;
SQLiteConnection connexion = new SQLiteConnection("Data Source=" + Application.StartupPath + "\\cdCollector.db");
SQLiteCommand command = new SQLiteCommand(connexion);
SQLiteDataReader dr;
Thread thread;
connexion.Open();
while (true)
{
try
{
Console.WriteLine("Waiting for a client...");
data = socket.Receive(ref ipepClient);
Console.WriteLine("Message received from {0}:", ipepClient.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, data.Length));
command.CommandText = "SELECT KeyLocale FROM AssocKeys WHERE NomTable = 'Chanson' AND KeyWeb = "
+ int.Parse(Encoding.ASCII.GetString(data, 0, data.Length));
dr = command.ExecuteReader();
if (dr.HasRows)
{
dr.Read();
noChanson = dr.GetInt32(0);
dr.Close();
ThreadClient client = new ThreadClient();
client.setConnexion(ref connexion);
client.setIpepClient(ref ipepClient);
client.setNoChanson(noChanson);
client.setSocket(ref socket);
thread = new Thread(new ThreadStart(ThreadClient.send));
thread.Start();
}
else
socket.Send(Encoding.ASCII.GetBytes("Erreur: Chanson introuvable"), ("Erreur: Chanson introuvable").Length, ipepClient);
}
catch (SocketException se)
{
Console.WriteLine("Erreur Socket:" + se.Message);
}
catch (Exception ex)
{
Console.WriteLine("Erreur: " + ex.Message);
}
}
connexion.Close();
}
}
}
And the PHP code:
<?php
session_start();
$address="192.168.2.2";
$read = false;
$port = 7575;
$length = 0;
$started = false;
if (isset($port) and
($socket=socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) and
(socket_connect($socket, $address, $port)))
{
$text = "Connection successful on IP $address, port $port <br />";
$from = '';
$port = 0;
$length = 0;
socket_send( $socket, $_GET['no'], 1024, MSG_EOR );
socket_recvfrom( $socket, $buf, 1024, 12, $from, $port);
$lengthTotal = $buf;
echo "Taille prévue du fichier: " . $lengthTotal . "<br />";
if( file_exists( "temp" . $_SESSION['ID_Membre'] . ".flac" ) )
unlink("temp" . $_SESSION['ID_Membre'] . ".flac");
$file = fopen("temp" . $_SESSION['ID_Membre'] . ".flac", 'a');
$buf = null;
while( $length < $lengthTotal )
{
$length += socket_recvfrom( $socket, $buf, 1024, 12, $from, $port );
if( $length > 2048 && !$started )
{
?>
<script type="text/javascript">
<!--
alert("Lecture...");
//->
</script>
<?php
$started = true;
}
fputs($file, $buf);
flush();
}
echo "<br />" . $length . "<br />";
fclose($file);
}
else
$text="Unable to connect<pre>".socket_strerror(socket_last_error())."</pre>";
echo $text;
?>
Thanks a lot !
UDP is an inherently unreliable transport. You will need to implement acknowledgements, timeouts, retransmissions and sequence numbers on top of UDP in order to guarantee transmission of all of your data in the expected order, unless your client application can live with dropped packets. I would advise you to consider using TCP sockets instead if you need guaranteed transmission of data between server and client and don't want to have to implement all of this stuff yourself (which might need to include client-side buffering to rearrange out-of-order datagrams). If you want reliability on top of UDP, I would advise you to read a good textbook on the subject (e.g. "Unix Network Programming" by W. Richard Stevens etc.).
Pointers on TCP:
You should take a look at System.Net.Sockets.TcpClient and System.Net.Sockets.TcpListener for the C# side of things and consult the PHP documentation for info on the PHP side of things.
Using TCP sockets isn't really that much different except you'll be using send and recv (or C#/PHP equivalents) instead of send_to and recv_from. Setting up the server side of things is a little more complicated since you need to bind and listen etc. but there are plenty of resources, e.g.:
http://www.switchonthecode.com/tutorials/csharp-tutorial-simple-threaded-tcp-server
Thanks for your help. I changed what you told me, except adding 'b' to the fopen mode because my web server is on Ubuntu. I still receive plenty of errors to tell me that the client connection had to close... It seems like PHP think the download is finished and exit the loop, so it closes the connection of the socket. Also, many minutes after the page have load, the server is still sending data... I never did streaming before so I have difficulties to see where the problem is ...
Here's the new PHP code:
<?php
session_start();
$address="192.168.2.2";
$read = false;
$port = 7575;
$length = 0;
$started = false;
if (isset($port) and
($socket=socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) and
(socket_connect($socket, $address, $port)))
{
$text = "Connection successful on IP $address, port $port <br />";
$from = '';
$port = 0;
$length = 0;
socket_send( $socket, $_GET['no'], 1024, MSG_EOR );
socket_recvfrom( $socket, $buf, 1024, MSG_WAITALL, $from, $port);
$lengthTotal = $buf;
echo "Taille prévue du fichier: " . $lengthTotal . "<br />";
if( file_exists( "temp" . $_SESSION['ID_Membre'] . ".flac" ) )
unlink("temp" . $_SESSION['ID_Membre'] . ".flac");
$file = fopen("temp" . $_SESSION['ID_Membre'] . ".flac", 'a');
$buf = null;
while( $length !== FALSE && $length < $lengthTotal )
{
$length += socket_recvfrom( $socket, $buf, 1024, 12, $from, $port );
if( $length > 2048 && !$started )
{
?>
<script type="text/javascript">
<!--
alert("Lecture...");
//->
</script>
<?php
$started = true;
}
if( $length == FALSE )
echo "ERREUR";
fputs($file, $buf, $length);
flush();
}
echo "<br />" . $length . "<br />";
fclose($file);
}
else
$text="Unable to connect<pre>".socket_strerror(socket_last_error())."</pre>";
echo $text;
?>
Some points:
1.- socket_recvfrom could return FALSE if there is any error, you can check the error with false === socket_recvfrom.
2.- If you are using a windows server add b to the open mode: $file = fopen("temp" . $_SESSION['ID_Membre'] . ".flac", 'ab'); (you are writing a binary file).
3.- Use as third argument of the fputs function the value returned by the socket_recvfrom function (if this value !== FALSE).
4.- You are using the value 12 (MSG_DONTROUTE | MSG_EOR), try to use 0 or MSG_WAITALL (of course socket_recvfrom is going to wait to receive 1024 bytes).
Your reception loop must be:
$reclen = 0;
while( ($reclen !== FALSE) && ($length < $lengthTotal) )
{
$reclen = socket_recvfrom( $socket, $buf, 1024, 12, $from, $port );
if ($reclen === FALSE)
{
echo "ERREUR";
break;
}
$length += $reclen;
if( $length > 2048 && !$started )
{
?>
<script type="text/javascript">
<!--
alert("Lecture...");
//->
</script>
<?php
$started = true;
}
fputs($file, $buf, $length);
flush();
}
The problem is that you are adding the value returned by socket_recvfrom to $length if the return value is FALSE is going to add 0 to $length, that is the reason why you have to add an additional variable ($reclength).
Im using this code here: http://www.digiways.com/articles/php/httpredirects/
public function ReadHttpFile($strUrl, $iHttpRedirectMaxRecursiveCalls = 5)
{
// parsing the url getting web server name/IP, path and port.
$url = parse_url($strUrl);
// setting path to '/' if not present in $strUrl
if (isset($url['path']) === false)
$url['path'] = '/';
// setting port to default HTTP server port 80
if (isset($url['port']) === false)
$url['port'] = 80;
// connecting to the server]
// reseting class data
$this->success = false;
unset($this->strFile);
unset($this->aHeaderLines);
$this->strLocation = $strUrl;
$fp = fsockopen ($url['host'], $url['port'], $errno, $errstr, 30);
// Return if the socket was not open $this->success is set to false.
if (!$fp)
return;
$header = 'GET / HTTP/1.1\r\n';
$header .= 'Host: '.$url['host'].$url['path'];
if (isset($url['query']))
$header .= '?'.$url['query'];
$header .= '\r\n';
$header .= 'Connection: Close\r\n\r\n';
// sending the request to the server
echo "Header is: <br />".str_replace('\n', '\n<br />', $header)."<br />";
$length = strlen($header);
if($length != fwrite($fp, $header, $length))
{
echo 'error writing to header, exiting<br />';
return;
}
// $bHeader is set to true while we receive the HTTP header
// and after the empty line (end of HTTP header) it's set to false.
$bHeader = true;
// continuing untill there's no more text to read from the socket
while (!feof($fp))
{
echo "in loop";
// reading a line of text from the socket
// not more than 8192 symbols.
$good = $strLine = fgets($fp, 128);
if(!$good)
{
echo 'bad';
return;
}
// removing trailing \n and \r characters.
$strLine = ereg_replace('[\r\n]', '', $strLine);
if ($bHeader == false)
$this->strFile .= $strLine.'\n';
else
$this->aHeaderLines[] = trim($strLine);
if (strlen($strLine) == 0)
$bHeader = false;
echo "read: $strLine<br />";
return;
}
echo "<br />after loop<br />";
fclose ($fp);
}
This is all I get:
Header is:
GET / HTTP/1.1\r\n
Host: www.google.com/\r\n
Connection: Close\r\n\r\n
in loopbad
So it fails the fgets($fp, 128);
Is there a reason you aren't using PHP's built-in, enabled-by-default ability to fetch remote files using fopen?
$remote_page = file_get_contents('http://www.google.com/'); // <- Works!
There are also plenty of high-quality third-party libraries, if you need to do something like fetch headers without thinking too hard. Try Zend_Http_Client on for size.
The flaw is here:
$good = $strLine = fgets($fp, 128);
if(!$good)
{
echo 'bad';
return;
}
fgets() returns either a string on success, or FALSE on failure. However, if there was no more data to be returned, fgets() will return the empty string (''). So, both $good and $strLine are set to the empty string, which PHP will happily cast to FALSE in the if() test. You should rewrite as follows:
$strLine = fgets($fp, 128);
if ($strLine === FALSE) { // strict comparison - types and values must match
echo 'bad';
return;
}
There's no need for the double assignment, as you can test $strLine directly.