Просмотр файла includes/functions_icq.php

Размер файла: 13.76Kb
  1. <?php
  2. /***************************************************************************
  3. * mides.ru
  4. * -------------------
  5. ***************************************************************************/
  6. /*WebIcqLite: ICQ messages sender. v3.2b
  7. * (C) 2006 Sergey Akudovich, http://intrigue.ru
  8. ***************************************************************************/
  9.  
  10. class WebIcqLite_TLV {
  11. var $type;
  12. var $size;
  13. var $error;
  14. var $types = array
  15. (
  16. 'UIN' => 1, // 0x01
  17. 'DATA' => 2, // 0x02
  18. 'CLIENT' => 3, // 0x03
  19. 'ERROR_URL' => 4, // 0x04
  20. 'RECONECT_HERE' => 5, // 0x05
  21. 'COOKIE' => 6, // 0x06
  22. 'SNAC_VERSION' => 7, // 0x07
  23. 'ERROR_SUBCODE' => 8, // 0x08
  24. 'DISCONECT_REASON' => 9, // 0x09
  25. 'RECONECT_HOST' => 10, // 0x0A
  26. 'URL' => 11, // 0x0B
  27. 'DEBUG_DATA' => 12, // 0x0C
  28. 'SERVICE' => 13, // 0x0D
  29. 'CLIENT_COUNTRY' => 14, // 0x0E
  30. 'CLIENT_LNG' => 15, // 0x0F
  31. 'SCRIPT' => 16, // 0x10
  32. 'USER_EMAIL' => 17, // 0x11
  33. 'OLD_PASSWORD' => 18, // 0x12
  34. 'REG_STATUS' => 19, // 0x13
  35. 'DISTRIB_NUMBER' => 20, // 0x14
  36. 'PERSONAL_TEXT' => 21, // 0x15
  37. 'CLIENT_ID' => 22, // 0x16
  38. 'CLI_MAJOR_VER' => 23, // 0x17
  39. 'CLI_MINOR_VER' => 24, // 0x18
  40. 'CLI_LESSER_VER' => 25, // 0x19
  41. 'CLI_BUILD_NUMBER' => 26, // 0x1A
  42. // 'PASSWORD' => 37
  43. );
  44. function setTLV($type, $value, $length = false)
  45. {
  46. switch ($length)
  47. {
  48. case 1:
  49. $format = 'c';
  50. break;
  51. case 2:
  52. $format = 'n';
  53. break;
  54. case 4:
  55. $format = 'N';
  56. break;
  57. default:
  58. $format = 'a*';
  59. break;
  60. }
  61. if ($length === false)
  62. {
  63. $length = strlen($value);
  64. }
  65. return pack('nn'.$format, $this->types[$type], $length, $value);
  66. }
  67. function getTLV($data)
  68. {
  69. $arr = unpack('n2', substr($data, 0, 4));
  70. $this->type = $arr[1];
  71. $this->size = $arr[2];
  72. return substr($data, 4, $this->size);
  73. }
  74.  
  75. function getTLVFragment($data)
  76. {
  77. $frg = unpack('cid/cversion/nsize', substr($data, 0, 4));
  78. $frg['data'] = substr($data, 4, $frg['size']);
  79. return $frg;
  80. }
  81. }
  82.  
  83. class WebIcqLite_SNAC extends WebIcqLite_TLV {
  84. var $request_id = 0;
  85. var $uin;
  86. function setSNAC0102()
  87. {
  88. $this->request_id++;
  89. $out = pack('nnnN', 1, 2, 0, $this->request_id);
  90. $out .= pack('n*', 1, 3, 272, 650);
  91. $out .= pack('n*', 2, 1, 272, 650);
  92. $out .= pack('n*', 3, 1, 272, 650);
  93. $out .= pack('n*', 21, 1, 272, 650);
  94. $out .= pack('n*', 4, 1, 272, 650);
  95. $out .= pack('n*', 6, 1, 272, 650);
  96. $out .= pack('n*', 9, 1, 272, 650);
  97. $out .= pack('n*', 10, 1, 272, 650);
  98. return $out;
  99. }
  100. function setSNAC0406($uin, $message)
  101. {
  102. $this->request_id++;
  103. $cookie = microtime();
  104. $out = pack('nnnNdnca*', 4, 6, 0, $this->request_id, $cookie, 2, strlen($uin), $uin);
  105. $capabilities = pack('H*', '094613494C7F11D18222444553540000'); // utf-8 support
  106. // '97B12751243C4334AD22D6ABF73F1492' rtf support
  107. $data = pack('nd', 0, $cookie).$capabilities;
  108. $data .= pack('nnn', 10, 2, 1);
  109. $data .= pack('nn', 15, 0);
  110. $data .= pack('nnvvddnVn', 10001, strlen($message)+62, 27, 8, 0, 0, 0, 3, $this->request_id);
  111. $data .= pack('nndnn', 14, $this->request_id, 0, 0, 0); //45
  112. $data .= pack('ncvnva*', 1, 0, 0, 1, (strlen($message)+1), $message);
  113. $data .= pack('H*', '0000000000FFFFFF00');
  114. $out .= $this->setTLV('RECONECT_HERE', $data);
  115. $out .= $this->setTLV('CLIENT', '');
  116. return $out;
  117. }
  118. function setSNAC0406offline($uin, $message)
  119. {
  120. $this->request_id++;
  121. $cookie = microtime();
  122. $out = pack('nnnNdnca*', 4, 6, 0, $this->request_id, $cookie, 1, strlen($uin), $uin);
  123. $data = pack('ccnc', 5, 1, 1, 1);
  124. $data .= pack('ccnnna*', 1, 1, strlen($message)+4, 3, 0, $message);
  125. $out .= $this->setTLV('DATA', $data);
  126. $out .= $this->setTLV('CLIENT', '');
  127. $out .= $this->setTLV('COOKIE', '');
  128. return $out;
  129. }
  130. function getSNAC0407($body)
  131. {
  132. if (strlen($body))
  133. {
  134. $msg = unpack('nfamily/nsubtype/nflags/Nrequestid/N2msgid/nchannel/cnamesize', $body);
  135. if ($msg['family'] == 4 && $msg['subtype'] == 7)
  136. {
  137. $body = substr($body, 21);
  138. $from = substr($body, 0, $msg['namesize']);
  139. $channel = $msg['channel'];
  140. $body = substr($body, $msg['namesize']);
  141. $msg = unpack('nwarnlevel/nTLVnumber', $body);
  142. $body = substr($body, 4);
  143. for ($i = 0; $i <= $msg['TLVnumber']; $i++)
  144. {
  145. $part = $this->getTLV($body);
  146. $body = substr($body, 4 + $this->size);
  147. if ($channel == 1 && $this->type == 2)
  148. {
  149. while (strlen($part))
  150. {
  151. $frg = $this->getTLVFragment($part);
  152. if ($frg['id'] == 1 && $frg['version'] == 1)
  153. {
  154. return array('from' => $from, 'message' => substr($frg['data'], 4));
  155. }
  156. $part = substr($part, 4+$frg['size']);
  157. }
  158. return false;
  159. }
  160. }
  161. }
  162. }
  163. return false;
  164. }
  165. function dump($str)
  166. {
  167. $f = fopen('dump', 'a');
  168. fwrite($f, $str);
  169. fclose($f);
  170. }
  171. }
  172.  
  173. class WebIcqLite_FLAP extends WebIcqLite_SNAC{
  174. var $socet;
  175. var $command = 0x2A;
  176. var $channel;
  177. var $sequence;
  178. var $body;
  179. var $info = array();
  180.  
  181. function WebIcqLite_FLAP() {
  182. $this->sequence = rand(1, 30000);
  183. }
  184. function getFLAP()
  185. {
  186. if($this->socet && !socket_last_error($this->socet))
  187. {
  188. $header = socket_read($this->socet, 6);
  189. if ($header)
  190. {
  191. $header = unpack('c2channel/n2size', $header);
  192. $this->channel = $header['channel2'];
  193. $this->body = socket_read($this->socet, $header['size2']);
  194. return true;
  195. }
  196. else
  197. {
  198. return false;
  199. }
  200. }
  201. }
  202. function parseCookieFLAP()
  203. {
  204. $this->getFLAP();
  205. $this->info = array();
  206. while($this->body != '')
  207. {
  208. $info = $this->getTLV($this->body);
  209. $key = array_search($this->type, $this->types);
  210. if($key)
  211. {
  212. $this->info[$key] = $info;
  213. }
  214. $this->body = substr($this->body, ($this->size+4));
  215. }
  216. }
  217. function parseAnswerFLAP()
  218. {
  219. $this->getFLAP();
  220. $array = unpack('n3int/Nint', $this->body);
  221. while ($array['int'] != $this->request_id)
  222. {
  223. $this->getFLAP();
  224. $array = unpack('n3int/Nint', $this->body);
  225. }
  226.  
  227. $this->error = 'ОҐйЁўжІІој© піўжІ ж±ўж± ';
  228. if ($array['int1'] == 4)
  229. {
  230. switch ($array['int2'])
  231. {
  232. case 1:
  233. $this->error = 'Ү殨塭塮ౠ㬥;
  234. return false;
  235. break;
  236. case 0x0c:
  237. return true;
  238. break;
  239. }
  240. }
  241.  
  242. $this->error = 'ОҐйЁўжІІој© піўжІ ж±ўж± ';
  243. return false;
  244. }
  245. function prepare()
  246. {
  247. $this->sequence++;
  248. $out = pack('ccnn', $this->command, $this->channel, $this->sequence, strlen($this->body)).$this->body;
  249. return $out;
  250. }
  251. function login($uin, $password)
  252. {
  253. $this->getFLAP();
  254. $this->uin = $uin;
  255. $this->body .= $this->setTLV('UIN', "$uin");
  256. $this->body .= $this->setTLV('DATA', $this->xorpass($password));
  257. $this->body .= $this->setTLV('CLIENT', 'ICQBasic');
  258. $this->body .= $this->setTLV('CLIENT_ID', 266, 2);
  259. $this->body .= $this->setTLV('CLI_MAJOR_VER', 20, 2);
  260. $this->body .= $this->setTLV('CLI_MINOR_VER', 34, 2);
  261. $this->body .= $this->setTLV('CLI_LESSER_VER', 0, 2);
  262. $this->body .= $this->setTLV('CLI_BUILD_NUMBER', 2321, 2);
  263. $this->body .= $this->setTLV('DISTRIB_NUMBER', 1085, 4);
  264. $this->body .= $this->setTLV('CLIENT_LNG', 'en');
  265. $this->body .= $this->setTLV('CLIENT_COUNTRY', 'us');
  266. $this->channel = 1;
  267. $pack = $this->prepare();
  268. socket_write($this->socet, $pack, strlen($pack));
  269. $this->parseCookieFLAP();
  270. $this->body = 0x0000;
  271. $pack = $this->prepare();
  272. socket_write($this->socet, $pack, strlen($pack));
  273. $this->close();
  274. if(isset($this->info['RECONECT_HERE']))
  275. {
  276. $url = explode(':', $this->info['RECONECT_HERE']);
  277. if(!$this->open($url))
  278. {
  279. $this->error = isset($this->info['DISCONECT_REASON']) ? $this->info['DISCONECT_REASON'] : 'ОҐгЇ§нЇ¦о® п¦¤й®Ё';
  280. return false;
  281. }
  282. }
  283. else
  284. {
  285. $this->error = isset($this->info['DISCONECT_REASON']) ? $this->info['DISCONECT_REASON'] : 'UIN п±ін  иЎЎмЇЄй±®гЎ­. Ю硫겲ଠ௯곥 汥砲0 н©­';
  286. return false;
  287. }
  288.  
  289. $this->getFLAP();
  290. $this->body .= $this->setTLV('COOKIE', $this->info['COOKIE']);
  291. $pack = $this->prepare();
  292. if (!socket_write($this->socet, $pack, strlen($pack)))
  293. {
  294. $this->error = 'Cookie ﳯᣫ殻, 捻鮥 衪汢汮짻
  295. return false;
  296. }
  297. $this->getFLAP();
  298. $this->body = $this->setSNAC0102();
  299. $pack = $this->prepare();
  300. if (!socket_write($this->socet, $pack, strlen($pack)))
  301. {
  302. $this->error = 'ТЁд® лЎ­еЎ®а± г¬Ґн¬ п¦¤й®Ґо©Ґ иЎЄоЎ±ж±ўж±®м§»
  303. return false;
  304. }
  305. return true;
  306. }
  307. function write_message($uin, $message)
  308. {
  309. $this->body = $this->setSNAC0406($uin, $message);
  310. $pack = $this->prepare();
  311. if (!socket_write($this->socet, $pack, strlen($pack)))
  312. {
  313. $this->error = 'Ү殨塭塮ౠ㬥 捻鮥 衪汢汮짻
  314. return false;
  315. }
  316. if (! $this->parseAnswerFLAP()) {
  317. // try to send offline message
  318. $this->body = $this->setSNAC0406offline($uin, $message);
  319. $pack = $this->prepare();
  320. if (!socket_write($this->socet, $pack, strlen($pack)))
  321. {
  322. $this->error = 'ОҐгЇ§нЇ¦о® піЇбЈЁ пЇЎж®ЁеЎў offline, 捻鮥 иЎЄоЎ±ж±ўж±®м§»
  323. return false;
  324. }
  325. if (! $this->parseAnswerFLAP())
  326. {
  327. return false;
  328. }
  329. else
  330. {
  331. $this->error = 'Ю콧欼 offline. Ү殨塮ౠ㬥汢氧;
  332. return false;
  333. }
  334. }
  335. return true;
  336. }
  337. function read_message()
  338. {
  339. while($this->getFLAP())
  340. {
  341. $message = $this->getSNAC0407($this->body);
  342. if($message){
  343. return $message;
  344. }
  345. }
  346. return false;
  347. }
  348.  
  349. function xorpass($pass)
  350. {
  351. $roast = array(0xF3, 0x26, 0x81, 0xC4, 0x39, 0x86, 0xDB, 0x92, 0x71, 0xA3, 0xB9, 0xE6, 0x53, 0x7A, 0x95, 0x7c);
  352. $roasting_pass = '';
  353. for ($i=0; $i<strlen($pass); $i++)
  354. {
  355. $roasting_pass .= chr($roast[$i] ^ ord($pass{$i}));
  356. }
  357. return($roasting_pass);
  358. }
  359. function open($url = array('login.icq.com', 5190))
  360. {
  361. $this->socet = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  362. if ($this->socet < 0 || $this->socet === false)
  363. {
  364. $this->error = "socket_create() failed: reason: " . socket_strerror($this->socet);
  365. return false;
  366. }
  367. $result = socket_connect($this->socet, gethostbyname($url[0]), $url[1]);
  368. if ($result < 0 || $result === false)
  369. {
  370. $this->error = "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket));
  371. return false;
  372. }
  373. return true;
  374. }
  375.  
  376. function close()
  377. {
  378. return socket_close($this->socet);
  379. }
  380. }
  381.  
  382. class WebIcqLite extends WebIcqLite_FLAP {
  383.  
  384. function WebIcqLite ()
  385. {
  386. $this->WebIcqLite_FLAP();
  387. }
  388. function is_connected()
  389. {
  390. if(!$this->socet || socket_last_error($this->socet))
  391. {
  392. $this->error = socket_strerror(socket_last_error($socket));
  393. return false;
  394. }
  395. return true;
  396. }
  397. function connect($uin, $pass)
  398. {
  399. if (!$this->open())
  400. {
  401. return false;
  402. }
  403. return $this->login($uin, $pass);
  404. }
  405.  
  406. function disconnect()
  407. {
  408. return $this->close();
  409. }
  410.  
  411. function get_message()
  412. {
  413. return $this->read_message();
  414. }
  415. function send_message($uin, $message)
  416. {
  417. return $this->write_message($uin, $message);
  418. }
  419. }
  420. ?>