Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: momentas on May 22nd, 2012  |  syntax: None  |  size: 14.16 KB  |  hits: 24  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. <?php
  2. /*
  3. * WebIcqLite: ICQ messages sender. v3.2b
  4. * (C) 2006 Sergey Akudovich, http://intrigue.ru/
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. * See http://www.gnu.org/copyleft/lesser.html
  11. *
  12. */
  13.  
  14. class WebIcqLite_TLV {
  15.     var $type;
  16.     var $size;
  17.     var $error;
  18.    
  19.     var $types = array
  20.     (
  21.         'UIN'                 =>  1, // 0x01
  22.         'DATA'                =>  2, // 0x02
  23.         'CLIENT'            =>  3, // 0x03
  24.         'ERROR_URL'            =>  4, // 0x04
  25.         'RECONECT_HERE'        =>  5, // 0x05
  26.         'COOKIE'            =>  6, // 0x06
  27.         'SNAC_VERSION'        =>  7, // 0x07
  28.         'ERROR_SUBCODE'        =>  8, // 0x08
  29.         'DISCONECT_REASON'    =>  9, // 0x09
  30.         'RECONECT_HOST'        => 10, // 0x0A
  31.         'URL'                => 11, // 0x0B
  32.         'DEBUG_DATA'        => 12, // 0x0C
  33.         'SERVICE'            => 13, // 0x0D
  34.         'CLIENT_COUNTRY'    => 14, // 0x0E
  35.         'CLIENT_LNG'        => 15, // 0x0F
  36.         'SCRIPT'            => 16, // 0x10
  37.         'USER_EMAIL'        => 17, // 0x11
  38.         'OLD_PASSWORD'        => 18, // 0x12
  39.         'REG_STATUS'        => 19, // 0x13
  40.         'DISTRIB_NUMBER'    => 20, // 0x14
  41.         'PERSONAL_TEXT'        => 21, // 0x15
  42.         'CLIENT_ID'            => 22, // 0x16
  43.         'CLI_MAJOR_VER'     => 23, // 0x17
  44.         'CLI_MINOR_VER'     => 24, // 0x18
  45.         'CLI_LESSER_VER'     => 25, // 0x19
  46.         'CLI_BUILD_NUMBER'    => 26, // 0x1A
  47. //        'PASSWORD'            => 37
  48.     );
  49.    
  50.     function setTLV($type, $value, $length = false)
  51.     {
  52.         switch ($length)
  53.         {
  54.             case 1:
  55.                 $format = 'c';
  56.                 break;
  57.             case 2:
  58.                 $format = 'n';
  59.                 break;
  60.             case 4:
  61.                 $format = 'N';
  62.                 break;
  63.             default:
  64.                 $format = 'a*';
  65.                 break;
  66.         }
  67.         if ($length === false)
  68.         {
  69.             $length = strlen($value);
  70.         }
  71.         return pack('nn'.$format, $this->types[$type], $length, $value);
  72.     }
  73.    
  74.     function getTLV($data)
  75.     {
  76.         $arr = unpack('n2', substr($data, 0, 4));
  77.         $this->type = $arr[1];
  78.         $this->size = $arr[2];
  79.         return substr($data, 4, $this->size);
  80.     }
  81.  
  82.     function getTLVFragment($data)
  83.     {
  84.         $frg = unpack('cid/cversion/nsize', substr($data, 0, 4));
  85.         $frg['data'] = substr($data, 4, $frg['size']);
  86.         return $frg;
  87.     }
  88. }
  89.  
  90. class WebIcqLite_SNAC extends WebIcqLite_TLV {
  91.    
  92.     var $request_id = 0;
  93.     var $uin;
  94.    
  95.     function setSNAC0102()
  96.     {
  97.         $this->request_id++;
  98.         $out = pack('nnnN', 1, 2, 0, $this->request_id);
  99.         $out .= pack('n*', 1, 3, 272, 650);
  100.         $out .= pack('n*', 2, 1, 272, 650);
  101.         $out .= pack('n*', 3, 1, 272, 650);
  102.         $out .= pack('n*', 21, 1, 272, 650);
  103.         $out .= pack('n*', 4, 1, 272, 650);
  104.         $out .= pack('n*', 6, 1, 272, 650);
  105.         $out .= pack('n*', 9, 1, 272, 650);
  106.         $out .= pack('n*', 10, 1, 272, 650);
  107.        
  108.         return $out;
  109.     }
  110.    
  111.     function setSNAC0406($uin, $message)
  112.     {
  113.         $this->request_id++;
  114.         $cookie = microtime();
  115.         $out = pack('nnnNdnca*', 4, 6, 0, $this->request_id, $cookie, 2, strlen($uin), $uin);
  116.        
  117.         $capabilities = pack('H*', '094613494C7F11D18222444553540000'); // utf-8 support
  118.         // '97B12751243C4334AD22D6ABF73F1492' rtf support
  119.        
  120.         $data = pack('nd', 0, $cookie).$capabilities;
  121.         $data .= pack('nnn', 10, 2, 1);
  122.         $data .= pack('nn', 15, 0);
  123.         $data .= pack('nnvvddnVn', 10001, strlen($message)+62, 27, 8, 0, 0, 0, 3, $this->request_id);
  124.         $data .= pack('nndnn', 14, $this->request_id, 0, 0, 0); //45
  125.         $data .= pack('ncvnva*', 1, 0, 0, 1, (strlen($message)+1), $message);
  126.         $data .= pack('H*', '0000000000FFFFFF00');
  127.         $out .= $this->setTLV('RECONECT_HERE', $data);
  128.         $out .= $this->setTLV('CLIENT', '');
  129.         return $out;
  130.     }
  131.    
  132.     function setSNAC0406offline($uin, $message)
  133.     {
  134.         $this->request_id++;
  135.         $cookie = microtime();
  136.         $out = pack('nnnNdnca*', 4, 6, 0, $this->request_id, $cookie, 1, strlen($uin), $uin);
  137.        
  138.         $data = pack('ccnc', 5, 1, 1, 1);
  139.         $data .= pack('ccnnna*', 1, 1, strlen($message)+4, 3, 0, $message);
  140.         $out .= $this->setTLV('DATA', $data);
  141.         $out .= $this->setTLV('CLIENT', '');
  142.         $out .= $this->setTLV('COOKIE', '');
  143.         return $out;
  144.     }
  145.    
  146.     function getSNAC0407($body)
  147.     {
  148.         if (strlen($body))
  149.         {
  150.             $msg = unpack('nfamily/nsubtype/nflags/Nrequestid/N2msgid/nchannel/cnamesize', $body);
  151.             if ($msg['family'] == 4 && $msg['subtype'] == 7)
  152.             {
  153.                 $body = substr($body, 21);
  154.                 $from = substr($body, 0, $msg['namesize']);
  155.                 $channel = $msg['channel'];
  156.                 $body = substr($body, $msg['namesize']);
  157.                 $msg = unpack('nwarnlevel/nTLVnumber', $body);
  158.                 $body = substr($body, 4);
  159.                 for ($i = 0; $i <= $msg['TLVnumber']; $i++)
  160.                 {
  161.                     $part = $this->getTLV($body);
  162.                     $body = substr($body, 4 + $this->size);
  163.                     if ($channel == 1 && $this->type == 2)
  164.                     {
  165.                         while (strlen($part))
  166.                         {
  167.                             $frg = $this->getTLVFragment($part);
  168.                             if ($frg['id'] == 1 && $frg['version'] == 1)
  169.                             {
  170.                                 return array('from' => $from, 'message' => substr($frg['data'], 4));
  171.                             }
  172.                             $part = substr($part, 4+$frg['size']);
  173.                         }
  174.                         return false;
  175.                     }
  176.                 }
  177.             }
  178.         }
  179.         return false;
  180.     }
  181.     function dump($str)
  182.     {
  183.         $f = fopen('dump', 'a');
  184.         fwrite($f, $str);
  185.         fclose($f);
  186.     }
  187.    
  188. }
  189.  
  190. class WebIcqLite_FLAP extends WebIcqLite_SNAC{
  191.    
  192.     var $socet;
  193.     var $command = 0x2A;
  194.     var $channel;
  195.     var $sequence;
  196.     var $body;
  197.     var $info = array();
  198.  
  199.     function WebIcqLite_FLAP() {
  200.         $this->sequence = rand(1, 30000);
  201.     }
  202.    
  203.     function getFLAP()
  204.     {
  205.         if($this->socet && !socket_last_error($this->socet))
  206.         {
  207.             $header = socket_read($this->socet, 6);
  208.             if ($header)
  209.             {
  210.                 $header = unpack('c2channel/n2size', $header);
  211.                 $this->channel = $header['channel2'];
  212.                 $this->body = socket_read($this->socet, $header['size2']);
  213.                 return true;
  214.             }
  215.             else
  216.             {
  217.                 return false;
  218.             }
  219.         }
  220.     }
  221.    
  222.     function parseCookieFLAP()
  223.     {
  224.         $this->getFLAP();
  225.         $this->info = array();
  226.         while($this->body != '')
  227.         {
  228.             $info = $this->getTLV($this->body);
  229.             $key = array_search($this->type, $this->types);
  230.             if($key)
  231.             {
  232.                 $this->info[$key] = $info;
  233.             }
  234.             $this->body = substr($this->body, ($this->size+4));
  235.         }
  236.     }
  237.    
  238.     function parseAnswerFLAP()
  239.     {
  240.         $this->getFLAP();
  241.         $array = unpack('n3int/Nint', $this->body);
  242.         while ($array['int'] != $this->request_id)
  243.         {
  244.             $this->getFLAP();
  245.             $array = unpack('n3int/Nint', $this->body);
  246.         }
  247.  
  248.         $this->error = 'Unknown serwer answer';
  249.         if ($array['int1'] == 4)
  250.         {
  251.             switch ($array['int2'])
  252.             {
  253.                 case 1:
  254.                         $this->error = 'Error to sent message';
  255.                         return false;
  256.                     break;
  257.                 case 0x0c:
  258.                         return true;
  259.                     break;
  260.             }
  261.         }
  262.  
  263.         $this->error = 'Unknown serwer answer';
  264.         return false;
  265.     }
  266.    
  267.     function prepare()
  268.     {
  269.         $this->sequence++;
  270.         $out = pack('ccnn', $this->command, $this->channel, $this->sequence, strlen($this->body)).$this->body;
  271.         return $out;
  272.     }
  273.    
  274.     function login($uin, $password)
  275.     {
  276.         $this->getFLAP();
  277.         $this->uin = $uin;
  278.         $this->body .= $this->setTLV('UIN',                 "$uin");
  279.         $this->body .= $this->setTLV('DATA',                 $this->xorpass($password));
  280.         $this->body .= $this->setTLV('CLIENT',                 'ICQBasic');
  281.         $this->body .= $this->setTLV('CLIENT_ID',             266, 2);
  282.         $this->body .= $this->setTLV('CLI_MAJOR_VER',         20, 2);
  283.         $this->body .= $this->setTLV('CLI_MINOR_VER',         34, 2);
  284.         $this->body .= $this->setTLV('CLI_LESSER_VER',         0, 2);
  285.         $this->body .= $this->setTLV('CLI_BUILD_NUMBER',     2321, 2);
  286.         $this->body .= $this->setTLV('DISTRIB_NUMBER',         1085, 4);
  287.         $this->body .= $this->setTLV('CLIENT_LNG',             'en');
  288.         $this->body .= $this->setTLV('CLIENT_COUNTRY',         'us');
  289.        
  290.        
  291.         $this->channel = 1;
  292.         $pack = $this->prepare();
  293.         socket_write($this->socet, $pack, strlen($pack));
  294.         $this->parseCookieFLAP();
  295.        
  296.         $this->body = 0x0000;
  297.         $pack = $this->prepare();
  298.         socket_write($this->socet, $pack, strlen($pack));
  299.         $this->close();
  300.        
  301.         if(isset($this->info['RECONECT_HERE']))
  302.         {
  303.             $url = explode(':', $this->info['RECONECT_HERE']);
  304.             if(!$this->open($url))
  305.             {
  306.                 $this->error = isset($this->info['DISCONECT_REASON']) ? $this->info['DISCONECT_REASON'] : 'Unable to reconnect';
  307.                 return false;
  308.             }
  309.         }
  310.         else
  311.         {
  312.             $this->error = isset($this->info['DISCONECT_REASON']) ? $this->info['DISCONECT_REASON'] : 'UIN blocked, please try again 20 min later.';
  313.             return false;
  314.         }
  315.  
  316.         $this->getFLAP();
  317.         $this->body .= $this->setTLV('COOKIE', $this->info['COOKIE']);
  318.         $pack = $this->prepare();
  319.         if (!socket_write($this->socet, $pack, strlen($pack)))
  320.         {
  321.             $this->error = 'Can`t send cookie, server close connection';
  322.             return false;
  323.         }
  324.         $this->getFLAP();
  325.         $this->body = $this->setSNAC0102();
  326.         $pack = $this->prepare();
  327.         if (!socket_write($this->socet, $pack, strlen($pack)))
  328.         {
  329.             $this->error = 'Can`t send ready signal, server close connection';
  330.             return false;
  331.         }
  332.         return true;
  333.     }
  334.    
  335.     function write_message($uin, $message)
  336.     {
  337.         $this->body = $this->setSNAC0406($uin, $message);
  338.         $pack = $this->prepare();
  339.         if (!socket_write($this->socet, $pack, strlen($pack)))
  340.         {
  341.             $this->error = 'Can`t send message, server close connection';
  342.             return false;
  343.         }
  344.         if (! $this->parseAnswerFLAP()) {
  345.             // try to send offline message
  346.            
  347.             $this->body = $this->setSNAC0406offline($uin, $message);
  348.             $pack = $this->prepare();
  349.             if (!socket_write($this->socet, $pack, strlen($pack)))
  350.             {
  351.                 $this->error = 'Can`t send offline message, server close connection';
  352.                 return false;
  353.             }
  354.             if (! $this->parseAnswerFLAP())
  355.             {
  356.                 return false;
  357.             }
  358.             else
  359.             {
  360.                 $this->error = 'Client is offline. Message sent to server.';
  361.                 return false;
  362.             }
  363.         }
  364.        
  365.         return true;
  366.     }
  367.    
  368.     function read_message()
  369.     {
  370.         while($this->getFLAP())
  371.         {
  372.             $message = $this->getSNAC0407($this->body);
  373.             if($message){
  374.                 return $message;
  375.             }
  376.         }
  377.         return false;
  378.     }
  379.  
  380.     function xorpass($pass)
  381.     {
  382.         $roast = array(0xF3, 0x26, 0x81, 0xC4, 0x39, 0x86, 0xDB, 0x92, 0x71, 0xA3, 0xB9, 0xE6, 0x53, 0x7A, 0x95, 0x7c);
  383.         $roasting_pass = '';
  384.         for ($i=0; $i<strlen($pass); $i++)
  385.         {
  386.             $roasting_pass .= chr($roast[$i] ^ ord($pass{$i}));
  387.         }
  388.         return($roasting_pass);
  389.     }
  390.    
  391.     function open($url = array('login.icq.com', 5190))
  392.     {
  393.         $this->socet = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  394.         if ($this->socet < 0 || $this->socet === false)
  395.         {
  396.             $this->error = "socket_create() failed: reason: " . socket_strerror($this->socet);
  397.             return false;
  398.         }
  399.         $result = socket_connect($this->socet, gethostbyname($url[0]), $url[1]);
  400.         if ($result < 0 || $result === false)
  401.         {
  402.             $this->error = "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket));
  403.             return false;
  404.         }
  405.         return true;
  406.     }
  407.  
  408.     function close()
  409.     {
  410.         return socket_close($this->socet);
  411.     }
  412. }
  413.  
  414. class WebIcqLite extends WebIcqLite_FLAP {
  415.  
  416.     function WebIcqLite ()
  417.     {
  418.         $this->WebIcqLite_FLAP();
  419.     }
  420.    
  421.     function is_connected()
  422.     {
  423.         if(!$this->socet || socket_last_error($this->socet))
  424.         {
  425.             $this->error = socket_strerror(socket_last_error($socket));
  426.             return false;
  427.         }
  428.         return true;
  429.     }
  430.    
  431.     function connect($uin, $pass)
  432.     {
  433.         if (!$this->open())
  434.         {
  435.             return false;
  436.         }
  437.        
  438.         return $this->login($uin, $pass);
  439.     }
  440.  
  441.     function disconnect()
  442.     {
  443.         return $this->close();
  444.     }
  445.  
  446.     function get_message()
  447.     {
  448.         return $this->read_message();
  449.     }
  450.    
  451.     function send_message($uin, $message)
  452.     {
  453.         return $this->write_message($uin, $message);
  454.     }
  455. }
  456. ?>