Código PHP:
<?
class msnclass {
function msnclass ($login,$password) {
isset($login) ? $this->msnuser=$login : die ("No se ha especificado usuario");
isset($password) ? $this->msnpassword=$password : die ("No se ha especificado password");
$this->dispatchserver="messenger.hotmail.com";
$this->dispatch_port="1863";
$this->msnlogin();
$this->trid=5;
}
function msnlogin () {
$this->msn_stream=$this->new_msn_stream ($this->dispatchserver,$this->dispatch_port);
$this->simple_io ($this->msn_stream,"VER 1 MSNP10 MSNP9 MSNP8 MSNP7 MSNP6 MSNP5 MSNP4 CVR0\r\n");
$this->simple_io ($this->msn_stream,"CVR 2 0x0409 winnt 5.1 i386 MSNMSGR 5.0.0540 MSMSGS $this->msnuser\r\n");
$new_ip=$this->simple_io ($this->msn_stream,"USR 3 TWN I $this->msnuser\r\n");
// XF3 3 NS 207.46.106.35:1863 0 207.46.104.20:1863
$new_ip=explode (" ",$new_ip);
$new_ip=explode (":",$new_ip[3]);
$ip=$new_ip[0];
$port=$new_ip[1];
unset ($new_ip);
//$this->msn_close ($this->msn_stream); lo cierra solo
// Este es el stream definitivo, el que hay que mantener
$this->msn_stream=$this->new_msn_stream ($ip,$port);
$this->simple_io ($this->msn_stream,"VER 1 MSNP10 MSNP9 MSNP8 MSNP7 MSNP6 MSNP5 MSNP4 CVR0\r\n");
$this->simple_io ($this->msn_stream,"CVR 2 0x0409 winnt 5.1 i386 MSNMSGR 5.0.0540 MSMSGS $this->msnuser\r\n");
$semilla_dispatch=$this->simple_io ($this->msn_stream,"USR 3 TWN I $this->msnuser\r\n");
$semilla_dispatch=explode (" ",$semilla_dispatch);
$semilla_dispatch=$semilla_dispatch[4];
$this->msnuser=urlencode ($this->msnuser);
$this->msnpassword=urlencode ($this->msnpassword);
// Consultamos el servidor para login al nexus passport
$server=$this->nexus_passport();
$this->host=$server[0];
$this->path=$server[1];
while ($ticket=="relogin" || !$ticket) {
$ticket=$this->login_server ($this->host,$this->path,$this->msnuser,$this->msnpassword,$semilla_dispatch);
}
$this->$nick_user=$this->raw_io ($this->msn_stream,"USR 4 TWN S $ticket\r\n");
}
function recupera_nick () {
$nick_user=explode (" ",$this->$nick_user);
return urldecode($nick_user[4]);
}
function anade_usuario($email) { // trids a partir del 7
$posible_error=$this->raw_io ($this->msn_stream,"ADD $this->trid AL $email $email\r\n");
$this->trid++;
return $posible_error;
}
function new_msn_stream ($servidor,$puerto) {
$msn_stream=fsockopen ($servidor,$puerto) or die ("No se pudo conectar al servidor $servidor");
return $msn_stream;
}
function nexus_passport() {
// Por otro lado, recogemos el servidor que nos proporcionara el ticket
$passport_stream=$this->new_msn_stream ("ssl://nexus.passport.com",443);
$headers=$this->raw_io ($passport_stream, "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n");
//$this->msn_close ($passport_stream); lo cierra solo
preg_match ("/DALogin=(.*?),/ie",$headers,$datos_login);
$datos_login=$datos_login[1];
$partes_host=explode ("/",$datos_login);
$host=$partes_host[0];
if (count($partes_host)>2) {
$path=implode ("/",array_slice ($partes_host,1));
}
else $path="/".$partes_host[1];
return array ($host,$path);
}
function login_server ($host,$path,$user,$password,$semilla) {
$login_stream=$this->new_msn_stream ("ssl://$host",443);
$cadena="GET $path HTTP/1.1\r\n";
$cadena.="Authorization: Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=$user,pwd=$password,$semilla";
$cadena.="Host: $host\r\n\r\n";
$headers=$this->raw_io ($login_stream,$cadena);
fclose($login_stream);
if (eregi("HTTP/1.1 302 Found",$headers)) {
$nuevo_login=array();
preg_match ("/Location: https:\/\/(.*)\/(.*)/i",$headers,$nuevo_login);
$this->host=$nuevo_login[1];
$this->path="/".$nuevo_login[2];
return $cadena="relogin";
}
elseif (eregi("HTTP/1.1 200 OK",$headers)) {
$ticket=array();
preg_match("/from-PP=\'(.*)\',ru/i", $headers,$ticket);
return $ticket[1];
}
else return false;
}
function estado_invisible () {
$usuarios_online=$this->raw_io ($this->msn_stream,"CHG $this->trid HDN\r\n");
$this->trid++;
$usuarios_online=explode ("\n",$usuarios_online);
$usuarios_online=array_splice($usuarios_online,1,count($usuarios_online)-5);
$devolver=array();
foreach ($usuarios_online as $user) {
$user=explode (" ",$user);
$devolver["$user[3]"]=array ($user[4],$user[2]);
}
$this->raw_io ($this->msn_stream,"");
return $devolver;
}
function lista_contactos () {
$todos=$this->raw_io ($this->msn_stream,"SYN $this->trid 0\r\n");
$this->trid++;
$todos=explode ("\n",$todos);
return $todos;
}
function responder_ping($semilla) {
$this->trid++;
fputs($this->msn_stream,"QRY $this->trid [email protected] 32\r\n");
// pk aqui va el $this->trid++ antes es facil de entender
// los pings siempre le llegan si ha habido instruccion (k es cuando recogemos valores)
// con lo que no se puede usar el trid actual, porque ésta ya lo habrá utilizado
// cuando acabe la instruccion inicial, ya le suma otro +1 a trid.
$semilla=md5($semilla."Q1P7W2E4J9R8U3S5");
// la semilla es el hash md5 del numero enviado por CHL mas el string Q1P7W2E4...
$query=$this->simple_io($this->msn_stream,$semilla);
// Atencion, el payload va sin retorno de carro
}
function simple_io ($stream,$cadena) {
fputs ($stream,$cadena);
$output=fgets ($stream,512);
//echo $output."\n"; //descomentalo para debugear
return $output;
}
function raw_io ($stream,$cadena) {
fputs ($stream,$cadena);
while ($linea=trim (fgets ($stream,512))) {
//deteccion de PING's del servidor, formato->CHL 0 12312345543534 <- semilla
if (ereg ("CHL 0",$linea)) {
$semilla=explode (" ",$linea);
$this->responder_ping($semilla[2]);
}
$output.=$linea."\n";
}
//echo $output; //descomentalo para debugear
return $output;
}
function msn_close () {
fclose ($this->msn_stream);
}
}
?>