Example #1
0
 /**
  * @param ProtocolNode $node
  */
 protected function writeInternal($node)
 {
     $len = 1;
     if ($node->getAttributes() != null) {
         $len += count($node->getAttributes()) * 2;
     }
     if (count($node->getChildren()) > 0) {
         $len += 1;
     }
     if (strlen($node->getData()) > 0) {
         $len += 1;
     }
     $this->writeListStart($len);
     $this->writeString($node->getTag());
     $this->writeAttributes($node->getAttributes());
     if (strlen($node->getData()) > 0) {
         $this->writeBytes($node->getData());
     }
     if ($node->getChildren()) {
         $this->writeListStart(count($node->getChildren()));
         foreach ($node->getChildren() as $child) {
             $this->writeInternal($child);
         }
     }
 }
Example #2
0
 /**
  * Will process the data from the server after it's been decrypted and parsed.
  *
  * This also provides a convenient method to use to unit test the event framework.
  *
  */
 protected function processInboundDataNode(ProtocolNode $node, $autoReceipt = true)
 {
     $this->debugPrint($node->nodeString("rx  ") . "\n");
     $this->serverReceivedId = $node->getAttribute('id');
     if ($node->getTag() == "challenge") {
         $this->processChallenge($node);
     } elseif ($node->getTag() == "failure") {
         $this->loginStatus = static::DISCONNECTED_STATUS;
     } elseif ($node->getTag() == "success") {
         $this->loginStatus = static::CONNECTED_STATUS;
         $challengeData = $node->getData();
         file_put_contents($this->challengeFilename, $challengeData);
         $this->writer->setKey($this->outputKey);
     } elseif ($node->getTag() == "failure") {
         $this->eventManager()->fireLoginFailed($this->phoneNumber, $node->getChild(0)->getTag());
     } elseif ($node->getTag() == '' && $node->getAttribute("class") == "message") {
         $this->eventManager()->fireMessageReceivedServer($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('class'));
     } elseif ($node->getTag() == 'receipt') {
         $this->eventManager()->fireMessageReceivedClient($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('class'), $node->getAttribute('t'));
     }
     if ($node->getTag() == "message") {
         array_push($this->messageQueue, $node);
         if ($node->hasChild('x') && $this->lastId == $node->getAttribute('id')) {
             $this->sendNextMessage();
         }
         if ($this->newMsgBind && $node->getChild('body')) {
             $this->newMsgBind->process($node);
         }
         if ($node->getAttribute("type") == "text" && $node->getChild('body') != null) {
             $author = $node->getAttribute("participant");
             if ($author == "") {
                 //private chat message
                 $this->eventManager()->fireGetMessage($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('type'), $node->getAttribute('t'), $node->getAttribute("notify"), $node->getChild("body")->getData());
             } else {
                 //group chat message
                 $this->eventManager()->fireGetGroupMessage($this->phoneNumber, $node->getAttribute('from'), $author, $node->getAttribute('id'), $node->getAttribute('type'), $node->getAttribute('t'), $node->getAttribute("notify"), $node->getChild("body")->getData());
             }
             if ($autoReceipt) {
                 $this->sendMessageReceived($node);
             }
         }
         if ($node->getAttribute("type") == "media" && $node->getChild('media') != null) {
             if ($node->getChild("media")->getAttribute('type') == 'image') {
                 $this->eventManager()->fireGetImage($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('type'), $node->getAttribute('t'), $node->getAttribute('notify'), $node->getChild("media")->getAttribute('size'), $node->getChild("media")->getAttribute('url'), $node->getChild("media")->getAttribute('file'), $node->getChild("media")->getAttribute('mimetype'), $node->getChild("media")->getAttribute('filehash'), $node->getChild("media")->getAttribute('width'), $node->getChild("media")->getAttribute('height'), $node->getChild("media")->getData());
             } elseif ($node->getChild("media")->getAttribute('type') == 'video') {
                 $this->eventManager()->fireGetVideo($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('type'), $node->getAttribute('t'), $node->getAttribute('notify'), $node->getChild("media")->getAttribute('url'), $node->getChild("media")->getAttribute('file'), $node->getChild("media")->getAttribute('size'), $node->getChild("media")->getAttribute('mimetype'), $node->getChild("media")->getAttribute('filehash'), $node->getChild("media")->getAttribute('duration'), $node->getChild("media")->getAttribute('vcodec'), $node->getChild("media")->getAttribute('acodec'), $node->getChild("media")->getData());
             } elseif ($node->getChild("media")->getAttribute('type') == 'audio') {
                 $this->eventManager()->fireGetAudio($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('type'), $node->getAttribute('t'), $node->getAttribute('notify'), $node->getChild("media")->getAttribute('size'), $node->getChild("media")->getAttribute('url'), $node->getChild("media")->getAttribute('file'), $node->getChild("media")->getAttribute('mimetype'), $node->getChild("media")->getAttribute('filehash'), $node->getChild("media")->getAttribute('duration'), $node->getChild("media")->getAttribute('acodec'));
             } elseif ($node->getChild("media")->getAttribute('type') == 'vcard') {
                 $this->eventManager()->fireGetvCard($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('type'), $node->getAttribute('t'), $node->getAttribute('notify'), $node->getChild("media")->getChild("vcard")->getAttribute('name'), $node->getChild("media")->getChild("vcard")->getData());
             } elseif ($node->getChild("media")->getAttribute('type') == 'location') {
                 $url = $node->getChild("media")->getAttribute('url');
                 $name = $node->getChild("media")->getAttribute('name');
                 $this->eventManager()->fireGetLocation($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('type'), $node->getAttribute('t'), $node->getAttribute('notify'), $name, $node->getChild("media")->getAttribute('longitude'), $node->getChild("media")->getAttribute('latitude'), $url, $node->getChild("media")->getData());
             }
             if ($autoReceipt) {
                 $this->sendMessageReceived($node);
             }
         }
         if ($node->getChild('received') != null) {
             $this->eventManager()->fireMessageReceivedClient($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('type'), $node->getAttribute('t'));
         }
     }
     if ($node->getTag() == "presence" && $node->getAttribute("status") == "dirty") {
         //clear dirty
         $categories = array();
         if (count($node->getChildren()) > 0) {
             foreach ($node->getChildren() as $child) {
                 if ($child->getTag() == "category") {
                     $categories[] = $child->getAttribute("name");
                 }
             }
         }
         $this->sendClearDirty($categories);
     }
     if (strcmp($node->getTag(), "presence") == 0 && strncmp($node->getAttribute('from'), $this->phoneNumber, strlen($this->phoneNumber)) != 0 && strpos($node->getAttribute('from'), "-") == false) {
         $presence = array();
         if ($node->getAttribute('type') == null) {
             $this->eventManager()->firePresence($this->phoneNumber, $node->getAttribute('from'), $presence['type'] = "available");
         } else {
             $this->eventManager()->firePresence($this->phoneNumber, $node->getAttribute('from'), $presence['type'] = "unavailable");
         }
     }
     if ($node->getTag() == "presence" && strncmp($node->getAttribute('from'), $this->phoneNumber, strlen($this->phoneNumber)) != 0 && strpos($node->getAttribute('from'), "-") !== false && $node->getAttribute('type') != null) {
         $groupId = self::parseJID($node->getAttribute('from'));
         if ($node->getAttribute('add') != null) {
             $this->eventManager()->fireGroupsParticipantsAdd($this->phoneNumber, $groupId, self::parseJID($node->getAttribute('add')));
         } elseif ($node->getAttribute('remove') != null) {
             $this->eventManager()->fireGroupsParticipantsRemove($this->phoneNumber, $groupId, self::parseJID($node->getAttribute('remove')), self::parseJID($node->getAttribute('author')));
         }
     }
     if (strcmp($node->getTag(), "chatstate") == 0 && strncmp($node->getAttribute('from'), $this->phoneNumber, strlen($this->phoneNumber)) != 0 && strpos($node->getAttribute('from'), "-") == false) {
         if ($node->getChild(0)->getTag() == "composing") {
             $this->eventManager()->fireMessageComposing($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), "composing", $node->getAttribute('t'));
         } else {
             $this->eventManager()->fireMessagePaused($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), "paused", $node->getAttribute('t'));
         }
     }
     if ($node->getTag() == "iq" && $node->getAttribute('type') == "get" && $node->getAttribute('xmlns') == "urn:xmpp:ping") {
         $this->eventManager()->firePing($this->phoneNumber, $node->getAttribute('id'));
         $this->sendPong($node->getAttribute('id'));
     }
     if ($node->getTag() == "iq" && $node->getChild("sync") != null) {
         //sync result
         $sync = $node->getChild('sync');
         $existing = $sync->getChild("in");
         $nonexisting = $sync->getChild("out");
         //process existing first
         $existingUsers = array();
         if (!empty($existing)) {
             foreach ($existing->getChildren() as $child) {
                 $existingUsers[$child->getData()] = $child->getAttribute("jid");
             }
         }
         //now process failed numbers
         $failedNumbers = array();
         if (!empty($nonexisting)) {
             foreach ($nonexisting->getChildren() as $child) {
                 $failedNumbers[] = str_replace('+', '', $child->getData());
             }
         }
         $index = $sync->getAttribute("index");
         $result = new SyncResult($index, $sync->getAttribute("sync"), $existingUsers, $failedNumbers);
         $this->eventManager()->fireGetSyncResult($result);
     }
     if ($node->getTag() == "receipt") {
         $this->eventManager()->fireGetReceipt($node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('offline'), $node->getAttribute('retry'));
     }
     if ($node->getTag() == "iq" && $node->getAttribute('type') == "result") {
         if ($node->getChild("query") != null) {
             if ($node->getChild(0)->getAttribute('xmlns') == 'jabber:iq:privacy') {
                 // ToDo: We need to get explicitly list out the children as arguments
                 //       here.
                 $this->eventManager()->fireGetPrivacyBlockedList($this->phoneNumber, $node->getChild(0)->getChild(0)->getChildren());
             }
             $this->eventManager()->fireGetRequestLastSeen($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getChild(0)->getAttribute('seconds'));
             array_push($this->messageQueue, $node);
         }
         if ($node->getChild("props") != null) {
             //server properties
             $props = array();
             foreach ($node->getChild(0)->getChildren() as $child) {
                 $props[$child->getAttribute("name")] = $child->getAttribute("value");
             }
             $this->eventManager()->fireGetServerProperties($this->phoneNumber, $node->getChild(0)->getAttribute("version"), $props);
         }
         if ($node->getChild("picture") != null) {
             $this->eventManager()->fireGetProfilePicture($this->phoneNumber, $node->getAttribute("from"), $node->getChild("picture")->getAttribute("type"), $node->getChild("picture")->getData());
         }
         if ($node->getChild("media") != null || $node->getChild("duplicate") != null) {
             $this->processUploadResponse($node);
         }
         if ($node->nodeIdContains("group")) {
             //There are multiple types of Group reponses. Also a valid group response can have NO children.
             //Events fired depend on text in the ID field.
             $groupList = array();
             if ($node->getChild(0) != null) {
                 foreach ($node->getChildren() as $child) {
                     $groupList[] = $child->getAttributes();
                 }
             }
             if ($node->nodeIdContains('creategroup')) {
                 $this->groupId = $node->getChild(0)->getAttribute('id');
                 $this->eventManager()->fireGroupsChatCreate($this->phoneNumber, $this->groupId);
             }
             if ($node->nodeIdContains('endgroup')) {
                 $this->groupId = $node->getChild(0)->getChild(0)->getAttribute('id');
                 $this->eventManager()->fireGroupsChatEnd($this->phoneNumber, $this->groupId);
             }
             if ($node->nodeIdContains('getgroups')) {
                 $this->eventManager()->fireGetGroups($this->phoneNumber, $groupList);
             }
             if ($node->nodeIdContains('getgroupinfo')) {
                 $this->eventManager()->fireGetGroupsInfo($this->phoneNumber, $groupList);
             }
             if ($node->nodeIdContains('getgroupparticipants')) {
                 $groupId = self::parseJID($node->getAttribute('from'));
                 $this->eventManager()->fireGetGroupParticipants($this->phoneNumber, $groupId, $groupList);
             }
         }
         if ($node->getChild("status") != null) {
             $child = $node->getChild("status");
             foreach ($child->getChildren() as $status) {
                 $this->eventManager()->fireGetStatus($this->phoneNumber, $status->getAttribute("jid"), "requested", $node->getAttribute("id"), $status->getAttribute("t"), $status->getData());
             }
         }
     }
     if ($node->getTag() == "iq" && $node->getAttribute('type') == "error") {
         $this->eventManager()->fireGetError($this->phoneNumber, $node->getAttribute('id'), $node->getChild(0));
     }
     $children = $node->getChild(0);
     if ($node->getTag() == "stream:error" && empty($children) == false && $node->getChild(0)->getTag() == "system-shutdown") {
         throw new Exception('Error system-shutdown');
     }
     if ($node->getTag() == "notification") {
         $name = $node->getAttribute("notify");
         $type = $node->getAttribute("type");
         switch ($type) {
             case "status":
                 $this->eventManager()->fireGetStatus($this->phoneNumber, $node->getAttribute("from"), $node->getChild(0)->getTag(), $node->getAttribute("id"), $node->getAttribute("t"), $node->getChild(0)->getData());
                 //status message
                 break;
             case "picture":
                 if ($node->hasChild('set')) {
                     $this->eventManager()->fireProfilePictureChanged($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('t'));
                 } else {
                     if ($node->hasChild('delete')) {
                         $this->eventManager()->fireProfilePictureDeleted($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('id'), $node->getAttribute('t'));
                     }
                 }
                 //TODO
                 break;
             case "contacts":
                 //TODO
                 break;
             case "participant":
                 if ($node->hasChild('remove')) {
                     $this->eventManager()->fireGroupsParticipantsRemove($this->phoneNumber, $node->getAttribute('from'), $node->getChild(0)->getAttribute('jid'), $node->getChild(0)->getAttribute('author'));
                 } else {
                     if ($node->hasChild('add')) {
                         $this->eventManager()->fireGroupsParticipantsAdd($this->phoneNumber, $node->getAttribute('from'), $node->getChild(0)->getAttribute('jid'));
                     }
                 }
                 //TODO
                 break;
             case "subject":
                 $this->eventManager()->fireGetGroupsSubject($this->phoneNumber, $node->getAttribute('from'), $node->getAttribute('t'), $node->getAttribute('participant'), $node->getAttribute('participant'), $node->getAttribute('notify'), $node->getChild(0)->getData());
                 //TODO
                 break;
             default:
                 throw new Exception("Method {$type} not implemented");
         }
         $this->sendNotificationAck($node);
     }
     if ($node->getTag() == "ib") {
         foreach ($node->getChildren() as $child) {
             switch ($child->getTag()) {
                 case "dirty":
                     $this->sendClearDirty(array($child->getAttribute("type")));
                     break;
                 case "offline":
                     break;
                 default:
                     throw new Exception("ib handler for " . $child->getTag() . " not implemented");
             }
         }
     }
     if ($node->getTag() == "ack") {
         ////on get ack
     }
 }
 /**
  * Send node to the servers.
  *
  * @param              $to
  * @param ProtocolNode $node
  * @param null         $id
  *
  * @return string            Message ID.
  */
 protected function sendMessageNode($to, $node, $id = null)
 {
     $msgId = $id == null ? $this->createMsgId() : $id;
     $to = $this->getJID($to);
     $messageNode = new ProtocolNode("message", array('to' => $to, 'type' => $node->getTag() == "body" ? 'text' : 'media', 'id' => $msgId, 't' => time()), array($node), "");
     $this->sendNode($messageNode);
     $this->eventManager()->fire("onSendMessage", array($this->phoneNumber, $to, $msgId, $node));
     $this->waitForServer($msgId);
     return $msgId;
 }
Example #4
0
 /**
  * Send node to the servers.
  *
  * @param              $to
  * @param ProtocolNode $node
  * @param null         $id
  *
  * @return string            Message ID.
  */
 protected function sendMessageNode($to, $node, $id = null)
 {
     $msgId = $id == null ? $this->createMsgId() : $id;
     $to = $this->getJID($to);
     if ($node->getTag() == "body" || $node->getTag() == "enc") {
         $type = 'text';
     } else {
         $type = 'media';
     }
     $messageNode = new ProtocolNode("message", array('to' => $to, 'type' => $type, 'id' => $msgId, 't' => time(), 'notify' => $this->name), array($node), "");
     $this->sendNode($messageNode);
     $this->logFile('info', '{type} message with id {id} sent to {to}', array('type' => $type, 'id' => $msgId, 'to' => ExtractNumber($to)));
     $this->eventManager()->fire("onSendMessage", array($this->phoneNumber, $to, $msgId, $node));
     $this->waitForServer($msgId);
     return $msgId;
 }
Example #5
0
 /**
  * Send node to the servers.
  *
  * @param              $to
  * @param ProtocolNode $node
  * @param null         $id
  *
  * @return string Message ID.
  */
 protected function sendMessageNode($to, $node, $id = null, $plaintextNode = null)
 {
     $msgId = $id == null ? $this->createMsgId() : $id;
     $to = $this->getJID($to);
     if ($node->getTag() == 'body' || $node->getTag() == 'enc') {
         $type = 'text';
     } else {
         $type = 'media';
     }
     $messageNode = new ProtocolNode('message', ['to' => $to, 'type' => $type, 'id' => $msgId, 't' => time(), 'notify' => $this->name], [$node], '');
     $this->sendNode($messageNode);
     if ($node->getTag() == 'enc') {
         $node = $plaintextNode;
     }
     $this->logFile('info', '{type} message with id {id} sent to {to}', ['type' => $type, 'id' => $msgId, 'to' => ExtractNumber($to)]);
     $this->eventManager()->fire('onSendMessage', [$this->phoneNumber, $to, $msgId, $node]);
     // $this->waitForServer($msgId);
     return $msgId;
 }
 /**
  * Send node to the servers.
  *
  * @param              $to
  * @param ProtocolNode $node
  * @param null         $id
  * @return null|string
  */
 protected function sendMessageNode($to, $node, $id = null)
 {
     $messageHash = array();
     $messageHash["to"] = $this->getJID($to);
     if ($node->getTag() == "body") {
         $messageHash["type"] = "text";
     } else {
         $messageHash["type"] = "media";
     }
     $messageHash["id"] = $id == null ? $this->createMsgId("message") : $id;
     $messageHash["t"] = time();
     $messageNode = new ProtocolNode("message", $messageHash, array($node), "");
     $this->sendNode($messageNode);
     $this->eventManager()->fire("onSendMessage", array($this->phoneNumber, $this->getJID($to), $messageHash["id"], $node));
     return $messageHash["id"];
 }
Example #7
0
 /**
  * Send node to the servers.
  *
  * @param              $to
  * @param ProtocolNode $node
  * @param null         $id
  *
  * @return string Message ID.
  */
 protected function sendMessageNode($to, $node, $id = null, $plaintextNode = null)
 {
     $msgId = $id == null ? $this->createMsgId() : $id;
     $to = $this->getJID($to);
     if ($node->getTag() == 'body' || $node->getTag() == 'enc') {
         $type = 'text';
     } else {
         $type = 'media';
     }
     $messageNode = new ProtocolNode('message', ['to' => $to, 'type' => $type, 'id' => $msgId, 't' => time(), 'notify' => $this->name], [$node], '');
     $this->sendNode($messageNode);
     if ($node->getTag() == 'enc') {
         $node = $plaintextNode;
     }
     $this->logFile('info', Language::getMessageByKey("MESSAGE_WHATSPORT_WARNING_MESSAGE_SEND", self::FILE_PACK_LANGUAGE, Constants::LANGUAGE, array('TYPE' => $type, 'ID' => $msgId, 'TO' => ExtractNumber($to))));
     $this->eventManager()->fire('onSendMessage', [$this->phoneNumber, $to, $msgId, $node]);
     // $this->waitForServer($msgId);
     return $msgId;
 }