function configure() { $this->pid = getmypid(); $this->mode = isset($_REQUEST['jaxl']) ? "cgi" : "cli"; if (!JAXLUtil::isWin() && JAXLUtil::pcntlEnabled() && $config['sigh'] != FALSE) { pcntl_signal(SIGTERM, array($this, "shutdown")); pcntl_signal(SIGINT, array($this, "shutdown")); JAXLog::log("Registering shutdown for SIGH Terms ...", 0, $this); } if (JAXLUtil::sslEnabled()) { JAXLog::log("Openssl enabled ...", 0, $this); } if ($this->mode == "cli") { if (!function_exists('fsockopen')) { die("Jaxl requires fsockopen method ..."); } file_put_contents(JAXL_PID_PATH, $this->pid); } if ($this->mode == "cgi") { if (!function_exists('curl_init')) { die("Jaxl requires curl_init method ..."); } } // include service discovery XEP, recommended for every IM client jaxl_require('JAXL0030', $this, array('category' => 'client', 'type' => 'bot', 'name' => JAXL_NAME, 'lang' => 'en')); }
public static function getPresence($payloads, $jaxl) { $html = ''; foreach ($payloads as $payload) { if (in_array($payload['type'], array('', 'available', 'unavailable'))) { list($room, $domain, $nick) = JAXLUtil::splitJid($payload['from']); $html .= '<div class="presIn">'; $html .= '<p class="from">' . $nick; if ($payload['type'] == 'unavailable') { $html .= ' left the room</p>'; } else { $html .= ' joined the room</p>'; } $html .= '</div>'; } } if ($html != '') { $response = array('jaxl' => 'presence', 'presence' => urlencode($html)); $jaxl->JAXL0206('out', $response); } return $payloads; }
$body = file_get_contents("php://input"); $body = new SimpleXMLElement($body); $attrs = $body->attributes(); if (!@$attrs['to'] && !@$attrs['rid'] && !@$attrs['wait'] && !@$attrs['hold']) { echo "invalid input"; exit; } // // initialize JAXL object with initial config // require_once 'jaxl.php'; $to = $attrs['to']; $rid = $attrs['rid']; $wait = $attrs['wait']; $hold = $attrs['hold']; echo $to . " " . $rid . " " . $wait . " " . $hold; exit; list($host, $port) = JAXLUtil::get_dns_srv($to); $client = new JAXL(array('domain' => $to, 'host' => $host, 'port' => $port, 'bosh_url' => 'http://localhost:5280/http-bind', 'bosh_rid' => $rid, 'bosh_wait' => $wait, 'bosh_hold' => $hold, 'auth_type' => 'ANONYMOUS')); $client->add_cb('on_auth_success', function () { global $client; _info($client->full_jid->to_string()); _info($client->xeps['0206']->sid); _info($client->xeps['0206']->rid); exit; }); // // finally start configured xmpp stream // $client->start(); echo "done\n";
public static function sendBody($xml, $jaxl) { $xml = JAXLPlugin::execute('jaxl_pre_curl', $xml, $jaxl); if ($xml != false) { JAXLog::log("[[XMPPSend]] body\n" . $xml, 4, $jaxl); $payload = JAXLUtil::curl($jaxl->bosh['url'], 'POST', $jaxl->bosh['headers'], $xml); $payload = $payload['content']; XMPPGet::handler($payload, $jaxl); } return $xml; }
public static function startAuth($type, $jaxl) { $jaxl->authType = $type; $xml = '<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="' . $type . '">'; switch ($type) { case 'DIGEST-MD5': break; case 'PLAIN': $xml .= base64_encode("" . $jaxl->user . "" . $jaxl->pass); break; case 'ANONYMOUS': break; case 'X-FACEBOOK-PLATFORM': break; case 'CRAM-MD5': break; case 'SCRAM-SHA-1': $xml .= base64_encode("n,,n=" . $jaxl->user . ",r=" . base64_encode(JAXLUtil::generateNonce())); break; default: break; } $xml .= '</auth>'; JAXLog::log("Performing Auth type: " . $type, 0, $jaxl); return self::xml($xml, $jaxl); }
public static function getResponse($authType, $challenge, $jaxl) { $response = array(); $decoded = base64_decode($challenge); $xml = '<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">'; if ($authType == 'X-FACEBOOK-PLATFORM') { $decoded = explode('&', $decoded); foreach ($decoded as $k => $v) { list($kk, $vv) = explode('=', $v); $decoded[$kk] = $vv; unset($decoded[$k]); } list($secret, $decoded['api_key'], $decoded['session_key']) = JAXLPlugin::execute('jaxl_get_facebook_key', false, $jaxl); $decoded['call_id'] = time(); $decoded['v'] = '1.0'; $base_string = ''; foreach (array('api_key', 'call_id', 'method', 'nonce', 'session_key', 'v') as $key) { if (isset($decoded[$key])) { $response[$key] = $decoded[$key]; $base_string .= $key . '=' . $decoded[$key]; } } $base_string .= $secret; $response['sig'] = md5($base_string); $responseURI = ''; foreach ($response as $k => $v) { if ($responseURI == '') { $responseURI .= $k . '=' . urlencode($v); } else { $responseURI .= '&' . $k . '=' . urlencode($v); } } $xml .= base64_encode($responseURI); } else { if ($authType == 'DIGEST-MD5') { $decoded = JAXLUtil::explodeData($decoded); if (!isset($decoded['digest-uri'])) { $decoded['digest-uri'] = 'xmpp/' . $jaxl->domain; } $decoded['cnonce'] = base64_encode(JAXLUtil::generateNonce()); if (isset($decoded['qop']) && $decoded['qop'] != 'auth' && strpos($decoded['qop'], 'auth') !== false) { $decoded['qop'] = 'auth'; } $response = array('username' => $jaxl->user, 'response' => JAXLUtil::encryptPassword(array_merge($decoded, array('nc' => '00000001')), $jaxl->user, $jaxl->pass), 'charset' => 'utf-8', 'nc' => '00000001', 'qop' => 'auth'); foreach (array('nonce', 'digest-uri', 'realm', 'cnonce') as $key) { if (isset($decoded[$key])) { $response[$key] = $decoded[$key]; } } $xml .= base64_encode(JAXLUtil::implodeData($response)); } else { if ($authType == 'SCRAM-SHA-1') { $decoded = JAXLUtil::explodeData($decoded); // SaltedPassword := Hi(Normalize(password), salt, i) $saltedPasswd = JAXLUtil::pbkdf2($jaxl->pass, $decoded['s'], $decoded['i']); // ClientKey := HMAC(SaltedPassword, "Client Key") $clientKey = JAXLUtil::hashMD5($saltedPassword, "Client Key"); // StoredKey := H(ClientKey) $storedKey = sha1("Client Key"); // assemble client-final-message-without-proof $clientFinalMessage = "c=bwis,r=" . $decoded['r']; // AuthMessage := client-first-message-bare + "," + server-first-message + "," + client-final-message-without-proof // ClientSignature := HMAC(StoredKey, AuthMessage) // ClientProof := ClientKey XOR ClientSignature // ServerKey := HMAC(SaltedPassword, "Server Key") // ServerSignature := HMAC(ServerKey, AuthMessage) foreach (array('c', 'r', 'p') as $key) { if (isset($decoded[$key])) { $response[$key] = $decoded[$key]; } } $xml .= base64_encode(JAXLUtil::implodeData($response)); } else { if ($authType == 'CRAM-MD5') { $xml .= base64_encode($jaxl->user . ' ' . hash_hmac('md5', $jaxl->pass, $arr['challenge'])); } } } } $xml .= '</response>'; $jaxl->secondChallenge = true; return $xml; }
public function get_challenge_response($decoded) { $response = array(); $nc = '00000001'; if (!isset($decoded['digest-uri'])) { $decoded['digest-uri'] = 'xmpp/' . $this->jid->domain; } $decoded['cnonce'] = base64_encode(JAXLUtil::get_nonce()); if (isset($decoded['qop']) && $decoded['qop'] != 'auth' && strpos($decoded['qop'], 'auth') !== false) { $decoded['qop'] = 'auth'; } $data = array_merge($decoded, array('nc' => $nc)); $response = array('username' => $this->jid->node, 'response' => $this->encrypt_password($data, $this->jid->node, $this->pass), 'charset' => 'utf-8', 'nc' => $nc, 'qop' => 'auth'); foreach (array('nonce', 'digest-uri', 'realm', 'cnonce') as $key) { if (isset($decoded[$key])) { $response[$key] = $decoded[$key]; } } return base64_encode($this->implode_data($response)); }
/** * Tracks all incoming presence stanza's */ function _handlePresence($payloads, $jaxl) { foreach ($payloads as $payload) { if ($this->trackPresence) { // update local $roster cache $jid = JAXLUtil::getBareJid($payload['from']); $this->_addRosterNode($jid, false); if (!isset($this->roster[$jid]['presence'][$payload['from']])) { $this->roster[$jid]['presence'][$payload['from']] = array(); } $this->roster[$jid]['presence'][$payload['from']]['type'] = $payload['type'] == '' ? 'available' : $payload['type']; $this->roster[$jid]['presence'][$payload['from']]['status'] = $payload['status']; $this->roster[$jid]['presence'][$payload['from']]['show'] = $payload['show']; $this->roster[$jid]['presence'][$payload['from']]['priority'] = $payload['priority']; } if ($payload['type'] == 'subscribe' && $this->autoSubscribe) { $this->subscribed($payload['from']); $this->subscribe($payload['from']); $this->executePlugin('jaxl_post_subscription_request', $payload); } else { if ($payload['type'] == 'subscribed') { $this->executePlugin('jaxl_post_subscription_accept', $payload); } } } return $payloads; }
public function get_scram_sha1_response($pass, $challenge) { // it contains users iteration count i and the user salt // also server will append it's own nonce to the one we specified $decoded = $this->explode_data(base64_decode($challenge)); // r=,s=,i= $nonce = $decoded['r']; $salt = base64_decode($decoded['s']); $iteration = intval($decoded['i']); // SaltedPassword := Hi(Normalize(password), salt, i) $salted = JAXLUtil::pbkdf2($this->pass, $salt, $iteration); // ClientKey := HMAC(SaltedPassword, "Client Key") $client_key = hash_hmac('sha1', $salted, "Client Key", true); // StoredKey := H(ClientKey) $stored_key = hash('sha1', $client_key, true); // AuthMessage := client-first-message-bare + "," + server-first-message + "," + client-final-message-without-proof $auth_message = ''; // ClientSignature := HMAC(StoredKey, AuthMessage) $signature = hash_hmac('sha1', $stored_key, $auth_message, true); // ClientProof := ClientKey XOR ClientSignature $client_proof = $client_key ^ $signature; $proof = 'c=biws,r=' . $nonce . ',p=' . base64_encode($client_proof); return base64_encode($proof); }
/** * Routes incoming XMPP data to appropriate handlers */ function handler($payload) { if ($payload == '' && $this->mode == 'cli') { return ''; } if ($payload != '' && $this->mode == 'cgi') { $this->log("[[XMPPGet]] \n" . $payload, 4); } $payload = $this->executePlugin('jaxl_pre_handler', $payload); $xmls = JAXLUtil::splitXML($payload); $pktCnt = count($xmls); $this->totalRcvdPkt += $pktCnt; $buffer = array(); foreach ($xmls as $pktNo => $xml) { if ($pktNo == $pktCnt - 1) { if (substr($xml, -1, 1) != '>') { $this->buffer .= $xml; break; } } if (substr($xml, 0, 7) == '<stream') { $arr = $this->xml->xmlize($xml); } else { $arr = JAXLXml::parse($xml, $this->getSXE); } if ($arr === false) { $this->buffer .= $xml; continue; } switch (true) { case isset($arr['stream:stream']): XMPPGet::streamStream($arr['stream:stream'], $this); break; case isset($arr['stream:features']): XMPPGet::streamFeatures($arr['stream:features'], $this); break; case isset($arr['stream:error']): XMPPGet::streamError($arr['stream:error'], $this); break; case isset($arr['failure']): XMPPGet::failure($arr['failure'], $this); break; case isset($arr['proceed']): XMPPGet::proceed($arr['proceed'], $this); break; case isset($arr['challenge']): XMPPGet::challenge($arr['challenge'], $this); break; case isset($arr['success']): XMPPGet::success($arr['success'], $this); break; case isset($arr['presence']): $buffer['presence'][] = $arr['presence']; break; case isset($arr['message']): $buffer['message'][] = $arr['message']; break; case isset($arr['iq']): $this->payloadRaw = $arr['xml']; XMPPGet::iq($arr['iq'], $this); break; default: $jaxl->log("[[XMPPGet]] \nUnrecognized payload received from jabber server..."); throw new JAXLException("[[XMPPGet]] Unrecognized payload received from jabber server..."); break; } } if (isset($buffer['presence'])) { XMPPGet::presence($buffer['presence'], $this); } if (isset($buffer['message'])) { XMPPGet::message($buffer['message'], $this); } unset($buffer); $this->executePlugin('jaxl_post_handler', $payload); return $payload; }
private static function preparePresence($jaxl, $to, $from, $child, $type, $id, $ns) { $xml = '<presence'; if ($type) { $xml .= ' type="' . $type . '"'; } if ($from) { $xml .= ' from="' . $from . '"'; } if ($to) { $xml .= ' to="' . htmlspecialchars($to) . '"'; } if ($id) { $xml .= ' id="' . $id . '"'; } $xml .= '>'; if ($child) { if (isset($child['show'])) { $xml .= '<show>' . $child['show'] . '</show>'; } if (isset($child['status'])) { $xml .= '<status>' . JAXLUtil::xmlentities($child['status']) . '</status>'; } if (isset($child['priority'])) { $xml .= '<priority>' . $child['priority'] . '</priority>'; } if (isset($child['payload'])) { $xml .= $child['payload']; } } $xml .= '</presence>'; return $xml; }
public static function handler($payload, &$jaxl) { JAXLog::log("[[XMPPGet]] \n" . $payload, 4, $jaxl); $buffer = array(); $payload = JAXLPlugin::execute('jaxl_pre_handler', $payload, $jaxl); $xmls = JAXLUtil::splitXML($payload); $pktCnt = count($xmls); foreach ($xmls as $pktNo => $xml) { if ($pktNo == $pktCnt - 1) { if (substr($xml, -1, 1) != '>') { $jaxl->buffer = $xml; break; } } if (substr($xml, 0, 7) == '<stream') { $arr = $jaxl->xml->xmlize($xml); } else { $arr = JAXLXml::parse($xml); } switch (true) { case isset($arr['stream:stream']): self::streamStream($arr['stream:stream'], $jaxl); break; case isset($arr['stream:features']): self::streamFeatures($arr['stream:features'], $jaxl); break; case isset($arr['stream:error']): self::streamError($arr['stream:error'], $jaxl); break; case isset($arr['failure']): self::failure($arr['failure'], $jaxl); break; case isset($arr['proceed']): self::proceed($arr['proceed'], $jaxl); break; case isset($arr['challenge']): self::challenge($arr['challenge'], $jaxl); break; case isset($arr['success']): self::success($arr['success'], $jaxl); break; case isset($arr['presence']): $buffer['presence'][] = $arr['presence']; break; case isset($arr['message']): $buffer['message'][] = $arr['message']; break; case isset($arr['iq']): self::iq($arr['iq'], $jaxl); break; default: print "Unrecognized payload received from jabber server..."; break; } } if (isset($buffer['presence'])) { self::presence($buffer['presence'], $jaxl); } if (isset($buffer['message'])) { self::message($buffer['message'], $jaxl); } unset($buffer); JAXLPlugin::execute('jaxl_post_handler', $payload, $jaxl); }
/** * Configures Jaxl instance to run across various platforms (*nix/windows) * * Configure method tunes connecting Jaxl instance for * OS compatibility, SSL support and dependencies over PHP methods */ protected function configure() { // register shutdown function if (!JAXLUtil::isWin() && JAXLUtil::pcntlEnabled() && $this->sigh) { pcntl_signal(SIGTERM, array($this, "shutdown")); pcntl_signal(SIGINT, array($this, "shutdown")); $this->log("Registering callbacks for CTRL+C and kill."); } else { $this->log("No callbacks registered for CTRL+C and kill."); } // check Jaxl dependency on PHP extension in cli mode if ($this->mode == "cli") { if ($this->openSSL = JAXLUtil::sslEnabled()) { $this->log("OpenSSL extension is loaded."); } else { $this->log("OpenSSL extension not loaded."); } if (!function_exists('fsockopen')) { die("Jaxl requires fsockopen method"); } if (@is_writable($this->pidPath)) { file_put_contents($this->pidPath, $this->pid); } } // check Jaxl dependency on PHP extension in cgi mode if ($this->mode == "cgi") { if (!function_exists('curl_init')) { die("Jaxl requires CURL PHP extension"); } if (!function_exists('json_encode')) { die("Jaxl requires JSON PHP extension."); } } }
public static function sendBody($xml, $jaxl) { $xml = self::saveSession($xml, $jaxl); if ($xml != false) { $jaxl->log("[[XMPPSend]] body\n" . $xml, 4); $payload = JAXLUtil::curl($jaxl->bosh['url'], 'POST', $jaxl->bosh['headers'], $xml); $payload = $payload['content']; $jaxl->handler($payload); } return $xml; }
public static function sendBody($xml, $jaxl) { $xml = self::saveSession($xml, $jaxl); if ($xml != false) { $jaxl->log("[[XMPPSend]] body\n" . $xml, 4); $payload = JAXLUtil::curl($jaxl->bosh['url'], 'POST', $jaxl->bosh['headers'], $xml); // curl error handling if ($payload['errno'] != 0) { $log = "[[JAXL0124]] Curl errno " . $payload['errno'] . " encountered"; switch ($payload['errno']) { case 7: $log .= ". Failed to connect with " . $jaxl->bosh['url']; break; case 52: $log .= ". Empty response rcvd from bosh endpoint"; break; default: break; } $jaxl->executePlugin('jaxl_get_bosh_curl_error', $payload); $jaxl->log($log); } $payload = $payload['content']; $jaxl->handler($payload); } return $xml; }
public static function postBind($arr, $jaxl) { if ($arr["type"] == "result") { $jaxl->jid = $arr["bindJid"]; list($user, $domain, $resource) = JAXLUtil::splitJid($jaxl->jid); $jaxl->resource = $resource; $jaxl->executePlugin('jaxl_post_bind', false); if ($jaxl->sessionRequired) { $jaxl->startSession(); } else { $jaxl->auth = true; $jaxl->log("[[XMPPGet]] Auth completed..."); $jaxl->executePlugin('jaxl_post_auth', false); } } }