I want to check if a quake3 game server is online or offline. If offline then echo 'Server is offline' if online then echo 'Server is online'.
I'm using this library:
As you see in the library there's already an isOnline function I think that's for server is online or no?! but I don't know how to output that.
Calling the game server data's:
<?php
include 'test/GameServerQuery.php';
$data = GameServerQuery::queryQuake3('1.1.1.1', 28960);
echo 'Hostname: ' . $data['sv_hostname'] . '<br />';
echo 'Players online: ' . $data['sv_maxclients'] . '<br />'; /// How can I count online players / maxclients? ex.: 0/20
echo 'Punkbuster: ' . $data['sv_punkbuster'] . '<br />';
?>
Here is relevant code from the library (in case the link should die or change):
public static function isOnline ($host, $port, $type)
{
if ($type == 'minecraft') { // No need for the full ping
return #fclose (#fsockopen ( $host , $port , $err , $errstr , 2 ));
}
if (method_exists('GameServerQuery', 'query'.$type)) {
return self::{'query'.$type}($host , $port);
}
return #fclose (#fsockopen ( $host , $port , $err , $errstr , 2 ));
}
public static function queryQuake3($host, $port)
{
$reponse = self::ping($host, $port, "\xFF\xFF\xFF\xFFgetstatus\x00");
if ($reponse === false || substr($reponse, 0, 5) !== "\xFF\xFF\xFF\xFFs") {
return false;
}
$reponse = substr($reponse, strpos($reponse, chr(10))+2);
$info = array();
$joueurs = substr($reponse, strpos($reponse,chr(10))+2);
$reponse = substr($reponse, 0, strpos($reponse, chr(10)));
while($reponse != ''){
$info[self::getString($reponse, '\\')] = self::getString($reponse, '\\');
}
if (!empty($joueurs)) {
$info['players'] = array();
while ($joueurs != ''){
$details = self::getString($joueurs, chr(10));
$info['players'][] = array('frag' => self::getString($details, ' '),
'ping' => self::getString($details, ' '),
'name' => $details);
}
}
return $info;
}
private static function ping($host, $port, $command)
{
$socket = #stream_socket_client('udp://'.$host.':'.$port, $errno, $errstr, 2);
if (!$errno && $socket) {
stream_set_timeout($socket, 2);
fwrite($socket, $command);
$buffer = #fread($socket, 1500);
fclose($socket);
return $buffer;
}
return false;
}
private static function getString(&$chaine, $chr = "\x00")
{
$data = strstr($chaine, $chr, true);
$chaine = substr($chaine, strlen($data) + 1);
return $data;
}
It's a static function, just like the one you're already calling. Something like this would do the job, I think:
$result = GameServerQuery::isOnline('1.1.1.1', 28960, "Quake3");
print_r($result);
That will show you what result you get back. I suspect it will be the same as the queryQuake3 function actually, because if you specify "Quake3" as the last parameter, the isOnline function will simply call the "queryQuake3" function and pass the result back directly.
So, the function should return either false if the server is offline or otherwise unresponsive, and either true, or a more complex dataset if it's online.
So in fact I think you could write:
$result = GameServerQuery::isOnline('1.1.1.1', 28960, "Quake3");
if ($result === false) {
echo "Server is offline";
}
else {
echo "Server is online";
}
Related
I have a server hosted on ipaddress:8728. I can access it's service perfectly using my Java Client program. Now I am trying to access this service from my codeigniter web app hosted on the web using stream_socket_client(). But it returns Error 111(Connection Refused). Then I moved my server to port 80(ipaddress:80) and stream_socket_client program is working fine. Why does stream socket client fails to fetch data from from server on port other than port 80 and when my java socket client is working perfectly fine.
Bellow is my PHP code.
public function connect($ip, $login, $password)
{
for ($ATTEMPT = 1; $ATTEMPT <= $this->attempts; $ATTEMPT++) {
$this->connected = false;
$PROTOCOL = ($this->ssl ? 'ssl://' : '' );
$context = stream_context_create(array('ssl' => array('ciphers' => 'ADH:ALL', 'verify_peer' => false, 'verify_peer_name' => false)));
$this->debug('Connection attempt #' . $ATTEMPT . ' to ' . $PROTOCOL . $ip . ':' . $this->port . '...');
$this->socket = #stream_socket_client($PROTOCOL . $ip.':'. $this->port, $this->error_no, $this->error_str, $this->timeout, STREAM_CLIENT_CONNECT,$context);//this line has exception
if ($this->socket) {
echo "\nSocket is not null";
socket_set_timeout($this->socket, $this->timeout);
$this->write('/login', false);
$this->write('=name=' . $login, false);
$this->write('=password=' . $password);
$RESPONSE = $this->read(false);
if (isset($RESPONSE[0])) {
if ($RESPONSE[0] == '!done') {
if (!isset($RESPONSE[1])) {
// Login method post-v6.43
$this->connected = true;
break;
} else {
// Login method pre-v6.43
$MATCHES = array();
if (preg_match_all('/[^=]+/i', $RESPONSE[1], $MATCHES)) {
if ($MATCHES[0][0] == 'ret' && strlen($MATCHES[0][1]) == 32) {
$this->write('/login', false);
$this->write('=name=' . $login, false);
$this->write('=response=00' . md5(chr(0) . $password . pack('H*', $MATCHES[0][1])));
$RESPONSE = $this->read(false);
if (isset($RESPONSE[0]) && $RESPONSE[0] == '!done') {
$this->connected = true;
break;
}
}
}
}
}
}
fclose($this->socket);
}else{
echo "||\nError no = ".$this->error_no."||";
echo "||\n Error Message = ".$this->error_str."||";
echo "||\nsocket is null||";
}
sleep($this->delay);
}
if ($this->connected) {
$this->debug('Connected...');
} else {
$this->debug('Error...');
}
return $this->connected;
}
Is it happening for mistake in my code? or some protective feature on the server where web app is hosted?
I 'm writing a PHP code to be executed under apache (unfortunately under window OS by using xampp PHP 7.2.x). The PHP script should call an octave in an interactive way in order to be able to execute more commands in sequence without creating for each one a dedicated octave process.
here below an PHP script example.
I have a problem with the interactive working mode; I mean, I'm able to execute an octave script and have back the result but I'm not able to send several octave commands in sequence.
<?php
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to, you can specify a file as well
);
$octave = 'C:\Octave\Octave-4.4.0\bin\octave-cli-4.4.0 ';
$cmd = $octave . ' --no-gui -i -q --eval disp(10)';
$process = proc_open($cmd, $descriptorspec, $pipes);
if (!is_resource($process)) {
die("PROCESS CREATION ERROR CMD: $cmd");
}
$str = "eval('disp(20)');\r\n" . chr(13);
if(fwrite($pipes[0],$str) === false){
die("fwrite ERROR");
}
$str = stream_get_contents($pipes[1]);
if($str === false){
die("stream_get_contents ERROR");
}else{
echo $str;
}
fclose($pipes[0]);
fclose($pipes[1]);
$return_value = proc_close($process);
echo "command returned $return_value\n";
?>
In this case, the output is: 10 commands returned 0
Instead if define $cmd = $octave . ' --no-gui -i -q';
The script is blocked waiting for a returning charter to the stream_get_contents. Same result using fgets.
My understanding is that the fwrite command is not correctly received by an octave and so it doesn't print back the result (even if the fwrite doesn't return any error). Maybe the problem is due to the code to be sent as carriage return in order to tell to octave to execute the code. Moreover, it is not clear, if I should use the eval function or just write the command. However, in all tries done nothing is changed.
Any ideas?
Here below the code review, working if can be useful.
I have also created a dedicated class (octave_stream) in order to provide an interface that permits, for instance, an html pages to start a dedicated octave process ondemand (using a SSE communication) and then send one by one commands as ajax request. The sw will close the octave process whenever the user leave the page or after an unused time.
here below the whole code based on the following 4 files: octave.php, octave_sse.php, octave_com.php.
octave.php
<?php
class octave {
private $pipes = null;
private $process = null;
private $add_semicolon = false;
private $debug = false;
private $print = false;
function __destruct() {
$this->close_octave();
}
public function close_octave(){
if ($this->pipes !== null){
fclose($this->pipes[0]);
fclose($this->pipes[1]);
$return_value = proc_close($this->process);
if($this->debug){ echo "command returned $return_value<br>";}
return $return_value;
}
return false;
}
public function open_octave(){
$dir = sys_get_temp_dir();
$error_file_name = tempnam($dir, "npt");
$descriptorspec = array(
0 => array("pipe", "rb"), // stdin is a pipe that the child will read from
1 => array("pipe", "wb"), // stdout is a pipe that the child will write to
2 => array("file", $error_file_name,"a") // stderr:: you HAVE TO specify a file
);
$octave = 'C:\Octave\Octave-4.4.0\bin\octave-cli-4.4.0 ';
$cmd = $octave . ' --no-gui -i -q';
$pipes = array();
$this->process = proc_open($cmd, $descriptorspec, $pipes);
if (!is_resource($this->process)) {
echo "PROCESS CREATION ERROR CMD: $cmd";
return false;
}
if (count($pipes) == 0){
echo 'pipes: '; var_dump($pipes); echo '<br>';
echo "PROCESS CREATION ERROR CMD: $cmd";
return false;
}
//stream_set_blocking($pipes[1],false); // doesn't work on STDIN / OUT
$this->pipes = $pipes;
$cmd_id = 0;
$this->read($cmd_id);
return true;
} //end open_octave
private function raw_read(){
$str = fread($this->pipes[1],8192);
if($str === false){
echo '<br>'. __FUNCTION__ . ' fgets ERROR for CMD: ' . htmlentities($cmd);
return false;
}
//echo "READ: $str<br>";
return $str;
} //end read
private function read(&$cmd_num){
$result = '';
$string = $this->raw_read();
if($this->debug){echo '<br>' . __FUNCTION__ . ' RAW_READ1: ' . $string; }
if($string[0] == '>'){
//special case, multiple line statement
if($this->debug){echo '<br>' . __FUNCTION__ . ' multiple line statement.' ; }
$cmd_num = -1;
return '';
}
$tok = strtok($string, "octave:");
while (($tok === false) || ($tok == $string)) {
//the response do not conatin the promt; therefore, other rows are coming, read them as well and concatenate to the current response
$result .= $string;
usleep(100);
$string = $this->raw_read();
if($this->debug){echo '<br>' . __FUNCTION__ . ' RAW_READ NEXT: ' . $string; }
$tok = strtok($string, "octave:");
}
$cmd_num = -1;
//in this case string include the promt; nothing more to be read. tok is the string without the "ocatve:" but you still have the 'num>' to be removed.
$allTheRest = strtok( '' );
if(($allTheRest === false) || ($allTheRest == '')){
//tok has the promt rest
list($cmd_num) = sscanf($tok,'%u>');
}else{
$result .= $tok;
list($cmd_num) = sscanf($allTheRest,'ctave:%u>');
}
if($this->debug){echo '<br>' . __FUNCTION__ . " RAW_READ TOK: '$tok' STRING: '$string' RESULT: '$result' allTheRest: '$allTheRest' cmd_num: $cmd_num ## "; }
return $result;
}
//return the command answer removing the promt. Therefore, in case no retrun message command an empty string is given
public function octave_cmd($cmd,&$cmd_num){
if($this->add_semicolon){
$last_chr = strlen($cmd) - 1;
if(substr($cmd, $last_chr, 1) != ';'){
$cmd = $cmd . ';'; // adding ; at the input command required by octave
}
}
//echo "$cmd<br>";exit(0);
$cmd = $cmd . PHP_EOL ;// "\r\n"
if(fwrite($this->pipes[0],$cmd) === false){
echo '<br>'. __FUNCTION__ . ' fwrite ERROR for CMD: ' . htmlentities($cmd);
return false;
}
//usleep(100); // needed when more output row are given ... without this you read before the progam write the next row ... and you lost it ... a nice solution anyway should be to read again unil you find the promt that is always the latest given.
$ret = $this->read($cmd_num);
if($this->print){
echo "<br>COMMAND # $cmd_num: " .htmlentities($cmd) . (($ret != '')?(' RESULT: ' . nl2br(htmlentities($ret))):'') . ' END<br>';
}
return $ret;
}
public function print_cmd($cmd){
$cmd_id = 0;
$ret = $this->octave_cmd($cmd,$cmd_id);
echo "<br>COMMAND # $cmd_id: " .htmlentities($cmd) . (($ret != '')?(' RESULT: ' . nl2br(htmlentities($ret))):'') . ' END<br>';
}
}
class octave_stream {
private $address = 'tcp://127.0.0.1';
private $port = 5454;
private $errno = 0;
private $errstr = '';
private $server_istance = false;
private $sse = false;
/*This function start octave process, open a tcp connection and waits for incoming commands.
(to send the commands use the func. send_cmd)
Each command received is forwared to octave and the ocatve answer is forwared to who sent the command.
To stop the server a special command has to be sent. The caller has to use the stop_server()
*/
public function create_server($accept_max_retray = 30){
$this->server_istance = true; // first command to be done
$available_port = $this->find_usable_listening_port($this->port);
if($available_port === false){
$this->server_log('NOT FOUND AN AVAILABLE PORT TO START THE LISTENING SERVER');
return false;
}else{
$this->port = $available_port;
}
$oct_obj = new octave();
if(!$oct_obj->open_octave()){
return false;
}
$this->server_log('OCTAVE PROCESS STARTED');
$cmd_id = 0;
$server_socket_address = 'tcp://127.0.0.1:' . $this->port;
$socket = stream_socket_server($server_socket_address, $errno, $errstr);
if (!$socket) {
$this->errstr = "$errstr ($errno)<br />\n";
$this->errno = $errno;
$oct_obj->close_octave();
$this->server_log("<b>LISTENING SOCKET CREATION ERROR: $this->errstr</b>");
return false;
}
$exit = false;
$this->server_log("LISTENING SOCKET CREATED: $server_socket_address DEFAULT SOCKET TIMEOUT:" . ini_get("default_socket_timeout"));
$this->server_log($server_socket_address,'server_ready'); // dedicated event type sent, html page has a dedicated event listener on it
$accept_retray = -1;
$conn_id = 0;
do{
$accept_retray += 1;
while ($conn = stream_socket_accept($socket)) {
$this->server_log("LISTENING SOCKET CONNECTION ACCEPTED: $conn_id");
$accept_retray = -1;
//cmd: received octave command request to be sent to octave
$cmd = '';
$cmd = fread($conn,8192);
if($cmd === false){
$this->server_log( __FUNCTION__ . "[$conn_id] fread ERROR for CMD: " . htmlentities($cmd));
return false;
}
$this->server_log("[$conn_id] RECEIVED RAW COMMAND: $cmd");
if(strpos($cmd, '#exit#') !== false){
//special command EXIT
$this->server_log("[$conn_id] RECEIVED EXIT COMMAND.");
fwrite($conn,self::prefix($conn_id) . 'RECEIVED EXIT COMMAND.'); // you need always to send an answer to the calling (it is waiting on read it
$exit = true;
}else if (strpos($cmd, '#loopback:') !== false) {
//special command LOOPBACK
$this->server_log("[$conn_id] RECEIVED LOOPBACK COMMAND: $cmd");
fwrite($conn,self::prefix($conn_id) . $cmd); // you need always to send an answer to the calling (it is waiting on read it
} else {
//OCATVE COMMAND
$this->server_log("[$conn_id] RECEIVED COMMAND FOR OCTAVE: $cmd");
$cmd_id = 0;
$ret = $oct_obj->octave_cmd($cmd,$cmd_id);
$this->server_log("[$conn_id] COMMAND # $cmd_id: " .htmlentities($cmd) . (($ret != '')?(' RESULT: ' . nl2br(htmlentities($ret))):'') . ' END<br>');
fwrite($conn,self::prefix($conn_id) . 'RESULT:'. $ret);
$this->server_log("[$conn_id] SENT ANSWER: RESULT:". $ret);
}
fclose($conn);
$this->server_log("[$conn_id] CLOSE CONNECTION");
$conn_id++;
if($exit) break;
}
if($exit) break;
//note, calling the server_log func here you are testing the socket between this script and the html pages. If the sse connection is no more working, the PHP engine will close this script.
$this->server_log("LISTENING SOCKET CONNECTION TIMEOUT RETRAY: $accept_retray MAX_RETRAY: $accept_max_retray");
}while($accept_retray < $accept_max_retray);
$this->server_log($server_socket_address,'server_stopped'); // dedicated event type sent
fclose($socket);
$this->server_log('SOCKET CLOSED.');
unset($oct_obj);
$this->server_log('OCTAVE PROCESS STOPPED.');
return true;
} // end start_server
private static function prefix($conn_id){
return "[$conn_id] [" . date('n/j/Y g:i:s a') .'] ';
}
//return the ocatve command answer to be encoded e.g. json to be delivered to the http page or false
public function send_cmd($cmd){
if($this->server_istance){
$this->errstr = '<br>'. __FUNCTION__ . ' SERVER ISTANCE.';
return false;
}
$ret = '';
$fp = stream_socket_client($this->address . ':' .$this->port , $errno, $errstr, 30);
if ($fp === false) {
$this->errstr = "$errstr ($errno)<br />\n";
$this->errno = $errno;
return false;
} else {
//fwrite($fp, "GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n");
fwrite($fp, $cmd);
while (!feof($fp)) {
$ret .= fgets($fp, 1024);
}
fclose($fp);
}
return $ret;
} // end send_cmd
//return false or the server answer
public function stop_server(){
if($this->server_istance){
$this->errstr = '<br>'. __FUNCTION__ . ' SERVER ISTANCE.';
$this->errno = 0;
return false;
}
return $this->send_cmd('#exit#');
} //
//return false or the server answer
public function loopback_msg($msg){
if($this->server_istance){
$this->errstr = '<br>'. __FUNCTION__ . ' SERVER ISTANCE.';
$this->errno = 0;
return false;
}
return $this->send_cmd('#loopback:' . $msg);
}
public function get_errstr(&$errno){
$ret = $this->errstr;
$this->errstr = '';
$errno = $this->errno;
$this->errno = 0;
return $ret;
}
//$ip_name: IP or dns name
public function set_address_connection($ip_name,$port){
$this->address = 'tcp://' . $ip_name ;
$this->port = $port;
}
//str can be encoded as json if you need to transfert more data field.
//see: https://www.html5rocks.com/en/tutorials/eventsource/basics/
private function server_log($str,$event_name = ''){
$msg = '<br>[' . date('n/j/Y g:i:s a') .'] '. $str ;
if($this->sse){
if($event_name != ''){
echo "event: $event_name" . PHP_EOL;
echo "data: $str" . PHP_EOL;
}else{
echo "data: $msg" . PHP_EOL;
}
echo PHP_EOL;
}else{
echo $msg;
}
ob_flush();
flush();
}
public function set_sse($sse){
$this->sse = $sse;
}
private function check_server_running_on_port($port,&$ret_errstr,&$errno){
if(!$this->server_istance){
$ret_errstr = '<br>'. __FUNCTION__ . ' REQUIRED SERVER ISTANCE.';
$errno = 0;
return false;
}
$ret_errstr ='';
$errno = 0;
$msg = __FUNCTION__ . ' PORT CHECK: ' . $port;
$cmd = '#loopback:' . $msg; // you cannot change it, is the defined loopback command
$fp = stream_socket_client($this->address . ':' .$port , $errno, $errstr, 30);
if ($fp === false) {
$ret_errstr = "$errstr ($errno)<br />\n";
return false;
}
fwrite($fp, $cmd);
while (!feof($fp)) {
$ret .= fgets($fp, 1024);
}
fclose($fp);
return true;
}
private function find_usable_listening_port($start_port){
if(!$this->server_istance){
$this->errstr = '<br>'. __FUNCTION__ . ' REQUIRED SERVER ISTANCE.';
$this->errno = 0;
return false;
}
$ret_errstr ='';
$errno = 0;
$max_port = $start_port +10;
$port = $start_port;
do{
//ret = true server running, so I need to find another unused port
$ret = $this->check_server_running_on_port($port,$ret_errstr,$errno);
if($ret){
$this->server_log("CHECK USABLE LISTENING PORT: PORT=$port ALREADY USED.");
}else{
$this->server_log("CHECK USABLE LISTENING PORT: PORT=$port NOT USED. GIVEN ERROR: $ret_errstr" );
return $port;
}
$port++;
if($port > $max_port) return false;
}while($ret);
return false;
}
} // end class
?>
octave_sse.php
<?php
/* this page should be called by the web page as sse
this page calling the create_server func start the octave process and the communication server as well.
The function return only when the exit command is received over the server channel created.
Then the page has to send a polling to the web page to test the presence of the page itself.
*/
function sendMsg($sse,$msg) {
if($sse){
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
}else{
echo $msg;
}
ob_flush();
flush();
}
$sse = false;
if(isset($_GET['sse'])){
if($_GET['sse'] > 0){
$sse = true;
}
}
if($sse){
header('Content-Type: text/event-stream');
}else{
header( 'Content-type: text/html; charset=utf-8' );
}
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.
require 'octave.php';
set_time_limit(4000);
$oct_server_obj = new octave_stream();
if($sse){
$oct_server_obj->set_sse(true);
}
sendMsg($sse,'<br>[' . date('n/j/Y g:i:s a') .'] CALLING create_server.<br>');
$ret = $oct_server_obj->create_server();
sendMsg($sse,'<br>[' . date('n/j/Y g:i:s a') .'] create_server EXIT. return: '. (($ret)?'TRUE':'FALSE').'<br>');
//you are here only at the end when the web page send the exit command to the created server
do{
sleep(2);
sendMsg($sse,'<br>[' . date('n/j/Y g:i:s a') .'] create_server PING<br>');
}while(true);
?>
octave_com.php
<?php
/*
This page is called using a json post request from web page.
Each request has a octave command. special param is to terminate the server.
*/
/** Error reporting: this is not used since you are using myErrorHandler */
if($_SERVER['SERVER_NAME'] == "localhost"){ // my PC
error_reporting(E_ALL);
}else{
error_reporting(E_ERROR | E_PARSE);
}
//http://php.net/manual/it/errorfunc.configuration.php#ini.display-errors
/* The errors are redirect over the stderr and not over the stdout.
In this way, you have to properly send the error using json without using the set_error_handler.
ini_set('display_errors','Off');
//ini_set('display_errors','On');
*/
function myErrorHandler ($errno, $errstr, $errfile, $errline) {
if (0 === error_reporting()) { return false;}
$errorType = array (
E_ERROR => 'ERROR',
E_WARNING => 'WARNING',
E_PARSE => 'PARSING ERROR',
E_NOTICE => 'NOTICE',
E_CORE_ERROR => 'CORE ERROR',
E_CORE_WARNING => 'CORE WARNING',
E_COMPILE_ERROR => 'COMPILE ERROR',
E_COMPILE_WARNING => 'COMPILE WARNING',
E_USER_ERROR => 'USER ERROR',
E_USER_WARNING => 'USER WARNING',
E_USER_NOTICE => 'USER NOTICE',
E_STRICT => 'STRICT NOTICE',
E_RECOVERABLE_ERROR => 'RECOVERABLE ERROR');
// create error message
if (array_key_exists($errno, $errorType)) {
$err = $errorType[$errno];
} else {
$err = 'CAUGHT EXCEPTION';
}
if($_SERVER['SERVER_NAME'] != "localhost"){ // not my PC
if (!($errorType == E_ERROR ) || ($errorType == E_PARSE ))
return;
}
$str_err = "$err($errno) <br> in line: " .$errline. " of file: " .$errfile . " <br> PHP: " . PHP_VERSION . " (". PHP_OS .")<br> $errstr";
terminate($str_err);
} // end myErrorHandler
// configura il gestore dell'errore definito dall'utente
$old_error_handler = set_error_handler("myErrorHandler");
// functions
function terminate($str_err, $txt=false){
if($txt){
die($str_err);
}
header("Content-Type: application/json;charset=utf-8");
echo json_encode(array("result"=>"false","error"=>$str_err));
exit(0);
} // end terminate
require 'octave.php';
if(isset($_POST['send_loopback'])){
if(!isset($_POST['message'])){
terminate("message not present!");
}else{
$message = $_POST['message'];
}
$address = '';
$ip='';
$port = 0;
if(isset($_POST['address'])){
$address = $_POST['address'];
$pos = strrpos($address,':');
$ip = substr($address,6,$pos-6);
$port = substr($address,$pos+1);
}
$oct_server_obj = new octave_stream();
//it is supposed to have the server already running ready to manage the sent messages here below
//echo '<br>[' . date('n/j/Y g:i:s a') .'] SEND THE LOOPBACK MESSAGE.<br>';
if($ip != '' and is_numeric($port)){
$oct_server_obj->set_address_connection($ip,$port);
}
$msg = $oct_server_obj->loopback_msg($message);
if($msg === false){
$errno = 0;
terminate($oct_server_obj->get_errstr($errno));
}
echo json_encode(array('result' => 'true', 'error' => '', 'loopback_msg' => $msg)) ;
exit(0);
} // end send_loopback
if(isset($_POST['send_octave_msg'])){
if(!isset($_POST['message'])){
terminate("message not present!");
}else{
$message = $_POST['message'];
}
$address = '';
$ip='';
$port = 0;
if(isset($_POST['address'])){
$address = $_POST['address'];
$pos = strrpos($address,':');
$ip = substr($address,6,$pos-6);
$port = substr($address,$pos+1);
}
$oct_server_obj = new octave_stream();
//it is supposed to have the server already running ready to manage the sent messages here below
//echo '<br>[' . date('n/j/Y g:i:s a') .'] SEND THE LOOPBACK MESSAGE.<br>';
if($ip != '' and is_numeric($port)){
$oct_server_obj->set_address_connection($ip,$port);
}
$msg = $oct_server_obj->send_cmd($message);
if($msg === false){
$errno = 0;
terminate($oct_server_obj->get_errstr($errno));
}
$pos = strpos($msg,'RESULT:');
$ret = trim(substr($msg,$pos+strlen('RESULT:')));
$ret = nl2br(htmlentities($ret));
echo json_encode(array('result' => 'true', 'error' => '', 'msg' => $msg, 'return' => $ret)) ;
exit(0);
} // end send_octave_msg
if(isset($_GET['send_exit_msg'])){
$address = '';
$ip='';
$port = 0;
if(isset($_GET['address'])){
$address = $_GET['address'];
$pos = strrpos($address,':');
$ip = substr($address,6,$pos-6);
$port = substr($address,$pos+1);
}
$oct_server_obj = new octave_stream();
//it is supposed to have the server already running ready to manage the sent messages here below
//echo '<br>[' . date('n/j/Y g:i:s a') .'] SEND THE LOOPBACK MESSAGE.<br>' . "ADDRESS: $address IP: $ip PORT: $port<br>" ;
if($ip != '' and is_numeric($port)){
$oct_server_obj->set_address_connection($ip,$port);
}
$msg = $oct_server_obj->stop_server();
if($msg === false){
$errno = 0;
terminate($oct_server_obj->get_errstr($errno));
}
echo json_encode(array('result' => 'true', 'error' => '', 'return' => $msg)) ;
exit(0);
} // end send_exit_msg
?>
The html web page to be used together with the above code.
octave_shell.html:
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../../jquery/jqueryui/jquery-ui-1.11.3.custom/jquery-ui.css">
<link rel="stylesheet" href="../../libs/messi/messi.min.css" />
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="../../jquery/jqueryui/jquery-ui-1.11.3.custom/jquery-ui.js"></script>
<script src="../../libs/messi/my_messi.min.js"></script>
<script src="../../libs/chosen/chosen.jquery.min.js"></script>
<title>OCTAVE SHELL</title>
</head>
<body>
<h2>OCTAVE WEB INTERFACE</h2>
<script type="text/javascript">
var server_ready = false; // true, octave process running and ready to accept commands
var sse_source; // sse_obj
var octave_close_req = false; // true when the user stop octave
var address = ''; //address on which the server is in listening for commands at server side
function clearArray(array_tbc){
array_tbc.splice(0,array_tbc.length); // set the array to empty
array_tbc.length = 0;
}
function isParamExist(paramName){
if($.inArray(paramName,Object.getOwnPropertyNames(urlParams)) > -1){
console.log("isParamExist:" + paramName + " return TRUE");
return true;
}
console.log("isParamExist:" + paramName + " return FALSE");
return false;
} //end isParamExist
function getParam(urlParams) {
var match,
pl = /\+/g, // Regex for replacing addition symbol with a space
search = /([^&=]+)=?([^&]*)/g,
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
query = window.location.search.substring(1);
while (match = search.exec(query))
urlParams[decode(match[1])] = decode(match[2]);
console.log(Object.getOwnPropertyNames(urlParams));
} //end getParam
function octave_close(){
octave_close_req = true;
$.getJSON('octave_com.php',
{send_exit_msg: 1,
address: address},
function(data) {
if(data.result == "true"){
$('#octave_shell').append("<p><b>"+ data.return +"</b></p>" );
}else{
//alert("Error : " + data.error);
new Messi('Error : ' + data.error, {title: 'ERROR from JSON', titleClass: 'anim error', buttons: [{id: 0, label: 'Close', val: 'X'}]});
}
}
);
} //end octave_close
function ping_server(){
var message = 'HELLO!';
$.post( "octave_com.php",
{ send_loopback: 1,
address: address,
message: message } ,
function( data ) {
if(data.result == 'true'){
var msg = data.loopback_msg;
$('#octave_shell').append("<p><b>"+ msg +"</b></p>" );
}else{
var err = data.error;
new Messi("LOOPBACK ERROR: err: " + err, {title: 'LOOPBACK MESSAGE', titleClass: 'anim warning', buttons: [{id: 0, label: 'Close', val: 'X'}]});
}
},
"json");
} //end ping_server
function send_octave_cmd(cmd){
$.post( "octave_com.php",
{ send_octave_msg: 1,
address: address,
message: cmd } ,
function( data ) {
if(data.result == 'true'){
var msg = data.return;
if(msg == '') msg = 'OK';
$('#octave_shell').append("<p>OCTAVE ANSWER: " + msg + "</p>");
console.log('OCTAVE MESSAGE: ' + data.msg);
}else{
var err = data.error;
new Messi("OCTAVE COMMAND: err: " + err, {title: 'OCTAVE COMMAND ERROR', titleClass: 'anim warning', buttons: [{id: 0, label: 'Close', val: 'X'}]});
}
},
"json");
} //end send_octave_cmd
$(function(){
if(typeof(EventSource) !== "undefined") {
sse_source = new EventSource("octave_sse.php?sse=1");
sse_source.onmessage = function(event) {
console.log('SSE MSG: ' + event.data);
document.getElementById("sse_log").innerHTML += event.data + "<br>";
};
sse_source.addEventListener('open', function(e) {
// Connection was opened.
console.log('SSE OPEN.');
document.getElementById("sse_log").innerHTML += 'SSE OPEN.' + "<br>";
}, false);
sse_source.addEventListener('error', function(e) {
if (e.readyState == EventSource.CLOSED) {
// Connection was closed.
server_ready = false;
console.log('SSE CLOSED.');
document.getElementById("sse_log").innerHTML += 'SSE CLOSED.' + "<br>";
}
}, false);
//user defined event types
sse_source.addEventListener('server_ready', function(e) {
// server_ready event received.
server_ready = true;
address = e.data;
console.log('SSE server_ready EVENT ADDR: ' + address);
$('#octave_status').text('SERVER READY TO ACCEPT OCTAVE COMMANDS ON: '+ address);
}, false);
sse_source.addEventListener('server_stopped', function(e) {
// server_stopped event received.
server_ready = false;
console.log('SSE server_stopped EVENT');
setTimeout(function(){ sse_source.close(); }, 3000); //close the sse connection as well, you don't need anymore.
if(!octave_close_req){
$('#octave_status').text('SERVER HAS BEEN CLOSED FOR TIMEOUT. RE-LOAD THE PAGE TO START A NEW WORKING SESSION.');
new Messi(
'OCTAVE PROCESS STOPPED FOR TIMEOUT. RE-LOAD THE PAGE TO START A NEW WORKING SESSION.',
{
title: 'OCTAVE PROCESS STOPPED',
titleClass: 'anim info',
buttons: [ {id: 0, label: 'Close', val: 'X'} ]
}
);
}else{
$('#octave_status').text('SERVER HAS BEEN CLOSED FOR USER DECISION. RE-LOAD THE PAGE TO START A NEW WORKING SESSION.');
new Messi(
'YOU HAVE CLOSED CORRECTLY THE OCTAVE PROCESS. RE-LOAD THE PAGE TO START A NEW WORKING SESSION.',
{
title: 'OCTAVE PROCESS STOPPED',
titleClass: 'anim info',
buttons: [ {id: 0, label: 'Close', val: 'X'} ]
}
);
}
}, false);
} else {
alert('NO SSE SUPPORT. Please do not use an obsolete browser!');
}
$('#close_octave_id').click(function() {
console.log('CLOSE OCTAVE REQUEST');
octave_close();
});
$('#send_ping_id').click(function() {
console.log('PING DISPATCHER SERVER REQUEST');
ping_server();
});
$('#send_octave_cmd_id').click(function() {
var cmd = $('#write_octave_cmd_id').val();
//console.log('SEND OCTAVE CMD REQUEST: ' + cmd);
$('#octave_shell').append("<p>OCTAVE: " + cmd + "</p>");
send_octave_cmd(cmd);
$('#write_octave_cmd_id').val('');
});
$('#write_octave_cmd_id').keypress(function (e) {
var key = e.which;
if(key == 13) // the enter key code
{
$('#send_octave_cmd_id').click();
return false;
}
});
//getParam(urlParams);
/*
if(!isParamExist('json_file_net_name')){
//load the NPT results
loadNPTData();
}else{
// load DESIGN results
loadJSONData();
}
*/
}); // end startup page
</script>
<div id='octave_cmd'>
<h4>Write your OCTAVE commands here, press enter or click on SEND OCTAVE CMD to execute them.<br>
<b>IMPORTANT: </b>Don't forget to terminate the commands with semicolon as per OCTAVE syntax.</h4>
<br><p>Some example commands: disp(10) just to print 10,<br>
to solve a non linear system equation writes the following commands line by line pressing enter for each row:<br>
<i>function y = test6(x)<br>
y(1) = 18.028*cosd(x(1))+10*cosd(45)-15*cosd(x(2))<br>
y(2) = 18.028*sind(x(1))+10*sind(45)-15*sind(x(2))<br>
endfunction<br>
[x, fval, info] = fsolve(#test6, [0;0]);<br>
disp(x);<br>
disp(info);</i><br>
</p><br>
</div><br>
<br><a href='#' id='close_octave_id' >CLOSE OCTAVE - CLICK WHEN YOU HAVE TERMINATED.</a><br>
<br><a href='#' id='send_ping_id' >PING DISPATCHER SERVER </a><br>
<div id='octave_status'></div>
<br><div id='octave_shell'><h4>OCTAVE SHELL:</h4><br></div><br>
<input type='text' id='write_octave_cmd_id' size="400"><br>
<a href='#' id='send_octave_cmd_id' >SEND OCTAVE CMD</a>
<br><div id='sse_log'><h4>SSE LOG:</h4><br></div><br>
</body>
</html>
Trying to sent packages from my webhost to a game server, using this code. However it always results in Unable to open socket: Connection timed out (110) ad I can't figure out why it times out. When I try this on my localhost, it works perfectly but when on webhost, it just times out. I've tried to set the timeout to something else but it didn't help.
define("SERVERDATA_EXECCOMMAND",2);
define("SERVERDATA_AUTH",3);
class RCon {
var $Password;
var $Host;
var $Port = 27015;
var $_Sock = null;
var $_Id = 0;
function RCon ($Host,$Port,$Password) {
$this->Password = $Password;
$this->Host = $Host;
$this->Port = $Port;
$this->_Sock = #fsockopen($this->Host,$this->Port, $errno, $errstr, 30) or
die("Unable to open socket: $errstr ($errno)\n");
$this->_Set_Timeout($this->_Sock,2,500);
}
function Auth () {
$PackID = $this->_Write(SERVERDATA_AUTH,$this->Password);
// Real response (id: -1 = failure)
$ret = $this->_PacketRead();
if ($ret[1]['id'] == -1) {
die("Authentication Failure\n");
}
}
function _Set_Timeout(&$res,$s,$m=0) {
if (version_compare(phpversion(),'4.3.0','<')) {
return socket_set_timeout($res,$s,$m);
}
return stream_set_timeout($res,$s,$m);
}
function _Write($cmd, $s1='', $s2='') {
// Get and increment the packet id
$id = ++$this->_Id;
// Put our packet together
$data = pack("VV",$id,$cmd).$s1.chr(0).$s2.chr(0);
// Prefix the packet size
$data = pack("V",strlen($data)).$data;
// Send packet
fwrite($this->_Sock,$data,strlen($data));
// In case we want it later we'll return the packet id
return $id;
}
function _PacketRead() {
//Declare the return array
$retarray = array();
//Fetch the packet size
while ($size = #fread($this->_Sock,4)) {
$size = unpack('V1Size',$size);
//Work around valve breaking the protocol
if ($size["Size"] > 4096) {
//pad with 8 nulls
$packet = "\x00\x00\x00\x00\x00\x00\x00\x00".fread($this->_Sock,4096);
} else {
//Read the packet back
$packet = fread($this->_Sock,$size["Size"]);
}
array_push($retarray,unpack("V1ID/V1Response/a*S1/a*S2",$packet));
}
return $retarray;
}
function Read() {
$Packets = $this->_PacketRead();
foreach($Packets as $pack) {
if (isset($ret[$pack['ID']])) {
$ret[$pack['ID']]['S1'] .= $pack['S1'];
$ret[$pack['ID']]['S2'] .= $pack['S1'];
} else {
$ret[$pack['ID']] = array(
'Response' => $pack['Response'],
'S1' => $pack['S1'],
'S2' => $pack['S2'],
);
}
}
return $ret;
}
function sendCommand($Command) {
$Command = '"'.trim(str_replace(' ','" "', $Command)).'"';
$this->_Write(SERVERDATA_EXECCOMMAND,$Command,'');
}
function rconCommand($Command) {
$this->sendcommand($Command);
$ret = $this->Read();
//ATM: Source servers don't return the request id, but if they fix this the code below should read as
// return $ret[$this->_Id]['S1'];
return $ret[0]['S1'];
}
}
If I specify udp connection in fsockopen it does not timeout, however if I try tcp, it times out. Most likely caused by the host, but I have no idea where to go from this.
https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
https://developer.valvesoftware.com/wiki/Server_queries
I am trying to study class.openid.php because it is simpler and smaller than
lightopenid. for my purposes 200 lines do matter. But class.openid.php does not work with google openID https://www.google.com/accounts/o8/id, prints to me such error:
ERROR CODE: OPENID_NOSERVERSFOUND
ERROR DESCRIPTION: Cannot find OpenID Server TAG on Identity page.
is it possible to make class.openid.php (any version) work with google openID and how to do such thing?
class.openid.php can be taken here but it did not worked for me out of the box so I had to find all <? and replace tham with <?php in case someone would like to see code I've got:
html interface page:
<?php
require('class.openid.v3.php');
if ($_POST['openid_action'] == "login"){ // Get identity from user and redirect browser to OpenID Server
$openid = new SimpleOpenID;
$openid->SetIdentity($_POST['openid_url']);
$openid->SetTrustRoot('http://' . $_SERVER["HTTP_HOST"]);
$openid->SetRequiredFields(array('email','fullname'));
$openid->SetOptionalFields(array('dob','gender','postcode','country','language','timezone'));
if ($openid->GetOpenIDServer()){
$openid->SetApprovedURL('http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PATH_INFO"]); // Send Response from OpenID server to this script
$openid->Redirect(); // This will redirect user to OpenID Server
}else{
$error = $openid->GetError();
echo "ERROR CODE: " . $error['code'] . "<br>";
echo "ERROR DESCRIPTION: " . $error['description'] . "<br>";
}
exit;
}
else if($_GET['openid_mode'] == 'id_res'){ // Perform HTTP Request to OpenID server to validate key
$openid = new SimpleOpenID;
$openid->SetIdentity($_GET['openid_identity']);
$openid_validation_result = $openid->ValidateWithServer();
if ($openid_validation_result == true){ // OK HERE KEY IS VALID
echo "VALID";
}else if($openid->IsError() == true){ // ON THE WAY, WE GOT SOME ERROR
$error = $openid->GetError();
echo "ERROR CODE: " . $error['code'] . "<br>";
echo "ERROR DESCRIPTION: " . $error['description'] . "<br>";
}else{ // Signature Verification Failed
echo "INVALID AUTHORIZATION";
}
}else if ($_GET['openid_mode'] == 'cancel'){ // User Canceled your Request
echo "USER CANCELED REQUEST";
}
?>
<html>
<head>
<title>OpenID Example</title>
</head>
<body>
<div>
<fieldset id="openid">
<legend>OpenID Login</legend>
<form action="<?php echo 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PATH_INFO"]; ?>" method="post" onsubmit="this.login.disabled=true;">
<input type="hidden" name="openid_action" value="login">
<div><input type="text" name="openid_url" class="openid_login"><input type="submit" name="login" value="login >>"></div>
<div><a href="http://www.myopenid.com/" class="link" >Get an OpenID</a></div>
</form>
</fieldset>
</div>
<div style="margin-top: 2em; font-family: arial; font-size: 0.8em; border-top:1px solid gray; padding: 4px;">Sponsored by: FiveStores - get your free online store; includes extensive API for developers; <i style="color: gray;">integrated with OpenID</i></div>
</body>
</html>
and php class
<?php
/*
FREE TO USE Under License: GPLv3
Simple OpenID PHP Class
Some modifications by Eddie Roosenmaallen, eddie#roosenmaallen.com
*/
class SimpleOpenID{
var $openid_url_identity;
var $URLs = array();
var $error = array();
var $fields = array(
'required' => array(),
'optional' => array(),
);
function SimpleOpenID(){
if (!function_exists('curl_exec')) {
die('Error: Class SimpleOpenID requires curl extension to work');
}
}
function SetOpenIDServer($a){
$this->URLs['openid_server'] = $a;
}
function SetTrustRoot($a){
$this->URLs['trust_root'] = $a;
}
function SetCancelURL($a){
$this->URLs['cancel'] = $a;
}
function SetApprovedURL($a){
$this->URLs['approved'] = $a;
}
function SetRequiredFields($a){
if (is_array($a)){
$this->fields['required'] = $a;
}else{
$this->fields['required'][] = $a;
}
}
function SetOptionalFields($a){
if (is_array($a)){
$this->fields['optional'] = $a;
}else{
$this->fields['optional'][] = $a;
}
}
function SetIdentity($a){ // Set Identity URL
if ((stripos($a, 'http://') === false)
&& (stripos($a, 'https://') === false)){
$a = 'http://'.$a;
}
$this->openid_url_identity = $a;
}
function GetIdentity(){ // Get Identity
return $this->openid_url_identity;
}
function GetError(){
$e = $this->error;
return array('code'=>$e[0],'description'=>$e[1]);
}
function ErrorStore($code, $desc = null){
$errs['OPENID_NOSERVERSFOUND'] = 'Cannot find OpenID Server TAG on Identity page.';
if ($desc == null){
$desc = $errs[$code];
}
$this->error = array($code,$desc);
}
function IsError(){
if (count($this->error) > 0){
return true;
}else{
return false;
}
}
function splitResponse($response) {
$r = array();
$response = explode("\n", $response);
foreach($response as $line) {
$line = trim($line);
if ($line != "") {
list($key, $value) = explode(":", $line, 2);
$r[trim($key)] = trim($value);
}
}
return $r;
}
function OpenID_Standarize($openid_identity = null){
if ($openid_identity === null)
$openid_identity = $this->openid_url_identity;
$u = parse_url(strtolower(trim($openid_identity)));
if (!isset($u['path']) || ($u['path'] == '/')) {
$u['path'] = '';
}
if(substr($u['path'],-1,1) == '/'){
$u['path'] = substr($u['path'], 0, strlen($u['path'])-1);
}
if (isset($u['query'])){ // If there is a query string, then use identity as is
return $u['host'] . $u['path'] . '?' . $u['query'];
}else{
return $u['host'] . $u['path'];
}
}
function array2url($arr){ // converts associated array to URL Query String
if (!is_array($arr)){
return false;
}
$query = '';
foreach($arr as $key => $value){
$query .= $key . "=" . $value . "&";
}
return $query;
}
function CURL_Request($url, $method="GET", $params = "") { // Remember, SSL MUST BE SUPPORTED
if (is_array($params)) $params = $this->array2url($params);
$curl = curl_init($url . ($method == "GET" && $params != "" ? "?" . $params : ""));
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_HTTPGET, ($method == "GET"));
curl_setopt($curl, CURLOPT_POST, ($method == "POST"));
if ($method == "POST") curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
if (curl_errno($curl) == 0){
$response;
}else{
$this->ErrorStore('OPENID_CURL', curl_error($curl));
}
return $response;
}
function HTML2OpenIDServer($content) {
$get = array();
// Get details of their OpenID server and (optional) delegate
preg_match_all('/<link[^>]*rel=[\'"]openid.server[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/i', $content, $matches1);
preg_match_all('/<link[^>]*href=\'"([^\'"]+)[\'"][^>]*rel=[\'"]openid.server[\'"][^>]*\/?>/i', $content, $matches2);
$servers = array_merge($matches1[1], $matches2[1]);
preg_match_all('/<link[^>]*rel=[\'"]openid.delegate[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/i', $content, $matches1);
preg_match_all('/<link[^>]*href=[\'"]([^\'"]+)[\'"][^>]*rel=[\'"]openid.delegate[\'"][^>]*\/?>/i', $content, $matches2);
$delegates = array_merge($matches1[1], $matches2[1]);
$ret = array($servers, $delegates);
return $ret;
}
function GetOpenIDServer(){
$response = $this->CURL_Request($this->openid_url_identity);
list($servers, $delegates) = $this->HTML2OpenIDServer($response);
if (count($servers) == 0){
$this->ErrorStore('OPENID_NOSERVERSFOUND');
return false;
}
if (isset($delegates[0])
&& ($delegates[0] != "")){
$this->SetIdentity($delegates[0]);
}
$this->SetOpenIDServer($servers[0]);
return $servers[0];
}
function GetRedirectURL(){
$params = array();
$params['openid.return_to'] = urlencode($this->URLs['approved']);
$params['openid.mode'] = 'checkid_setup';
$params['openid.identity'] = urlencode($this->openid_url_identity);
$params['openid.trust_root'] = urlencode($this->URLs['trust_root']);
if (isset($this->fields['required'])
&& (count($this->fields['required']) > 0)) {
$params['openid.sreg.required'] = implode(',',$this->fields['required']);
}
if (isset($this->fields['optional'])
&& (count($this->fields['optional']) > 0)) {
$params['openid.sreg.optional'] = implode(',',$this->fields['optional']);
}
return $this->URLs['openid_server'] . "?". $this->array2url($params);
}
function Redirect(){
$redirect_to = $this->GetRedirectURL();
if (headers_sent()){ // Use JavaScript to redirect if content has been previously sent (not recommended, but safe)
echo '<script language="JavaScript" type="text/javascript">window.location=\'';
echo $redirect_to;
echo '\';</script>';
}else{ // Default Header Redirect
header('Location: ' . $redirect_to);
}
}
function ValidateWithServer(){
$params = array(
'openid.assoc_handle' => urlencode($_GET['openid_assoc_handle']),
'openid.signed' => urlencode($_GET['openid_signed']),
'openid.sig' => urlencode($_GET['openid_sig'])
);
// Send only required parameters to confirm validity
$arr_signed = explode(",",str_replace('sreg.','sreg_',$_GET['openid_signed']));
for ($i=0; $i<count($arr_signed); $i++){
$s = str_replace('sreg_','sreg.', $arr_signed[$i]);
$c = $_GET['openid_' . $arr_signed[$i]];
// if ($c != ""){
$params['openid.' . $s] = urlencode($c);
// }
}
$params['openid.mode'] = "check_authentication";
$openid_server = $this->GetOpenIDServer();
if ($openid_server == false){
return false;
}
$response = $this->CURL_Request($openid_server,'POST',$params);
$data = $this->splitResponse($response);
if ($data['is_valid'] == "true") {
return true;
}else{
return false;
}
}
}
?>
The problem is that Google doesn't just supply an OpenID endpoint.
OpenId endpoints include an identifier for the user.
What we are having here is called a Discovery Url.
This is a static url that you can direct any user to, and the service itself will recognise the user and return a per-user unique identifying url.
This however is NOT implemented correctly by most openid client libraries, including the majority linked on the official openid website.
Even the Zend Framework libraries are incapable of handling that.
However I found a class that I analysed from various perspectives and that I am very satisfied with. At the company I work at we already integrated it successfully in several production environments and have not experienced any problems.
You may also be interested in another post of mine dealing with the issue of making Facebook an openid Provider. The class I am using, that also supports Google, can also be found there:
Best way to implement Single-Sign-On with all major providers?
The class in your question does not support OpenID 2.0 at all. Therefore, it will not work with Google without adding a lot of code.
Are you searching something like :
http://wiki.openid.net/w/page/12995176/Libraries
?
There is a PHP section in that.
I have a script that parses the page for the link tag, but as there are multiple ways to download a page ( wget, file_get_contents, curl, etc ... ) and there are multiple ways to include a favicon, the script is getting to big.
Is there a concise way to do this? Maybe an API that could be used?
Below is the growing script:
<?php
// Use a direct GET request for debugging, just pass in the domain ( ?domain=test.com )
if($_GET)
{
$obj = new FaviconFinder();
$obj->invokeDebug($_GET);
}
class FaviconFinder
{
// domain before and after redirects
private $domain;
private $real_domain;
// the file and how it was obtained
private $file_code = '0';
private $file_page;
// the favicon and how it was obtained
private $favicon_code = 'z';
private $file_favicon;
private $ext;
// paths local to server and on the internet (URL)
private $path_local1 = "../../favicons/";
private $path_local;
private $path_internet;
/****************************************************************************************************
invokeTest
****************************************************************************************************/
public function invokeTest($pipe)
{
exec('wget ' . $pipe['domain'] . ' -O ../sites/temp.html 2>&1', $output);
print_r($output);
}
/****************************************************************************************************
invokeDebug
****************************************************************************************************/
public function invokeDebug($pipe)
{
echo "<br><br> domain: " . $pipe['domain'] . "";
$pipe = $this->invoke($pipe);
echo "<br><br> real_domain: " . $this->real_domain . "";
echo "<br><br> file_code | " . $this->file_code;
echo "<br><br> favicon_code | " . $this->favicon_code;
echo "<br><br> favicon_path | " . $this->path_internet;
echo "<br><br> favicon_file | " . $this->file_favicon;
echo "<br><br> favicon_file type | " . gettype($this->file_favicon);
echo "<br><br> favicon_file length | " . strlen($this->file_favicon);
echo "<br><br> IMAGE: ";
if ($this->file_favicon)
{
echo "<br><br> path_local | " . $this->path_local . "<br><br>";
$file64 = base64_encode($this->file_favicon);
echo "<img src= 'data:image/" . $this->ext . ";base64," . $file64 . "'></img>";
}
echo "<br><br>";
}
/****************************************************************************************************
invoke
****************************************************************************************************/
public function invoke( $pipe )
{
$domain = $pipe['domain'];
if ( $this->pageFound($domain) && $this->linkFound() && $this->faviconFoundFromLink() )
{
$pipe = $this->saveFavicon($pipe);
$pipe['favicon'] = $this->path_internet;
$pipe['favicon_local'] = $this->path_local;
} else {
$pipe['favicon'] = 'NULL';
$pipe['favicon_local'] = 'image_generic.png';
}
$pipe['method'] = $this->file_code . $this->favicon_code;
return $pipe;
}
/****************************************************************************************************
pageFound - uses the facade pattern to find a page and record how it was found
****************************************************************************************************/
private function pageFound ($domain)
{
return $this->pageFoundCurl($domain) || $this->pageFoundGet($domain);
}
// wget is another way to get past login page
// https://stackoverflow.com/questions/1324421/how-to-get-past-the-login-page-with-wget
// uses curl_exec to retreive a page
private function pageFoundCurl ($domain)
{
$types = array(
"curl - 4"=>'https://www.' . $domain,
"curl - 3"=>'http://www.' . $domain,
"curl - 6"=>'https://' . $domain,
"curl - 5"=>'http://' . $domain,
// returned 302 errors for test.com
"curl - 1"=>$domain,
"curl - 2"=>'www.' . $domain
);
foreach ($types as $key => $value) {
$this->file_page = $this->curlExec($value, true);
if ($this->file_page)
{
$this->file_code = $key;
return true;
}
}
return false;
}
// uses file_get_contents to retreive a page
private function pageFoundGet( $domain )
{
$types = array(
"file_get - 3"=>'http://www.' . $domain,
"file_get - 4"=>'https://www.' . $domain,
"file_get - 5"=>'http://' . $domain,
"file_get - 6"=>'https://' . $domain,
"file_get - 1"=>$domain,
"file_get - 2"=>'www.' . $domain
);
foreach ($types as $key => $value) {
if ($this->file_page = $this->fileGetContents( $value ))
{
$this->file_code = $key;
return true;
}
}
return false;
}
/****************************************************************************************************
linkFound
****************************************************************************************************/
private function linkFound()
{
$domain = $this->real_domain;
$regex = '#<link\s+(?=[^>]*rel=(?:\'|")(?:shortcut\s)?icon(?:\'|")\s*)(?:[^>]*href=(?:\'|")(.+?)(?:\'|")).*>#i';
$link_found = preg_match( $regex , $this->file_page, $matches );
if($link_found === 1)
{
$path = $matches[1];
// handles ( // )
if ( $path[0] === '/' && $path[1] === '/' )
{
$this->favicon_code = 'a';
$this->path_internet = 'http:' . $path;
}
// handles ( / )
else if( $path[0] === '/' )
{
$this->favicon_code = 'b';
$this->path_internet = 'http://www.' . $domain . $path;
}
// handles ( http:// || https:// )
else if ( substr($path, 0, 4) === 'http' )
{
$this->favicon_code = 'c';
$this->path_internet = $path;
}
// difference between b and d?
else
{
$this->favicon_code = 'd';
$this->path_internet = 'http://www.' . $domain . '/' . $path;
}
}
else
{
$default_location = 'http://www.' . $domain . '/favicon.ico';
/*
if( $this->faviconFound($default_location) )
{
$this->favicon_code = 'e';
$this->path_internet = $default_location;
}
*/
$this->path_internet = null;
$this->favicon_code = 'g';
return false;
}
return true;
}
/****************************************************************************************************
faviconFound
****************************************************************************************************/
private function faviconFoundFromLink ()
{
$this->file_favicon = $this->faviconFoundFacade( $this->path_internet );
return $this->file_favicon ? true : false;
}
private function faviconFound ($default_location)
{
$this->file_favicon = $this->faviconFoundFacade( $default_location );
return $this->file_favicon ? true : false;
}
/****************************************************************************************************
More
****************************************************************************************************/
private function faviconFoundFacade($url)
{
return $this->faviconFoundCurl($url) ;
}
private function faviconFoundExec($url)
{
exec('wget ' . $url . ' -O ../sites/temp.html 2>&1', $output);
}
private function faviconFoundGet($url)
{
return #file_get_contents( $url );
}
// make less than 10 characters equate to false so I don't save bogus files
// prisonexp.org does this
// bestbuy.com does similar
private function faviconFoundCurl($url)
{
$temp = $this->curlExec( $url, false );
if($temp === false)
{
return false;
}
if(strlen($temp) < 20)
{
return false;
}
return $temp;
}
/****************************************************************************************************
saveFavicon
****************************************************************************************************/
public function saveFavicon( $pipe )
{
// this will remove any query parameters on the favicon link
// and create a valid file name from the real domain
$arr = parse_url($this->path_internet);
$this->ext = pathinfo($arr['path'], PATHINFO_EXTENSION);
$name = str_replace('.', '_', $this->real_domain);
// add the extension if it exists, verify you need to to do this
if ($this->ext) {
$name = $name . "." . $this->ext;
}
// finally save it
file_put_contents($this->path_local1 . $name, $this->file_favicon);
$this->path_local = $name;
return $pipe;
}
/****************************************************************************************************
helper and wrapper functions
****************************************************************************************************/
// curl_exec wrapper
private function curlExec ($url, $set)
{
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
));
$temp = curl_exec($curl);
if ($set) $this->setRealDomain($curl);
curl_close($curl);
return $temp;
}
private function setRealDomain ($curl)
{
$url = curl_getinfo( $curl )['url'];
$url = parse_url($url);
$url = $url['host'];
$this->real_domain = preg_replace('#^www\.(.+\.)#i', '$1', $url);
}
// deprecated as curl can do everything I need, just in case though
// https://stackoverflow.com/questions/
// 6009284/how-do-i-ignore-a-moved-header-with-file-get-contents-in-php
private function fileGetContents($value)
{
$opts = array(
'http'=>array(
'follow_location' => true,
'max_redirects' => 20
)
);
$context = stream_context_create($opts);
return #file_get_contents( $value, false, $context );
}
/****************************************************************************************************
removed
****************************************************************************************************/
private function removed ()
{
$res = preg_match('#(.*?)([^\.]*)(\.)([^\.]*)$#', $domain, $matches);
if($matches[1])
{
$main = $matches[2] . $matches[3] . $matches[4];
$default_location = 'http://www.' . $main . '/favicon.ico';
$this->file_favicon = #file_get_contents( $default_location );
if( $this->file_favicon )
{
$this->path_internet = $default_location;
$this->favicon_code = 'f';
return true;
}
}
}
}
Here is one API for the front-side.
To check favicon using Google API
There is no strategy or API for favicons. Parse the HTML, look for:
<link rel="shortcut icon" href="...">
or just:
<link rel="icon" href="...">
and extract the value of the href attribute.
If no such tag exists (or the referenced icon is not there) then check for /favicon.ico (this is how everything started in 1999, on Internet Explorer 5).
Additionally, iOS (and some versions of Android) searches for extra <link> elements having rel="apple-touch-icon" or rel="apple-touch-icon-precomposed".
Everything else is just guessing and speculations.
See also: https://en.wikipedia.org/wiki/Favicon#History