You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

608 lines
15 KiB

15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
  1. <?php
  2. /**
  3. * @file Jabber.php
  4. * This file is part of MOVIM.
  5. *
  6. * @brief Wrapper around Jaxl to handle mid-level functionalities
  7. *
  8. * @author Etenil <etenil@etenilsrealm.nl>
  9. *
  10. * @version 1.0
  11. * @date 13 October 2010
  12. *
  13. * Copyright (C)2010 Movim Project
  14. *
  15. * See COPYING for licensing information.
  16. */
  17. define('JAXL_COMPONENT_PORT', 5559);
  18. define('JAXL_LOG_PATH', BASE_PATH . 'log/jaxl.log');
  19. define('JAXL_LOG_EVENT', true);
  20. define('JAXL_LOG_ROTATE', false);
  21. define('JAXL_BASE_PATH', LIB_PATH . 'Jaxl/');
  22. include(LIB_PATH . 'Jaxl/core/jaxl.class.php');
  23. class Jabber
  24. {
  25. private static $instance;
  26. private $jaxl;
  27. private $payload;
  28. /**
  29. * Firing up basic parts of jaxl and setting variables.
  30. */
  31. private function __construct($jid)
  32. {
  33. $userConf = Conf::getUserConf($jid);
  34. $serverConf = Conf::getServerConf();
  35. $sess = Session::start(APP_NAME);
  36. $sess->remove('jid'); // ???
  37. $this->jaxl = new JAXL(array(
  38. // User Configuration
  39. 'host' => $userConf['host'],
  40. 'domain' => isset($userConf['domain']) ? $userConf['domain'] : $userConf['host'],
  41. 'boshHost' => $userConf['boshHost'],
  42. 'boshSuffix' => $userConf['boshSuffix'],
  43. 'boshPort' => $userConf['boshPort'],
  44. // Server configuration
  45. 'boshCookieTTL' => $serverConf['boshCookieTTL'],
  46. 'boshCookiePath' => $serverConf['boshCookiePath'],
  47. 'boshCookieDomain' => $serverConf['boshCookieDomain'],
  48. 'boshCookieHTTPS' => $serverConf['boshCookieHTTPS'],
  49. 'boshCookieHTTPOnly' => $serverConf['boshCookieHTTPOnly'],
  50. 'logLevel' => $serverConf['logLevel'],
  51. 'boshOut'=>false,
  52. ));
  53. // Loading required XEPS
  54. $this->jaxl->requires(array(
  55. 'JAXL0030', // Service Discovery
  56. 'JAXL0054', // VCard
  57. 'JAXL0060', // Pubsub
  58. 'JAXL0115', // Entity Capabilities
  59. 'JAXL0133', // Service Administration
  60. 'JAXL0085', // Chat State Notification
  61. 'JAXL0092', // Software Version
  62. 'JAXL0203', // Delayed Delivery
  63. 'JAXL0202', // Entity Time
  64. 'JAXL0206', // Jabber over Bosh
  65. 'JAXL0277' // Microblogging
  66. ));
  67. // Defining call-backs
  68. // Connect-Disconnect
  69. $this->jaxl->addPlugin('jaxl_post_auth', array(&$this, 'postAuth'));
  70. $this->jaxl->addPlugin('jaxl_post_auth_failure', array(&$this, 'postAuthFailure'));
  71. //$this->jaxl->addPlugin('jaxl_post_roster_update', array(&$this, 'postRosterUpdate'));
  72. $this->jaxl->addPlugin('jaxl_post_disconnect', array(&$this, 'postDisconnect'));
  73. $this->jaxl->addPlugin('jaxl_get_auth_mech', array(&$this, 'postAuthMech'));
  74. // The handlers
  75. $this->jaxl->addPlugin('jaxl_get_iq', array(&$this, 'getIq'));
  76. $this->jaxl->addPlugin('jaxl_get_message', array(&$this, 'getMessage'));
  77. $this->jaxl->addPlugin('jaxl_get_presence', array(&$this, 'getPresence'));
  78. // Others hooks
  79. $this->jaxl->addPlugin('jaxl_get_bosh_curl_error', array(&$this, 'boshCurlError'));
  80. $this->jaxl->addplugin('jaxl_get_empty_body', array(&$this, 'getEmptyBody'));
  81. }
  82. /**
  83. * Get the current instance
  84. *
  85. * @param string $jid = false
  86. * @return instance
  87. */
  88. public function getInstance($jid = false)
  89. {
  90. if(!is_object(self::$instance)) {
  91. if(!$jid) {
  92. $user = new User();
  93. if(!$user->isLogged()) {
  94. throw new MovimException(t("User not logged in."));
  95. } else {
  96. $jid = $user->getLogin();
  97. if($jid = "")
  98. throw new MovimException(t("JID not provided."));
  99. }
  100. } else {
  101. self::$instance = new Jabber($jid);
  102. }
  103. }
  104. return self::$instance;
  105. }
  106. /**
  107. * Start the BOSH connection
  108. *
  109. * @param string $jid
  110. * @param string $pass
  111. * @return void
  112. */
  113. public function login($jid, $pass)
  114. {
  115. if(!$this->checkJid($jid)) {
  116. throw new MovimException(t("jid '%s' is incorrect", $jid));
  117. } else {
  118. $id = explode('@',$jid);
  119. $user = $id[0];
  120. $userConf = $id[1];
  121. $domain = $id[1];
  122. $this->jaxl->user = $user;
  123. $this->jaxl->pass = $pass;
  124. $this->jaxl->startCore('bosh');
  125. }
  126. self::setStatus(false, false);
  127. }
  128. /**
  129. * postAuth
  130. *
  131. * @return void
  132. */
  133. public function postAuth() {
  134. $this->jaxl->getRosterList();
  135. $this->jaxl->getVCard();
  136. }
  137. /**
  138. * postAuthFailure
  139. *
  140. * @return void
  141. */
  142. public function postAuthFailure() {
  143. $this->jaxl->shutdown();
  144. throw new MovimException("Login error.");
  145. $user = new User();
  146. $user->desauth();
  147. }
  148. /**
  149. * Return the current ressource
  150. *
  151. * @return string
  152. */
  153. public function getResource()
  154. {
  155. $res = JAXLUtil::splitJid($this->jaxl->jid);
  156. return $res[2];
  157. }
  158. /**
  159. * Return the current Jid
  160. *
  161. * @return string
  162. */
  163. public function getJid() {
  164. return $this->jaxl->jid;
  165. }
  166. public function boshCurlError() {
  167. // $this->jaxl->shutdown();
  168. // throw new MovimException("Bosh connection error.");
  169. // $user = new User();
  170. // $user->desauth();
  171. }
  172. /**
  173. * Auth mechanism
  174. *
  175. * @param array $mechanism
  176. * @return void
  177. */
  178. public function postAuthMech($mechanism) {
  179. movim_log($mechanism);
  180. if(in_array("DIGEST-MD5", $mechanism))
  181. $this->jaxl->auth('DIGEST-MD5');
  182. elseif(in_array("PLAIN", $mechanism))
  183. $this->jaxl->auth('PLAIN');
  184. }
  185. /**
  186. * Close the BOSH connection
  187. *
  188. * @return void
  189. */
  190. public function logout()
  191. {
  192. $this->jaxl->JAXL0206('endStream');
  193. }
  194. /**
  195. * postDisconnect
  196. *
  197. * @param array $data
  198. * @return void
  199. */
  200. public function postDisconnect($data)
  201. {
  202. $evt = new Event();
  203. $evt->runEvent('postdisconnected', $data);
  204. }
  205. /**
  206. * Pings the server. This must be done regularly in order to keep the
  207. * session running
  208. *
  209. * @return void
  210. */
  211. public function pingServer()
  212. {
  213. $this->jaxl->JAXL0206('ping');
  214. }
  215. /**
  216. * Get an empty body
  217. *
  218. * @param array $payload
  219. * @return void
  220. */
  221. public function getEmptyBody($payload) {
  222. $evt = new Event();
  223. // Oooooh, am I disconnected??
  224. if(preg_match('/condition=[\'"]item-not-found[\'"]/', $payload)) {
  225. $evt->runEvent('serverdisconnect', null);
  226. } else {
  227. $evt->runEvent('incomingemptybody', 'ping');
  228. }
  229. }
  230. /**
  231. * Iq handler
  232. *
  233. * @param array $payload
  234. * @return void
  235. */
  236. public function getIq($payload) {
  237. movim_log($payload);
  238. $evt = new Event();
  239. // vCard case
  240. if(isset($payload['vCard'])) { // Holy mackerel, that's a vcard!
  241. if($payload['from'] == reset(explode("/", $payload['to'])) || $payload['from'] == NULL) {
  242. Cache::c("myvcard", $payload);
  243. $evt->runEvent('myvcardreceived', $payload);
  244. } else {
  245. Cache::c("vcard".$payload["from"], $payload);
  246. $res = JAXLUtil::splitJid($payload['to']);
  247. Conf::savePicture($res[0].'@'.$res[1], $payload['from'], $payload['vCardPhotoBinVal'], $payload["vCardPhotoType"]);
  248. $evt->runEvent('vcardreceived', $payload);
  249. }
  250. }
  251. // Roster case
  252. elseif($payload['queryXmlns'] == "jabber:iq:roster") {
  253. if($payload['type'] == "result") {
  254. Cache::c("roster", $payload);
  255. $evt->runEvent('rosterreceived', $payload);
  256. } elseif($payload['type'] == "set") {
  257. $this->getRosterList();
  258. }
  259. }
  260. // Pubsub node case
  261. elseif($payload["pubsubNode"] == "urn:xmpp:microblog:0") {
  262. $evt->runEvent('streamreceived', $payload);
  263. }
  264. elseif(isset($payload["pubsubNode"])) {
  265. $evt->runEvent('thread', $payload);
  266. }
  267. elseif($payload["queryXmlns"] == "http://jabber.org/protocol/disco#items") {
  268. $evt->runEvent('disconodes', $payload);
  269. } else {
  270. $evt->runEvent('none', var_export($payload, true));
  271. }
  272. }
  273. /**
  274. * Message handler
  275. *
  276. * @param array $payloads
  277. * @return void
  278. */
  279. public function getMessage($payloads) {
  280. movim_log($payloads);
  281. foreach($payloads as $payload) {
  282. if($payload['offline'] != JAXL0203::$ns && $payload['type'] == 'chat') { // reject offline message
  283. $evt = new Event();
  284. if($payload['chatState'] == 'active' && $payload['body'] == NULL) {
  285. $evt->runEvent('incomeactive', $payload);
  286. }
  287. elseif($payload['chatState'] == 'composing') {
  288. $evt->runEvent('incomecomposing', $payload);
  289. }
  290. elseif($payload['chatState'] == 'paused') {
  291. $evt->runEvent('incomepaused', $payload);
  292. }
  293. else {
  294. $evt->runEvent('incomemessage', $payload);
  295. }
  296. }
  297. }
  298. }
  299. /**
  300. * Presence handler
  301. *
  302. * @param array $payloads
  303. * @return void
  304. */
  305. public function getPresence($payloads) {
  306. foreach($payloads as $payload) {
  307. if($payload['type'] == 'subscribe') {
  308. $evt = new Event();
  309. $evt->runEvent('incomesubscribe', $payload);
  310. } elseif($payload['type'] == 'result') {
  311. } elseif($payload['type'] == '' || in_array($payload['type'], array('available', 'unavailable'))) {
  312. // We create the events
  313. $evt = new Event();
  314. $evt->runEvent('incomepresence', $payload);
  315. if($payload['from'] == $this->getJid())
  316. $evt->runEvent('incomemypresence', $payload);
  317. // We update the presence array
  318. $session = Session::start(APP_NAME);
  319. $presences = $session->get('presences');
  320. list($jid, $ressource) = explode('/',$payload['from']);
  321. if(!is_array($presences[$jid]))
  322. $presences[$jid] = array();
  323. $presences[$jid]['status'] = $payload['status'];
  324. if($payload['type'] == 'unavailable') {
  325. if($payload['from'] == $this->jaxl->jid)
  326. $evt->runEvent('postdisconnected', $data);
  327. else {
  328. $presences[$jid][$ressource] = 4;
  329. $evt->runEvent('incomeoffline', $payload);
  330. }
  331. }
  332. elseif($payload['show'] == 'xa') {
  333. $presences[$jid][$ressource] = 5;
  334. $evt->runEvent('incomeaway', $payload);
  335. }
  336. elseif($payload['show'] == 'away') {
  337. $presences[$jid][$ressource] = 3;
  338. $evt->runEvent('incomeaway', $payload);
  339. }
  340. elseif($payload['show'] == 'dnd') {
  341. $presences[$jid][$ressource] = 2;
  342. $evt->runEvent('incomednd', $payload);
  343. }
  344. else {
  345. $presences[$jid][$ressource] = 1;
  346. $evt->runEvent('incomeonline', $payload);
  347. }
  348. $session->set('presences', $presences);
  349. }
  350. }
  351. }
  352. /*public function postRosterUpdate($payload) {
  353. $evt = new Event();
  354. $evt->runEvent('rosterreceived', $payload);
  355. }*/
  356. /**
  357. * Ask for a vCard
  358. *
  359. * @param string $jid = false
  360. * @return void
  361. */
  362. public function getVCard($jid = false)
  363. {
  364. $this->jaxl->JAXL0054('getVCard', $jid, $this->jaxl->jid, false);
  365. }
  366. /**
  367. * sendVcard
  368. *
  369. * @param array $vcard
  370. * @return void
  371. */
  372. public function updateVcard($vcard)
  373. {
  374. $this->jaxl->JAXL0054('updateVCard', $vcard);
  375. $this->getVCard();
  376. }
  377. /**
  378. * Ask for some items
  379. *
  380. * @param unknown $jid = false
  381. * @return void
  382. */
  383. public function getWall($jid = false) {
  384. $this->jaxl->JAXL0277('getItems', $jid);
  385. }
  386. /**
  387. * Ask for some comments of an article
  388. *
  389. * @param string $jid
  390. * @param string $id
  391. * @return void
  392. */
  393. public function getComments($jid, $id) {
  394. $this->jaxl->JAXL0277('getComments', 'pubsub.jappix.com', $id);
  395. }
  396. /**
  397. * Service Discovery
  398. *
  399. * @param string $jid = false
  400. * @return void
  401. */
  402. public function discover($jid = false)
  403. {
  404. //$this->jaxl->JAXL0030('discoInfo', $jid, $this->jaxl->jid, false, false);
  405. //$this->jaxl->JAXL0030('discoItems', $jid, $this->jaxl->jid, false, false);mov
  406. $this->jaxl->JAXL0277('getItems', 'edhelas@jappix.com');
  407. //psgxs.linkmauve.fr
  408. }
  409. public function discoNodes($pod)
  410. {
  411. $this->jaxl->JAXL0060('discoNodes', $pod, $this->jaxl->jid);
  412. }
  413. public function discoItems($pod, $node)
  414. {
  415. $this->jaxl->JAXL0060('getNodeItems', $pod, $this->jaxl->jid, $node);
  416. }
  417. /**
  418. * Ask for the roster
  419. *
  420. * @return void
  421. */
  422. public function getRosterList()
  423. {
  424. $this->jaxl->getRosterList();
  425. }
  426. /**
  427. * Set a new status
  428. *
  429. * @param string $status
  430. * @param string $show
  431. * @return void
  432. */
  433. public function setStatus($status, $show)
  434. {
  435. $this->jaxl->setStatus($status, $show, 41, true);
  436. }
  437. /**
  438. * Check the current Jid
  439. *
  440. * @param string $jid
  441. * @return bool
  442. */
  443. private function checkJid($jid)
  444. {
  445. return true; /*
  446. preg_match('/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\(?:.[a-z]{2,5})?$/',
  447. $jid); */
  448. }
  449. /**
  450. * Send a message
  451. *
  452. * @param string $addressee
  453. * @param steirng $body
  454. * @return void
  455. */
  456. public function sendMessage($addressee, $body)
  457. {
  458. // Checking on the jid.
  459. if($this->checkJid($addressee)) {
  460. $this->jaxl->sendMessage($addressee, $body, false, 'chat');
  461. } else {
  462. throw new MovimException("Incorrect JID `$addressee'");
  463. }
  464. }
  465. /**
  466. * Subscribe to a contact request
  467. *
  468. * @param unknown $jid
  469. * @return void
  470. */
  471. public function subscribedContact($jid) {
  472. if($this->checkJid($jid)) {
  473. $this->jaxl->subscribed($jid);
  474. } else {
  475. throw new MovimException("Incorrect JID `$jid'");
  476. }
  477. }
  478. /**
  479. * Accecpt a new contact
  480. *
  481. * @param string $jid
  482. * @param string $group
  483. * @param string $alias
  484. * @return void
  485. */
  486. public function acceptContact($jid, $group, $alias)
  487. {
  488. if($this->checkJid($jid)) {
  489. $this->jaxl->addRoster($jid, $group, $alias);
  490. $this->jaxl->subscribe($jid);
  491. } else {
  492. throw new MovimException("Incorrect JID `$jid'");
  493. }
  494. }
  495. /**
  496. * Add a new contact
  497. *
  498. * @param string $jid
  499. * @param string $grJaxloup
  500. * @param string $alias
  501. * @return void
  502. */
  503. public function addContact($jid, $group, $alias) {
  504. if($this->checkJid($jid)) {
  505. $this->jaxl->subscribe($jid);
  506. $this->jaxl->addRoster($jid, $group, $alias);
  507. } else {
  508. throw new MovimException("Incorrect JID `$jid'");
  509. }
  510. }
  511. /**
  512. * Remove a contact
  513. *
  514. * @param string $jid
  515. * @return void
  516. */
  517. public function removeContact($jid) {
  518. if($this->checkJid($jid)) {
  519. $this->jaxl->deleteRoster($jid);
  520. $this->jaxl->unsubscribe($jid);
  521. } else {
  522. throw new MovimException("Incorrect JID `$jid'");
  523. }
  524. }
  525. /**
  526. * Unsubscribe to a contact
  527. *
  528. * @param unknown $jid
  529. * @return void
  530. */
  531. public function unsubscribed($jid) {
  532. $this->jaxl->unsubscribed($jid);
  533. }
  534. }
  535. ?>