%PDF- %PDF-
| Direktori : /var/www/projetos/suporte.iigd.com.br/plugins/glpiinventory/inc/ |
| Current File : /var/www/projetos/suporte.iigd.com.br/plugins/glpiinventory/inc/deployfile.class.php |
<?php
/**
* ---------------------------------------------------------------------
* GLPI Inventory Plugin
* Copyright (C) 2021 Teclib' and contributors.
*
* http://glpi-project.org
*
* based on FusionInventory for GLPI
* Copyright (C) 2010-2021 by the FusionInventory Development Team.
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI Inventory Plugin.
*
* GLPI Inventory Plugin 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.
*
* GLPI Inventory Plugin 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 GLPI Inventory Plugin. If not, see <https://www.gnu.org/licenses/>.
* ---------------------------------------------------------------------
*/
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access directly to this file");
}
/**
* Manage the files to deploy.
*/
class PluginGlpiinventoryDeployFile extends PluginGlpiinventoryDeployPackageItem
{
public $shortname = 'files';
public $json_name = 'associatedFiles';
/**
* The right name for this class
*
* @var string
*/
public static $rightname = 'plugin_glpiinventory_package';
const REGISTRY_NO_DB_ENTRY = 0x1;
const REGISTRY_NO_MANIFEST = 0x2;
/**
* Get the 2 types to add files
*
* @return array
*/
public function getTypes()
{
$types = [
'Computer' => __("Upload from computer", 'glpiinventory')
];
if (GLPI_INSTALL_MODE !== 'CLOUD') {
$types['Server'] = __("Upload from server", 'glpiinventory');
}
return $types;
}
/**
* Display list of files
*
* @global array $CFG_GLPI
* @param PluginGlpiinventoryDeployPackage $package PluginGlpiinventoryDeployPackage instance
* @param array $data array converted of 'json' field in DB where stored actions
* @param string $rand unique element id used to identify/update an element
*/
public function displayList(PluginGlpiinventoryDeployPackage $package, $data, $rand)
{
global $CFG_GLPI;
$package_id = $package->getID();
$canedit = $package->canUpdateContent();
// compute short shas to find the corresponding entries in database
$short_shas = [];
foreach ($data['jobs']['associatedFiles'] as $sha512) {
$short_shas[] = substr($sha512, 0, 6);
}
// find corresponding file entries
$files = $this->find(['shortsha512' => $short_shas]);
// do a quick mapping between database id and short shas
$files_mapping = [];
foreach ($files as $file) {
$files_mapping[$file['shortsha512']] = $file['id'];
}
echo "<table class='tab_cadrehov package_item_list' id='table_files_$rand'>";
$i = 0;
foreach ($data['jobs']['associatedFiles'] as $sha512) {
$short_sha = substr($sha512, 0, 6);
$file_id = 0;
$fileregistry_error = 0;
// check if the files is registered in database
if (!array_key_exists($short_sha, $files_mapping)) {
$fileregistry_error |= self::REGISTRY_NO_DB_ENTRY;
}
if (!$this->checkPresenceManifest($sha512)) {
$fileregistry_error |= self::REGISTRY_NO_MANIFEST;
}
// get database entries
if (!$fileregistry_error) {
$file_id = $files_mapping[$short_sha];
$file_name = $files[$file_id]['name'];
$file_size = $files[$file_id]['filesize'];
//mimetype icon
if (isset($files[$file_id]['mimetype'])) {
$file_mimetype =
str_replace('/', '__', $files[$file_id]['mimetype']);
} else {
$file_mimetype = null;
}
} else {
// get file's name from what has been saved in json
$file_name = $data['associatedFiles'][$sha512]['name'];
$file_size = null;
$file_mimetype = null;
}
$file_uncompress = $data['associatedFiles'][$sha512]['uncompress'];
$file_p2p = $data['associatedFiles'][$sha512]['p2p'];
$file_p2p_retention_duration =
$data['associatedFiles'][$sha512]['p2p-retention-duration'];
// start new line
$pics_path = Plugin::getWebDir('glpiinventory') . "/pics/";
echo Search::showNewLine(Search::HTML_OUTPUT, ($i % 2));
if ($canedit) {
echo "<td class='control'>";
Html::showCheckbox(['name' => 'file_entries[' . $i . ']', 'value' => 0]);
echo "</td>";
}
echo "<td class='filename'>";
if (
!empty($file_mimetype)
&& file_exists($pics_path . "extensions/$file_mimetype.png")
) {
echo "<img src='" . $pics_path . "extensions/$file_mimetype.png' />";
} else {
echo "<img src='" . $pics_path . "extensions/documents.png' />";
}
//filename
echo " ";
if ($canedit) {
echo "<a class='edit'
onclick=\"edit_subtype('file', $package_id, $rand ,this)\">";
}
echo $file_name;
if ($canedit) {
echo "</a>";
}
//p2p icon
if (
isset($file_p2p)
&& $file_p2p != 0
) {
echo "<a title='" . __('p2p', 'glpiinventory') . ", "
. __("retention", 'glpiinventory') . " : " .
$file_p2p_retention_duration . " " .
__("Minute(s)", 'glpiinventory') . "' class='more'>";
echo "<img src='" . $pics_path . "p2p.png' />";
echo "<sup>" . $file_p2p_retention_duration . "</sup>";
echo "</a>";
}
//uncompress icon
if (
isset($file_uncompress)
&& $file_uncompress != 0
) {
echo "<a title='" .
__('uncompress', 'glpiinventory') .
"' class='more'><img src='" .
$pics_path .
"uncompress.png' /></a>";
}
//download file
if (!$fileregistry_error) {
$path = Plugin::getWebDir('glpiinventory') . "/front/deployfile_download.php?deployfile_id=" . $file_id;
echo "<a href='" . $path . "' title='" . __('Download', 'glpiinventory') .
"' class='download' data-bs-toggle='tooltip' target='_blank' ><i class='ti ti-download'></a>";
}
//sha fingerprint
$sha_status = "good";
if ($fileregistry_error != 0) {
$sha_status = "bad";
}
echo "<div class='fingerprint'>";
echo "<div class='fingerprint_" . $sha_status . "'>" . $sha512;
if ($fileregistry_error & self::REGISTRY_NO_DB_ENTRY) {
echo "<div class='fingerprint_badmsg'>" .
__("This file is not correctly registered in database.") . "<br/>" .
__("You can fix it by uploading or selecting the good one.");
echo "</div>";
}
if ($fileregistry_error & self::REGISTRY_NO_MANIFEST) {
echo "<div class='fingerprint_badmsg'>" .
__("This file doesn't have any manifest file associated.") . "<br/>" .
__("You must upload the file.");
echo "</div>";
}
echo "</div>";
echo "</div>";
//filesize
if (!$fileregistry_error) {
echo "<div class='size'>";
echo __('Size') . ": " . $this->processFilesize($file_size);
echo "</div>";
}
echo "</td>";
if ($canedit) {
echo "<td class='rowhandler control' title='" .
__('drag', 'glpiinventory') .
"'><div class='drag row'></div></td>";
}
$i++;
}
if ($canedit) {
echo "<tr><th>";
echo Html::getCheckAllAsCheckbox("filesList$rand", mt_rand());
echo "</th><th colspan='3' class='mark'></th></tr>";
}
echo "</table>";
if ($canedit) {
echo " <img src='" . $CFG_GLPI["root_doc"] . "/pics/arrow-left.png' alt=''>";
echo "<input type='submit' name='delete' value=\"" .
__('Delete', 'glpiinventory') . "\" class='submit'>";
}
}
/**
* Display different fields relative the file selected
*
* @global array $CFG_GLPI
* @param array $config
* @param array $request_data
* @param string $rand unique element id used to identify/update an element
* @param string $mode mode in use (create, edit...)
* @return void
*/
public function displayAjaxValues($config, $request_data, $rand, $mode)
{
$fi_path = Plugin::getWebDir('glpiinventory');
$pfDeployPackage = new PluginGlpiinventoryDeployPackage();
if (isset($request_data['packages_id'])) {
$pfDeployPackage->getFromDB($request_data['packages_id']);
} else {
$pfDeployPackage->getEmpty();
}
$p2p = 0;
$p2p_retention_duration = 0;
$uncompress = 0;
if ($mode === self::CREATE) {
$source = $request_data['value'];
/**
* No need to continue if there is no selected source
*/
if ($source === '0') {
return;
}
} else {
$p2p = $config['data']['p2p'];
$p2p_retention_duration = $config['data']['p2p-retention-duration'];
$uncompress = $config['data']['uncompress'];
}
echo "<table class='package_item'>";
/*
* Display file upload input only in 'create' mode
*/
echo "<tr>";
echo "<th>" . __("File", 'glpiinventory') . "</th>";
echo "<td>";
if ($mode === self::CREATE) {
switch ($request_data['value']) {
case "Computer":
echo "<input type='file' name='file' value='" .
__("filename", 'glpiinventory') . "' />";
echo " <i>" . $this->getMaxUploadSize() . "</i>";
break;
case "Server":
echo "<input type='text' name='filename' id='server_filename$rand'" .
" style='width:500px;float:left' />";
echo "<input type='button' class='submit' value='" . __("Choose", 'glpiinventory') .
"' onclick='fileModal$rand.show();' />";
Ajax::createModalWindow(
"fileModal$rand",
$fi_path . "/ajax/deployfilemodal.php",
['title' => __('Select the file on server', 'glpiinventory'),
'extraparams' => [
'rand' => $rand
]]
);
break;
}
} else {
/*
* Display only name in 'edit' mode
*/
echo $config['data']['name'];
}
echo "</td>";
echo "</tr>";
echo "<tr>";
echo "<th>" . __("Uncompress", 'glpiinventory') . "<img style='float:right' " .
"src='" . $fi_path . "/pics/uncompress.png' /></th>";
echo "<td>";
Html::showCheckbox(['name' => 'uncompress', 'checked' => $uncompress]);
echo "</td>";
echo "</tr>";
echo "<tr>";
echo "<th>" . __("P2P", 'glpiinventory') .
"<img style='float:right' src='" . $fi_path .
"/pics/p2p.png' /></th>";
echo "<td>";
Html::showCheckbox(['name' => 'p2p', 'checked' => $p2p]);
echo "</td>";
echo "</tr>";
echo "<tr>";
echo "<th>" . __("retention", 'glpiinventory') .
" - " . __("Minute(s)", 'glpiinventory') . "</th>";
echo "<td>";
echo "<input type='number' name='p2p-retention-duration' value='$p2p_retention_duration' />";
echo "</td>";
echo "</tr>";
$this->addOrSaveButton($pfDeployPackage, $mode);
echo "</table>";
}
/**
* Show files / directory on server.
* This is used when get a file on the server
*
* @global array $CFG_GLPI
* @param string $rand unique element id used to identify/update an element
*/
public static function showServerFileTree($rand)
{
echo "<script type='text/javascript'>";
echo "Ext.Ajax.defaultHeaders = {'X-Glpi-Csrf-Token' : getAjaxCsrfToken()};";
echo "var Tree_Category_Loader$rand = new Ext.tree.TreeLoader({
dataUrl:'" . Plugin::getWebDir('glpiinventory') . "/ajax/serverfilestreesons.php'
});";
echo "var Tree_Category$rand = new Ext.tree.TreePanel({
collapsible : false,
animCollapse : false,
border : false,
id : 'tree_projectcategory$rand',
el : 'tree_projectcategory$rand',
autoScroll : true,
animate : false,
enableDD : true,
containerScroll : true,
height : 320,
width : 670,
loader : Tree_Category_Loader$rand,
rootVisible : false,
listeners: {
click: function(node, event) {
if (node.leaf == true) {
console.log('server_filename$rand');
Ext.get('server_filename$rand').dom.value = node.id;
fileModal$rand.hide();
}
}
}
});";
// SET the root node.
echo "var Tree_Category_Root$rand = new Ext.tree.AsyncTreeNode({
text : '',
draggable : false,
id : '-1' // this IS the id of the startnode
});
Tree_Category$rand.setRootNode(Tree_Category_Root$rand);";
// Render the tree.
echo "Tree_Category$rand.render();
Tree_Category_Root$rand.expand();";
echo "</script>";
echo '<div class="alert alert-info d-flex" role="alert">';
echo '<i class="fas fa-exclamation-circle fa-2x me-2"></i>';
echo '<p>' . sprintf(__('Files need to be uploaded to %s folder to be displayed here', 'glpiinventory'), '<mark>/files/_plugins/glpiinventory/upload/</mark>') . '</p>';
echo '</div>';
echo "<div id='tree_projectcategory$rand' ></div>";
echo "</div>";
}
/**
* Get files / directories on server
*
* @param string $node
*/
public static function getServerFileTree($node)
{
$nodes = [];
$pfConfig = new PluginGlpiinventoryConfig();
$dir = $pfConfig->getValue('server_upload_path');
$security_problem = false;
if ($node != "-1") {
if (strstr($node, "..")) {
$security_problem = true;
}
$matches = [];
preg_match("/^(" . str_replace("/", "\/", $dir) . ")(.*)$/", $node, $matches);
if (count($matches) != 3) {
$security_problem = true;
}
}
if (!$security_problem) {
// leaf node
if ($node != -1) {
$dir = $node;
}
if (($handle = opendir($dir))) {
$folders = $files = [];
//list files in dir selected
//we store folders and files separately to sort them alphabetically separately
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
$filepath = $dir . "/" . $entry;
if (is_dir($filepath)) {
$folders[$filepath] = $entry;
} else {
$files[$filepath] = $entry;
}
}
}
//sort folders and files (and maintain index association)
asort($folders);
asort($files);
//add folders in json
foreach ($folders as $filepath => $entry) {
$path['text'] = $entry;
$path['id'] = $filepath;
$path['draggable'] = false;
$path['leaf'] = false;
$path['cls'] = 'folder';
$nodes[] = $path;
}
//add files in json
foreach ($files as $filepath => $entry) {
$path['text'] = $entry;
$path['id'] = $filepath;
$path['draggable'] = false;
$path['leaf'] = true;
$path['cls'] = 'file';
$nodes[] = $path;
}
closedir($handle);
}
}
print json_encode($nodes);
}
/**
* Add a new item in files of the package
*
* @param array $params list of fields with value of the file
*/
public function add_item($params)
{
switch ($params['filestype']) {
case 'Server':
return $this->uploadFileFromServer($params);
break;
default:
return $this->uploadFileFromComputer($params);
}
return false;
}
/**
* Remove an item
*
* @param array $params
* @return boolean
*/
public function remove_item($params)
{
if (!isset($params['file_entries'])) {
return false;
}
$shasToRemove = [];
//get current order json
$data = json_decode($this->getJson($params['packages_id']), true);
$files = $data['jobs']['associatedFiles'];
//remove selected checks
foreach ($params['file_entries'] as $index => $checked) {
if ($checked >= "1" || $checked == "on") {
//get sha512
$sha512 = $data['jobs']['associatedFiles'][$index];
//remove file
unset($files[$index]);
unset($data['associatedFiles'][$sha512]);
$shasToRemove[] = $sha512;
}
}
$data['jobs']['associatedFiles'] = array_values($files);
//update order
$this->updateOrderJson($params['packages_id'], $data);
//remove files in repo
foreach ($shasToRemove as $sha512) {
$this->removeFileInRepo($sha512);
}
return true;
}
/**
* Save the item in files
*
* @param array $params list of fields with value of the file
*/
public function save_item($params)
{
//get current order json
$data = json_decode($this->getJson($params['id']), true);
//get sha512
$sha512 = $data['jobs'][$this->json_name][$params['index']];
//get file in json
$file = $data[$this->json_name][$sha512];
//remove value in json
unset($data[$this->json_name][$sha512]);
//update values
$file['p2p'] = isset($params['p2p']) ? $params['p2p'] : 0;
$file['p2p-retention-duration'] = $params['p2p-retention-duration'];
$file['uncompress'] = isset($params['uncompress']) ? $params['uncompress'] : 0;
//add modified entry
$data[$this->json_name][$sha512] = $file;
//update order
$this->updateOrderJson($params['id'], $data);
}
/**
* Upload file from user computer
*
* @param array $params
* @return boolean
*/
public function uploadFileFromComputer($params)
{
if (isset($params["id"])) {
//file uploaded?
if (
isset($_FILES['file']['tmp_name'])
&& !empty($_FILES['file']['tmp_name'])
) {
$file_tmp_name = $_FILES['file']['tmp_name'];
}
if (
isset($_FILES['file']['name'])
&& !empty($_FILES['file']['name'])
) {
$filename = $_FILES['file']['name'];
}
//file upload errors
if (isset($_FILES['file']['error'])) {
$error = true;
$msg = __("Upload error", 'glpiinventory');
switch ($_FILES['file']['error']) {
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$msg = __("Transfer error: the file size is too big", 'glpiinventory');
break;
case UPLOAD_ERR_PARTIAL:
$msg = __("The uploaded file was only partially uploaded", 'glpiinventory');
break;
case UPLOAD_ERR_NO_FILE:
$msg = __("No file was uploaded", 'glpiinventory');
break;
case UPLOAD_ERR_NO_TMP_DIR:
$msg = __("Missing a temporary folder", 'glpiinventory');
break;
case UPLOAD_ERR_CANT_WRITE:
$msg = __("Failed to write file to disk", 'glpiinventory');
break;
case UPLOAD_ERR_EXTENSION:
$msg = __("PHP extension stopped the file upload", 'glpiinventory');
break;
case UPLOAD_ERR_OK:
//no error, continue
$error = false;
}
if ($error) {
Session::addMessageAfterRedirect($msg);
return false;
}
}
//prepare file data for insertion in repo
$data = [
'id' => $params['id'],
'file_tmp_name' => $file_tmp_name ?? '',
'mime_type' => $_FILES['file']['type'],
'filesize' => $_FILES['file']['size'],
'filename' => $filename ?? '',
'p2p' => isset($params['p2p']) ? $params['p2p'] : 0,
'uncompress' => isset($params['uncompress']) ? $params['uncompress'] : 0,
'p2p-retention-duration' => (is_numeric($params['p2p-retention-duration'])
? $params['p2p-retention-duration'] : 0)
];
//Add file in repo
if (isset($filename) && $this->addFileInRepo($data)) {
Session::addMessageAfterRedirect(__('File saved!', 'glpiinventory'));
return true;
} else {
Session::addMessageAfterRedirect(__('Failed to copy file', 'glpiinventory'));
return false;
}
}
Session::addMessageAfterRedirect(__('File missing', 'glpiinventory'));
return false;
}
/**
* Upload file from temp folder in server
*
* @param array $params
* @return boolean
*/
public function uploadFileFromServer($params)
{
if (preg_match('/\.\./', $params['filename'])) {
die;
}
if (isset($params["id"])) {
$file_path = $params['filename'];
$filename = basename($file_path);
$mime_type = '';
if (
function_exists('finfo_open')
&& ($finfo = finfo_open(FILEINFO_MIME))
) {
$mime_type = finfo_file($finfo, $file_path);
finfo_close($finfo);
} elseif (function_exists('mime_content_type')) {
$mime_type = mime_content_type($file_path);
}
$filesize = filesize($file_path);
//prepare file data for insertion in repo
$data = [
'file_tmp_name' => $file_path,
'mime_type' => $mime_type,
'filesize' => $filesize,
'filename' => $filename,
'p2p' => isset($params['p2p']) ? $params['p2p'] : 0,
'uncompress' => isset($params['uncompress']) ? $params['uncompress'] : 0,
'p2p-retention-duration' => (
isset($params['p2p-retention-duration'])
&& is_numeric($params['p2p-retention-duration'])
? $params['p2p-retention-duration']
: 0
),
'id' => $params['id']
];
//Add file in repo
if ($filename && $this->addFileInRepo($data)) {
Session::addMessageAfterRedirect(__('File saved!', 'glpiinventory'));
return true;
} else {
Session::addMessageAfterRedirect(__('Failed to copy file', 'glpiinventory'));
return false;
}
}
Session::addMessageAfterRedirect(__('File missing', 'glpiinventory'));
return false;
}
/**
* Get directories based on sha512
*
* @param string $sha512
* @return string the directories based on sha512
*/
public function getDirBySha512($sha512)
{
$first = substr($sha512, 0, 1);
$second = substr($sha512, 0, 2);
return "$first/$second";
}
/**
* Create a configuration request data
*
* @since 9.2
*/
public function getItemConfig(PluginGlpiinventoryDeployPackage $package, $request_data)
{
$element = $package->getSubElement($this->json_name, $request_data['index']);
$config = [];
if ($element) {
$config = [
'hash' => $element,
'data' => $package->getAssociatedFile($element),
];
}
return $config;
}
/**
* Move uploaded file part in right/final directory
*
* @param string $filePath path of the file + filename
* @param boolean $skip_creation
* @return string
*/
public function registerFilepart($filePath, $skip_creation = false)
{
$sha512 = hash_file('sha512', $filePath);
if (!$skip_creation) {
$dir = PLUGIN_GLPI_INVENTORY_REPOSITORY_DIR . $this->getDirBySha512($sha512);
if (!file_exists($dir)) {
mkdir($dir, 0777, true);
}
copy($filePath, $dir . '/' . $sha512);
}
return $sha512;
}
/**
* Add file in the repository
*
* @param array $params
* @return boolean
*/
public function addFileInRepo($params)
{
$filename = addslashes($params['filename']);
$file_tmp_name = $params['file_tmp_name'];
$maxPartSize = 1024 * 1024;
$tmpFilepart = tempnam(GLPI_PLUGIN_DOC_DIR . "/glpiinventory/", "filestore");
$sha512 = hash_file('sha512', $file_tmp_name);
$short_sha512 = substr($sha512, 0, 6);
$file_present_in_repo = false;
if ($this->checkPresenceFile($sha512)) {
$file_present_in_repo = true;
}
$file_present_in_db =
(!empty($this->find(['shortsha512' => $short_sha512])));
$new_entry = [
'name' => $filename,
'p2p' => $params['p2p'],
'p2p-retention-duration' => $params['p2p-retention-duration'],
'uncompress' => $params['uncompress'],
];
$fdIn = fopen($file_tmp_name, 'rb');
if (!$fdIn) {
return false;
}
$fdPart = null;
$multiparts = [];
do {
clearstatcache();
if (file_exists($tmpFilepart)) {
if (feof($fdIn) || filesize($tmpFilepart) >= $maxPartSize) {
$part_sha512 = $this->registerFilepart(
$tmpFilepart,
$file_present_in_repo
);
unlink($tmpFilepart);
$multiparts[] = $part_sha512;
}
}
if (feof($fdIn)) {
break;
}
$data = fread($fdIn, 1024 * 1024);
$fdPart = gzopen($tmpFilepart, 'a');
gzwrite($fdPart, $data, strlen($data));
gzclose($fdPart);
} while (1);
//create manifest file
if (!$file_present_in_repo) {
$handle = fopen(
PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $sha512,
"w+"
);
if ($handle) {
foreach ($multiparts as $sha) {
fwrite($handle, $sha . "\n");
}
fclose($handle);
}
}
//TODO: Add a new files interface to list, create, manage entities and visibility
// entity on a file is just anticipated and will be fully used later
if (!$file_present_in_db) {
$entry = [
"name" => $filename,
"filesize" => $params['filesize'],
"mimetype" => $params['mime_type'],
"sha512" => $sha512,
"shortsha512" => $short_sha512,
"comments" => "",
"date_mod" => date('Y-m-d H:i:s'),
"entities_id" => 0,
"is_recursive" => 1
];
$this->add($entry);
}
//get current package json
$data = json_decode($this->getJson($params['id']), true);
//add new entry
$data[$this->json_name][$sha512] = $new_entry;
if (!in_array($sha512, $data['jobs'][$this->json_name])) {
$data['jobs'][$this->json_name][] = $sha512;
}
//update package
$this->updateOrderJson($params['id'], $data);
return true;
}
/**
* Remove file from the repository
*
* @param string $sha512 sha512 of the file
* @return boolean
*/
public function removeFileInRepo($sha512)
{
$pfDeployPackage = new PluginGlpiinventoryDeployPackage();
// try to find file in other packages
$rows = $pfDeployPackage->find(
[
['json' => ['LIKE', '%' . substr($sha512, 0, 6) . '%']],
['json' => ['LIKE', '%' . $sha512 . '%']]
]
);
//file found in other packages, do not remove parts in repo
if (count($rows) > 0) {
return false;
}
//get sha512 parts in manifest
if (!file_exists(PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $sha512)) {
return true;
}
$multiparts = file(PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $sha512);
//parse all files part
foreach ($multiparts as $part_sha512) {
$firstdir = PLUGIN_GLPI_INVENTORY_REPOSITORY_DIR . substr($part_sha512, 0, 1) . "/";
$fulldir = PLUGIN_GLPI_INVENTORY_REPOSITORY_DIR . $this->getDirBySha512($part_sha512) . '/';
//delete file parts
unlink(trim($fulldir . $part_sha512));
//delete folders if empty
if (is_dir($fulldir)) {
$count_second_folder = count(scandir($fulldir)) - 2;
if ($count_second_folder === 0) {
rmdir($fulldir);
}
}
if (is_dir($firstdir)) {
$count_first_folder = count(scandir($firstdir)) - 2; // -2 for . and ..
if ($count_first_folder === 0) {
rmdir($firstdir);
}
}
}
//remove manifest
if (file_exists(PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $sha512)) {
unlink(PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $sha512);
}
return true;
}
/**
* Return all subpart path
*
* @param string $sha512 sha512 of the file
* @return array
*/
public function getFilePath($sha512)
{
if (!$this->checkPresenceFile($sha512)) {
return false;
}
$path = [];
$handle = fopen(PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $sha512, "r");
$error = $handle === false;
if ($handle) {
while (($buffer = fgets($handle)) !== false) {
$path[] = PLUGIN_GLPI_INVENTORY_REPOSITORY_DIR . $this->getDirBySha512($buffer) . "/" . trim($buffer, "\n");
}
if (!feof($handle)) {
$error = true;
}
fclose($handle);
}
if ($error) {
trigger_error(
sprintf('Unable to read file %s manifest.', $sha512),
E_USER_WARNING
);
return false;
}
return $path;
}
/**
* Check if the manifest relative to the sha512 exist
*
* @param string $sha512 sha512 of the file
* @return boolean
*/
public function checkPresenceManifest($sha512)
{
if (!file_exists(PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $sha512)) {
return false;
}
return true;
}
/**
* Check if the file relative to the sha512 exist
*
* @param string $sha512 sha512 of the file
* @return boolean
*/
public function checkPresenceFile($sha512)
{
//Do not continue if the manifest is not found
if (!$this->checkPresenceManifest($sha512)) {
return false;
}
//Does the file needs to be created ?
// Even if fileparts exists, we need to be sure
// the manifest file is created
$fileparts_ok = true;
$fileparts_cnt = 0;
$handle = fopen(PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $sha512, "r");
if ($handle) {
while (($buffer = fgets($handle)) !== false) {
$fileparts_cnt++;
$path = $this->getDirBySha512($buffer) . "/" . trim($buffer, "\n");
//Check if the filepart exists
if (!file_exists(PLUGIN_GLPI_INVENTORY_REPOSITORY_DIR . $path)) {
$fileparts_ok = false;
break;
}
}
fclose($handle);
}
// Does the file is empty ?
if ($fileparts_cnt == 0) {
return false;
}
//Does the file needs to be replaced ?
if (!$fileparts_ok) {
return false;
}
//Nothing to do because the manifest and associated fileparts seems to be fine.
return true;
}
/**
* Get the maximum size the php can accept for upload file
*
* @return string
*/
public function getMaxUploadSize()
{
$max_upload = (int)(ini_get('upload_max_filesize'));
$max_post = (int)(ini_get('post_max_size'));
$memory_limit = (int)(ini_get('memory_limit'));
return __('Max file size', 'glpiinventory')
. " : " . min($max_upload, $max_post, $memory_limit) . __('Mio', 'glpiinventory');
}
/**
* List number of files not used in packages
*/
public function numberUnusedFiles()
{
echo "<table width='950' class='tab_cadre_fixe'>";
echo "<tr>";
echo "<th>";
echo __('Unused file', 'glpiinventory');
echo "</th>";
echo "<th>";
echo __('Size', 'glpiinventory');
echo "</th>";
echo "</tr>";
$a_files = $this->find();
foreach ($a_files as $data) {
$cnt = countElementsInTable(
'glpi_plugin_glpiinventory_deploypackages',
['json' => ['LIKE', '%"' . $data['sha512'] . '"%']]
);
if ($cnt == 0) {
echo "<tr class='tab_bg_1'>";
echo "<td>";
echo $data['name'];
echo "</td>";
echo "<td>";
echo round($data['filesize'] / 1000000, 1) . " " . __('Mio');
echo "</td>";
echo "</tr>";
}
}
echo "</table>";
}
/**
* Delete the files not used in packages
*/
public function deleteUnusedFiles()
{
$a_files = $this->find();
foreach ($a_files as $data) {
$cnt = countElementsInTable(
'glpi_plugin_glpiinventory_deploypackages',
['json' => ['LIKE', '%"' . $data['sha512'] . '"%']]
);
if ($cnt == 0) {
$this->delete($data);
$manifest_filename = PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $data['sha512'];
if (file_exists($manifest_filename)) {
$handle = @fopen($manifest_filename, "r");
if ($handle) {
while (!feof($handle)) {
$buffer = trim(fgets($handle));
if ($buffer != '') {
$part_path = $this->getDirBySha512($buffer) . "/" . $buffer;
unlink(PLUGIN_GLPI_INVENTORY_REPOSITORY_DIR . $part_path);
}
}
fclose($handle);
}
unlink($manifest_filename);
}
}
}
}
}