PageRenderTime 69ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/main/class/notify/notify_jabber.php

https://gitlab.com/Korko/Fire-Soft-Board-2
PHP | 2009 lines | 1341 code | 501 blank | 167 comment | 181 complexity | b0f60c82ce8627812bb813b48d6138d0 MD5 | raw file
  1. <?php
  2. /***************************************************************************
  3. Class.Jabber.PHP v0.4.2
  4. (c) 2004 Nathan "Fritzy" Fritz
  5. http://cjphp.netflint.net *** fritzy@netflint.net
  6. This is a bugfix version, specifically for those who can't get
  7. 0.4 to work on Jabberd2 servers.
  8. last modified: 24.03.2004 13:01:53
  9. ***************************************************************************/
  10. /***************************************************************************
  11. *
  12. *
  13. ***************************************************************************/
  14. /*
  15. Jabber::Connect()
  16. Jabber::Disconnect()
  17. Jabber::SendAuth()
  18. Jabber::AccountRegistration($reg_email {string}, $reg_name {string})
  19. Jabber::Listen()
  20. Jabber::SendPacket($xml {string})
  21. Jabber::RosterUpdate()
  22. Jabber::RosterAddUser($jid {string}, $id {string}, $name {string})
  23. Jabber::RosterRemoveUser($jid {string}, $id {string})
  24. Jabber::RosterExistsJID($jid {string})
  25. Jabber::Subscribe($jid {string})
  26. Jabber::Unsubscribe($jid {string})
  27. Jabber::CallHandler($message {array})
  28. Jabber::CruiseControl([$seconds {number}])
  29. Jabber::SubscriptionApproveRequest($to {string})
  30. Jabber::SubscriptionDenyRequest($to {string})
  31. Jabber::GetFirstFromQueue()
  32. Jabber::GetFromQueueById($packet_type {string}, $id {string})
  33. Jabber::SendMessage($to {string}, $id {number}, $type {string}, $content {array}[, $payload {array}])
  34. Jabber::SendIq($to {string}, $type {string}, $id {string}, $xmlns {string}[, $payload {string}])
  35. Jabber::SendPresence($type {string}[, $to {string}[, $status {string}[, $show {string}[, $priority {number}]]]])
  36. Jabber::SendError($to {string}, $id {string}, $error_number {number}[, $error_message {string}])
  37. Jabber::TransportRegistrationDetails($transport {string})
  38. Jabber::TransportRegistration($transport {string}, $details {array})
  39. Jabber::GetvCard($jid {string}[, $id {string}]) -- EXPERIMENTAL --
  40. Jabber::GetInfoFromMessageFrom($packet {array})
  41. Jabber::GetInfoFromMessageType($packet {array})
  42. Jabber::GetInfoFromMessageId($packet {array})
  43. Jabber::GetInfoFromMessageThread($packet {array})
  44. Jabber::GetInfoFromMessageSubject($packet {array})
  45. Jabber::GetInfoFromMessageBody($packet {array})
  46. Jabber::GetInfoFromMessageError($packet {array})
  47. Jabber::GetInfoFromIqFrom($packet {array})
  48. Jabber::GetInfoFromIqType($packet {array})
  49. Jabber::GetInfoFromIqId($packet {array})
  50. Jabber::GetInfoFromIqKey($packet {array})
  51. Jabber::GetInfoFromIqError($packet {array})
  52. Jabber::GetInfoFromPresenceFrom($packet {array})
  53. Jabber::GetInfoFromPresenceType($packet {array})
  54. Jabber::GetInfoFromPresenceStatus($packet {array})
  55. Jabber::GetInfoFromPresenceShow($packet {array})
  56. Jabber::GetInfoFromPresencePriority($packet {array})
  57. Jabber::AddToLog($string {string})
  58. Jabber::PrintLog()
  59. MakeXML::AddPacketDetails($string {string}[, $value {string/number}])
  60. MakeXML::BuildPacket([$array {array}])
  61. */
  62. class Notify_jabber
  63. {
  64. public $server;
  65. public $port;
  66. public $username;
  67. public $password;
  68. public $resource;
  69. public $jid;
  70. public $connection;
  71. public $delay_disconnect;
  72. public $stream_id;
  73. public $roster;
  74. public $enable_logging;
  75. public $log_array;
  76. public $log_filename;
  77. public $log_filehandler;
  78. public $iq_sleep_timer;
  79. public $last_ping_time;
  80. public $packet_queue;
  81. public $subscription_queue;
  82. public $iq_version_name;
  83. public $iq_version_os;
  84. public $iq_version_version;
  85. public $error_codes;
  86. public $connected;
  87. public $keep_alive_id;
  88. public $returned_keep_alive;
  89. public $txnid;
  90. public $CONNECTOR;
  91. public function __construct()
  92. {
  93. $this->server = "localhost";
  94. $this->port = "5222";
  95. $this->username = "larry";
  96. $this->password = "curly";
  97. $this->resource = null;
  98. $this->enable_logging = false;
  99. $this->log_array = array();
  100. $this->log_filename = '';
  101. $this->log_filehandler = false;
  102. $this->packet_queue = array();
  103. $this->subscription_queue = array();
  104. $this->iq_sleep_timer = 1;
  105. $this->delay_disconnect = 1;
  106. $this->returned_keep_alive = true;
  107. $this->txnid = 0;
  108. $this->iq_version_name = "Class.Jabber.PHP -- http://cjphp.netflint.net -- by Nathan 'Fritzy' Fritz, fritz@netflint.net";
  109. $this->iq_version_version = "0.4";
  110. $this->iq_version_os = $_SERVER['SERVER_SOFTWARE'];
  111. $this->connection_class = "CJP_StandardConnector";
  112. $this->error_codes = array(400 => "Bad Request",
  113. 401 => "Unauthorized",
  114. 402 => "Payment Required",
  115. 403 => "Forbidden",
  116. 404 => "Not Found",
  117. 405 => "Not Allowed",
  118. 406 => "Not Acceptable",
  119. 407 => "Registration Required",
  120. 408 => "Request Timeout",
  121. 409 => "Conflict",
  122. 500 => "Internal Server Error",
  123. 501 => "Not Implemented",
  124. 502 => "Remove Server Error",
  125. 503 => "Service Unavailable",
  126. 504 => "Remove Server Timeout",
  127. 510 => "Disconnected");
  128. }
  129. public function Connect()
  130. {
  131. $this->_create_logfile();
  132. $this->CONNECTOR = new $this->connection_class;
  133. if ($this->CONNECTOR->OpenSocket($this->server, $this->port))
  134. {
  135. $this->SendPacket("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
  136. $this->SendPacket("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
  137. sleep(2);
  138. if ($this->_check_connected())
  139. {
  140. $this->connected = true; // Nathan Fritz
  141. return true;
  142. }
  143. else
  144. {
  145. $this->AddToLog("ERROR: Connect() #1");
  146. return false;
  147. }
  148. }
  149. else
  150. {
  151. $this->AddToLog("ERROR: Connect() #2");
  152. return false;
  153. }
  154. }
  155. public function Disconnect()
  156. {
  157. if (is_int($this->delay_disconnect))
  158. {
  159. sleep($this->delay_disconnect);
  160. }
  161. $this->SendPacket("</stream:stream>");
  162. $this->CONNECTOR->CloseSocket();
  163. $this->_close_logfile();
  164. $this->PrintLog();
  165. }
  166. public function SendAuth()
  167. {
  168. $this->auth_id = "auth_" . md5(time() . $_SERVER['REMOTE_ADDR']);
  169. $this->resource = ($this->resource != null) ? $this->resource : ("Class.Jabber.PHP " . md5($this->auth_id));
  170. $this->jid = "{$this->username}@{$this->server}/{$this->resource}";
  171. // request available authentication methods
  172. $payload = "<username>{$this->username}</username>";
  173. $packet = $this->SendIq(null, 'get', $this->auth_id, "jabber:iq:auth", $payload);
  174. // was a result returned?
  175. if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
  176. {
  177. // yes, now check for auth method availability in descending order (best to worst)
  178. if (!function_exists("mhash"))
  179. {
  180. $this->AddToLog("ATTENTION: SendAuth() - mhash() is not available; screw 0k and digest method, we need to go with plaintext auth");
  181. }
  182. // auth_0k
  183. if (function_exists("mhash") && isset($packet['iq']['#']['query'][0]['#']['sequence'][0]["#"]) && isset($packet['iq']['#']['query'][0]['#']['token'][0]["#"]))
  184. {
  185. return $this->_sendauth_0k($packet['iq']['#']['query'][0]['#']['token'][0]["#"], $packet['iq']['#']['query'][0]['#']['sequence'][0]["#"]);
  186. }
  187. // digest
  188. elseif (function_exists("mhash") && isset($packet['iq']['#']['query'][0]['#']['digest']))
  189. {
  190. return $this->_sendauth_digest();
  191. }
  192. // plain text
  193. elseif ($packet['iq']['#']['query'][0]['#']['password'])
  194. {
  195. return $this->_sendauth_plaintext();
  196. }
  197. // dude, you're fucked
  198. {
  199. $this->AddToLog("ERROR: SendAuth() #2 - No auth method available!");
  200. return false;
  201. }
  202. }
  203. else
  204. {
  205. // no result returned
  206. $this->AddToLog("ERROR: SendAuth() #1");
  207. return false;
  208. }
  209. }
  210. public function AccountRegistration($reg_email = null, $reg_name = null)
  211. {
  212. $packet = $this->SendIq($this->server, 'get', 'reg_01', 'jabber:iq:register');
  213. if ($packet)
  214. {
  215. $key = $this->GetInfoFromIqKey($packet); // just in case a key was passed back from the server
  216. unset($packet);
  217. $payload = "<username>{$this->username}</username>
  218. <password>{$this->password}</password>
  219. <email>$reg_email</email>
  220. <name>$reg_name</name>\n";
  221. $payload .= ($key) ? "<key>$key</key>\n" : '';
  222. $packet = $this->SendIq($this->server, 'set', "reg_01", "jabber:iq:register", $payload);
  223. if ($this->GetInfoFromIqType($packet) == 'result')
  224. {
  225. if (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#']))
  226. {
  227. $return_code = 1;
  228. }
  229. else
  230. {
  231. $return_code = 2;
  232. }
  233. if ($this->resource)
  234. {
  235. $this->jid = "{$this->username}@{$this->server}/{$this->resource}";
  236. }
  237. else
  238. {
  239. $this->jid = "{$this->username}@{$this->server}";
  240. }
  241. }
  242. elseif ($this->GetInfoFromIqType($packet) == 'error' && isset($packet['iq']['#']['error'][0]['#']))
  243. {
  244. // "conflict" error, i.e. already registered
  245. if ($packet['iq']['#']['error'][0]['@']['code'] == '409')
  246. {
  247. $return_code = 1;
  248. }
  249. else
  250. {
  251. $return_code = "Error " . $packet['iq']['#']['error'][0]['@']['code'] . ": " . $packet['iq']['#']['error'][0]['#'];
  252. }
  253. }
  254. return $return_code;
  255. }
  256. else
  257. {
  258. return 3;
  259. }
  260. }
  261. public function SendPacket($xml)
  262. {
  263. $xml = trim($xml);
  264. if ($this->CONNECTOR->WriteToSocket($xml))
  265. {
  266. $this->AddToLog("SEND: $xml");
  267. return true;
  268. }
  269. else
  270. {
  271. $this->AddToLog('ERROR: SendPacket() #1');
  272. return false;
  273. }
  274. }
  275. public function Listen()
  276. {
  277. unset($incoming);
  278. $incoming = '';
  279. while ($line = $this->CONNECTOR->ReadFromSocket(4096))
  280. {
  281. $incoming .= $line;
  282. }
  283. $incoming = trim($incoming);
  284. if ($incoming != "")
  285. {
  286. $this->AddToLog("RECV: $incoming");
  287. }
  288. if ($incoming != "")
  289. {
  290. $temp = $this->_split_incoming($incoming);
  291. for ($a = 0; $a < count($temp); $a++)
  292. {
  293. $this->packet_queue[] = $this->xmlize($temp[$a]);
  294. }
  295. }
  296. return true;
  297. }
  298. public function StripJID($jid = null)
  299. {
  300. preg_match("/(.*)\/(.*)/Ui", $jid, $temp);
  301. return ($temp[1] != "") ? $temp[1] : $jid;
  302. }
  303. public function SendMessage($to, $type = "normal", $id = null, $content = null, $payload = null)
  304. {
  305. if ($to && is_array($content))
  306. {
  307. if (!$id)
  308. {
  309. $id = $type . "_" . time();
  310. }
  311. $content = $this->_array_htmlspecialchars($content);
  312. $xml = "<message to='$to' type='$type' id='$id'>\n";
  313. if (isset($content['subject']))
  314. {
  315. $xml .= "<subject>" . $content['subject'] . "</subject>\n";
  316. }
  317. if (isset($content['thread']))
  318. {
  319. $xml .= "<thread>" . $content['thread'] . "</thread>\n";
  320. }
  321. $xml .= "<body>" . $content['body'] . "</body>\n";
  322. $xml .= $payload;
  323. $xml .= "</message>\n";
  324. if ($this->SendPacket($xml))
  325. {
  326. return true;
  327. }
  328. else
  329. {
  330. $this->AddToLog("ERROR: SendMessage() #1");
  331. return false;
  332. }
  333. }
  334. else
  335. {
  336. $this->AddToLog("ERROR: SendMessage() #2");
  337. return false;
  338. }
  339. }
  340. public function SendPresence($type = null, $to = null, $status = null, $show = null, $priority = null)
  341. {
  342. $xml = "<presence";
  343. $xml .= ($to) ? " to='$to'" : '';
  344. $xml .= ($type) ? " type='$type'" : '';
  345. $xml .= ($status || $show || $priority) ? ">\n" : " />\n";
  346. $xml .= ($status) ? " <status>$status</status>\n" : '';
  347. $xml .= ($show) ? " <show>$show</show>\n" : '';
  348. $xml .= ($priority) ? " <priority>$priority</priority>\n" : '';
  349. $xml .= ($status || $show || $priority) ? "</presence>\n" : '';
  350. if ($this->SendPacket($xml))
  351. {
  352. return true;
  353. }
  354. else
  355. {
  356. $this->AddToLog("ERROR: SendPresence() #1");
  357. return false;
  358. }
  359. }
  360. public function SendError($to, $id = null, $error_number, $error_message = null)
  361. {
  362. $xml = "<iq type='error' to='$to'";
  363. $xml .= ($id) ? " id='$id'" : '';
  364. $xml .= ">\n";
  365. $xml .= " <error code='$error_number'>";
  366. $xml .= ($error_message) ? $error_message : $this->error_codes[$error_number];
  367. $xml .= "</error>\n";
  368. $xml .= "</iq>";
  369. $this->SendPacket($xml);
  370. }
  371. public function RosterUpdate()
  372. {
  373. $roster_request_id = "roster_" . time();
  374. $incoming_array = $this->SendIq(null, 'get', $roster_request_id, "jabber:iq:roster");
  375. if (is_array($incoming_array))
  376. {
  377. if ($incoming_array['iq']['@']['type'] == 'result'
  378. && $incoming_array['iq']['@']['id'] == $roster_request_id
  379. && $incoming_array['iq']['#']['query']['0']['@']['xmlns'] == "jabber:iq:roster")
  380. {
  381. $number_of_contacts = count($incoming_array['iq']['#']['query'][0]['#']['item']);
  382. $this->roster = array();
  383. for ($a = 0; $a < $number_of_contacts; $a++)
  384. {
  385. $this->roster[$a] = array( "jid" => strtolower($incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['jid']),
  386. "name" => $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['name'],
  387. "subscription" => $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['subscription'],
  388. "group" => $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['#']['group'][0]['#']
  389. );
  390. }
  391. return true;
  392. }
  393. else
  394. {
  395. $this->AddToLog("ERROR: RosterUpdate() #1");
  396. return false;
  397. }
  398. }
  399. else
  400. {
  401. $this->AddToLog("ERROR: RosterUpdate() #2");
  402. return false;
  403. }
  404. }
  405. public function RosterAddUser($jid = null, $id = null, $name = null)
  406. {
  407. $id = ($id) ? $id : "adduser_" . time();
  408. if ($jid)
  409. {
  410. $payload = " <item jid='$jid'";
  411. $payload .= ($name) ? " name='" . htmlspecialchars($name) . "'" : '';
  412. $payload .= "/>\n";
  413. $packet = $this->SendIq(null, 'set', $id, "jabber:iq:roster", $payload);
  414. if ($this->GetInfoFromIqType($packet) == 'result')
  415. {
  416. $this->RosterUpdate();
  417. return true;
  418. }
  419. else
  420. {
  421. $this->AddToLog("ERROR: RosterAddUser() #2");
  422. return false;
  423. }
  424. }
  425. else
  426. {
  427. $this->AddToLog("ERROR: RosterAddUser() #1");
  428. return false;
  429. }
  430. }
  431. public function RosterRemoveUser($jid = null, $id = null)
  432. {
  433. $id = ($id) ? $id : 'deluser_' . time();
  434. if ($jid && $id)
  435. {
  436. $packet = $this->SendIq(null, 'set', $id, "jabber:iq:roster", "<item jid='$jid' subscription='remove'/>");
  437. if ($this->GetInfoFromIqType($packet) == 'result')
  438. {
  439. $this->RosterUpdate();
  440. return true;
  441. }
  442. else
  443. {
  444. $this->AddToLog("ERROR: RosterRemoveUser() #2");
  445. return false;
  446. }
  447. }
  448. else
  449. {
  450. $this->AddToLog("ERROR: RosterRemoveUser() #1");
  451. return false;
  452. }
  453. }
  454. public function RosterExistsJID($jid = null)
  455. {
  456. if ($jid)
  457. {
  458. if ($this->roster)
  459. {
  460. for ($a = 0; $a < count($this->roster); $a++)
  461. {
  462. if ($this->roster[$a]['jid'] == strtolower($jid))
  463. {
  464. return $a;
  465. }
  466. }
  467. }
  468. else
  469. {
  470. $this->AddToLog("ERROR: RosterExistsJID() #2");
  471. return false;
  472. }
  473. }
  474. else
  475. {
  476. $this->AddToLog("ERROR: RosterExistsJID() #1");
  477. return false;
  478. }
  479. }
  480. public function GetFirstFromQueue()
  481. {
  482. return array_shift($this->packet_queue);
  483. }
  484. public function GetFromQueueById($packet_type, $id)
  485. {
  486. $found_message = false;
  487. foreach ($this->packet_queue as $key => $value)
  488. {
  489. if ($value[$packet_type]['@']['id'] == $id)
  490. {
  491. $found_message = $value;
  492. unset($this->packet_queue[$key]);
  493. break;
  494. }
  495. }
  496. return (is_array($found_message)) ? $found_message : false;
  497. }
  498. public function CallHandler($packet = null)
  499. {
  500. $packet_type = $this->_get_packet_type($packet);
  501. if ($packet_type == "message")
  502. {
  503. $type = $packet['message']['@']['type'];
  504. $type = ($type != "") ? $type : "normal";
  505. $funcmeth = "Handler_message_$type";
  506. }
  507. elseif ($packet_type == "iq")
  508. {
  509. $namespace = $packet['iq']['#']['query'][0]['@']['xmlns'];
  510. $namespace = str_replace(":", "_", $namespace);
  511. $funcmeth = "Handler_iq_$namespace";
  512. }
  513. elseif ($packet_type == "presence")
  514. {
  515. $type = $packet['presence']['@']['type'];
  516. $type = ($type != "") ? $type : "available";
  517. $funcmeth = "Handler_presence_$type";
  518. }
  519. if ($funcmeth != '')
  520. {
  521. if (function_exists($funcmeth))
  522. {
  523. call_user_func($funcmeth, $packet);
  524. }
  525. elseif (method_exists($this, $funcmeth))
  526. {
  527. call_user_func(array(&$this, $funcmeth), $packet);
  528. }
  529. else
  530. {
  531. $this->Handler_NOT_IMPLEMENTED($packet);
  532. $this->AddToLog("ERROR: CallHandler() #1 - neither method nor function $funcmeth() available");
  533. }
  534. }
  535. }
  536. public function CruiseControl($seconds = -1)
  537. {
  538. $count = 0;
  539. while ($count != $seconds)
  540. {
  541. $this->Listen();
  542. do {
  543. $packet = $this->GetFirstFromQueue();
  544. if ($packet) {
  545. $this->CallHandler($packet);
  546. }
  547. } while (count($this->packet_queue) > 1);
  548. $count += 1;
  549. sleep(1);
  550. if ($this->last_ping_time + 180 < time())
  551. {
  552. // Modified by Nathan Fritz
  553. if ($this->returned_keep_alive == false)
  554. {
  555. $this->connected = false;
  556. $this->AddToLog('EVENT: Disconnected');
  557. }
  558. if ($this->returned_keep_alive == true)
  559. {
  560. $this->connected = true;
  561. }
  562. $this->returned_keep_alive = false;
  563. $this->keep_alive_id = 'keep_alive_' . time();
  564. //$this->SendPacket("<iq id='{$this->keep_alive_id}'/>", 'CruiseControl');
  565. $this->SendPacket("<iq type='get' from='" . $this->username . "@" . $this->server . "/" . $this->resource . "' to='" . $this->server . "' id='" . $this->keep_alive_id . "'><query xmlns='jabber:iq:time' /></iq>");
  566. // **
  567. $this->last_ping_time = time();
  568. }
  569. }
  570. return true;
  571. }
  572. public function SubscriptionAcceptRequest($to = null)
  573. {
  574. return ($to) ? $this->SendPresence("subscribed", $to) : false;
  575. }
  576. public function SubscriptionDenyRequest($to = null)
  577. {
  578. return ($to) ? $this->SendPresence("unsubscribed", $to) : false;
  579. }
  580. public function Subscribe($to = null)
  581. {
  582. return ($to) ? $this->SendPresence("subscribe", $to) : false;
  583. }
  584. public function Unsubscribe($to = null)
  585. {
  586. return ($to) ? $this->SendPresence("unsubscribe", $to) : false;
  587. }
  588. public function SendIq($to = null, $type = 'get', $id = null, $xmlns = null, $payload = null, $from = null)
  589. {
  590. if (!preg_match("/^(get|set|result|error)$/", $type))
  591. {
  592. unset($type);
  593. $this->AddToLog("ERROR: SendIq() #2 - type must be 'get', 'set', 'result' or 'error'");
  594. return false;
  595. }
  596. elseif ($id && $xmlns)
  597. {
  598. $xml = "<iq type='$type' id='$id'";
  599. $xml .= ($to) ? " to='" . htmlspecialchars($to) . "'" : '';
  600. $xml .= ($from) ? " from='$from'" : '';
  601. $xml .= ">
  602. <query xmlns='$xmlns'>
  603. $payload
  604. </query>
  605. </iq>";
  606. $this->SendPacket($xml);
  607. sleep($this->iq_sleep_timer);
  608. $this->Listen();
  609. return (preg_match("/^(get|set)$/", $type)) ? $this->GetFromQueueById("iq", $id) : true;
  610. }
  611. else
  612. {
  613. $this->AddToLog("ERROR: SendIq() #1 - to, id and xmlns are mandatory");
  614. return false;
  615. }
  616. }
  617. // get the transport registration fields
  618. // method written by Steve Blinch, http://www.blitzaffe.com
  619. public function TransportRegistrationDetails($transport)
  620. {
  621. $this->txnid++;
  622. $packet = $this->SendIq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", null, $this->jid);
  623. if ($packet)
  624. {
  625. $res = array();
  626. foreach ($packet['iq']['#']['query'][0]['#'] as $element => $data)
  627. {
  628. if ($element != 'instructions' && $element != 'key')
  629. {
  630. $res[] = $element;
  631. }
  632. }
  633. return $res;
  634. }
  635. else
  636. {
  637. return 3;
  638. }
  639. }
  640. // register with the transport
  641. // method written by Steve Blinch, http://www.blitzaffe.com
  642. public function TransportRegistration($transport, $details)
  643. {
  644. $this->txnid++;
  645. $packet = $this->SendIq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", null, $this->jid);
  646. if ($packet)
  647. {
  648. $key = $this->GetInfoFromIqKey($packet); // just in case a key was passed back from the server
  649. unset($packet);
  650. $payload = ($key) ? "<key>$key</key>\n" : '';
  651. foreach ($details as $element => $value)
  652. {
  653. $payload .= "<$element>$value</$element>\n";
  654. }
  655. $packet = $this->SendIq($transport, 'set', "reg_{$this->txnid}", "jabber:iq:register", $payload);
  656. if ($this->GetInfoFromIqType($packet) == 'result')
  657. {
  658. if (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#']))
  659. {
  660. $return_code = 1;
  661. }
  662. else
  663. {
  664. $return_code = 2;
  665. }
  666. }
  667. elseif ($this->GetInfoFromIqType($packet) == 'error')
  668. {
  669. if (isset($packet['iq']['#']['error'][0]['#']))
  670. {
  671. $return_code = "Error " . $packet['iq']['#']['error'][0]['@']['code'] . ": " . $packet['iq']['#']['error'][0]['#'];
  672. $this->AddToLog('ERROR: TransportRegistration()');
  673. }
  674. }
  675. return $return_code;
  676. }
  677. else
  678. {
  679. return 3;
  680. }
  681. }
  682. public function GetvCard($jid = null, $id = null)
  683. {
  684. if (!$id)
  685. {
  686. $id = "vCard_" . md5(time() . $_SERVER['REMOTE_ADDR']);
  687. }
  688. if ($jid)
  689. {
  690. $xml = "<iq type='get' to='$jid' id='$id'>
  691. <vCard xmlns='vcard-temp'/>
  692. </iq>";
  693. $this->SendPacket($xml);
  694. sleep($this->iq_sleep_timer);
  695. $this->Listen();
  696. return $this->GetFromQueueById("iq", $id);
  697. }
  698. else
  699. {
  700. $this->AddToLog("ERROR: GetvCard() #1 - to and id are mandatory");
  701. return false;
  702. }
  703. }
  704. public function PrintLog()
  705. {
  706. if ($this->enable_logging)
  707. {
  708. if ($this->log_filehandler)
  709. {
  710. echo "<h2>Logging enabled, logged events have been written to the file {$this->log_filename}.</h2>\n";
  711. }
  712. else
  713. {
  714. echo "<h2>Logging enabled, logged events below:</h2>\n";
  715. echo "<pre>\n";
  716. echo (count($this->log_array) > 0) ? implode("\n\n\n", $this->log_array) : "No logged events.";
  717. echo "</pre>\n";
  718. }
  719. }
  720. }
  721. // ======================================================================
  722. // private methods
  723. // ======================================================================
  724. public function _sendauth_0k($zerok_token, $zerok_sequence)
  725. {
  726. // initial hash of password
  727. $zerok_hash = mhash(MHASH_SHA1, $this->password);
  728. $zerok_hash = bin2hex($zerok_hash);
  729. // sequence 0: hash of hashed-password and token
  730. $zerok_hash = mhash(MHASH_SHA1, $zerok_hash . $zerok_token);
  731. $zerok_hash = bin2hex($zerok_hash);
  732. // repeat as often as needed
  733. for ($a = 0; $a < $zerok_sequence; $a++)
  734. {
  735. $zerok_hash = mhash(MHASH_SHA1, $zerok_hash);
  736. $zerok_hash = bin2hex($zerok_hash);
  737. }
  738. $payload = "<username>{$this->username}</username>
  739. <hash>$zerok_hash</hash>
  740. <resource>{$this->resource}</resource>";
  741. $packet = $this->SendIq(null, 'set', $this->auth_id, "jabber:iq:auth", $payload);
  742. // was a result returned?
  743. if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
  744. {
  745. return true;
  746. }
  747. else
  748. {
  749. $this->AddToLog("ERROR: _sendauth_0k() #1");
  750. return false;
  751. }
  752. }
  753. public function _sendauth_digest()
  754. {
  755. $payload = "<username>{$this->username}</username>
  756. <resource>{$this->resource}</resource>
  757. <digest>" . bin2hex(mhash(MHASH_SHA1, $this->stream_id . $this->password)) . "</digest>";
  758. $packet = $this->SendIq(null, 'set', $this->auth_id, "jabber:iq:auth", $payload);
  759. // was a result returned?
  760. if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
  761. {
  762. return true;
  763. }
  764. else
  765. {
  766. $this->AddToLog("ERROR: _sendauth_digest() #1");
  767. return false;
  768. }
  769. }
  770. public function _sendauth_plaintext()
  771. {
  772. $payload = "<username>{$this->username}</username>
  773. <password>{$this->password}</password>
  774. <resource>{$this->resource}</resource>";
  775. $packet = $this->SendIq(null, 'set', $this->auth_id, "jabber:iq:auth", $payload);
  776. // was a result returned?
  777. if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
  778. {
  779. return true;
  780. }
  781. else
  782. {
  783. $this->AddToLog("ERROR: _sendauth_plaintext() #1");
  784. return false;
  785. }
  786. }
  787. public function _listen_incoming()
  788. {
  789. unset($incoming);
  790. $incoming = '';
  791. while ($line = $this->CONNECTOR->ReadFromSocket(4096))
  792. {
  793. $incoming .= $line;
  794. }
  795. $incoming = trim($incoming);
  796. if ($incoming != "")
  797. {
  798. $this->AddToLog("RECV: $incoming");
  799. }
  800. return $this->xmlize($incoming);
  801. }
  802. public function _check_connected()
  803. {
  804. $incoming_array = $this->_listen_incoming();
  805. if (is_array($incoming_array))
  806. {
  807. if ($incoming_array["stream:stream"]['@']['from'] == $this->server
  808. && $incoming_array["stream:stream"]['@']['xmlns'] == "jabber:client"
  809. && $incoming_array["stream:stream"]['@']["xmlns:stream"] == "http://etherx.jabber.org/streams")
  810. {
  811. $this->stream_id = $incoming_array["stream:stream"]['@']['id'];
  812. if ($incoming_array["stream:stream"]["#"]["stream:features"][0]["#"]["starttls"][0]["@"]["xmlns"] == "urn:ietf:params:xml:ns:xmpp-tls")
  813. {
  814. return $this->_starttls();
  815. }
  816. else
  817. {
  818. return true;
  819. }
  820. }
  821. else
  822. {
  823. $this->AddToLog("ERROR: _check_connected() #1");
  824. return false;
  825. }
  826. }
  827. else
  828. {
  829. $this->AddToLog("ERROR: _check_connected() #2");
  830. return false;
  831. }
  832. }
  833. public function _starttls()
  834. {
  835. if (!function_exists("stream_socket_enable_crypto"))
  836. {
  837. $this->AddToLog("WARNING: TLS is not available");
  838. return true;
  839. }
  840. $this->SendPacket("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n");
  841. sleep(2);
  842. $incoming_array = $this->_listen_incoming();
  843. if (!is_array($incoming_array))
  844. {
  845. $this->AddToLog("ERROR: _starttls() #1");
  846. return false;
  847. }
  848. if ($incoming_array["proceed"]["@"]["xmlns"] != "urn:ietf:params:xml:ns:xmpp-tls")
  849. {
  850. $this->AddToLog("ERROR: _starttls() #2");
  851. return false;
  852. }
  853. $meta = stream_get_meta_data($this->CONNECTOR->active_socket);
  854. socket_set_blocking($this->CONNECTOR->active_socket, 1);
  855. if (!@stream_socket_enable_crypto($this->CONNECTOR->active_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT))
  856. {
  857. socket_set_blocking($this->CONNECTOR->active_socket, $meta["blocked"]);
  858. $this->AddToLog("ERROR: _starttls() #3");
  859. return false;
  860. }
  861. socket_set_blocking($this->CONNECTOR->active_socket, $meta["blocked"]);
  862. $this->SendPacket("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
  863. $this->SendPacket("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
  864. sleep(2);
  865. if (!$this->_check_connected())
  866. {
  867. $this->AddToLog("ERROR: _starttls() #4");
  868. return false;
  869. }
  870. return true;
  871. }
  872. public function _get_packet_type($packet = null)
  873. {
  874. if (is_array($packet))
  875. {
  876. reset($packet);
  877. $packet_type = key($packet);
  878. }
  879. return ($packet_type) ? $packet_type : false;
  880. }
  881. public function _split_incoming($incoming)
  882. {
  883. $temp = preg_split("/<(message|iq|presence|stream)/", $incoming, -1, PREG_SPLIT_DELIM_CAPTURE);
  884. $array = array();
  885. for ($a = 1; $a < count($temp); $a = $a + 2)
  886. {
  887. $array[] = "<" . $temp[$a] . $temp[($a + 1)];
  888. }
  889. return $array;
  890. }
  891. public function _create_logfile()
  892. {
  893. if ($this->log_filename != '' && $this->enable_logging)
  894. {
  895. $this->log_filehandler = fopen($this->log_filename, 'w');
  896. }
  897. }
  898. public function AddToLog($string)
  899. {
  900. if ($this->enable_logging)
  901. {
  902. if ($this->log_filehandler)
  903. {
  904. #fwrite($this->log_filehandler, $string . "\n\n");
  905. print "$string \n\n";
  906. }
  907. else
  908. {
  909. $this->log_array[] = htmlspecialchars($string);
  910. }
  911. }
  912. }
  913. public function _close_logfile()
  914. {
  915. if ($this->log_filehandler)
  916. {
  917. fclose($this->log_filehandler);
  918. }
  919. }
  920. // _array_htmlspecialchars()
  921. // applies htmlspecialchars() to all values in an array
  922. public function _array_htmlspecialchars($array)
  923. {
  924. if (is_array($array))
  925. {
  926. foreach ($array as $k => $v)
  927. {
  928. if (is_array($v))
  929. {
  930. $v = $this->_array_htmlspecialchars($v);
  931. }
  932. else
  933. {
  934. $v = htmlspecialchars($v);
  935. }
  936. }
  937. }
  938. return $array;
  939. }
  940. // ======================================================================
  941. // <message/> parsers
  942. // ======================================================================
  943. public function GetInfoFromMessageFrom($packet = null)
  944. {
  945. return (is_array($packet)) ? $packet['message']['@']['from'] : false;
  946. }
  947. public function GetInfoFromMessageType($packet = null)
  948. {
  949. return (is_array($packet)) ? $packet['message']['@']['type'] : false;
  950. }
  951. public function GetInfoFromMessageId($packet = null)
  952. {
  953. return (is_array($packet)) ? $packet['message']['@']['id'] : false;
  954. }
  955. public function GetInfoFromMessageThread($packet = null)
  956. {
  957. return (is_array($packet)) ? $packet['message']['#']['thread'][0]['#'] : false;
  958. }
  959. public function GetInfoFromMessageSubject($packet = null)
  960. {
  961. return (is_array($packet)) ? $packet['message']['#']['subject'][0]['#'] : false;
  962. }
  963. public function GetInfoFromMessageBody($packet = null)
  964. {
  965. return (is_array($packet)) ? $packet['message']['#']['body'][0]['#'] : false;
  966. }
  967. public function GetInfoFromMessageXMLNS($packet = null)
  968. {
  969. return (is_array($packet)) ? $packet['message']['#']['x'] : false;
  970. }
  971. public function GetInfoFromMessageError($packet = null)
  972. {
  973. $error = preg_replace("/^\/$/", "", ($packet['message']['#']['error'][0]['@']['code'] . "/" . $packet['message']['#']['error'][0]['#']));
  974. return (is_array($packet)) ? $error : false;
  975. }
  976. // ======================================================================
  977. // <iq/> parsers
  978. // ======================================================================
  979. public function GetInfoFromIqFrom($packet = null)
  980. {
  981. return (is_array($packet)) ? $packet['iq']['@']['from'] : false;
  982. }
  983. public function GetInfoFromIqType($packet = null)
  984. {
  985. return (is_array($packet)) ? $packet['iq']['@']['type'] : false;
  986. }
  987. public function GetInfoFromIqId($packet = null)
  988. {
  989. return (is_array($packet)) ? $packet['iq']['@']['id'] : false;
  990. }
  991. public function GetInfoFromIqKey($packet = null)
  992. {
  993. return (is_array($packet)) ? $packet['iq']['#']['query'][0]['#']['key'][0]['#'] : false;
  994. }
  995. public function GetInfoFromIqError($packet = null)
  996. {
  997. $error = preg_replace("/^\/$/", "", ($packet['iq']['#']['error'][0]['@']['code'] . "/" . $packet['iq']['#']['error'][0]['#']));
  998. return (is_array($packet)) ? $error : false;
  999. }
  1000. // ======================================================================
  1001. // <presence/> parsers
  1002. // ======================================================================
  1003. public function GetInfoFromPresenceFrom($packet = null)
  1004. {
  1005. return (is_array($packet)) ? $packet['presence']['@']['from'] : false;
  1006. }
  1007. public function GetInfoFromPresenceType($packet = null)
  1008. {
  1009. return (is_array($packet)) ? $packet['presence']['@']['type'] : false;
  1010. }
  1011. public function GetInfoFromPresenceStatus($packet = null)
  1012. {
  1013. return (is_array($packet)) ? $packet['presence']['#']['status'][0]['#'] : false;
  1014. }
  1015. public function GetInfoFromPresenceShow($packet = null)
  1016. {
  1017. return (is_array($packet)) ? $packet['presence']['#']['show'][0]['#'] : false;
  1018. }
  1019. public function GetInfoFromPresencePriority($packet = null)
  1020. {
  1021. return (is_array($packet)) ? $packet['presence']['#']['priority'][0]['#'] : false;
  1022. }
  1023. // ======================================================================
  1024. // <message/> handlers
  1025. // ======================================================================
  1026. public function Handler_message_normal($packet)
  1027. {
  1028. $from = $packet['message']['@']['from'];
  1029. $this->AddToLog("EVENT: Message (type normal) from $from");
  1030. }
  1031. public function Handler_message_chat($packet)
  1032. {
  1033. $from = $packet['message']['@']['from'];
  1034. $this->AddToLog("EVENT: Message (type chat) from $from");
  1035. }
  1036. public function Handler_message_groupchat($packet)
  1037. {
  1038. $from = $packet['message']['@']['from'];
  1039. $this->AddToLog("EVENT: Message (type groupchat) from $from");
  1040. }
  1041. public function Handler_message_headline($packet)
  1042. {
  1043. $from = $packet['message']['@']['from'];
  1044. $this->AddToLog("EVENT: Message (type headline) from $from");
  1045. }
  1046. public function Handler_message_error($packet)
  1047. {
  1048. $from = $packet['message']['@']['from'];
  1049. $this->AddToLog("EVENT: Message (type error) from $from");
  1050. }
  1051. // ======================================================================
  1052. // <iq/> handlers
  1053. // ======================================================================
  1054. // application version updates
  1055. public function Handler_iq_jabber_iq_autoupdate($packet)
  1056. {
  1057. $from = $this->GetInfoFromIqFrom($packet);
  1058. $id = $this->GetInfoFromIqId($packet);
  1059. $this->SendError($from, $id, 501);
  1060. $this->AddToLog("EVENT: jabber:iq:autoupdate from $from");
  1061. }
  1062. // interactive server component properties
  1063. public function Handler_iq_jabber_iq_agent($packet)
  1064. {
  1065. $from = $this->GetInfoFromIqFrom($packet);
  1066. $id = $this->GetInfoFromIqId($packet);
  1067. $this->SendError($from, $id, 501);
  1068. $this->AddToLog("EVENT: jabber:iq:agent from $from");
  1069. }
  1070. // method to query interactive server components
  1071. public function Handler_iq_jabber_iq_agents($packet)
  1072. {
  1073. $from = $this->GetInfoFromIqFrom($packet);
  1074. $id = $this->GetInfoFromIqId($packet);
  1075. $this->SendError($from, $id, 501);
  1076. $this->AddToLog("EVENT: jabber:iq:agents from $from");
  1077. }
  1078. // simple client authentication
  1079. public function Handler_iq_jabber_iq_auth($packet)
  1080. {
  1081. $from = $this->GetInfoFromIqFrom($packet);
  1082. $id = $this->GetInfoFromIqId($packet);
  1083. $this->SendError($from, $id, 501);
  1084. $this->AddToLog("EVENT: jabber:iq:auth from $from");
  1085. }
  1086. // out of band data
  1087. public function Handler_iq_jabber_iq_oob($packet)
  1088. {
  1089. $from = $this->GetInfoFromIqFrom($packet);
  1090. $id = $this->GetInfoFromIqId($packet);
  1091. $this->SendError($from, $id, 501);
  1092. $this->AddToLog("EVENT: jabber:iq:oob from $from");
  1093. }
  1094. // method to store private data on the server
  1095. public function Handler_iq_jabber_iq_private($packet)
  1096. {
  1097. $from = $this->GetInfoFromIqFrom($packet);
  1098. $id = $this->GetInfoFromIqId($packet);
  1099. $this->SendError($from, $id, 501);
  1100. $this->AddToLog("EVENT: jabber:iq:private from $from");
  1101. }
  1102. // method for interactive registration
  1103. public function Handler_iq_jabber_iq_register($packet)
  1104. {
  1105. $from = $this->GetInfoFromIqFrom($packet);
  1106. $id = $this->GetInfoFromIqId($packet);
  1107. $this->SendError($from, $id, 501);
  1108. $this->AddToLog("EVENT: jabber:iq:register from $from");
  1109. }
  1110. // client roster management
  1111. public function Handler_iq_jabber_iq_roster($packet)
  1112. {
  1113. $from = $this->GetInfoFromIqFrom($packet);
  1114. $id = $this->GetInfoFromIqId($packet);
  1115. $this->SendError($from, $id, 501);
  1116. $this->AddToLog("EVENT: jabber:iq:roster from $from");
  1117. }
  1118. // method for searching a user database
  1119. public function Handler_iq_jabber_iq_search($packet)
  1120. {
  1121. $from = $this->GetInfoFromIqFrom($packet);
  1122. $id = $this->GetInfoFromIqId($packet);
  1123. $this->SendError($from, $id, 501);
  1124. $this->AddToLog("EVENT: jabber:iq:search from $from");
  1125. }
  1126. // method for requesting the current time
  1127. public function Handler_iq_jabber_iq_time($packet)
  1128. {
  1129. if ($this->keep_alive_id == $this->GetInfoFromIqId($packet))
  1130. {
  1131. $this->returned_keep_alive = true;
  1132. $this->connected = true;
  1133. $this->AddToLog('EVENT: Keep-Alive returned, connection alive.');
  1134. }
  1135. $type = $this->GetInfoFromIqType($packet);
  1136. $from = $this->GetInfoFromIqFrom($packet);
  1137. $id = $this->GetInfoFromIqId($packet);
  1138. $id = ($id != "") ? $id : "time_" . time();
  1139. if ($type == 'get')
  1140. {
  1141. $payload = "<utc>" . gmdate("Ydm\TH:i:s") . "</utc>
  1142. <tz>" . date("T") . "</tz>
  1143. <display>" . date("Y/d/m h:i:s A") . "</display>";
  1144. $this->SendIq($from, 'result', $id, "jabber:iq:time", $payload);
  1145. }
  1146. $this->AddToLog("EVENT: jabber:iq:time (type $type) from $from");
  1147. }
  1148. public function Handler_iq_error($packet)
  1149. {
  1150. // We'll do something with these later. This is a placeholder so that errors don't bounce back and forth.
  1151. }
  1152. // method for requesting version
  1153. public function Handler_iq_jabber_iq_version($packet)
  1154. {
  1155. $type = $this->GetInfoFromIqType($packet);
  1156. $from = $this->GetInfoFromIqFrom($packet);
  1157. $id = $this->GetInfoFromIqId($packet);
  1158. $id = ($id != "") ? $id : "version_" . time();
  1159. if ($type == 'get')
  1160. {
  1161. $payload = "<name>{$this->iq_version_name}</name>
  1162. <os>{$this->iq_version_os}</os>
  1163. <version>{$this->iq_version_version}</version>";
  1164. #$this->SendIq($from, 'result', $id, "jabber:iq:version", $payload);
  1165. }
  1166. $this->AddToLog("EVENT: jabber:iq:version (type $type) from $from -- DISABLED");
  1167. }
  1168. // keepalive method, added by Nathan Fritz
  1169. /*
  1170. public function Handler_jabber_iq_time($packet)
  1171. {
  1172. if ($this->keep_alive_id == $this->GetInfoFromIqId($packet))
  1173. {
  1174. $this->returned_keep_alive = true;
  1175. $this->connected = true;
  1176. $this->AddToLog('EVENT: Keep-Alive returned, connection alive.');
  1177. }
  1178. }
  1179. */
  1180. // ======================================================================
  1181. // <presence/> handlers
  1182. // ======================================================================
  1183. public function Handler_presence_available($packet)
  1184. {
  1185. $from = $this->GetInfoFromPresenceFrom($packet);
  1186. $show_status = $this->GetInfoFromPresenceStatus($packet) . " / " . $this->GetInfoFromPresenceShow($packet);
  1187. $show_status = ($show_status != " / ") ? " ($addendum)" : '';
  1188. $this->AddToLog("EVENT: Presence (type: available) - $from is available $show_status");
  1189. }
  1190. public function Handler_presence_unavailable($packet)
  1191. {
  1192. $from = $this->GetInfoFromPresenceFrom($packet);
  1193. $show_status = $this->GetInfoFromPresenceStatus($packet) . " / " . $this->GetInfoFromPresenceShow($packet);
  1194. $show_status = ($show_status != " / ") ? " ($addendum)" : '';
  1195. $this->AddToLog("EVENT: Presence (type: unavailable) - $from is unavailable $show_status");
  1196. }
  1197. public function Handler_presence_subscribe($packet)
  1198. {
  1199. $from = $this->GetInfoFromPresenceFrom($packet);
  1200. $this->SubscriptionAcceptRequest($from);
  1201. $this->RosterUpdate();
  1202. $this->log_array[] = "<b>Presence:</b> (type: subscribe) - Subscription request from $from, was added to \$this->subscription_queue, roster updated";
  1203. }
  1204. public function Handler_presence_subscribed($packet)
  1205. {
  1206. $from = $this->GetInfoFromPresenceFrom($packet);
  1207. $this->RosterUpdate();
  1208. $this->AddToLog("EVENT: Presence (type: subscribed) - Subscription allowed by $from, roster updated");
  1209. }
  1210. public function Handler_presence_unsubscribe($packet)
  1211. {
  1212. $from = $this->GetInfoFromPresenceFrom($packet);
  1213. $this->SendPresence("unsubscribed", $from);
  1214. $this->RosterUpdate();
  1215. $this->AddToLog("EVENT: Presence (type: unsubscribe) - Request to unsubscribe from $from, was automatically approved, roster updated");
  1216. }
  1217. public function Handler_presence_unsubscribed($packet)
  1218. {
  1219. $from = $this->GetInfoFromPresenceFrom($packet);
  1220. $this->RosterUpdate();
  1221. $this->AddToLog("EVENT: Presence (type: unsubscribed) - Unsubscribed from $from's presence");
  1222. }
  1223. // Added By Nathan Fritz
  1224. public function Handler_presence_error($packet)
  1225. {
  1226. $from = $this->GetInfoFromPresenceFrom($packet);
  1227. $this->AddToLog("EVENT: Presence (type: error) - Error in $from's presence");
  1228. }
  1229. // ======================================================================
  1230. // Generic handlers
  1231. // ======================================================================
  1232. // Generic handler for unsupported requests
  1233. public function Handler_NOT_IMPLEMENTED($packet)
  1234. {
  1235. $packet_type = $this->_get_packet_type($packet);
  1236. $from = call_user_func(array(&$this, "GetInfoFrom" . ucfirst($packet_type) . "From"), $packet);
  1237. $id = call_user_func(array(&$this, "GetInfoFrom" . ucfirst($packet_type) . "Id"), $packet);
  1238. $this->SendError($from, $id, 501);
  1239. $this->AddToLog("EVENT: Unrecognized <$packet_type/> from $from");
  1240. }
  1241. // ======================================================================
  1242. // Third party code
  1243. // m@d pr0ps to the coders ;)
  1244. // ======================================================================
  1245. // xmlize()
  1246. // (c) Hans Anderson / http://www.hansanderson.com/php/xml/
  1247. public function xmlize($data, $WHITE=1, $encoding='UTF-8') {
  1248. $data = trim($data);
  1249. $vals = $index = $array = array();
  1250. $parser = xml_parser_create($encoding);
  1251. xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
  1252. xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $WHITE);
  1253. xml_parse_into_struct($parser, $data, $vals, $index);
  1254. xml_parser_free($parser);
  1255. $i = 0;
  1256. $tagname = $vals[$i]['tag'];
  1257. if ( isset ($vals[$i]['attributes'] ) )
  1258. {
  1259. $array[$tagname]['@'] = $vals[$i]['attributes'];
  1260. } else {
  1261. $array[$tagname]['@'] = array();
  1262. }
  1263. $array[$tagname]["#"] = $this->_xml_depth($vals, $i);
  1264. return $array;
  1265. }
  1266. // _xml_depth()
  1267. // (c) Hans Anderson / http://www.hansanderson.com/php/xml/
  1268. public function _xml_depth($vals, &$i) {
  1269. $children = array();
  1270. if ( isset($vals[$i]['value']) )
  1271. {
  1272. array_push($children, $vals[$i]['value']);
  1273. }
  1274. while (++$i < count($vals)) {
  1275. switch ($vals[$i]['type']) {
  1276. case 'open':
  1277. if ( isset ( $vals[$i]['tag'] ) )
  1278. {
  1279. $tagname = $vals[$i]['tag'];
  1280. } else {
  1281. $tagname = '';
  1282. }
  1283. if ( isset ( $children[$tagname] ) )
  1284. {
  1285. $size = sizeof($children[$tagname]);
  1286. } else {
  1287. $size = 0;
  1288. }
  1289. if ( isset ( $vals[$i]['attributes'] ) ) {
  1290. $children[$tagname][$size]['@'] = $vals[$i]["attributes"];
  1291. }
  1292. $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i);
  1293. break;
  1294. case 'cdata':
  1295. array_push($children, $vals[$i]['value']);
  1296. break;
  1297. case 'complete':
  1298. $tagname = $vals[$i]['tag'];
  1299. if( isset ($children[$tagname]) )
  1300. {
  1301. $size = sizeof($children[$tagname]);
  1302. } else {
  1303. $size = 0;
  1304. }
  1305. if( isset ( $vals[$i]['value'] ) )
  1306. {
  1307. $children[$tagname][$size]["#"] = $vals[$i]['value'];
  1308. } else {
  1309. $children[$tagname][$size]["#"] = array();
  1310. }
  1311. if ( isset ($vals[$i]['attributes']) ) {
  1312. $children[$tagname][$size]['@']
  1313. = $vals[$i]['attributes'];
  1314. }
  1315. break;
  1316. case 'close':
  1317. return $children;
  1318. break;
  1319. }
  1320. }
  1321. return $children;
  1322. }
  1323. // TraverseXMLize()
  1324. // (c) acebone@f2s.com, a HUGE help!
  1325. public function TraverseXMLize($array, $arrName = "array", $level = 0) {
  1326. if ($level == 0)
  1327. {
  1328. echo "<pre>";
  1329. }
  1330. foreach($array as $key=>$val)
  1331. {
  1332. if ( is_array($val) )
  1333. {
  1334. $this->TraverseXMLize($val, $arrName . "[" . $key . "]", $level + 1);
  1335. } else {
  1336. $GLOBALS['traverse_array'][] = '$' . $arrName . '[' . $key . '] = "' . $val . "\"\n";
  1337. }
  1338. }
  1339. if ($level == 0)
  1340. {
  1341. echo "</pre>";
  1342. }
  1343. return 1;
  1344. }
  1345. }
  1346. class MakeXML extends Jabber
  1347. {
  1348. public $nodes;
  1349. public function MakeXML()
  1350. {
  1351. $nodes = array();
  1352. }
  1353. public function AddPacketDetails($string, $value = null)
  1354. {
  1355. if (preg_match("/\(([0-9]*)\)$/i", $string))
  1356. {
  1357. $string .= "/[\"#\"]";
  1358. }
  1359. $temp = @explode("/", $string);
  1360. for ($a = 0; $a < count($temp); $a++)
  1361. {
  1362. $temp[$a] = preg_replace("/^[@]{1}([a-z0-9_]*)$/i", "[\"@\"][\"\\1\"]", $temp[$a]);
  1363. $temp[$a] = preg_replace("/^([a-z0-9_]*)\(([0-9]*)\)$/i", "[\"\\1\"][\\2]", $temp[$a]);
  1364. $temp[$a] = preg_replace("/^([a-z0-9_]*)$/i", "[\"\\1\"]", $temp[$a]);
  1365. }
  1366. $node = implode("", $temp);
  1367. // Yeahyeahyeah, I know it's ugly... get over it. ;)
  1368. echo "\$this->nodes$node = \"" . htmlspecialchars($value) . "\";<br/>";
  1369. eval("\$this->nodes$node = \"" . htmlspecialchars($value) . "\";");
  1370. }
  1371. public function BuildPacket($array = null)
  1372. {
  1373. if (!$array)
  1374. {
  1375. $array = $this->nodes;
  1376. }
  1377. if (is_array($array))
  1378. {
  1379. array_multisort($array, SORT_ASC, SORT_STRING);
  1380. foreach ($array as $key => $value)
  1381. {
  1382. if (is_array($value) && $key == "@")
  1383. {
  1384. foreach ($value as $subkey => $subvalue)
  1385. {
  1386. $subvalue = htmlspecialchars($subvalue);
  1387. $text .= " $subkey='$subvalue'";
  1388. }
  1389. $text .= ">\n";
  1390. }
  1391. elseif ($key == "#")
  1392. {
  1393. $text .= htmlspecialchars($value);
  1394. }
  1395. elseif (is_array($value))
  1396. {
  1397. for ($a = 0; $a < count($value); $a++)
  1398. {
  1399. $text .= "<$key";
  1400. if (!$this->_preg_grep_keys("/^@/", $value[$a]))
  1401. {
  1402. $text .= ">";
  1403. }
  1404. $text .= $this->BuildPacket($value[$a]);
  1405. $text .= "</$key>\n";
  1406. }
  1407. }
  1408. else
  1409. {
  1410. $value = htmlspecialchars($value);
  1411. $text .= "<$key>$value</$key>\n";
  1412. }
  1413. }
  1414. return $text;
  1415. }
  1416. }
  1417. public function _preg_grep_keys($pattern, $array)
  1418. {
  1419. while (list($key, $val) = each($array))
  1420. {
  1421. if (preg_match($pattern, $key))
  1422. {
  1423. $newarray[$key] = $val;
  1424. }
  1425. }
  1426. return (is_array($newarray)) ? $newarray : false;
  1427. }
  1428. }
  1429. class CJP_StandardConnector
  1430. {
  1431. public $active_socket;
  1432. public function OpenSocket($server, $port)
  1433. {
  1434. if (function_exists("dns_get_record"))
  1435. {
  1436. $record = dns_get_record("_xmpp-client._tcp.$server", DNS_SRV);
  1437. if (!empty($record))
  1438. {
  1439. $server = $record[0]["target"];
  1440. $port = $record[0]["port"];
  1441. }
  1442. }
  1443. if ($this->active_socket = fsockopen($server, $port))
  1444. {
  1445. socket_set_blocking($this->active_socket, 0);
  1446. socket_set_timeout($this->active_socket, 31536000);
  1447. return true;
  1448. }
  1449. else
  1450. {
  1451. return false;
  1452. }
  1453. }
  1454. public function CloseSocket()
  1455. {
  1456. return fclose($this->active_socket);
  1457. }
  1458. public function WriteToSocket($data)
  1459. {
  1460. if (false)
  1461. {
  1462. echo '>>> <pre>' . htmlspecialchars($data) . '</pre>';
  1463. }
  1464. return fwrite($this->active_socket, $data);
  1465. }
  1466. public function ReadFromSocket($chunksize)
  1467. {
  1468. set_magic_quotes_runtime(0);
  1469. $buffer = fread($this->active_socket, $chunksize);
  1470. set_magic_quotes_runtime(get_magic_quotes_gpc());
  1471. return $buffer;
  1472. }
  1473. }
  1474. /* EOF */