1<?php
2
3/*
4   ------------------------------------------------------------------------
5   FusionInventory
6   Copyright (C) 2010-2016 by the FusionInventory Development Team.
7
8   http://www.fusioninventory.org/   http://forge.fusioninventory.org/
9   ------------------------------------------------------------------------
10
11   LICENSE
12
13   This file is part of FusionInventory project.
14
15   FusionInventory is free software: you can redistribute it and/or modify
16   it under the terms of the GNU Affero General Public License as published by
17   the Free Software Foundation, either version 3 of the License, or
18   (at your option) any later version.
19
20   FusionInventory is distributed in the hope that it will be useful,
21   but WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23   GNU Affero General Public License for more details.
24
25   You should have received a copy of the GNU Affero General Public License
26   along with FusionInventory. If not, see <http://www.gnu.org/licenses/>.
27
28   ------------------------------------------------------------------------
29
30   @package   FusionInventory
31   @author    David Durieux
32   @co-author
33   @copyright Copyright (c) 2010-2016 FusionInventory team
34   @license   AGPL License 3.0 or (at your option) any later version
35              http://www.gnu.org/licenses/agpl-3.0-standalone.html
36   @link      http://www.fusioninventory.org/
37   @link      http://forge.fusioninventory.org/projects/fusioninventory-for-glpi/
38   @since     2010
39
40   ------------------------------------------------------------------------
41 */
42
43if (!defined('GLPI_ROOT')) {
44   die("Sorry. You can't access directly to this file");
45}
46
47class PluginFusioninventoryAgent extends CommonDBTM {
48
49   public $dohistory = TRUE;
50
51   static $rightname = 'plugin_fusioninventory_agent';
52
53   /**
54   * Get name of this type
55   *
56   * @return text name of this type by language of the user connected
57   *
58   **/
59   static function getTypeName($nb=0) {
60      return __('Agent', 'fusioninventory');
61   }
62
63
64
65   function getSearchOptions() {
66
67      $tab = array();
68
69      $tab['common'] = __('Agent', 'fusioninventory');
70
71      $tab[1]['table']     = $this->getTable();
72      $tab[1]['field']     = 'name';
73      $tab[1]['linkfield'] = 'name';
74      $tab[1]['name']      = __('Name');
75      $tab[1]['datatype']  = 'itemlink';
76
77      $tab[2]['table']     = 'glpi_entities';
78      $tab[2]['field']     = 'completename';
79      $tab[2]['name']      = __('Entity');
80      $tab[2]['datatype'] = 'dropdown';
81
82      $tab[3]['table']     = $this->getTable();
83      $tab[3]['field']     = 'is_recursive';
84      $tab[3]['linkfield'] = 'is_recursive';
85      $tab[3]['name']      = __('Child entities');
86      $tab[3]['datatype']  = 'bool';
87
88      $tab[4]['table']     = $this->getTable();
89      $tab[4]['field']     = 'last_contact';
90      $tab[4]['linkfield'] = '';
91      $tab[4]['name']      = __('Last contact', 'fusioninventory');
92      $tab[4]['datatype']  = 'datetime';
93
94      $tab[5]['table']     = $this->getTable();
95      $tab[5]['field']     = 'lock';
96      $tab[5]['linkfield'] = 'lock';
97      $tab[5]['name']      = __('locked', 'fusioninventory');
98      $tab[5]['datatype']  = 'bool';
99
100      $tab[6]['table']     = $this->getTable();
101      $tab[6]['field']     = 'device_id';
102      $tab[6]['linkfield'] = 'device_id';
103      $tab[6]['name']      = __('Device_id', 'fusioninventory');
104      $tab[6]['datatype']  = 'text';
105      $tab[6]['massiveaction'] = FALSE;
106
107      $tab[7]['table']         = 'glpi_computers';
108      $tab[7]['field']         = 'name';
109      $tab[7]['name']          = __('Computer link', 'fusioninventory');
110      $tab[7]['datatype']      = 'itemlink';
111      $tab[7]['itemlink_type'] = 'Computer';
112      $tab[7]['massiveaction'] = FALSE;
113
114      $tab[8]['table']     = $this->getTable();
115      $tab[8]['field']     = 'version';
116      $tab[8]['linkfield'] = 'version';
117      $tab[8]['name']      = __('Version');
118      $tab[8]['datatype']  = 'text';
119      $tab[8]['massiveaction'] = FALSE;
120
121      $tab[9]['table']     = $this->getTable();
122      $tab[9]['field']     = 'token';
123      $tab[9]['linkfield'] = 'token';
124      $tab[9]['name']      = __('Token');
125      $tab[9]['datatype']  = 'text';
126      $tab[9]['massiveaction'] = FALSE;
127
128      $tab[10]['table']     = $this->getTable();
129      $tab[10]['field']     = 'useragent';
130      $tab[10]['linkfield'] = 'useragent';
131      $tab[10]['name']      = __('Useragent', 'fusioninventory');
132      $tab[10]['datatype']  = 'text';
133      $tab[10]['massiveaction'] = FALSE;
134
135      $tab[11]['table']     = $this->getTable();
136      $tab[11]['field']     = 'tag';
137      $tab[11]['name']      = __('FusionInventory tag', 'fusioninventory');
138      $tab[11]['datatype']  = 'text';
139      $tab[11]['massiveaction'] = FALSE;
140
141      $tab[12]['table']     = $this->getTable();
142      $tab[12]['field']     = 'threads_networkdiscovery';
143      $tab[12]['name']      = __('Threads number', 'fusioninventory')."&nbsp;(".
144                                 strtolower(__('Network discovery', 'fusioninventory')).
145                                 ")";
146      $tab[12]['datatype']  = 'integer';
147
148      $tab[13]['table']     = $this->getTable();
149      $tab[13]['field']     = 'threads_networkinventory';
150      $tab[13]['name']      = __('Threads number', 'fusioninventory')."&nbsp;(".
151                                 strtolower(__('Network inventory (SNMP)', 'fusioninventory')).
152                                 ")";
153      $tab[13]['datatype']  = 'integer';
154
155      $tab[14]['table']     = $this->getTable();
156      $tab[14]['field']     = 'agent_port';
157      $tab[14]['linkfield'] = 'agent_port';
158      $tab[14]['name']      = __('Agent port', 'fusioninventory');
159
160      $i = 20;
161      $pfAgentmodule = new PluginFusioninventoryAgentmodule();
162      $a_modules = $pfAgentmodule->find();
163      foreach ($a_modules as $data) {
164         $tab[$i]['table']         = $pfAgentmodule->getTable();
165         $tab[$i]['field']         = $data["modulename"];
166         $tab[$i]['linkfield']     = $data["modulename"];
167         $tab[$i]['name']          = __('Module', 'fusioninventory')." - ".$data["modulename"];
168         $tab[$i]['datatype']      = 'bool';
169         $tab[$i]['massiveaction'] = FALSE;
170         $i++;
171      }
172      return $tab;
173   }
174
175
176
177   function defineTabs($options=array()){
178
179      $ong = array();
180      $this->addDefaultFormTab($ong);
181      $this->addStandardTab('PluginFusioninventoryAgentmodule', $ong, $options);
182      $this->addStandardTab('Log', $ong, $options);
183
184      return $ong;
185   }
186
187   function getTabNameForItem(CommonGLPI $item, $withtemplate=0) {
188      global $CFG_GLPI;
189      $tab_names = array();
190      if ( $this->can(0, CREATE) ) {
191         if ($item->getType() == 'Computer') {
192            $tab_names[] = __('FusInv', 'fusioninventory').' '. __('Agent');
193         }
194
195      }
196
197      if (!empty($tab_names)) {
198         return $tab_names;
199      } else {
200         return '';
201      }
202   }
203
204   static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0) {
205
206      if ($item->getType() == 'Computer') {
207
208         // Possibility to remote agent
209         if (PluginFusioninventoryToolbox::isAllowurlfopen(1)) {
210            $pfAgent = new PluginFusioninventoryAgent();
211            if ($pfAgent->getAgentWithComputerid($item->fields['id'])) {
212               $pfAgent->showRemoteStatus($item);
213            }
214         }
215      }
216   }
217
218   /**
219    * Display personalized comments (in tooltip) of item
220    */
221   function getComments() {
222
223      $comment = __('Useragent', 'fusioninventory').' : '.$this->fields['useragent'].'<br/>'.
224         __('Last contact', 'fusioninventory').' : '.
225         Html::convDateTime($this->fields['last_contact']).' minutes';
226
227      if (!empty($comment)) {
228         return Html::showToolTip($comment, array('display' => FALSE));
229      }
230      return $comment;
231   }
232
233
234
235   /**
236    * Massive action ()
237    */
238   function getSpecificMassiveActions($checkitem=NULL) {
239
240      $actions = array();
241      if (Session::haveRight("plugin_fusioninventory_agent", UPDATE)) {
242         $pfAgentmodule = new PluginFusioninventoryAgentmodule();
243         $a_modules = $pfAgentmodule->find();
244         foreach ($a_modules as $data) {
245            $actions[__CLASS__.MassiveAction::CLASS_ACTION_SEPARATOR.$data["modulename"]] =
246                     __('Module', 'fusioninventory')." - ".$data['modulename'];
247         }
248         $actions[__CLASS__.MassiveAction::CLASS_ACTION_SEPARATOR.'transfert'] = __('Transfer');
249      }
250
251      return $actions;
252   }
253
254
255
256   /**
257    * @since version 0.85
258    *
259    * @see CommonDBTM::showMassiveActionsSubForm()
260   **/
261   static function showMassiveActionsSubForm(MassiveAction $ma) {
262
263      switch ($ma->getAction()) {
264         case 'transfert' :
265            Dropdown::show('Entity');
266            echo "<br><br>".Html::submit(__('Post'),
267                                         array('name' => 'massiveaction'));
268            return true;
269
270      }
271      $pfAgentmodule = new PluginFusioninventoryAgentmodule();
272      $a_modules = $pfAgentmodule->find();
273      foreach ($a_modules as $data) {
274         if ($ma->getAction() == $data['modulename']) {
275            Dropdown::showYesNo($ma->getAction());
276            echo "<br><br>".Html::submit(__('Post'),
277                                         array('name' => 'massiveaction'));
278            return true;
279         }
280      }
281      return parent::showMassiveActionsSubForm($ma);
282   }
283
284
285
286   static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBTM $item,
287                                                       array $ids) {
288
289      $pfAgent = new self();
290
291      switch ($ma->getAction()) {
292
293         case 'transfert' :
294            foreach ($ids as $key) {
295               if ($pfAgent->getFromDB($key)) {
296                  $input = array();
297                  $input['id'] = $key;
298                  $input['entities_id'] = $_POST['entities_id'];
299                  if ($pfAgent->update($input)) {
300                     //set action massive ok for this item
301                     $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK);
302                  } else {
303                     // KO
304                     $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO);
305                  }
306               }
307            }
308            return;
309            break;
310      }
311
312      $pfAgentmodule = new PluginFusioninventoryAgentmodule();
313      $a_modules = $pfAgentmodule->find();
314      foreach ($a_modules as $data2) {
315         if ($ma->getAction() == $data2['modulename']) {
316            foreach ($ids as $key) {
317               if ($ma->POST[$data2['modulename']] == $data2['is_active']) {
318                  // Remove from exceptions
319                  $a_exceptions = importArrayFromDB($data2['exceptions']);
320                  if (in_array($key, $a_exceptions)) {
321                     foreach ($a_exceptions as $key2=>$value2) {
322                        if ($value2 == $key) {
323                           unset($a_exceptions[$key2]);
324                        }
325                     }
326                  }
327                  $data2['exceptions'] = exportArrayToDB($a_exceptions);
328               } else {
329                  // Add to exceptions
330                  $a_exceptions = importArrayFromDB($data2['exceptions']);
331                  if (!in_array($key, $a_exceptions)) {
332                     $a_exceptions[] = (string)$key;
333                  }
334                  $data2['exceptions'] = exportArrayToDB($a_exceptions);
335               }
336               $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK);
337            }
338            $pfAgentmodule->update($data2);
339         }
340      }
341
342      return;
343   }
344
345
346
347   /**
348   * Display form for agent configuration
349   *
350   * @param $computers_id integer ID of the agent
351   * @param $options array
352   *
353   * @return bool TRUE if form is ok
354   *
355   **/
356   function showForm($computers_id, $options=array()) {
357
358
359      if ($computers_id!='') {
360         $this->getFromDB($computers_id);
361      } else {
362         $this->getEmpty();
363         $pfConfig = new PluginFusioninventoryConfig();
364         unset($this->fields['id']);
365         $this->fields['threads_networkdiscovery'] =
366                 $pfConfig->getValue('threads_networkdiscovery');
367         $this->fields['timeout_networkdiscovery'] =
368                 $pfConfig->getValue('timeout_networkdiscovery');
369         $this->fields['threads_networkinventory'] =
370                 $pfConfig->getValue('threads_networkinventory');
371         $this->fields['timeout_networkinventory'] =
372                 $pfConfig->getValue('timeout_networkinventory');
373         $this->fields['senddico'] = 0;
374      }
375      $this->initForm($computers_id, $options);
376      $this->showFormHeader($options);
377
378      echo "<tr class='tab_bg_1'>";
379      echo "<td>".__('Name')." :</td>";
380      echo "<td align='center'>";
381      Html::autocompletionTextField($this,'name', array('size' => 40));
382      echo "</td>";
383      echo "<td>".__('Device_id', 'fusioninventory')."&nbsp;:</td>";
384      echo "<td align='center'>";
385      echo $this->fields["device_id"];
386      echo "</td>";
387      echo "</tr>";
388
389      echo "<tr class='tab_bg_1'>";
390      echo "<td>".__('Computer link', 'fusioninventory')."&nbsp:</td>";
391      echo "<td align='center'>";
392      if (!empty($this->fields["computers_id"])) {
393         $oComputer = new Computer();
394         $oComputer->getFromDB($this->fields["computers_id"]);
395         echo $oComputer->getLink(1);
396         echo Html::hidden('computers_id',
397                           array('value' => $this->fields["computers_id"]));
398      } else {
399         Computer_Item::dropdownConnect("Computer", "Computer", 'computers_id',
400                                        $_SESSION['glpiactive_entity']);
401      }
402      echo "</td>";
403      echo "<td>".__('Token')."&nbsp:</td>";
404      echo "<td align='center'>";
405      echo $this->fields["token"];
406      echo "</td>";
407      echo "</tr>";
408
409      echo "<tr class='tab_bg_1'>";
410      echo "<td>".__('locked', 'fusioninventory')."&nbsp:</td>";
411      echo "<td align='center'>";
412      Dropdown::showYesNo('lock', $this->fields["lock"]);
413      echo "</td>";
414      echo "<td>".__('Version')."&nbsp:</td>";
415      echo "<td align='center'>";
416      $a_versions = importArrayFromDB($this->fields["version"]);
417      foreach ($a_versions as $module => $version) {
418         echo "<strong>".$module. "</strong>: ".$version."<br/>";
419      }
420      echo "</td>";
421      echo "</tr>";
422
423      echo "<tr class='tab_bg_1'>";
424      echo "<td>".__('Threads number', 'fusioninventory')."&nbsp;".
425              "(".strtolower(__('Network discovery', 'fusioninventory')).")&nbsp;:</td>";
426      echo "<td align='center'>";
427      Dropdown::showNumber("threads_networkdiscovery", array(
428             'value' => $this->fields["threads_networkdiscovery"],
429             'min' => 1,
430             'max' => 400)
431         );
432
433      echo "</td>";
434      echo "<td>".__('Useragent', 'fusioninventory')."&nbsp:</td>";
435      echo "<td align='center'>";
436      echo $this->fields["useragent"];
437      echo "</td>";
438      echo "</tr>";
439
440      echo "<tr class='tab_bg_1'>";
441      echo "<td>".__('SNMP timeout', 'fusioninventory')."&nbsp;".
442              "(".strtolower(__('Network discovery', 'fusioninventory')).")&nbsp;:</td>";
443      echo "<td align='center'>";
444      Dropdown::showNumber("timeout_networkdiscovery", array(
445             'value' => $this->fields["timeout_networkdiscovery"],
446             'min' => 0,
447             'max' => 60)
448         );
449      echo "</td>";
450      echo "<td>".__('Last contact', 'fusioninventory')."&nbsp:</td>";
451      echo "<td align='center'>";
452      echo Html::convDateTime($this->fields["last_contact"]);
453      echo "</td>";
454      echo "</tr>";
455
456
457      echo "<tr class='tab_bg_1'>";
458      echo "<td>".__('Threads number', 'fusioninventory')."&nbsp;".
459              "(".strtolower(__('Network inventory (SNMP)', 'fusioninventory')).")&nbsp;:</td>";
460      echo "<td align='center'>";
461      Dropdown::showNumber("threads_networkinventory", array(
462             'value' => $this->fields["threads_networkinventory"],
463             'min' => 1,
464             'max' => 400)
465      );
466      echo "</td>";
467      echo "<td>".__('FusionInventory tag', 'fusioninventory')."&nbsp:</td>";
468      echo "<td align='center'>";
469      echo $this->fields["tag"];
470      echo "</td>";
471      echo "</tr>";
472
473      echo "<td>".__('SNMP timeout', 'fusioninventory')."&nbsp;".
474              "(".strtolower(__('Network inventory (SNMP)', 'fusioninventory')).")&nbsp;:</td>";
475      echo "<td align='center'>";
476      Dropdown::showNumber("timeout_networkinventory", array(
477             'value' => $this->fields["timeout_networkinventory"],
478             'min' => 0,
479             'max' => 60)
480      );
481      echo "</td>";
482      echo "<td colspan='2'>";
483      echo "</td>";
484      echo "</tr>";
485
486      echo "<tr class='tab_bg_1'>";
487      $pfConfig = new PluginFusioninventoryConfig();
488      echo "<td>".__('Agent port', 'fusioninventory')." (".
489              __('if empty use port configured in general options', 'fusioninventory')
490              ." <i>".$pfConfig->getValue('agent_port')."</i>)&nbsp:</td>";
491      echo "<td align='center'>";
492      echo "<input type='text' name='agent_port' value='".$this->fields['agent_port']."'/>";
493      echo "</td>";
494      echo "<td colspan='2'>";
495      echo "</td>";
496      echo "</tr>";
497
498      $this->showFormButtons($options);
499
500      return TRUE;
501   }
502
503
504
505   /**
506   * Get agent informations by device_id
507   *
508   * @param $device_id value device_id unique of agent (key)
509   *
510   * @return array all DB fields of this agent
511   *
512   **/
513   function InfosByKey($device_id) {
514      global $DB;
515
516      $query = "SELECT * FROM `".$this->getTable()."`
517         WHERE `device_id`='".$device_id."' LIMIT 1";
518
519      $agent = array();
520      $result = $DB->query($query);
521      if ($result) {
522         if ($DB->numrows($result) != 0) {
523            $agent = $DB->fetch_assoc($result);
524         }
525      }
526      return $agent;
527   }
528
529
530
531   /**
532   * Import agent : create if not exist and update if yet exist
533   *
534   * @param $p_xml simpleXMLobject
535   *
536   **/
537   function importToken($arrayinventory) {
538
539      if (isset($arrayinventory['DEVICEID'])) {
540         $pfAgent = new PluginFusioninventoryAgent();
541         $a_agent = $pfAgent->find("`device_id`='".$arrayinventory['DEVICEID']."'", "", "1");
542         if (empty($a_agent)) {
543            $a_input = array();
544            if (isset($arrayinventory['TOKEN'])) {
545               $a_input['token'] = $arrayinventory['TOKEN'];
546            }
547            $a_input['name']         = $arrayinventory['DEVICEID'];
548            $a_input['device_id']    = $arrayinventory['DEVICEID'];
549            $a_input['entities_id']  = 0;
550            $a_input['last_contact'] = date("Y-m-d H:i:s");
551            if (isset($_SERVER['HTTP_USER_AGENT'])) {
552               $a_input['useragent'] = $_SERVER['HTTP_USER_AGENT'];
553            }
554            return $pfAgent->add($a_input);
555         } else {
556            foreach ($a_agent as $data) {
557               $input = array();
558               $input['id'] = $data['id'];
559               if (isset($arrayinventory['TOKEN'])) {
560                  $input['token'] = $arrayinventory['TOKEN'];
561               }
562               $input['last_contact'] = date("Y-m-d H:i:s");
563               if (isset($_SERVER['HTTP_USER_AGENT'])) {
564                  $input['useragent'] = $_SERVER['HTTP_USER_AGENT'];
565               }
566               $pfAgent->update($input);
567               return $data['id'];
568            }
569         }
570      }
571      return;
572   }
573
574
575
576   /**
577   * Get all IP of an agent or a computer
578   *
579   * @param $items_id integer ID of the item
580   * @param $type 'Agent' by default to get IP of agent or of a computer if set other text
581   *
582   * @return Every IP addresses registered for this agent or false
583   *
584   **/
585   function getIPs() {
586      $ip_addresses = array();
587
588      $computers_id = 0;
589
590      if (isset($this->fields['computers_id']) ) {
591         if ( $this->fields['computers_id'] > 0 ) {
592         }
593      } else {
594         trigger_error('Agent must be initialized');
595      }
596
597      $ip_addresses = PluginFusioninventoryToolbox::getIPforDevice('Computer', $this->fields['computers_id']);
598
599      return $ip_addresses;
600   }
601
602
603
604   /**
605   * Get agent id of a computer
606   *
607   * @param $computers_id integer ID of the computer
608   *
609   * @return agent id or False
610   *
611   **/
612   function getAgentWithComputerid($computers_id) {
613
614      $agent = $this->find("`computers_id`='".$computers_id."'", "", 1);
615
616      if (count($agent) == '1') {
617         $data = current($agent);
618         $this->getFromDB($data['id']);
619         return $data['id'];
620      }
621      return FALSE;
622   }
623
624   /**
625   * Get agent id of a computer
626   *
627   * @param $computers_id integer ID of the computer
628   *
629   * @return agent id or False
630   *
631   **/
632   function getAgentsFromComputers($computer_ids = array()) {
633
634      if (count($computer_ids) == 0) {
635         return array();
636      }
637
638      $computer_ids = "'" . implode("','", $computer_ids) . "'";
639
640      $agents = $this->find("`computers_id` in (".$computer_ids.")", "");
641
642      return $agents;
643   }
644
645   /**
646   * Get Computer associated with this agent
647   *
648   * @return A Computer object or False
649   *
650   **/
651
652   function getAssociatedComputer() {
653
654      $computer = new Computer();
655
656      if (!isset($this->fields['id'])) {
657         trigger_error("Agent must be initialized!");
658         return false;
659      }
660
661      $computer->getFromDB($this->fields['computers_id']);
662      return $computer;
663   }
664
665
666   /**
667   * Create links between agent and computer.
668   *
669   * @param $computers_id integer ID of the computer
670   * @param $device_id value of device_id from XML to identify agent
671   * @param $entities_id integer ID of the computer entity
672   *
673   * @return Nothing
674   *
675   **/
676   function setAgentWithComputerid($computers_id, $device_id, $entities_id) {
677
678      $a_agent = $this->find("`computers_id`='".$computers_id."'", "", 1);
679      // Is this computer already linked to an agent?
680      $agent = array_shift($a_agent);
681      if (is_array($agent)) {
682
683         // relation
684         if ($agent['device_id'] != $device_id
685                 || $agent['entities_id'] != $entities_id) {
686            $input = array();
687            $input['id'] = $agent['id'];
688            $input['device_id'] = $device_id;
689            $input['entities_id'] = $entities_id;
690            $this->update($input);
691         }
692
693//         // Clean up the agent list
694//         $oldAgent_deviceids = $this->find(
695//            // computer linked to the wrong agent
696//            "(`computers_id`='".$computers_id."' AND `device_id` <> '".$device_id."')");
697//         foreach ($oldAgent_deviceids as $oldAgent) {
698//            $this->delete($oldAgent);
699//         }
700         $oldAgents = $this->find(
701            // the same device_id but linked on the wrong computer
702            "(`device_id`='".$device_id."' AND `computers_id`<>'".$computers_id."')");
703         foreach ($oldAgents as $oldAgent) {
704            $input = array();
705            $input['id']            = $agent['id'];
706            $input['last_contact']  = $oldAgent['last_contact'];
707            $input['version']       = $oldAgent['version'];
708            $input['name']          = $oldAgent['name'];
709            $input['useragent']     = $oldAgent['useragent'];
710            $input['token']         = $oldAgent['token'];
711            $input['tag']           = $oldAgent['tag'];
712            $input['entities_id']   = $entities_id;
713            $this->update($input);
714            $this->delete($oldAgent);
715         }
716         return TRUE;
717      } else { # This is a new computer
718         // Link agent with computer
719         $agent = $this->InfosByKey($device_id);
720         if (isset($agent['id'])) {
721             $agent['computers_id'] = $computers_id;
722             $agent['entities_id']  = $entities_id;
723             $this->update($agent);
724             return TRUE;
725         }
726      }
727      return FALSE;
728   }
729
730
731
732   /**
733   * Display if agent is online
734   *
735   * @return Nothing (display)
736   *
737   **/
738   function showRemoteStatus($computer = null) {
739      global $CFG_GLPI;
740
741      /**
742       * Check for initialized agent
743       */
744      if (!isset($this->fields['id'])) {
745         return;
746      }
747
748      /**
749       * Check for initialized $computer
750       */
751      if ( is_null($computer) && !isset($computer->fields['id']) ) {
752         return;
753      }
754
755      $agent_id = $this->fields['id'];
756
757      $pfTaskjob = new PluginFusioninventoryTaskjob();
758
759      echo "<form method='post' name='' id=''  action=\"".$CFG_GLPI['root_doc'] .
760         "/plugins/fusioninventory/front/agent.form.php\">";
761      echo "<table class='tab_cadre' width='500'>";
762
763      echo "<tr>";
764      echo "<th colspan='2'>";
765      echo __('Agent state', 'fusioninventory');
766      echo "</th>";
767      echo "</tr>";
768
769      echo "<tr class='tab_bg_1'>";
770      echo "<td>";
771      echo __('Agent', 'fusioninventory')."&nbsp:";
772      echo "</td>";
773      echo "<td>";
774      echo $this->getLink(1);
775      echo "</td>";
776      echo "</tr>";
777
778      echo "<tr class='tab_bg_1'>";
779      echo "<td>";
780      echo __('Status')."&nbsp;:";
781      echo "</td>";
782      echo "<td>";
783
784      $waiting = 0;
785
786      $agentStatus = $this->getStatus();
787
788      switch($agentStatus['message']) {
789
790         case 'executing scheduled tasks':
791         case 'running':
792            echo __('Running');
793            break;
794
795         case 'noanswer':
796            echo __('Impossible to communicate with agent!', 'fusioninventory');
797            break;
798
799         case 'waiting':
800            $waiting = 1;
801            echo __(
802               'Available on <a target="_blank" href="'. $agentStatus['url_ok'] . '">' .
803               $agentStatus['url_ok'] .
804               '</a>'
805            );
806            echo Html::hidden('agent_id', array('value' => $agent_id));
807            break;
808
809         default:
810            if (strstr($agentStatus['message'], 'running')) {
811               echo $agentStatus['message'];
812            } else {
813               echo "SELinux problem, do 'setsebool -P httpd_can_network_connect on'";
814            }
815            break;
816
817      }
818
819      echo "</td>";
820      echo "</tr>";
821
822      if ($waiting == '1') {
823         echo "<tr>";
824         echo "<th colspan='2'>";
825         echo "<input name='startagent' value=\"".__('Force inventory', 'fusioninventory').
826            "\" class='submit' type='submit'>";
827         echo "</th>";
828         echo "</tr>";
829      }
830
831      echo "</table>";
832      Html::closeForm();
833      echo "<br/>";
834   }
835
836   /**
837    * Get current state of the agent
838    *
839    * @param $items_id integer id of the agent
840    *
841    * @return string message/state of the agent
842    *
843    */
844   function getStatus() {
845
846      $url_addresses = $this->getAgentStatusURLs();
847
848      $this->disableDebug();
849
850      ob_start();
851      ini_set("allow_url_fopen", "1");
852
853      $ctx = stream_context_create(array(
854         'http' => array(
855            'timeout' => 1
856            )
857         )
858      );
859
860      $contents="";
861      $url_ok = null;
862      $url_headers=array();
863      foreach( $url_addresses as $url) {
864         if ( $stream = fopen($url, 'r', false, $ctx) ) {
865            //$result = file_get_contents($url, FALSE, $ctx);
866            $contents = stream_get_contents($stream);
867            $url_headers[$url] = stream_get_meta_data($stream);
868            fclose($stream);
869            if ($contents !== false) {
870               $url_ok = $url;
871               break;
872            }
873         }
874      }
875      $error = ob_get_contents();
876      ob_end_clean();
877      $this->restoreDebug();
878
879      $status = array(
880         "url_ok" => $url_ok,
881         "message" => ""
882      );
883
884      if ($contents !== "") {
885         $status['message'] = preg_replace("/^status: /", "", $contents);
886      }
887
888      if ($contents == '' AND !strstr($error, "failed to open stream: Permission denied")) {
889         $status['message'] = "noanswer";
890      }
891
892      return $status;
893   }
894
895
896   /**
897   * Start agent remotly from server
898   *
899   * @param $agent_id integer id of the agent
900   *
901   * @return bool TRUE if agent wake up
902   *
903   **/
904   function wakeUp() {
905
906      $ret = FALSE;
907
908      $this->disableDebug();
909      $urls = $this->getAgentRunURLs();
910
911      $ctx = stream_context_create(array('http' => array('timeout' => 2)));
912      foreach ( $urls as $url ) {
913         if (!$ret) {
914            if (@file_get_contents($url, 0, $ctx) !== FALSE) {
915               $ret = TRUE;
916               break;
917            }
918         }
919      }
920      $this->restoreDebug();
921
922      return $ret;
923   }
924
925   /**
926   * Get state of agent
927   *
928   * @param $ip value IP address of the computer where agent is installed
929   * @param $agentid integer id of the agent
930   *
931   * @return bool TRUE if agent is ready else FALSE
932   *
933   **/
934   function isAgentAlive() {
935
936      if ( $this->getStatus() === 'waiting') {
937         return true;
938      }
939
940      return false;
941   }
942
943
944   /**
945   * Disable debug mode because we don't want the errors
946   *
947   **/
948   function disableDebug() {
949      error_reporting(0);
950      set_error_handler(array($this, 'errorempty'));
951   }
952
953   /**
954   * When debug is disabled, we transfer every errors in this emtpy function.
955   *
956   **/
957   static function errorempty() {}
958
959   /**
960   * Resotre debug mode if it has been explicitely set by the user in his settings.
961   *
962   **/
963   function restoreDebug() {
964      if ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE){
965         ini_set('display_errors', 'On');
966         // Recommended development settings
967         error_reporting(E_ALL | E_STRICT);
968         set_error_handler(array('Toolbox', 'userErrorHandlerDebug'));
969      } else {
970         ini_set('display_errors', 'Off');
971         error_reporting(E_ALL);
972         set_error_handler(array('Toolbox', 'userErrorHandlerNormal'));
973      }
974
975   }
976
977   /**
978   * Set agent version of each module
979   *
980   * @param $agent_id integer ID of the agent
981   * @param $module value Module name (WAKEONLAN, NETWORKDISCOVERY, INVENTORY, NETWORKINVENTORY...)
982   * @param $version value version of the module
983   *
984   * @return nothing
985   *
986   **/
987   function setAgentVersions($agent_id, $module, $version) {
988      $this->getFromDB($agent_id);
989      $a_version = importArrayFromDB($this->fields['version']);
990      if (!is_array($a_version)) {
991         $versionTmp             = $a_version;
992         $a_version              = array();
993         $a_version["INVENTORY"] = $versionTmp;
994      }
995      $a_version[$module] = $version;
996      $input = array();
997      $input['id'] = $this->fields['id'];
998      $input['version'] = exportArrayToDB($a_version);
999      $this->update($input);
1000   }
1001
1002
1003
1004   /**
1005    * Get agent version
1006    *
1007    * @param type $agent_id
1008    */
1009   function getAgentVersion($agent_id) {
1010      $this->getFromDB($agent_id);
1011      $a_version = importArrayFromDB($this->fields['version']);
1012      if (isset($a_version['INVENTORY'])) {
1013         return str_replace('v', '', $a_version['INVENTORY']);
1014      }
1015      return '0';
1016   }
1017
1018
1019
1020   /**
1021    * Return an agent by it deviceid
1022    *
1023    * @param device_id the device_id coming from the agent itself
1024    *
1025    * @return an array with the agent's attributes or an empty array if no agent found
1026    */
1027   static function getByDeviceID($device_id) {
1028      $agents =  getAllDatasFromTable('glpi_plugin_fusioninventory_agents',
1029                                      "`device_id`='$device_id' AND `lock`='0'");
1030      if (!empty($agents)) {
1031         return array_pop($agents);
1032      } else {
1033         return FALSE;
1034      }
1035   }
1036
1037
1038
1039   /**
1040    * Get base URL to communicate with an agent
1041    *
1042    * @param ip agent's IP
1043    *
1044    * @return a list of http url to contact the agent
1045    */
1046   public function getAgentBaseURLs() {
1047      $config  = new PluginFusioninventoryConfig();
1048
1049      $port = $config->getValue('agent_port');
1050      $url_addresses = array();
1051
1052
1053      if ( isset($this->fields['id']) ) {
1054         $computer = $this->getAssociatedComputer();
1055         if ($this->fields['agent_port'] != ''
1056                 && is_numeric($this->fields['agent_port'])) {
1057            $port = $this->fields['agent_port'];
1058         }
1059         if ($computer->fields["name"] && $computer->fields["name"] != "localhost") {
1060            array_push($url_addresses, "http://".$computer->fields["name"].
1061               ":".$port);
1062
1063            $domain = new Domain();
1064            if ($computer->fields['domains_id'] != 0) {
1065               $domain->getFromDB($computer->fields['domains_id']);
1066               array_push($url_addresses, "http://".
1067                  $computer->fields["name"].'.'.
1068                  $domain->fields["name"].
1069                  ":".$port);
1070            }
1071         }
1072      }
1073
1074      # Guess the machine name from the DEVICEID,
1075      # useful when Windows domain != DNS domain
1076      $stack = array();
1077      if(preg_match('/(\S+)-\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}$/',
1078                    $this->fields['name'],
1079                    $stack)) {
1080         array_push($url_addresses, "http://".$stack[1].":".$port);
1081      }
1082
1083      $ip_addresses = $this->getIPs();
1084      foreach ($ip_addresses as $ip_address) {
1085         if ($ip_address != '') {
1086            array_push($url_addresses, "http://".$ip_address.":".$port);
1087         }
1088      }
1089      return $url_addresses;
1090   }
1091
1092
1093
1094   /**
1095    * URL to get agent's state
1096    *
1097    * @param ip agent's IP
1098    *
1099    * @return an array of http url to get the agent's state
1100    */
1101   public function getAgentStatusURLs() {
1102      $ret = array();
1103
1104      foreach ($this->getAgentBaseURLs() as $url) {
1105         array_push($ret, $url."/status");
1106      }
1107      return $ret;
1108   }
1109
1110
1111
1112   /**
1113    * URL to ask the agent to wake up
1114    *
1115    * @param interger agents_id agent id
1116    *
1117    * @return an http url to ask the agent to wake up
1118    */
1119   public function getAgentRunURLs() {
1120      $ret = array();
1121
1122      foreach ($this->getAgentBaseURLs() as $url) {
1123         array_push($ret, $url."/now/".$this->fields['token']);
1124      }
1125      return $ret;
1126   }
1127
1128
1129
1130   /**
1131    * Show configuration form of agent
1132    *
1133    */
1134   static function showConfig() {
1135
1136      echo "<table width='950' class='tab_cadre_fixe'>";
1137
1138      echo "<tr>";
1139      echo "<th colspan='2'>";
1140      echo __('Informations for agent configuration', 'fusioninventory');
1141
1142      echo "</th>";
1143      echo "</tr>";
1144
1145      echo "<tr class='tab_bg_1'>";
1146      echo "<td width='50%'>";
1147      $array = explode("/", $_SERVER['HTTP_REFERER']);
1148      $create_url = $array[0]."//".$array[2].
1149              str_replace("front/wizard.php", "", $_SERVER['PHP_SELF']);
1150      echo __('Communication url of the server', 'fusioninventory')."&nbsp;:";
1151      echo "</td>";
1152      echo "<td>";
1153      echo "<strong>".$create_url."</strong>";
1154
1155      echo "</td>";
1156      echo "</tr>";
1157      echo "</table>";
1158   }
1159
1160
1161
1162   /**
1163    * Disable data to put in table glpi_logs
1164    *
1165    */
1166   function pre_updateInDB() {
1167      if (isset($this->oldvalues['version'])
1168              AND $this->input['version'] == $this->oldvalues['version']) {
1169
1170         $key = array_search('version', $this->updates);
1171         unset($this->updates[$key]);
1172         unset($this->oldvalues['version']);
1173      }
1174      if (isset($this->oldvalues['last_contact'])) {
1175         $key = array_search('last_contact', $this->updates);
1176         unset($this->oldvalues['last_contact']);
1177      }
1178      if (isset($this->oldvalues['token'])) {
1179         $key = array_search('token', $this->updates);
1180         unset($this->oldvalues['token']);
1181      }
1182   }
1183
1184
1185
1186   /**
1187    * Display agent infos for a computer
1188    *
1189    * @param type $computers_id id of the computer
1190    */
1191   function showInfoForComputer($computers_id) {
1192
1193      if ($this->getAgentWithComputerid($computers_id)) {
1194
1195         echo '<tr class="tab_bg_1">';
1196         echo '<td>'.__('Agent', 'fusioninventory').'</td>';
1197         echo '<td>'.$this->getLink(1).'</td>';
1198         echo '</tr>';
1199
1200         echo '<tr class="tab_bg_1">';
1201         echo '<td>'.__('Useragent', 'fusioninventory').'</td>';
1202         echo '<td>'.$this->fields['useragent'].'</td>';
1203         echo '</tr>';
1204
1205         echo '<tr class="tab_bg_1">';
1206         echo '<td>'.__('FusionInventory tag', 'fusioninventory').'</td>';
1207         echo '<td>'.$this->fields['tag'].'</td>';
1208         echo '</tr>';
1209      }
1210   }
1211
1212
1213
1214   /**
1215   * Clean agent too old (so haven't contacted glpi
1216    * since xx days)
1217   *
1218   * @return bool cron is ok or not
1219   *
1220   **/
1221   static function cronCleanoldagents($task=NULL) {
1222      global $DB;
1223
1224      $pfConfig = new PluginFusioninventoryConfig();
1225      $pfAgent  = new PluginFusioninventoryAgent();
1226
1227      $retentiontime = $pfConfig->getValue('agents_old_days');
1228      if ($retentiontime == 0) {
1229         return TRUE;
1230      }
1231      $sql = "SELECT * FROM `glpi_plugin_fusioninventory_agents`
1232                   WHERE `last_contact` < date_add(now(), interval -".$retentiontime." day)";
1233      $result = $DB->query($sql);
1234
1235      if ($result) {
1236         $cron_status = FALSE;
1237         $action = $pfConfig->getValue('agents_action');
1238         if ($action == PluginFusioninventoryConfig::ACTION_CLEAN) {
1239            //delete agents
1240            while ($data = $DB->fetch_array($result)) {
1241               $pfAgent->delete($data);
1242               $task->addVolume(1);
1243               $cron_status = TRUE;
1244            }
1245         } else {
1246            //change status of agents
1247            while ($data = $DB->fetch_array($result)) {
1248               $computer = new Computer();
1249               if($computer->getFromDB($data['computers_id'])){
1250                  $computer->update(array(
1251                      'id' => $data['computers_id'],
1252                      'states_id' => $pfConfig->getValue('agents_status')));
1253                  $task->addVolume(1);
1254                  $cron_status = TRUE;
1255               }
1256            }
1257         }
1258      }
1259      return $cron_status;
1260   }
1261
1262}
1263
1264?>
1265