Version: 1
Type: Class
Category: Networking
License: GNU General Public License
Description: Telnet script class. Written in french, but may be translatable :-). Tested, seems to work fine.
<?
/*
Fichier : scriptTelnet.inc (fichier d'include dclarant la classe ScriptTelnet)
Role de la classe : Grer un script se droulant via une socket telnet
Exemple d'utilisation, ne tenant pas compte des codes retour des methodes :
$script = new ScriptTelnet;
$script->setHote("unhote.quelquepart.fr");
$script->setPrompt(">");
$script->connecter();
$script->lireJusqua("ogin: ");
$script->ecrire("Jojo"));
$script->lireJusqua("word: ");
$script->ecrire("monpasse");
$script->attendrePrompt();
$script->ecrire("ps");
$script->attendrePrompt();
$script->deconnecter();
Auteur : Marc Ennaji
*/
define ("TELNET_ERREUR", 0);
define ("TELNET_OK", 1);
define ("TELNET_DEMANDE_CONFIRMATION", 2);
define ("LIBELLE_CONFIRMATION", "[confirm]");
Class ScriptTelnet
{
var $socket = NULL;
var $hote = "";
var $port = "23";
var $libelleErreur = "";
var $codeErreur = "";
var $prompt = "\$ ";
var $log = NULL; // handle de fichier
var $repertoireLog= "";
var $nomFichierLog = "";
var $test;
//------------------------------------------------------------------------
function connecter()
{
$this->socket = fsockopen($this->hote,$this->port);
if (! $this->socket)
{
$this->libelleErreur = "Impossible d'etablir la connexion telnet : " . strerror ($this->socket) . "\n";
return TELNET_ERREUR;
}
socket_set_timeout($this->socket,5,0);
return TELNET_OK;
}
//------------------------------------------------------------------------
function lireJusqua($chaine)
{
$NULL = chr(0);
$IAC = chr(255);
$buf = '';
if (! $this->socket)
{
$this->libelleErreur = "socket telnet non ouverte";
return TELNET_ERREUR;
}
while (1)
{
$c = $this->getc();
if ($c === false) // plus de caracteres a lire sur la socket
{
if ($this->contientErreur($buf))
return TELNET_ERREUR;
$this->libelleErreur = " La chaine attendue : '" . $chaine . "', n'a pas trouve dans les donnes reues : '" . $buf . "'" ;
$this->logger($this->libelleErreur);
return TELNET_ERREUR;
}
if ($c == $NULL || $c == "\021")
continue;
if ($c == $IAC) // Interpreted As Command
{
$c = $this->getc();
if ($c != $IAC) // car le 'vrai' caractere 255 est doubl pour le differencier du IAC
if (! $this->negocierOptionTelnet($c))
return TELNET_ERREUR;
else
continue;
}
$buf .= $c;
// indiquer l'utilisateur de la classe qu'il a une demande de confirmation
if (substr($buf,strlen($buf)-strlen(LIBELLE_CONFIRMATION)) == LIBELLE_CONFIRMATION)
{
$this->logger($this->getDernieresLignes($buf));
return TELNET_DEMANDE_CONFIRMATION;
}
if ((substr($buf,strlen($buf)-strlen($chaine))) == $chaine)
{
// on a trouve la chaine attendue
$this->logger($this->getDernieresLignes($buf));
if ($this->contientErreur($buf))
return TELNET_ERREUR;
else
return TELNET_OK;
}
}
}
//------------------------------------------------------------------------
function getc()
{
return fgetc($this->socket);
}
//------------------------------------------------------------------------
function negocierOptionTelnet($commande)
{
// on negocie des options minimales
$IAC = chr(255);
$DONT = chr(254);
$DO = chr(253);
$WONT = chr(252);
$WILL = chr(251);
if (($commande == $DO) || ($commande == $DONT))
{
$opt = $this->getc();
//echo "wont ".ord($opt)."\n";
fwrite($this->socket,$IAC.$WONT.$opt);
}
else if (($commande == $WILL) || ($commande == $WONT))
{
$opt = fgetc($this->socket);
//echo "dont ".ord($opt)."\n";
fwrite($this->socket,$IAC.$DONT.$opt);
} else
{
$this->libelleErreur = "Erreur : commande inconnue ".ord($commande)."\n";
return false;
}
return true;
}
//------------------------------------------------------------------------
function ecrire($buffer, $valeurLoggee = "", $ajouterfinLigne = true)
{
if (! $this->socket)
{
$this->libelleErreur = "socket non ouverte";
return TELNET_ERREUR;
}
if ($ajouterfinLigne)
$buffer .= "\n";
if (fwrite($this->socket,$buffer) < 0)
{
$this->libelleErreur = "erreur d'ecriture sur la socket telnet";
return TELNET_ERREUR;
}
if ($valeurLoggee != "") // cacher les valeurs confidentielles dans la log (mots de passe...)
$buffer = $valeurLoggee . "\n";
if (! $ajouterfinLigne) // dans la log (mais pas sur la socket), rajouter tout de meme le caractere de fin de ligne
$buffer .= "\n";
$this->logger("> " .$buffer);
return TELNET_OK;
}
//------------------------------------------------------------------------
function deconnecter()
{
if ($this->socket)
{
if (! fclose($this->socket))
{
$this->libelleErreur = "erreur a la fermeture de la socket telnet";
return TELNET_ERREUR;
}
$this->socket = NULL;
}
$this->setLog(false,"");
return TELNET_OK;
}
//------------------------------------------------------------------------
function contientErreur($buf)
{
$messagesErreurs[] = "nvalid"; // Invalid input, ...
$messagesErreurs[] = "o specified"; // No specified atm, ...
$messagesErreurs[] = "nknown"; // Unknown profile, ...
$messagesErreurs[] = "o such file or directory"; // sauvegarde dans un repertoire inexistant
$messagesErreurs[] = "llegal"; // illegal file name, ...
foreach ($messagesErreurs as $erreur)
{
if (strpos ($buf, $erreur) === false)
continue;
// une erreur est dtecte
$this->libelleErreur = "Un message d'erreur a t dtect dans la rponse de l'hte distant : " .
"<BR><BR>" . $this->getDernieresLignes($buf,"<BR>") . "<BR>";
return true;
}
return false;
}
//------------------------------------------------------------------------
function attendrePrompt()
{
return $this->lireJusqua($this->prompt);
}
//------------------------------------------------------------------------
function setPrompt($s) { $this->prompt = $s; return TELNET_OK; }
//------------------------------------------------------------------------
function setHote($s) { $this->hote = $s;}
//------------------------------------------------------------------------
function setPort($s) { $this->port = $s;}
//------------------------------------------------------------------------
function getDerniereErreur() { return $this->libelleErreur; }
//------------------------------------------------------------------------
function setLog($activerLog, $traitement)
{
if ($this->log && $activerLog)
return TELNET_OK;
if ($activerLog)
{
$this->repertoireLog = "/log/" . date("m");
if (! file_exists($this->repertoireLog)) // repertoire mensuel inexistant ?
{
if (mkdir($this->repertoireLog, 0700) === false)
{
$this->libelleErreur = "Impossible de crer le repertoire de log " . $this->repertoireLog;
return TELNET_ERREUR;
}
}
global $HTTP_SERVER_VARS;
$this->nomFichierLog = date("d") . "_" .
date("H:i:s") . "_" .
$traitement . "_" .
$HTTP_SERVER_VARS["PHP_AUTH_USER"]
. ".log";
$this->log = fopen($this->repertoireLog . "/" . $this->nomFichierLog,"a");
if (empty($this->log))
{
$this->libelleErreur = "Impossible de crer le fichier de log " . $this->nomFichierLog;
return TELNET_ERREUR;
}
$this->logger("----------------------------------------------\r\n");
$this->logger("Dbut de la log de l'utilisateur " . $HTTP_SERVER_VARS["PHP_AUTH_USER"] .
", adresse IP " . $HTTP_SERVER_VARS["REMOTE_ADDR"] . "\r\n");
$this->logger("Connexion telnet sur " . $this->hote . ", port " . $this->port . "\r\n");
$this->logger("Date : " . date("d-m-Y"). " " . date("H:i:s") . "\r\n");
$this->logger("Type de traitement effectu : " . $traitement . "\r\n");
$this->logger("----------------------------------------------\r\n");
return TELNET_OK;
}
else
{
if ($this->log)
{
$this->logger("----------------------------------------------\r\n");
$this->logger("Fin de la log\r\n");
fflush($this->log);
if (! fclose($this->log))
{
$this->libelleErreur = "erreur a la fermeture du fichier de log";
return TELNET_ERREUR;
}
$this->log = NULL;
}
return TELNET_OK;
}
}
//------------------------------------------------------------------------
function logger($s)
{
if ($this->log)
fwrite($this->log, $s);
}
//------------------------------------------------------------------------
function getDernieresLignes($s, $separateur="\n")
{
// une reponse telnet contient (en principe) en premiere ligne l'echo de la commande utilisateur.
// cette methode renvoie tout sauf la premiere ligne, afin de ne pas polluer les logs telnet
$lignes = split("\n",$s);
$resultat = "";
$premiereLigne = true;
while(list($key, $data) = each($lignes))
{
if ($premiereLigne)
$premiereLigne = false;
else
if ($data != "")
$resultat .= $data . $separateur;
}
$resultat == substr($resultat,strlen($resultat)-1); // enlever le dernier caractere de fin de ligne
return $resultat;
}
//------------------------------------------------------------------------
} // Fin de la classe
?>