Chinaunix首页 | 论坛 | 博客
  • 博客访问: 303513
  • 博文数量: 153
  • 博客积分: 3347
  • 博客等级: 中校
  • 技术积分: 1556
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-30 17:50
文章分类

全部博文(153)

文章存档

2013年(7)

2012年(21)

2011年(46)

2010年(16)

2009年(63)

我的朋友

分类:

2009-12-30 18:41:30

/**
* 基于 版
* 去除大段注释,以及无用代码
* 仅使用发消息及获取好友列表功能
* 2008-12-15 李勇
*/
class MSN{
    
//dispatch服务器地址及端口
    
private $server 'messenger.hotmail.com';
    private 
$port 1863;

    private 
$passport_url '';

    private 
$prod_key 'PK}_A_0N_K%O?A9S';
    private 
$prod_id 'PROD0114ES4Z%Q5W';

    private 
$clientid '0x7000800C';

    private 
$id;
    private 
$fp false;
    private 
$error '';

    private 
$authed false;
    private 
$user '';
    private 
$password '';

    private 
$passport_policy '';
    private 
$oim_try 3;
    private 
$oim_ticket '';
    private 
$contact_ticket '';

    private 
$debug true;

    private 
$timeout 15;
    private 
$stream_timeout 2;

    private 
$sb;
    private 
$font_fn 'Arial';
    private 
$font_co '333333';
    private 
$font_ef '';

    private 
$max_msn_message_len 1664;
    private 
$max_yahoo_message_len 518;

    
/**
     * 构造函数,需要以下PHP扩展的支持curl,prece,mhash,mcrypt,bcmath
     *
     * @return MSN
     */
    
public function MSN(){
        if (!
function_exists('curl_init')) die("We need curl module!\n");
        if (!
function_exists('preg_match')) die("We need pcre module!\n");
        if (!
function_exists('mhash'))die("We need mhash module  !\n");
        if (!
function_exists('mcrypt_cbc')) die("We need mcrypt module !\n");
        if (!
function_exists('bcmod'))die("We need bcmath module !\n");

        return;
    }

    
/**
     * 登录指定MSN账号
     *
     * @param string $user
     * @param string $password
     * @return bool
     * @uses
     *      var
     *          id
     *          fp
     *          =>error
     *          =>authed
     *          timeout
     *          =>passport_policy
     *          =>oim_ticket
     *          =>contact_ticket
     *          =>user
     *          =>password
     *      function
     *          readln
     *          writeln
     *          readdata
     *          debug_message
     *          get_passport_ticket
     *          generateLoginBLOB
     */
    
public function connect($user$password){
        
$this->id 1;

        
$server='messenger.hotmail.com';
        
$port=1863;

        
$errno=0;
        
$errstr='';
        
$stream_timeout 2;

        
$this->fp = @fsockopen($server$port$errno$errstr5);
        if (!
$this->fp) {
            
$this->error "Can't connect to $server:$port, error => $errno, $errstr";
            return 
false;
        }

        
stream_set_timeout($this->fp$stream_timeout);
        
$this->authed false;

        
$this->writeln("VER $this->id MSNP15 CVR0");

        
$start_tm time();
        while (!
feof($this->fp)) {
            
$data $this->readln();
            
// no data?
            
if ($data === false) {
                if (
$this->timeout 0) {
                    
$now_tm time();
                    
$used_time = ($now_tm >= $start_tm) ? $now_tm $start_tm $now_tm;
                    if (
$used_time $this->timeout) {
                        
// logout now
                        // NS: >>> OUT
                        
$this->writeln("OUT");
                        
fclose($this->fp);
                        
$this->error 'Timeout, maybe protocol changed!';
                        
$this->debug_message("*** $this->error");
                        return 
false;
                    }
                }
                continue;
            }
            
$code substr($data03);
            
$start_tm time();
            switch (
$code) {
                case 
'VER':
                    
$this->writeln("CVR $this->id 0x0409 winnt 5.1 i386 MSMSGS 8.1.0178 msmsgs $user");
                    break;
                case 
'CVR':
                    
$this->writeln("USR $this->id SSO I $user");
                    break;
                case 
'USR':
                    if (
$this->authed) return true;

                    
// max. 16 digits for password
                    
if (strlen($password) > 16)
                    
$password substr($password016);

                    
$this->user $user;
                    
$this->password $password;

                    
// NS: <<< USR {id} SSO S {policy} {nonce}
                    
@list(/* USR *//* id *//* SSO *//* S */$policy$nonce,) = @explode(' '$data);

                    
$this->passport_policy $policy;
                    
$aTickets $this->get_passport_ticket();
                    if (!
$aTickets || !is_array($aTickets)) {
                        
// logout now
                        // NS: >>> OUT
                        
$this->writeln("OUT");
                        
fclose($this->fp);
                        
$this->error 'Passport authenticated fail!';
                        
$this->debug_message("*** $this->error");
                        return 
false;
                    }

                    
$this->oim_ticket $aTickets['oim_ticket'];
                    
$this->contact_ticket $aTickets['contact_ticket'];

                    
// NS: >>> USR {id} SSO S {ticket} {login_code}
                    
$this->writeln("USR $this->id SSO S ".$aTickets['ticket']." ".$this->generateLoginBLOB($aTickets['secret'], $nonce));

                    
$this->authed true;
                    break;
                case 
'XFR':
                    @list(
/* XFR *//* id *//* NS */$server/* ... */) = @explode(' '$data);
                    @list(
$ip$port) = @explode(':'$server);
                    
// this connection will close after XFR
                    
fclose($this->fp);

                    
$errno=0;
                    
$errstr='';
                    
$this->fp = @fsockopen($ip$port$errno$errstr5);
                    if (!
$this->fp) {
                        
$this->error "Can't connect to $ip:$port, error => $errno, $errstr";
                        
$this->debug_message("*** $this->error");
                        return 
false;
                    }

                    
stream_set_timeout($this->fp$this->stream_timeout);
                    
$this->writeln("VER $this->id MSNP15 CVR0");
                    break;
                case 
'GCF':
                    
// return some policy data after 'USR {id} SSO I {user}' command
                    // NS: <<< GCF 0 {size}
                    
@list(/* GCF *//* 0 */$size,) = @explode(' '$data);
                    
// we don't need the data, just read it and drop
                    
if (is_numeric($size) && $size 0)
                    
$this->readdata($size);
                    break;
                default:
                    
// we'll quit if got any error
                    
if (is_numeric($code)) {
                        
// logout now
                        // NS: >>> OUT
                        
$this->writeln("OUT");
                        
fclose($this->fp);
                        
$this->error "Error code: $code, please check the detail information from: ";
                        
$this->debug_message("*** $this->error");
                        return 
false;
                    }
                    
// unknown response from server, just ignore it
                    
break;
            }
        }
        
// never goto here
        
return false;
    }


    
/**
     * 获取通行证的令牌
     *
     * @param string $url
     * @return string
     * @uses
     *      var
     *          user<=
     *          password<=
     *          passport_url<=
     *          passport_policy<=
     *      function
     */
    
private function get_passport_ticket($url ''){
        
$user $this->user;
        
$password htmlspecialchars($this->password);
        if (
$url === '')
        
$passport_url $this->passport_url;
        else
        
$passport_url $url;
        
$XML '
          xmlns:wsse=""
          xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"
          xmlns:wsp=""
          xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
          xmlns:wsa=""
          xmlns:wssc=""
          xmlns:wst="">

  
    {7108E71A-9926-4FCB-BCC9-9A9D3F32E423}
    4
    1
    
    AQAAAAIAAABsYwQAAAAxMDMz
  
  
    
      '.$user.'
      '.$password.'
    
  



  
    
      http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue
      
        
          
        

      

    
    
      http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue
      
        
          messengerclear.live.com
        

      

      .$this->passport_policy.'">
    
    
      http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue
      
        
          messenger.msn.com
        

      

      
    
    
      http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue
      
        
          contacts.msn.com
        

      

      
    
    
      http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue
      
        
          messengersecure.live.com
        

      

      
    
    
      http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue
      
        
          spaces.live.com
        

      

      
    
    
      http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue
      
        
          storage.msn.com
        

      

      
    
  

'
;
        
$curl curl_init();
        
curl_setopt($curlCURLOPT_URL$passport_url);
        if (
$this->debugcurl_setopt($curlCURLOPT_HEADER1);
        
curl_setopt($curlCURLOPT_RETURNTRANSFER1);
        
curl_setopt($curlCURLOPT_FOLLOWLOCATION1);
        
curl_setopt($curlCURLOPT_SSL_VERIFYPEER0);
        
curl_setopt($curlCURLOPT_POST1);
        
curl_setopt($curlCURLOPT_POSTFIELDS$XML);
        
$data curl_exec($curl);
        
$http_code curl_getinfo($curlCURLINFO_HTTP_CODE);
        
curl_close($curl);

        if (
$http_code != 200) {
            
// sometimes, redirect to another URL
            // MSNP15
            //psf:Redirect
            //
            //Authentication Failure
            
if (strpos($data'psf:Redirect') === false) {
                
$this->debug_message("*** Can't get passport ticket! http code = $http_code");
                return 
false;
            }
            
preg_match("#(.*)#"$data$matches);
            if (
count($matches) == 0) {
                
$this->debug_message("*** redirect, but can't get redirect URL!");
                return 
false;
            }
            
$redirect_url $matches[1];
            if (
$redirect_url == $passport_url) {
                
$this->debug_message("*** redirect, but redirect to same URL!");
                return 
false;
            }
            
$this->debug_message("*** redirect to $redirect_url");
            return 
$this->get_passport_ticket($redirect_url);
        }
        
// sometimes, rediret to another URL, also return 200
        // MSNP15
        //psf:Redirect
        //
        //Authentication Failure
        
if (strpos($data'psf:Redirect') !== false) {
            
preg_match("#(.*)#"$data$matches);
            if (
count($matches) != 0) {
                
$redirect_url $matches[1];
                if (
$redirect_url == $passport_url) {
                    
$this->debug_message("*** redirect, but redirect to same URL!");
                    return 
false;
                }
                
$this->debug_message("*** redirect to $redirect_url");
                return 
$this->get_passport_ticket($redirect_url);
            }
        }

        
preg_match("#".
        
"(.*)(.*)".
        
"(.*)(.*)".
        
"(.*)(.*)".
        
"(.*)(.*)".
        
"(.*)(.*)".
        
"(.*)(.*)".
        
"(.*)(.*)".
        
"#",
        
$data$matches);
        
// no ticket found!
        
if (count($matches) == 0) {
            
$this->debug_message("*** Can't get passport ticket!");
            return 
false;
        }
        
// yes, we get ticket
        
$aTickets = array(
        
'ticket' => html_entity_decode($matches[1]),
        
'secret' => html_entity_decode($matches[3]),
        
'contact_ticket' => html_entity_decode($matches[7]),
        
'oim_ticket' => html_entity_decode($matches[9]),
        );
        return 
$aTickets;
    }


阅读(985) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~