<commit_before><?php
/**
 * LICENSE
 *
 * Copyright © 2016-2017 Teclib'
 * Copyright © 2010-2016 by the FusionInventory Development Team.
 *
 * This file is part of Flyve MDM Plugin for GLPI.
 *
 * Flyve MDM Plugin for GLPI is a subproject of Flyve MDM. Flyve MDM is a mobile
 * device management software.
 *
 * Flyve MDM Plugin for GLPI is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * Flyve MDM Plugin for GLPI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with Flyve MDM Plugin for GLPI. If not, see http://www.gnu.org/licenses/.
 * ------------------------------------------------------------------------------
 * @author    <NAME>
 * @copyright Copyright © 2017 Teclib
 * @license   AGPLv3+ http://www.gnu.org/licenses/agpl.txt
 * @link      https://github.com/flyve-mdm/flyve-mdm-glpi-plugin
 * @link      https://flyve-mdm.com/
 * ------------------------------------------------------------------------------
 */

if (!defined('GLPI_ROOT')) {
   die("Sorry. You can't access this file directly");
}

/**
 * @since 0.1.0
 */
class PluginFlyvemdmMqtthandler extends \sskaje\mqtt\MessageHandler {

   /**
    * @var PluginFlyvemdmMqttlog $log mqtt messages logger
    */
   protected $log;

   /**
    * @var integer $starttime Time when the subscribtion started
    */
   protected $startTime;

   protected $flyveManifestMissing = true;
   protected $publishedVersion = null;
   protected static $instance = null;

   protected function __construct() {
      $this->log = new \PluginFlyvemdmMqttlog();
      $this->startTime = time();
   }

   public static function getInstance() {
      if (self::$instance === null) {
         self::$instance = new static();
      }
      return self::$instance;
   }

   /**
    * Maintains a MQTT topic to publish the current version of the backend
    *
    * @param \sskaje\mqtt\MQTT $mqtt
    */
   protected function publishManifest(\sskaje\mqtt\MQTT $mqtt) {
      // Don't use version from the constant in setup.php because the backend may upgrade while this script is running
      // thus keep in RAM in an older version
      $config = Config::getConfigurationValues('flyvemdm', array('version'));
      $version = $config['version'];

      if ($this->flyveManifestMissing) {
         if (preg_match(\PluginFlyvemdmCommon::SEMVER_VERSION_REGEX, $version) == 1) {
            $mqtt->publish_async("/FlyvemdmManifest/Status/Version", json_encode(['version' => $version]), 0, 1);
            $this->flyveManifestMissing = false;
         }
      }
   }

   /**
    * Handle MQTT Ping response
    * @param sskaje\mqtt\MQTT $mqtt
    * @param sskaje\mqtt\Message\PINGRESP $pingresp_object
    */
   public function pingresp(\sskaje\mqtt\MQTT $mqtt, \sskaje\mqtt\Message\PINGRESP $pingresp_object) {
      global $DB;

      if (time() - $this->startTime > PluginFlyvemdmMqttclient::MQTT_MAXIMUM_DURATION) {
         $mqtt->unsubscribe(array('#'));
      } else {
         // Reconnect to DB to avoid timeouts
         $DB->connect();

         $this->publishManifest($mqtt);
      }
   }

   /**
    * Handle MQTT publish messages
    * @see \sskaje\mqtt\MessageHandler::publish()
    */
   public function publish(\sskaje\mqtt\MQTT $mqtt, \sskaje\mqtt\Message\PUBLISH $publish_object) {
      $topic = $publish_object->getTopic();
      $message = $publish_object->getMessage();
      $this->log->saveIngoingMqttMessage($topic, $message);

      $mqttPath = explode('/', $topic, 5);
      if (isset($mqttPath[4])) {
         if ($mqttPath[4] == "Status/Ping" && $message == "!") {
            $this->updateLastContact($topic, $message);
         } else if ($mqttPath[4] == "Status/Geolocation"  && $message != "?") {
            $this->saveGeolocationPosition($topic, $message);
         } else if ($mqttPath[4] == "Status/Unenroll") {
            $this->deleteAgent($topic, $message);
         } else if ($mqttPath[4] == "Status/Inventory") {
            $this->updateInventory($topic, $message);
         } else if ($mqttPath[4] == "Status/Online") {
            $this->updateOnlineStatus($topic, $message);
         } else if ($mqttPath[4] == "Status/Task") {
            $this->updateTaskStatus($topic, $message);
         } else if ($mqttPath[4] == "FlyvemdmManifest/Status/Version") {
            $this->updateAgentVersion($topic, $message);
         } else if (strpos($topic, "/FlyvemdmManifest") === 0) {
            if ($topic == '/FlyvemdmManifest/Status/Version') {
               $this->publishFlyveManifest();
            }
         }
      }
   }

   /**
    * Update the version of an agent
    * @param string $topic
    * @param string $message
    */
   protected function updateAgentVersion($topic, $message) {
      $agent = new \PluginFlyvemdmAgent();
      if ($agent->getByTopic($topic) !== false) {
         $sanitized = null;
         preg_match("#^[\d.]+$#", $message, $sanitized);
         if (!empty($sanitized[0])) {
            $agent->update([
                  'id'        => $agent->getID(),
                  'version'   => $sanitized[0],
            ]);
         }
      }
   }

   protected function publishFlyveManifest() {
      // Don't use version from the cosntant in setup.php because the backend may upgrade while this script is running
      // thus keep in RAM in an older version
      $config = Config::getConfigurationValues('flyvemdm', 'version');
      $version = $config['version'];

      $matches = null;
      preg_match('/^([\d\.]+)/', $version, $matches);
      if (!isset($matches[1]) || (isset($matches[1]) && $matches[1] != $message)) {
         $this->flyveManifestMissing = true;
         $this->publishManifest($mqtt);
      }
   }

   protected function updateInventory($topic, $message) {
      global $DB;

      $mqttPath = explode('/', $topic);
      $entityId = $mqttPath[1];
      $serial = $DB->escape($mqttPath[3]);
      $computer = new Computer();
      if ($computer->getFromDBByQuery("WHERE `entities_id` = '$entityId' AND `serial` = '$serial'")) {
         $_SESSION["MESSAGE_AFTER_REDIRECT"] = [];
         $inventoryXML = $message;
         $communication = new \PluginFusioninventoryCommunication();
         $communication->handleOCSCommunication('', $inventoryXML, 'glpi');
         if (count($_SESSION["MESSAGE_AFTER_REDIRECT"]) > 0) {
            foreach ($_SESSION["MESSAGE_AFTER_REDIRECT"][0] as $logMessage) {
               $logMessage = "Serial $serial : $logMessage\n";
               \Toolbox::logInFile('plugin_flyvemdm_inventory', $logMessage);
            }
         }

         $this->updateLastContact($topic, $message);
      }
   }

   /**
    * Updates the last contact of the agent
    * @param string $topic
    * @param string $message
    */
   protected function updateLastContact($topic, $message) {
      $agent = new \PluginFlyvemdmAgent();
      if ($agent->getByTopic($topic)) {

         $date = new \DateTime("now", new \DateTimeZone("UTC"));
         $agent->update([
               'id'              => $agent->getID(),<commit_msg>docs(updateLastContact): add description<commit_after><?php
/**
 * LICENSE
 *
 * Copyright © 2016-2017 Teclib'
 * Copyright © 2010-2016 by the FusionInventory Development Team.
 *
 * This file is part of Flyve MDM Plugin for GLPI.
 *
 * Flyve MDM Plugin for GLPI is a subproject of Flyve MDM. Flyve MDM is a mobile
 * device management software.
 *
 * Flyve MDM Plugin for GLPI is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * Flyve MDM Plugin for GLPI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with Flyve MDM Plugin for GLPI. If not, see http://www.gnu.org/licenses/.
 * ------------------------------------------------------------------------------
 * @author    <NAME>
 * @copyright Copyright © 2017 Teclib
 * @license   AGPLv3+ http://www.gnu.org/licenses/agpl.txt
 * @link      https://github.com/flyve-mdm/flyve-mdm-glpi-plugin
 * @link      https://flyve-mdm.com/
 * ------------------------------------------------------------------------------
 */

if (!defined('GLPI_ROOT')) {
   die("Sorry. You can't access this file directly");
}

/**
 * @since 0.1.0
 */
class PluginFlyvemdmMqtthandler extends \sskaje\mqtt\MessageHandler {

   /**
    * @var PluginFlyvemdmMqttlog $log mqtt messages logger
    */
   protected $log;

   /**
    * @var integer $starttime Time when the subscribtion started
    */
   protected $startTime;

   protected $flyveManifestMissing = true;
   protected $publishedVersion = null;
   protected static $instance = null;

   protected function __construct() {
      $this->log = new \PluginFlyvemdmMqttlog();
      $this->startTime = time();
   }

   public static function getInstance() {
      if (self::$instance === null) {
         self::$instance = new static();
      }
      return self::$instance;
   }

   /**
    * Maintains a MQTT topic to publish the current version of the backend
    *
    * @param \sskaje\mqtt\MQTT $mqtt
    */
   protected function publishManifest(\sskaje\mqtt\MQTT $mqtt) {
      // Don't use version from the constant in setup.php because the backend may upgrade while this script is running
      // thus keep in RAM in an older version
      $config = Config::getConfigurationValues('flyvemdm', array('version'));
      $version = $config['version'];

      if ($this->flyveManifestMissing) {
         if (preg_match(\PluginFlyvemdmCommon::SEMVER_VERSION_REGEX, $version) == 1) {
            $mqtt->publish_async("/FlyvemdmManifest/Status/Version", json_encode(['version' => $version]), 0, 1);
            $this->flyveManifestMissing = false;
         }
      }
   }

   /**
    * Handle MQTT Ping response
    * @param sskaje\mqtt\MQTT $mqtt
    * @param sskaje\mqtt\Message\PINGRESP $pingresp_object
    */
   public function pingresp(\sskaje\mqtt\MQTT $mqtt, \sskaje\mqtt\Message\PINGRESP $pingresp_object) {
      global $DB;

      if (time() - $this->startTime > PluginFlyvemdmMqttclient::MQTT_MAXIMUM_DURATION) {
         $mqtt->unsubscribe(array('#'));
      } else {
         // Reconnect to DB to avoid timeouts
         $DB->connect();

         $this->publishManifest($mqtt);
      }
   }

   /**
    * Handle MQTT publish messages
    * @see \sskaje\mqtt\MessageHandler::publish()
    */
   public function publish(\sskaje\mqtt\MQTT $mqtt, \sskaje\mqtt\Message\PUBLISH $publish_object) {
      $topic = $publish_object->getTopic();
      $message = $publish_object->getMessage();
      $this->log->saveIngoingMqttMessage($topic, $message);

      $mqttPath = explode('/', $topic, 5);
      if (isset($mqttPath[4])) {
         if ($mqttPath[4] == "Status/Ping" && $message == "!") {
            $this->updateLastContact($topic, $message);
         } else if ($mqttPath[4] == "Status/Geolocation"  && $message != "?") {
            $this->saveGeolocationPosition($topic, $message);
         } else if ($mqttPath[4] == "Status/Unenroll") {
            $this->deleteAgent($topic, $message);
         } else if ($mqttPath[4] == "Status/Inventory") {
            $this->updateInventory($topic, $message);
         } else if ($mqttPath[4] == "Status/Online") {
            $this->updateOnlineStatus($topic, $message);
         } else if ($mqttPath[4] == "Status/Task") {
            $this->updateTaskStatus($topic, $message);
         } else if ($mqttPath[4] == "FlyvemdmManifest/Status/Version") {
            $this->updateAgentVersion($topic, $message);
         } else if (strpos($topic, "/FlyvemdmManifest") === 0) {
            if ($topic == '/FlyvemdmManifest/Status/Version') {
               $this->publishFlyveManifest();
            }
         }
      }
   }

   /**
    * Update the version of an agent
    * @param string $topic
    * @param string $message
    */
   protected function updateAgentVersion($topic, $message) {
      $agent = new \PluginFlyvemdmAgent();
      if ($agent->getByTopic($topic) !== false) {
         $sanitized = null;
         preg_match("#^[\d.]+$#", $message, $sanitized);
         if (!empty($sanitized[0])) {
            $agent->update([
                  'id'        => $agent->getID(),
                  'version'   => $sanitized[0],
            ]);
         }
      }
   }

   protected function publishFlyveManifest() {
      // Don't use version from the cosntant in setup.php because the backend may upgrade while this script is running
      // thus keep in RAM in an older version
      $config = Config::getConfigurationValues('flyvemdm', 'version');
      $version = $config['version'];

      $matches = null;
      preg_match('/^([\d\.]+)/', $version, $matches);
      if (!isset($matches[1]) || (isset($matches[1]) && $matches[1] != $message)) {
         $this->flyveManifestMissing = true;
         $this->publishManifest($mqtt);
      }
   }

   protected function updateInventory($topic, $message) {
      global $DB;

      $mqttPath = explode('/', $topic);
      $entityId = $mqttPath[1];
      $serial = $DB->escape($mqttPath[3]);
      $computer = new Computer();
      if ($computer->getFromDBByQuery("WHERE `entities_id` = '$entityId' AND `serial` = '$serial'")) {
         $_SESSION["MESSAGE_AFTER_REDIRECT"] = [];
         $inventoryXML = $message;
         $communication = new \PluginFusioninventoryCommunication();
         $communication->handleOCSCommunication('', $inventoryXML, 'glpi');
         if (count($_SESSION["MESSAGE_AFTER_REDIRECT"]) > 0) {
            foreach ($_SESSION["MESSAGE_AFTER_REDIRECT"][0] as $logMessage) {
               $logMessage = "Serial $serial : $logMessage\n";
               \Toolbox::logInFile('plugin_flyvemdm_inventory', $logMessage);
            }
         }

         $this->updateLastContact($topic, $message);
      }
   }

   /**
    * Updates the last contact of the agent
    *
    * The data to update is a datetime
    *
    * @param string $topic
    * @param string $message
    */
   protected function updateLastContact($topic, $message) {
      $agent = new \PluginFlyvemdmAgent();
      if ($agent->getByTopic($topic)) {

         $date = new \DateTime("now", new \DateTimeZone("UTC"));
         $agent->update([
               'id'              => $agent->getID(),
{'fraction_non_alphanumeric': 0.1599627064464571, 'fraction_numerical': 0.006259989344698988, 'mean_word_length': 2.4705338571758726, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 83, 'https://': 4, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1971698', 'n_tokens_mistral': 4590, 'n_tokens_neox': 4431, 'n_words': 1128}