免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4392 | 回复: 1
打印 上一主题 下一主题

PHP 获取MSN好友列表 组信息 发送离线消息 (一) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-30 18:41 |只看该作者 |倒序浏览

               
/**
* 基于 http://code.google.com/p/phpmsnclass/ 1.8版
* 去除大段注释,以及无用代码
* 仅使用发消息及获取好友列表功能
* 2008-12-15 李勇
*/
class MSN{
    //dispatch服务器地址及端口
    private $server = 'messenger.hotmail.com';
    private $port = 1863;
    private $passport_url = 'https://login.live.com/RST.srf';
    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, $errstr, 5);
        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($data, 0, 3);
            $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($password, 0, 16);
                    $this->user = $user;
                    $this->password = $password;
                    // NS: @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, $errstr, 5);
                    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: @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: http://msnpiki.msnfanatic.com/index.php/Reference:Error_List";
                        $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
     *          userprivate function get_passport_ticket($url = ''){
        $user = $this->user;
        $password = htmlspecialchars($this->password);
        if ($url === '')
        $passport_url = $this->passport_url;
        else
        $passport_url = $url;
        $XML = '
  
    {7108E71A-9926-4FCB-BCC9-9A9D3F32E423}
    4
    1
   
    AQAAAAIAAABsYwQAAAAxMDMz
  
  
   
      '.$user.'
      '.$password.'
   
  
  
   
      http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue
      
        
          http://Passport.NET/tb
        
      
   
   
      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($curl, CURLOPT_URL, $passport_url);
        if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);
        $data = curl_exec($curl);
        $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        curl_close($curl);
        if ($http_code != 200) {
            // sometimes, redirect to another URL
            // MSNP15
            //psf:Redirect
            //https://msnia.login.live.com/pp450/RST.srf
            //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
        //https://msnia.login.live.com/pp450/RST.srf
        //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;
    }
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/109285/showart_2135808.html

论坛徽章:
0
2 [报告]
发表于 2010-01-13 15:55 |只看该作者

我简单修改了一下:获取好友列表时不再需要mhash扩展

我简单修改了一下:获取好友列表时不再需要mhash扩展;不使用发送消息功能时,不再需要bcmath扩展
修正2009/07/21后无法发送消息的问题

见:http://docs.google.com/View?id=dhq2k76t_20cqnmjkdg

[ 本帖最后由 SandersWang 于 2010-1-13 17:41 编辑 ]

msn.class.7z

9.14 KB, 下载次数: 98

msn.class.php

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP