Compare commits

..

31 Commits

Author SHA1 Message Date
9436fe7c60 fix 2022-11-01 19:13:08 +01:00
b84ca3e4e4 typo4 2022-11-01 18:56:43 +01:00
79a944c0e3 typo 3 2022-11-01 18:54:07 +01:00
a1e314b00c typo again 2022-11-01 18:51:43 +01:00
e169c19bd0 typo 2022-11-01 18:50:37 +01:00
d43842790a Change color depend of states_id 2022-11-01 18:47:00 +01:00
Jaroslav Drzik
5d3bfbc491 Fix name in href in url 2021-12-26 17:00:21 +01:00
72fe3d8335 Fix locales 2021-12-23 16:25:00 +01:00
3c461d4570 Fix typos 2021-12-23 16:14:34 +01:00
Jaroslav Drzik
07678cacd4 Fix go program and run mode in config 2021-12-22 20:20:36 +01:00
625c246ba9 Threads config support 2021-12-22 20:15:49 +01:00
8aaf241075 Fix typo 2021-12-22 19:57:56 +01:00
68e726fae3 Make parallel and serial checks 2021-12-22 19:50:52 +01:00
Jaroslav Drzik
1dc3c4a557 Use configurable variables 2021-12-22 19:19:23 +01:00
Jaroslav Drzik
cffcb3ea64 Config adding... 2021-12-22 11:36:32 +01:00
Jaroslav Drzik
a8e21ef76c Delete test.php 2021-12-15 10:26:57 +01:00
Jaroslav Drzik
f868d991b1 Port from config and path from plugin function 2021-12-15 10:24:10 +01:00
Jaroslav Drzik
a8e4ddb2e0 Update multiple ids with one query 2021-12-10 18:33:19 +01:00
Jaroslav Drzik
8ac143be27 Merge branch 'main' of https://git.bh.ttx.sk/jaro/remotesupport into main 2021-12-10 18:05:03 +01:00
Jaroslav Drzik
f0399c9c9d Multiple insert 2021-12-10 18:03:15 +01:00
6aee52c717 Update README.md 2021-12-10 12:35:36 +01:00
7e5d7d1d3c new file 2021-12-10 12:06:50 +01:00
a4e71a8992 reformatted, cleaned 2021-12-10 11:50:51 +01:00
Jaroslav Drzik
0cde20881a Add git ignore 2021-12-10 11:29:34 +01:00
Jaroslav Drzik
31983b6803 Add bin dir 2021-12-10 11:28:25 +01:00
Jaroslav Drzik
1689989bd4 Cleaned 2021-12-10 11:24:00 +01:00
Jaroslav Drzik
7d31e98713 Uninstall and install hook 2021-12-10 10:53:04 +01:00
Jaroslav Drzik
50e9338059 Use go program for checks 2021-12-09 18:30:30 +01:00
Jaroslav Drzik
6d0f7fb392 Array of states 2021-12-09 17:57:03 +01:00
Jaroslav Drzik
6d5d6e18f5 Merge branch 'main' of https://git.bh.ttx.sk/jaro/remotesupport into main 2021-12-06 22:06:51 +01:00
Jaroslav Drzik
ca9dafcab4 Go lang check agents 2021-12-06 21:59:24 +01:00
12 changed files with 781 additions and 165 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
bin/check_status

16
Makefile Normal file
View File

@@ -0,0 +1,16 @@
BINARY_NAME=check_status
GO_PRG=check_status.go
BIN_DIR=./bin
GO=/usr/local/go/bin/go
all: build test
build:
${GO} build -o ${BIN_DIR}/${BINARY_NAME} ${GO_PRG}
test:
${GO} test -v ${GO_PRG}
clean:
${GO} clean
rm ${BIN_DIR}/${BINARY_NAME}

View File

@@ -1,7 +1,7 @@
# RemoteSupport
GLPI Plugin for direct VNC connection inside ticket
GLPI Plugin for direct VNC connection from browser inside computer from server and update status of online computers, it checks computer with go program in glpi cron and with fusion inventory agent...
This Plugin add a simple button inside tickets:
This Plugin add a simple button inside computer:
![immagine](https://user-images.githubusercontent.com/35736369/142444042-0cd5627b-5a5d-4586-8022-083e51d6f06c.png)
@@ -10,35 +10,60 @@ If user is correctly connected to one or more computer it will launch a VNC conn
- Prerequisites
1) VNC Must be installed in the destination PC
2) PC Name must me correct and resolved inside your DNS Server
3) Add a script in your pc and add a node inside regedit
2) Fusion inventory must be installed on server with GLPI
3) Agent must be installed on remote PC
4) Easy noVNC must be installed on server with GLPI
1) write a script (you will find inside resources) like this (let's assume in c:\startVNC.bat)
> SET S=%1
>
> SET S=%S:~7,-2%
>
> call "C:\Program Files\TightVNC\tvnviewer.exe" %S%
>
> quit 0
clone it and build binnary with make, edit Makefile in remotesupport plugin and build with make
2) Open regedit and add
Windows Registry Editor Version 5.00
Create systemd unit file:
```
[HKEY_CLASSES_ROOT\vnc]
@="URL:vnc Protocol"
"URL Protocol"=""
[Unit]
Description=Easy NoVNC
[HKEY_CLASSES_ROOT\vnc\shell]
[Service]
ExecStart=/usr/local/bin/easy-novnc -a :8888 -H -P
[HKEY_CLASSES_ROOT\vnc\shell\open]
[HKEY_CLASSES_ROOT\vnc\shell\open\command]
@="\"c:\\startVNC.bat\" \"%1\""
[Install]
WantedBy=multi-user.target
```
3) Download and install the plugin as usual
It will listen on 8888 port on local host.
TODO: a lot of documentation
Secure connection to server if you want, some ports are hardcoded in current status of plugin
```
<IfModule mod_ssl.c>
<VirtualHost *:443>
RewriteEngine On
ProxyPreserveHost On
ProxyRequests Off
# allow for upgrading to websockets
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:8888/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /glpi/(.*) http://localhost/glpi/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) http://localhost:8888/$1 [P,L]
ProxyPass "/" "http://localhost:8888/"
ProxyPassReverse "/" "http://localhost:8888/"
ProxyPass "/glpi/" "http://localhost/glpi/"
ProxyPassReverse "/glpi/" "http://localhost/glpi/"
ProxyPass "/vnc" "ws://localhost:8888/vnc"
ProxyPassReverse "/vnc" "ws://localhost:8888/vnc
ServerName server.name.lan
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
</VirtualHost>
</IfModule>
```

4
bin/README.md Normal file
View File

@@ -0,0 +1,4 @@
# Go program for remotesupport plugin
- binnary program for checking states of hosts

137
check_status.go Normal file
View File

@@ -0,0 +1,137 @@
package main
import (
"fmt"
"os"
"strconv"
"net/http"
"time"
"io/ioutil"
"encoding/json"
)
// a struct to hold the result from each request including an index
// which will be used for sorting the results after they come in
type result struct {
id int
status int
err error
}
type check struct {
// defining struct variables
Url string `json:"url"`
Id int `json:"id"`
Computers_id int `json:"computers_id"`
Status string `json:"status"`
}
func boundedParallelGet(Checks []check, concurrencyLimit int) []check {
// this buffered channel will block at the concurrency limit
semaphoreChan := make(chan struct{}, concurrencyLimit)
// this channel will not block and collect the http request results
resultsChan := make(chan *result)
// make sure we close these channels when we're done with them
defer func() {
close(semaphoreChan)
close(resultsChan)
}()
// keen an index and loop through every url we will send a request to
for _,chck := range Checks {
// start a go routine with the index and url in a closure
go func(chck check) {
var status int
// this sends an empty struct into the semaphoreChan which
// is basically saying add one to the limit, but when the
// limit has been reached block until there is room
semaphoreChan <- struct{}{}
// send the request and put the response in a result struct
// along with the index so we can sort them later along with
// any error that might have occoured
//fmt.Println(chck.Url)
client := http.Client{
Timeout: 7 * time.Second,
}
res, err := client.Get(chck.Url)
status = 404
if err == nil {
status = res.StatusCode
}
result := &result{chck.Id, status, err}
// now we can send the result struct through the resultsChan
resultsChan <- result
// once we're done it's we read from the semaphoreChan which
// has the effect of removing one from the limit and allowing
// another goroutine to start
<-semaphoreChan
}(chck)
}
// make a slice to hold the results we're expecting
var results []result
// start listening for any results over the resultsChan
// once we get a result append it to the result slice
for {
result := <-resultsChan
results = append(results, *result)
// if we've reached the expected amount of urls then stop
if len(results) == len(Checks) {
break
}
}
var ret []check
for i := range results {
ch := m[results[i].id]
if results[i].status == 200 {
ch.Status = "OK"
ret = append(ret,*ch)
}
}
// now we're done we return the results
return ret
}
var checks []check
var m = make(map[int]*check)
func init() {
bytes, _ := ioutil.ReadAll(os.Stdin)
json.Unmarshal(bytes , &checks)
for i := range checks {
m[checks[i].Id] = &checks[i]
}
}
func main() {
// str_debug := os.Getenv("debug")
str_threads := os.Getenv("threads")
threads, _ := strconv.Atoi(str_threads)
// debug, _ := strconv.ParseBool(str_debug)
//startTime := time.Now()
results := boundedParallelGet(checks, threads)
//seconds := time.Since(startTime).Seconds()
//tmplate := "requests: %d/%d in %v"
// fmt.Printf(tmplate, len(results), len(checks), seconds)
val,_ := json.MarshalIndent(results, "", " ")
fmt.Print(string(val))
}

175
hook.php
View File

@@ -1,63 +1,136 @@
<?php
/*
-------------------------------------------------------------------------
Remote Spport (VNC)
Copyright (C) 2021 by Alessandro Carloni
https://github.com/Kaya84/RemoteSupport
-------------------------------------------------------------------------
Remote Spport (VNC)
Copyright (C) 2021 by Alessandro Carloni
https://github.com/Kaya84/RemoteSupport
-------------------------------------------------------------------------
LICENSE
This file is part of Camera Input.
Camera Input is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Camera Input 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Camera Input. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------
*/
-------------------------------------------------------------------------
LICENSE
This file is part of Camera Input.
Camera Input is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Camera Input 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Camera Input. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------
*/
function plugin_remotesupport_install(){
return true;
function plugin_remotesupport_install()
{
global $DB;
$config = new Config();
$config->setConfigurationValues('plugin:Remotesupport',
['run_mode' => 'None',
'threads' => 100,
'show_in_tickets' => true,
'show_in_computers' => true,
'easy_novnc' => true,
'fusion' => true]
);
Toolbox::logInFile("remotesupport", "Installing plugin");
$state_online = [
'name' => 'Online',
'entities_id' => 0,
'is_recursive' => 0,
'comment' => '',
'states_id' => 0,
'completename' => 'Online',
'level' => 1,
'ancestors_cache' => '[]',
'sons_cache' => 'NULL',
'is_visible_computer' => 1,
'is_visible_monitor' => 0,
'is_visible_networkequipment' => 0,
'is_visible_peripheral' => 0,
'is_visible_phone' => 0,
'is_visible_printer' => 0,
'is_visible_softwareversion' => 0,
'is_visible_softwarelicense' => 0,
'is_visible_line' => 0,
'is_visible_certificate' => 0,
'is_visible_rack' => 0,
'is_visible_passivedcequipment' => 0,
'is_visible_enclosure' => 0,
'is_visible_pdu' => 0,
'is_visible_cluster' => 0,
'is_visible_contract' => 0,
'is_visible_appliance' => 0];
$ret = $DB->insert(
'glpi_states', $state_online
);
$state_offline = $state_online;
$state_offline["name"] = 'Offline';
$state_offline["completename"] = 'Offline';
$ret = $DB->insert(
'glpi_states', $state_offline
);
return true;
}
function plugin_remotesupport_uninstall(){
return true;
function plugin_remotesupport_uninstall()
{
global $DB;
Toolbox::logInFile("remotsupport", "Uninstalling plugin");
CronTask::Unregister('remotesupport');
$req = $DB->request('glpi_states', ['FIELDS' => ['glpi_states' => ['id', 'name']]], ['OR' => ['name' => 'Online', 'name' => 'Offline']]);
$ret = $req->next();
$states_ids[$ret['name']] = $ret['id'];
$ret = $req->next();
$states_ids[$ret['name']] = $ret['id'];
$DB->query('UPDATE glpi_computers SET states_id=NULL WHERE id=' . $states_ids["Offline"]);
$DB->query('UPDATE glpi_computers SET states_id=NULL WHERE id=' . $states_ids["Online"]);
$DB->query('DELETE FROM glpi_states WHERE id=' . $states_ids["Offline"]);
$DB->query('DELETE FROM glpi_states WHERE id=' . $states_ids["Online"]);
return true;
}
function plugin_remotesupport_postinit() {
global $CFG_GLPI, $DB;
function plugin_remotesupport_postinit()
{
global $CFG_GLPI, $DB;
$config = Config::getConfigurationValues('plugin:Remotesupport');
if(isset($_GET['id']) && $_GET['id'] != 0 && isset($_GET['_itemtype']) && $_GET['_itemtype'] == "Ticket"){
$id = $_GET['id'];
//mysql> select * from glpi_tickets_users where tickets_id = 2 and type = 1;
$req = $DB->request(['FROM' => 'glpi_tickets_users', 'WHERE' => ['tickets_id' => $id, 'type' => 1]]);
//NB: Estraggo unicamente il primo richiedente
$row = $req->next();
$requester = $row['users_id'];
// select id, name, users_id from glpi_computers where users_id = 178;
if ($row['users_id'] != 0) {
$req2 = $DB->request(['FROM' => 'glpi_computers', 'WHERE' => ['users_id' => $requester, 'is_deleted' => 0]]);
$url = "";
if (isset($_GET['id']) && $_GET['id'] != 0 && isset($_GET['_itemtype']) && $_GET['_itemtype'] == "Ticket" && $config["show_in_tickets"]) {
$id = $_GET['id'];
while ($row2 = $req2->next()){
//$url .= "<li class=\"document\" onclick=\"location.href='vnc://" . $row2['name'] ."'\"$
$url .= "<li class=\"document\" onclick=\"location.href='vnc://" . $row2['name'] ."'\"><i class=\"fa fa-laptop-medical\"></i>" . $row2['name'] . "</li>";
}
//mysql> select * from glpi_tickets_users where tickets_id = 2 and type = 1;
if ($url != ""){
echo "<div><ul class=\"timeline_choices\"><h2>Remote support : </h2>";
echo $url;
echo "</ul></div>";
}
}
}
$req = $DB->request(['FROM' => 'glpi_tickets_users', 'WHERE' => ['tickets_id' => $id, 'type' => 1]]);
//NB: Estraggo unicamente il primo richiedente
$row = $req->next();
$requester = $row['users_id'];
// select id, name, users_id from glpi_computers where users_id = 178;
if ($row['users_id'] != 0) {
$req2 = $DB->request(['FROM' => 'glpi_computers', 'WHERE' => ['users_id' => $requester, 'is_deleted' => 0]]);
$url = "";
while ($row2 = $req2->next()) {
//$url .= "<li class=\"document\" onclick=\"location.href='vnc://" . $row2['name'] ."'\"$
$url .= "<li class=\"document\" onclick=\"location.href='vnc://" . $row2['name'] . "'\"><i class=\"fa fa-laptop-medical\"></i>" . $row2['name'] . "</li>";
}
if ($url != "") {
echo "<div><ul class=\"timeline_choices\"><h2>Remote support : </h2>";
echo $url;
echo "</ul></div>";
}
}
}
}
?>

1
inc/.gitigonre Normal file
View File

@@ -0,0 +1 @@
bin/check_status

112
inc/config.class.php Normal file
View File

@@ -0,0 +1,112 @@
<?php
/*
* @version $Id$
-------------------------------------------------------------------------
GLPI - Gestionnaire Libre de Parc Informatique
Copyright (C) 2003-2011 by the INDEPNET Development Team.
http://indepnet.net/ http://glpi-project.org
-------------------------------------------------------------------------
LICENSE
This file is part of GLPI.
GLPI is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with GLPI. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------
*/
class PluginRemotesupportConfig extends CommonDBTM {
static protected $notable = true;
function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
if (!$withtemplate) {
if ($item->getType() == 'Config') {
return __('Remote Support plugin');
}
}
return '';
}
static function configUpdate($input) {
$input['configuration'] = 1 - $input['configuration'];
return $input;
}
function showFormRemotesupport() {
global $CFG_GLPI;
if (!Session::haveRight("config", UPDATE)) {
return false;
}
$my_config = Config::getConfigurationValues('plugin:Remotesupport');
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL('Config')."\" method='post'>";
echo "<div class='center' id='tabsbody'>";
echo "<table class='tab_cadre_fixe'>";
echo "<input type='hidden' name='config_class' value='".__CLASS__."'>";
echo "<input type='hidden' name='config_context' value='plugin:Remotesupport'>";
echo "<tr><th colspan='4'>" . __('Remote support setup') . "</th></tr>";
echo "<tr>";
echo "<td >" . __('Run Mode:') . "</td>";
echo "<td>";
Dropdown::showFromArray('run_mode', array('None' => __('None'),'Serial'=>__('Serial'),'Parallel' => __('Parallel')), array('value' => $my_config['run_mode']));
echo "</td>";
echo "<td >" . __('EasyNoVNC Installed:') . "</td>";
echo "<td>";
Dropdown::showYesNo("easy_novnc", $my_config['easy_novnc']);
echo "</td></tr>";
echo "<tr>";
echo "<td >" . __('Show in Computers:') . "</td>";
echo "<td>";
Dropdown::showYesNo("show_in_computers", $my_config['show_in_computers']);
echo "</td>";
echo "<td >" . __('Show in Tickets:') . "</td>";
echo "<td>";
Dropdown::showYesNo("show_in_tickets", $my_config['show_in_tickets']);
echo "</td>";
echo "</tr>";
echo "<tr>";
echo "<td >" . __('Threads:') . "</td>";
echo "<td>";
Dropdown::showNumber("threads",
[
'value' => 100,
'min' => 1,
'max' => 100
]);
echo "</td>";
echo "<td >" . __('Fusion inventory:') . "</td>";
echo "<td>";
Dropdown::showYesNo("fusion", $my_config['fusion']);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td colspan='4' class='center'>";
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
echo "</td></tr>";
echo "</table></div>";
Html::closeForm();
}
static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
if ($item->getType() == 'Config') {
$config = new self();
$config->showFormRemotesupport();
}
}
}

88
inc/remote_status.php Normal file
View File

@@ -0,0 +1,88 @@
<?php
include "../../../inc/includes.php";
declare (ticks = 1);
global $DB, $agents;
$check_arr = [];
$comps = [];
$rs_path = Plugin::getPhpDir('remotesupport');
$pfConfig = new PluginFusioninventoryConfig();
$port = $pfConfig->getValue('agent_port');
$pfInventoryComputerComputer = new PluginFusioninventoryInventoryComputerComputer();
foreach (getAllDataFromTable(PluginFusioninventoryAgent::getTable()) as $a) {
$check = [];
$a_computerextend = $pfInventoryComputerComputer->hasAutomaticInventory($a["computers_id"]);
$check["url"] = "http://" . $a_computerextend["remote_addr"] . ":" . $port . "/status";
$check["id"] = $a["id"];
$check["computers_id"] = $a["computers_id"];
$check["status"] = "unknown";
$check_arr[] = $check;
$comps[$a["computers_id"]] = $check;
//print_r($agent->getAgentStatusURLs());
}
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("file", "/tmp/error-output.txt", "a"), // stderr is a file to write to
);
$cwd = '/tmp';
$env = array('debug' => 'false', 'threads' => 100);
$process = proc_open($rs_path . '/bin/check_status', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be appended to /tmp/error-output.txt
fwrite($pipes[0], json_encode($check_arr));
fclose($pipes[0]);
$checked = json_decode(stream_get_contents($pipes[1]));
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
$req = $DB->request('glpi_states', ['FIELDS' => ['glpi_states' => ['id', 'name']]], ['OR' => ['name' => 'Online', 'name' => 'Offline']]);
$ret = $req->next();
$states_ids[$ret['name']] = $ret['id'];
$ret = $req->next();
$states_ids[$ret['name']] = $ret['id'];
print_r($states_ids);
$DB->update("glpi_computers", [
'states_id' => $states_ids["Offline"] ] ,
[ '1' => '1' ]
);
$ids = [];
foreach ($checked as $s) {
echo $s->computers_id."\n";
$ids[] = $s->computers_id;
}
$DB->update("glpi_computers", [
'states_id' => $states_ids["Online"] ],
[ 'id' => $ids ]
);
// print_r($a_computerextend);
exit(0);

View File

@@ -1,54 +1,222 @@
<?php
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access directly to this file");
die("Sorry. You can't access directly to this file");
}
class PluginRemotesupportRemotesupport extends CommonDBTM
{
public static function showInfo($item)
{
$config = Config::getConfigurationValues('plugin:Remotesupport');
class PluginRemotesupportRemotesupport extends CommonDBTM {
if ($config["show_in_computers"] == false) {
return true;
}
static function showInfo($item) {
$statusids = self::getStatusArray();
$fi_path = Plugin::getWebDir('fusioninventory');
if ($config["fusion"] == true && $config["easy_novnc"] == true) {
$pfInventoryComputerComputer = new PluginFusioninventoryInventoryComputerComputer();
$a_computerextend = $pfInventoryComputerComputer->hasAutomaticInventory($item->getID());
if (empty($a_computerextend)) {
return true;
}
// Manage locks pictures
PluginFusioninventoryLock::showLockIcon('Computer');
$href = "https://" . $_SERVER['SERVER_NAME'] . "/vnc.html?path=vnc%2F" . $a_computerextend['remote_addr'] . "&autoconnect=true&resize=scale&reconnect=true&show_dot=true";
$name = $a_computerextend['remote_addr'];
} else {
$href = "vnc://" . $item->fields["name"];
$name = $item->fields["name"];
}
echo '<table class="tab_glpi" width="100%">';
echo '<tr>';
echo '<th>' . __('Remote Support') . '</th>';
echo '</tr>';
echo '<tr class="tab_bg_1">';
echo '<td>';
$pfInventoryComputerComputer = new PluginFusioninventoryInventoryComputerComputer();
$a_computerextend = $pfInventoryComputerComputer->hasAutomaticInventory($item->getID());
if (empty($a_computerextend)) {
return true;
}
$style = $statusids[$item->getID()] == "Offline" ? "style=\"background-color: red\"" : "";
$url = "<a target=\"_blank\" href=\"" . $href . "\"><li class=\"document\" ". $style ."><i class=\"fa fa-laptop-medical\"></i>" . $name . "</li></a>";
echo '<table class="tab_glpi" width="100%">';
echo '<tr>';
echo '<th>'.__('Remote Support').'</th>';
echo '</tr>';
echo '<tr class="tab_bg_1">';
echo '<td>';
$url .= "<a target=\"_blank\" href=\"https://" . $_SERVER['SERVER_ADDR']. "/vnc.html?path=vnc%2F". $a_computerextend['remote_addr'] ."&autoconnect=true&resize=scale&reconnect=true&show_dot=true\"><li class=\"document\"><i class=\"fa fa-laptop-medical\"></i>" . $a_computerextend['remote_addr'] . "</li></a>";
if ($url != ""){
if ($url != "") {
echo "<div><ul class=\"timeline_choices\"><h2>VNC connect : </h2>";
echo $url;
echo "</ul></div>";
}
echo '</td>';
echo '</tr>';
echo '</table>';
}
echo '</td>';
echo '</tr>';
echo '</table>';
}
}
static function cronRemotesupport($task) {
Toolbox::logInFile("remotsupport",'Starting search of agents');
return true;
}
public static function getStatesIds()
{
global $DB;
static function cronInfo($name) {
return [
'description' => "Agent search remotesupport"];
}
$states_ids = [];
$req = $DB->request('glpi_states', ['FIELDS' => ['glpi_states' => ['id', 'name']]], ['OR' => ['name' => 'Online', 'name' => 'Offline']]);
$ret = $req->next();
$states_ids[$ret['name']] = $ret['id'];
$ret = $req->next();
$states_ids[$ret['name']] = $ret['id'];
return $states_ids;
}
public static function getContactArray()
{
global $DB;
$req = $DB->request('glpi_computers', ['FIELDS' => ['glpi_computers' => ['id', 'contact']]]);
$contactids = [];
while ($ret = $req->next()) {
$contactids[$ret["id"]] = $ret["contact"];
}
return $contactids;
}
public static function getStatusArray()
{
global $DB;
$st = self::getStatesIds();
$req = $DB->request('glpi_computers', ['FIELDS' => ['glpi_computers' => ['id', 'states_id']]]);
$statusids = [];
while ($ret = $req->next()) {
$statusids[$ret["id"]] = $ret["states_id"] == $st["Offline"] ? "Offline" : "Online";
}
return $statusids;
}
public static function cronRemotesupport($task)
{
global $DB;
$config = Config::getConfigurationValues('plugin:Remotesupport');
if ($config["fusion"] == false || $config["run_mode"] == "None") {
return 0;
}
Toolbox::logInFile("remotesupport", "Starting search of agents\n");
if ($config["run_mode"] == "Parallel") {
$pfConfig = new PluginFusioninventoryConfig();
$port = $pfConfig->getValue('agent_port');
$rs_path = Plugin::getPhpDir('remotesupport');
$check_arr = [];
$comps = [];
$pfInventoryComputerComputer = new PluginFusioninventoryInventoryComputerComputer();
foreach (getAllDataFromTable(PluginFusioninventoryAgent::getTable()) as $a) {
$check = [];
$a_computerextend = $pfInventoryComputerComputer->hasAutomaticInventory($a["computers_id"]);
$check["url"] = "http://" . $a_computerextend["remote_addr"] . ":" . $port . "/status";
$check["id"] = $a["id"];
$check["computers_id"] = $a["computers_id"];
$check["status"] = "unknown";
$check_arr[] = $check;
$comps[$a["computers_id"]] = $check;
//print_r($agent->getAgentStatusURLs());
}
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("file", "/tmp/error-output.txt", "a"), // stderr is a file to write to
);
$cwd = '/tmp';
$env = array('debug' => 'false', 'threads' => $config["threads"]);
$process = proc_open($rs_path . '/bin/check_status', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be appended to /tmp/error-output.txt
fwrite($pipes[0], json_encode($check_arr));
fclose($pipes[0]);
$checked = json_decode(stream_get_contents($pipes[1]));
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
Toolbox::logInFile("remotesupport", "command returned $return_value\n");
}
} else {
$agents = [];
$data_set = [];
$checked = [];
foreach (getAllDataFromTable(PluginFusioninventoryAgent::getTable()) as $a) {
$data_set[] = $a["id"];
$agents[$a["id"]] = $a;
}
foreach ($data_set as $id) {
$agent = new PluginFusioninventoryAgent;
$agent->getFromDB((int) $id);
$st = $agent->getStatus();
if ($st["message"] != "noanswer") {
$check = new stdClass();
$check->computers_id = $agents[$id]["computers_id"];
$checked[] = $check;
}
}
}
$stids = self::getStatesIds();
$DB->update("glpi_computers", [
'states_id' => $stids["Offline"]],
['1' => '1']
);
$ids = [];
$cids = self::getContactArray();
foreach ($checked as $s) {
$comp = new Computer();
$comp->getFromDB($s->computers_id);
Toolbox::logInFile("remotesupport", $s->computers_id . " " . $cids[$s->computers_id] . "\n");
$ids[] = $s->computers_id;
}
$DB->update("glpi_computers", [
'states_id' => $stids["Online"]],
['id' => $ids]
);
return 0;
}
public static function cronInfo($name)
{
return [
'description' => __('Agent search remotesupport')];
}
}

View File

@@ -21,7 +21,7 @@
</authors>
<versions>
<version>
<num>0.0.1</num>
<num>0.0.2</num>
<compatibility>~9.5.0</compatibility>
</version>
</versions>

101
setup.php
View File

@@ -1,25 +1,25 @@
<?php
/*
-------------------------------------------------------------------------
Remote Spport (VNC)
Copyright (C) 2021 by Alessandro Carloni
https://github.com/Kaya84/RemoteSupport
-------------------------------------------------------------------------
Remote Spport (VNC)
Copyright (C) 2021 by Alessandro Carloni
https://github.com/Kaya84/RemoteSupport
-------------------------------------------------------------------------
LICENSE
This file is part of Camera Input.
Camera Input is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Camera Input 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Camera Input. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------
*/
-------------------------------------------------------------------------
LICENSE
This file is part of Camera Input.
Camera Input is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Camera Input 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Camera Input. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------
*/
define('PLUGIN_REMOTESUPPORT_VERSION', '0.0.1');
define('PLUGIN_REMOTESUPPORT_MIN_GLPI', '9.5.0');
@@ -28,49 +28,40 @@ define("PLUGIN_REMOTESUPPORT_DIR", GLPI_ROOT . "/plugins/remotesupport");
function plugin_init_remotesupport()
{
global $PLUGIN_HOOKS;
$PLUGIN_HOOKS['csrf_compliant']['remotesupport'] = true;
global $PLUGIN_HOOKS;
$PLUGIN_HOOKS['csrf_compliant']['remotesupport'] = true;
if (Plugin::isPluginActive('remotesupport')) {
// $PLUGIN_HOOKS['add_javascript']['remotesupport'][] = 'js/support.js';
// include(PLUGIN_REMOTESUPPORT_DIR . "/inc/remotesupport.class.php");
if (Plugin::isPluginActive('remotesupport')) {
$PLUGIN_HOOKS['autoinventory_information']['remotesupport'] = array(
'Computer' => array('PluginRemotesupportRemotesupport', 'showInfo')
);
$PLUGIN_HOOKS['autoinventory_information']['remotesupport'] = array(
'Computer' => array('PluginRemotesupportRemotesupport', 'showInfo'),
);
CronTask::Register('PluginRemotesupportRemotesupport', 'remotesupport', DAY_TIMESTAMP, [
'param' => 24,
'mode' => CronTask::MODE_EXTERNAL
]);
Plugin::registerClass('PluginRemotesupportConfig', ['addtabon' => 'Config']);
// Add Config Page
// Plugin::registerClass('PluginRemotesupportConfig', ['addtabon' => 'Config']);
// $PLUGIN_HOOKS["menu_toadd"]['remotesupport'] = ['tools' => 'PluginRemotesupportMenu'];
// $PLUGIN_HOOKS['config_page']['remotesupport'] = 'front/index.php';
$PLUGIN_HOOKS['menu']['remotesupport'] = true;
$PLUGIN_HOOKS['post_init']['remotesupport'] = 'plugin_remotesupport_postinit';
CronTask::Register('PluginRemotesupportRemotesupport', 'remotesupport', 300,
['mode' => 2, 'allowmode' => 3, 'logs_lifetime' => 30,
'comment' => 'Remotesupport crontab search agents']);
}
$PLUGIN_HOOKS['menu']['remotesupport'] = true;
$PLUGIN_HOOKS['post_init']['remotesupport'] = 'plugin_remotesupport_postinit';
}
}
function plugin_version_remotesupport()
{
return [
'name' => __('Remote Support Input', 'remotesupport'),
'version' => PLUGIN_REMOTESUPPORT_VERSION,
'author' => 'Alessandro Carloni',
'license' => 'GPLv2',
'homepage' =>'https://github.com/Kaya84/',
'requirements' => [
'glpi' => [
'min' => PLUGIN_REMOTESUPPORT_MIN_GLPI,
'max' => PLUGIN_REMOTESUPPORT_MAX_GLPI
]
]
];
return [
'name' => __('Remote Support Input', 'remotesupport'),
'version' => PLUGIN_REMOTESUPPORT_VERSION,
'author' => 'Alessandro Carloni',
'license' => 'GPLv2',
'homepage' => 'https://github.com/Kaya84/',
'requirements' => [
'glpi' => [
'min' => PLUGIN_REMOTESUPPORT_MIN_GLPI,
'max' => PLUGIN_REMOTESUPPORT_MAX_GLPI,
],
],
];
}