mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-27 22:24:12 +01:00
Compare commits
84 Commits
feature/ne
...
feature/91
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ddba19416 | ||
|
|
270e8fdb91 | ||
|
|
f0629724ea | ||
|
|
9b6d321ab0 | ||
|
|
329191aa47 | ||
|
|
6915df1409 | ||
|
|
fd68558d1c | ||
|
|
bd9129dee2 | ||
|
|
fe34a6f9c3 | ||
|
|
24aec0d08d | ||
|
|
a287527d29 | ||
|
|
a42b061f19 | ||
|
|
c4d7c89553 | ||
|
|
5b58e40fc9 | ||
|
|
2b21556c76 | ||
|
|
77626f8159 | ||
|
|
bb6248a6e7 | ||
|
|
130d98aa3f | ||
|
|
00c590232a | ||
|
|
97828225db | ||
|
|
03e59c9749 | ||
|
|
985a49dc9f | ||
|
|
adae35ccc4 | ||
|
|
f0c9629f5f | ||
|
|
4e96b297c2 | ||
|
|
ae620c6663 | ||
|
|
b5c51a2983 | ||
|
|
3b2d845c00 | ||
|
|
36c545a6c4 | ||
|
|
5ecb4936f0 | ||
|
|
af2c3b02bc | ||
|
|
cfc933b92b | ||
|
|
0582ae1038 | ||
|
|
13c18b611c | ||
|
|
8d2e0761e0 | ||
|
|
1e15eb1161 | ||
|
|
7df59427cb | ||
|
|
d647d92acf | ||
|
|
693e40b9c7 | ||
|
|
c3c2135ecc | ||
|
|
63e473e6d0 | ||
|
|
3a3f5736c0 | ||
|
|
0996e8fae0 | ||
|
|
43bd621731 | ||
|
|
d1e91087b9 | ||
|
|
73cb58a131 | ||
|
|
d1fde89129 | ||
|
|
1f4b96798a | ||
|
|
9768ffb19d | ||
|
|
e55bbf728b | ||
|
|
5f2604c610 | ||
|
|
57b3610100 | ||
|
|
9f3b8ec964 | ||
|
|
193c980057 | ||
|
|
fdfe9224c3 | ||
|
|
774fe22ece | ||
|
|
27b0f64328 | ||
|
|
8ad4670a2f | ||
|
|
f2e682c07c | ||
|
|
83973d102f | ||
|
|
85e28931f5 | ||
|
|
d33ca81198 | ||
|
|
1ef4462517 | ||
|
|
a2b0ad6c11 | ||
|
|
7844c9ffd0 | ||
|
|
1c45a4c49e | ||
|
|
8f47ca00a7 | ||
|
|
f9a1b444ab | ||
|
|
3b38dac8c6 | ||
|
|
b967fb7f20 | ||
|
|
195038c941 | ||
|
|
9a8d87e2b5 | ||
|
|
385302c44c | ||
|
|
b563f113d0 | ||
|
|
715d9d3b1c | ||
|
|
7a6c2bc6a4 | ||
|
|
8919184ef9 | ||
|
|
7bfaebe4db | ||
|
|
8e10cf9b72 | ||
|
|
9f3d7d2c36 | ||
|
|
ae980e365d | ||
|
|
a2b01b3ed4 | ||
|
|
9cdc707bc5 | ||
|
|
76178c16b8 |
14
.github/workflows/action.yml
vendored
14
.github/workflows/action.yml
vendored
@@ -26,23 +26,13 @@ jobs:
|
||||
|
||||
fi
|
||||
|
||||
- name: Add internal tag if member of the organization
|
||||
- name: Add internal tag if member
|
||||
if: env.is_member == 'true'
|
||||
run: |
|
||||
curl -X POST -H "Authorization: token ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
https://api.github.com/repos/Combodo/iTop/issues/${{ github.event.pull_request.number }}/labels \
|
||||
-d '{"labels":["internal"]}'
|
||||
|
||||
- name: Set PR author as assignee if member of the organization
|
||||
if: env.is_member == 'true'
|
||||
run: |
|
||||
curl -L \
|
||||
-X POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
|
||||
https://api.github.com/repos/Combodo/iTop/issues/${{ github.event.pull_request.number }}/assignees \
|
||||
-d '{"assignees":["${{ github.event.pull_request.user.login }}"]}'
|
||||
env:
|
||||
is_member: ${{ env.is_member }}
|
||||
|
||||
@@ -50,4 +40,4 @@ jobs:
|
||||
uses: actions/add-to-project@v1.0.2
|
||||
with:
|
||||
project-url: ${{ env.project_url }}
|
||||
github-token: ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}
|
||||
github-token: ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace PHPSTORM_META
|
||||
{
|
||||
override(\MetaModel::NewObject(0), map([
|
||||
'' => '@',
|
||||
]));
|
||||
override(\MetaModel::GetObject(0), map([
|
||||
'' => '@',
|
||||
]));
|
||||
}
|
||||
@@ -16,5 +16,5 @@ require_once(APPROOT.'/application/audit.category.class.inc.php');
|
||||
require_once(APPROOT.'/application/audit.domain.class.inc.php');
|
||||
require_once(APPROOT.'/application/audit.rule.class.inc.php');
|
||||
require_once(APPROOT.'/application/query.class.inc.php');
|
||||
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
|
||||
require_once(APPROOT.'/setup/moduleinstallation/moduleinstallation.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
|
||||
1624
application/dashboard.class.inc.php
Normal file
1624
application/dashboard.class.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,6 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\Dashlet\Service\DashletService;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardColumn;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
||||
@@ -31,7 +30,7 @@ use Combodo\iTop\Application\WebPage\WebPage;
|
||||
*/
|
||||
abstract class DashboardLayout
|
||||
{
|
||||
abstract public function Render($oPage, $aDashlets, $bEditMode = false, array $aExtraParams = []);
|
||||
abstract public function Render($oPage, $aDashlets, $bEditMode = false);
|
||||
|
||||
/**
|
||||
* @param int $iCellIdx
|
||||
@@ -44,8 +43,8 @@ abstract class DashboardLayout
|
||||
public static function GetInfo()
|
||||
{
|
||||
return [
|
||||
'label' => '',
|
||||
'icon' => '',
|
||||
'label' => '',
|
||||
'icon' => '',
|
||||
'description' => '',
|
||||
];
|
||||
}
|
||||
@@ -75,7 +74,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
}
|
||||
$idx++;
|
||||
}
|
||||
|
||||
return $aDashlets;
|
||||
}
|
||||
|
||||
@@ -96,7 +94,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
}
|
||||
$idx++;
|
||||
}
|
||||
|
||||
return $aCells;
|
||||
|
||||
}
|
||||
@@ -109,39 +106,26 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
*/
|
||||
public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = [])
|
||||
{
|
||||
/** @var DashletService $oDashletService */
|
||||
$oDashletService = MetaModel::GetService('DashletService');
|
||||
// Trim the list of cells to remove the invisible/empty ones at the end of the array
|
||||
$aCells = $this->TrimCellsArray($aCells);
|
||||
|
||||
$oDashboardLayout = new DashboardLayoutUIBlock($aExtraParams['dashboard_div_id']);
|
||||
$oDashboardLayout = new DashboardLayoutUIBlock();
|
||||
//$oPage->AddUiBlock($oDashboardLayout);
|
||||
|
||||
$iCellIdx = 0;
|
||||
$iNbRows = ceil(count($aCells) / $this->iNbCols);
|
||||
|
||||
// GRID LAYOUT: Global positioning
|
||||
$iGridCurrentX = 0;
|
||||
$iGridCurrentY = 0;
|
||||
$iGridColWidth = (int)(12 / $this->iNbCols);
|
||||
|
||||
//Js given by each dashlet to reload
|
||||
$sJSReload = "";
|
||||
$oDashboardGrid = new \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardGrid();
|
||||
$oDashboardLayout->SetGrid($oDashboardGrid);
|
||||
|
||||
for ($iRows = 0; $iRows < $iNbRows; $iRows++) {
|
||||
$oDashboardRow = new DashboardRow();
|
||||
|
||||
// GRID LAYOUT: Store the maximum column Y in this row
|
||||
$iGridMaxColY = -1;
|
||||
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||
|
||||
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
||||
$oDashboardColumn = new DashboardColumn($bEditMode);
|
||||
$oDashboardColumn->SetCellIndex($iCellIdx);
|
||||
|
||||
// GRID LAYOUT: Column positioning
|
||||
$iGridCurrentColX = 0;
|
||||
$iGridCurrentColY = 0;
|
||||
$iGridMaxHeightDashlet = -1;
|
||||
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
||||
|
||||
if (array_key_exists($iCellIdx, $aCells)) {
|
||||
$aDashlets = $aCells[$iCellIdx];
|
||||
@@ -149,41 +133,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
/** @var \Dashlet $oDashlet */
|
||||
foreach ($aDashlets as $oDashlet) {
|
||||
if ($oDashlet::IsVisible()) {
|
||||
$sDashletId = $oDashlet->GetID();
|
||||
$sDashletClass = $oDashlet->GetDashletType();
|
||||
$aDashletDenormalizedProperties = $oDashlet->GetModelData();
|
||||
$aDashletsInfo = $oDashletService->GetDashletDefinition($sDashletClass);
|
||||
|
||||
// GRID LAYOUT: Set position relative to grid
|
||||
$iPositionX = $iGridCurrentX + $iGridCurrentColX;
|
||||
$iPositionY = $iGridCurrentY + $iGridCurrentColY;
|
||||
$iWidth = array_key_exists('preferred_width', $aDashletsInfo) ? $aDashletsInfo['preferred_width'] : 1;
|
||||
// GRID LAYOUT: Limit dashlet width to fit column width
|
||||
if ($iWidth > $iGridColWidth) {
|
||||
$iWidth = $iGridColWidth;
|
||||
}
|
||||
$iHeight = array_key_exists('preferred_height', $aDashletsInfo) ? $aDashletsInfo['preferred_height'] : 1;
|
||||
// GRID LAYOUT: Store max height of dashlets in this current column
|
||||
if ($iHeight > $iGridMaxHeightDashlet) {
|
||||
$iGridMaxHeightDashlet = $iHeight;
|
||||
}
|
||||
// GRID LAYOUT: Ensure that dashlet fits in the current row of the column
|
||||
if ($iGridCurrentColX + $iWidth > $iGridColWidth) {
|
||||
$iPositionX = $iGridCurrentX;
|
||||
$iPositionY++;
|
||||
}
|
||||
|
||||
$oDashboardGrid->AddDashlet($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams), $sDashletId, $sDashletClass, $aDashletDenormalizedProperties, $iPositionX, $iPositionY, $iWidth, $iHeight);
|
||||
|
||||
// GRID LAYOUT: Update column cursor
|
||||
$iGridCurrentColX += $iWidth;
|
||||
if ($iGridCurrentColX >= $iGridColWidth) {
|
||||
$iGridCurrentColX = 0;
|
||||
$iGridCurrentColY += $iGridMaxHeightDashlet;
|
||||
$iGridMaxHeightDashlet = -1;
|
||||
}
|
||||
|
||||
//$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
|
||||
$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -193,25 +143,10 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||
}
|
||||
$iCellIdx++;
|
||||
|
||||
// GRID LAYOUT: Store max y in this current row
|
||||
if ($iGridCurrentColY > $iGridMaxColY) {
|
||||
$iGridMaxColY = $iGridCurrentColY;
|
||||
}
|
||||
|
||||
// GRID LAYOUT: Next column
|
||||
$iGridCurrentX += $iGridColWidth;
|
||||
|
||||
}
|
||||
|
||||
// GRID LAYOUT: Next Row
|
||||
$iGridCurrentY += ($iGridMaxColY + 1);
|
||||
$iGridCurrentX = 0;
|
||||
|
||||
$sJSReload .= $oDashboardRow->GetJSRefreshCallback()." ";
|
||||
}
|
||||
|
||||
// TODO 3.3 We can probably do better with the new dashboard
|
||||
$oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}");
|
||||
|
||||
if ($bEditMode) { // Add one row for extensibility
|
||||
@@ -233,8 +168,8 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
*/
|
||||
public function GetDashletCoordinates($iCellIdx)
|
||||
{
|
||||
$iColNumber = (int)$iCellIdx % $this->iNbCols;
|
||||
$iRowNumber = (int)floor($iCellIdx / $this->iNbCols);
|
||||
$iColNumber = (int) $iCellIdx % $this->iNbCols;
|
||||
$iRowNumber = (int) floor($iCellIdx / $this->iNbCols);
|
||||
|
||||
return [$iColNumber, $iRowNumber];
|
||||
}
|
||||
@@ -247,12 +182,11 @@ class DashboardLayoutOneCol extends DashboardLayoutMultiCol
|
||||
parent::__construct();
|
||||
$this->iNbCols = 1;
|
||||
}
|
||||
|
||||
public static function GetInfo()
|
||||
{
|
||||
return [
|
||||
'label' => 'One Column',
|
||||
'icon' => 'images/layout_1col.png',
|
||||
'label' => 'One Column',
|
||||
'icon' => 'images/layout_1col.png',
|
||||
'description' => '',
|
||||
];
|
||||
}
|
||||
@@ -265,12 +199,11 @@ class DashboardLayoutTwoCols extends DashboardLayoutMultiCol
|
||||
parent::__construct();
|
||||
$this->iNbCols = 2;
|
||||
}
|
||||
|
||||
public static function GetInfo()
|
||||
{
|
||||
return [
|
||||
'label' => 'Two Columns',
|
||||
'icon' => 'images/layout_2col.png',
|
||||
'label' => 'Two Columns',
|
||||
'icon' => 'images/layout_2col.png',
|
||||
'description' => '',
|
||||
];
|
||||
}
|
||||
@@ -283,12 +216,11 @@ class DashboardLayoutThreeCols extends DashboardLayoutMultiCol
|
||||
parent::__construct();
|
||||
$this->iNbCols = 3;
|
||||
}
|
||||
|
||||
public static function GetInfo()
|
||||
{
|
||||
return [
|
||||
'label' => 'Two Columns',
|
||||
'icon' => 'images/layout_3col.png',
|
||||
'label' => 'Two Columns',
|
||||
'icon' => 'images/layout_3col.png',
|
||||
'description' => '',
|
||||
];
|
||||
}
|
||||
|
||||
2337
application/dashlet.class.inc.php
Normal file
2337
application/dashlet.class.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://www.combodo.com/itop-schema/3.3"
|
||||
version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<classes>
|
||||
<class id="AbstractResource" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
<comment>/* Resource access control abstraction. Can be inherited by abstract resource access control classes. Generally controlled using UR_ACTION_MODIFY access right. */</comment>
|
||||
<comment>/* Resource access control abstraction. Can be herited by abstract resource access control classes. Generaly controlled using UR_ACTION_MODIFY access right. */</comment>
|
||||
<abstract>true</abstract>
|
||||
</properties>
|
||||
<presentation/>
|
||||
@@ -554,7 +552,7 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att
|
||||
<description><![CDATA[Inform the listeners about the connection states]]></description>
|
||||
<event_data>
|
||||
<event_datum id="code">
|
||||
<description>The login step result code (LoginWebPage::EXIT_CODE_...)</description>
|
||||
<description>The login step result code (LoginWebPage::EXIT_CODE_...) </description>
|
||||
<type>integer</type>
|
||||
</event_datum>
|
||||
<event_datum id="state">
|
||||
@@ -851,461 +849,5 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att
|
||||
</methods>
|
||||
</class>
|
||||
</classes>
|
||||
<dashlets>
|
||||
<dashlet id="DashletGroupByTable" _delta="define">
|
||||
<label>UI:DashletGroupByTable:Label</label>
|
||||
<icon>images/dashlets/icons8-transaction-list-48.png</icon>
|
||||
<description>UI:DashletGroupByTable:Description</description>
|
||||
<min_width>3</min_width>
|
||||
<min_height>2</min_height>
|
||||
<preferred_width>6</preferred_width>
|
||||
<preferred_height>3</preferred_height>
|
||||
<can_create_by_oql>true</can_create_by_oql>
|
||||
<configuration/>
|
||||
</dashlet>
|
||||
<dashlet id="DashletGroupByBars" _delta="define">
|
||||
<label>UI:DashletGroupByBars:Label</label>
|
||||
<icon>images/dashlets/icons8-bar-chart-48.png</icon>
|
||||
<description>UI:DashletGroupByBars:Description</description>
|
||||
<min_width>2</min_width>
|
||||
<min_height>2</min_height>
|
||||
<preferred_width>6</preferred_width>
|
||||
<preferred_height>3</preferred_height>
|
||||
<can_create_by_oql>true</can_create_by_oql>
|
||||
<configuration/>
|
||||
</dashlet>
|
||||
<dashlet id="DashletGroupByPie" _delta="define">
|
||||
<label>UI:DashletGroupByPie:Label</label>
|
||||
<icon>images/dashlets/icons8-pie-chart-48.png</icon>
|
||||
<description>UI:DashletGroupByPie:Description</description>
|
||||
<min_width>2</min_width>
|
||||
<min_height>2</min_height>
|
||||
<preferred_width>6</preferred_width>
|
||||
<preferred_height>3</preferred_height>
|
||||
<can_create_by_oql>true</can_create_by_oql>
|
||||
<configuration/>
|
||||
</dashlet>
|
||||
<dashlet id="DashletBadge" _delta="define">
|
||||
<label>UI:DashletBadge:Label</label>
|
||||
<icon>images/dashlets/icons8-badge-48.png</icon>
|
||||
<description>UI:DashletBadge:Description</description>
|
||||
<min_width>2</min_width>
|
||||
<min_height>1</min_height>
|
||||
<preferred_width>3</preferred_width>
|
||||
<preferred_height>1</preferred_height>
|
||||
<configuration/>
|
||||
</dashlet>
|
||||
<dashlet id="DashletHeaderDynamic" _delta="define">
|
||||
<label>UI:DashletHeaderDynamic:Label</label>
|
||||
<icon>images/dashlets/icons8-header-altered-48.png</icon>
|
||||
<description>UI:DashletHeaderDynamic:Description</description>
|
||||
<min_width>2</min_width>
|
||||
<min_height>1</min_height>
|
||||
<preferred_width>12</preferred_width>
|
||||
<preferred_height>2</preferred_height>
|
||||
<configuration/>
|
||||
</dashlet>
|
||||
<dashlet id="DashletHeaderStatic" _delta="define">
|
||||
<label>UI:DashletHeaderStatic:Label</label>
|
||||
<icon>images/dashlets/icons8-header-48.png</icon>
|
||||
<description>UI:DashletHeaderStatic:Description</description>
|
||||
<min_width>4</min_width>
|
||||
<min_height>1</min_height>
|
||||
<preferred_width>12</preferred_width>
|
||||
<preferred_height>1</preferred_height>
|
||||
<configuration/>
|
||||
</dashlet>
|
||||
<dashlet id="DashletObjectList" _delta="define">
|
||||
<label>UI:DashletObjectList:Label</label>
|
||||
<icon>images/dashlets/icons8-list-48.png</icon>
|
||||
<description>UI:DashletObjectList:Description</description>
|
||||
<min_width>2</min_width>
|
||||
<min_height>1</min_height>
|
||||
<preferred_width>12</preferred_width>
|
||||
<preferred_height>3</preferred_height>
|
||||
<can_create_by_oql>true</can_create_by_oql>
|
||||
<configuration/>
|
||||
</dashlet>
|
||||
<dashlet id="DashletPlainText" _delta="define">
|
||||
<label>UI:DashletPlainText:Label</label>
|
||||
<icon>images/dashlets/icons8-text-box-48.png</icon>
|
||||
<description>UI:DashletPlainText:Description</description>
|
||||
<min_width>2</min_width>
|
||||
<min_height>1</min_height>
|
||||
<preferred_width>2</preferred_width>
|
||||
<preferred_height>1</preferred_height>
|
||||
<configuration/>
|
||||
</dashlet>
|
||||
<dashlet id="DashletUnknown" _delta="define">
|
||||
<label>UI:DashletUnknown:Label</label>
|
||||
<icon>images/dashlet-unknown.png</icon>
|
||||
<description>UI:DashletUnknown:Description</description>
|
||||
<can_be_created>false</can_be_created>
|
||||
<configuration/>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
<property_types _delta="define">
|
||||
<property_type id="Dashboard" xsi:type="Combodo-AbstractPropertyType"/>
|
||||
<property_type id="DashboardGrid" xsi:type="Combodo-PropertyType">
|
||||
<extends>Dashboard</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<label>Dashboard</label>
|
||||
<nodes>
|
||||
<node id="title" xsi:type="Combodo-ValueType-String">
|
||||
<label>UI:DashboardEdit:DashboardTitle</label>
|
||||
</node>
|
||||
<node id="refresh" xsi:type="Combodo-ValueType-Choice"> <!-- Possible de le cacher, etc celui-ci nous met dedans -->
|
||||
<label>UI:DashboardEdit:AutoReload</label>
|
||||
<values>
|
||||
<value id="0">
|
||||
<label>No auto-refresh</label>
|
||||
</value>
|
||||
<value id="30">
|
||||
<label>Every 30 seconds</label>
|
||||
</value>
|
||||
<value id="60">
|
||||
<label>Every 1 minute</label>
|
||||
</value>
|
||||
<value id="300">
|
||||
<label>Every 5 minutes</label>
|
||||
</value>
|
||||
<value id="600">
|
||||
<label>Every 10 minutes</label>
|
||||
</value>
|
||||
<value id="1800">
|
||||
<label>Every 30 minutes</label>
|
||||
</value>
|
||||
<value id="3600">
|
||||
<label>Every 1 hour</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
<node id="pos_dashlets" xsi:type="Combodo-ValueType-Collection">
|
||||
<label>Dashlet List</label>
|
||||
<xml-format xsi:type="Combodo-XMLFormat-CollectionWithId">
|
||||
<tag-name>pos_dashlet</tag-name>
|
||||
</xml-format>
|
||||
<prototype>
|
||||
<node id="position_x" xsi:type="Combodo-ValueType-Integer">
|
||||
<label>X</label>
|
||||
</node>
|
||||
<node id="position_y" xsi:type="Combodo-ValueType-Integer">
|
||||
<label>Y</label>
|
||||
</node>
|
||||
<node id="width" xsi:type="Combodo-ValueType-Integer">
|
||||
<label>W</label>
|
||||
</node>
|
||||
<node id="height" xsi:type="Combodo-ValueType-Integer">
|
||||
<label>H</label>
|
||||
</node>
|
||||
<node id="dashlet" xsi:type="Combodo-ValueType-Polymorphic">
|
||||
<label>Dashlet</label>
|
||||
<allowed-types>
|
||||
<allowed-type>Dashlet</allowed-type>
|
||||
</allowed-types>
|
||||
</node>
|
||||
</prototype>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
<property_type id="Dashlet" xsi:type="Combodo-AbstractPropertyType"/>
|
||||
<property_type id="DashletGroupByTable" xsi:type="Combodo-PropertyType">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<label>UI:DashletGroupBy:Title</label>
|
||||
<nodes>
|
||||
<node id="title" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:DashletGroupBy:Prop-Title</label>
|
||||
</node>
|
||||
<node id="query" xsi:type="Combodo-ValueType-OQL">
|
||||
<label>UI:DashletGroupBy:Prop-Query</label>
|
||||
</node>
|
||||
<node id="group_by" xsi:type="Combodo-ValueType-ClassAttributeGroupBy">
|
||||
<label>UI:DashletGroupBy:Prop-GroupBy</label>
|
||||
<class>{{query.selected_class}}</class>
|
||||
</node>
|
||||
<node id="style" xsi:type="Combodo-ValueType-Choice"> <!-- Possible de le cacher, etc celui-ci nous met dedans -->
|
||||
<label>UI:DashletGroupBy:Prop-Style</label>
|
||||
<values>
|
||||
<value id="bars">
|
||||
<label>UI:DashletGroupByBars:Label</label>
|
||||
</value>
|
||||
<value id="pie">
|
||||
<label>UI:DashletGroupByPie:Label</label>
|
||||
</value>
|
||||
<value id="table">
|
||||
<label>UI:DashletGroupByTable:Label</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
<node id="aggregation_function" xsi:type="Combodo-ValueType-AggregateFunction">
|
||||
<label>UI:DashletGroupBy:Prop-Function</label>
|
||||
<class>{{query.selected_class}}</class> <!-- pour savoir si il y a des attributs additionnables -->
|
||||
</node>
|
||||
<node id="aggregation_attribute" xsi:type="Combodo-ValueType-ClassAttribute">
|
||||
<label>UI:DashletGroupBy:Prop-FunctionAttribute</label>
|
||||
<relevance-condition>{{aggregation_function.value != 'count'}}</relevance-condition>
|
||||
<class>{{query.selected_class}}</class>
|
||||
<category>numeric</category>
|
||||
</node>
|
||||
<node id="order_by" xsi:type="Combodo-ValueType-ChoiceFromInput">
|
||||
<label>UI:DashletGroupBy:Prop-OrderField</label>
|
||||
<values>
|
||||
<value id="attribute">
|
||||
<label>{{aggregation_attribute.label}}</label>
|
||||
</value>
|
||||
<value id="function">
|
||||
<label>{{aggregation_function.label}}</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
<node id="limit" xsi:type="Combodo-ValueType-Integer">
|
||||
<label>UI:DashletGroupBy:Prop-Limit</label>
|
||||
<relevance-condition>{{order_by.value = 'function'}}</relevance-condition>
|
||||
</node>
|
||||
<node id="order_direction" xsi:type="Combodo-ValueType-Choice">
|
||||
<label>UI:DashletGroupBy:Prop-OrderDirection</label>
|
||||
<values>
|
||||
<value id="asc">
|
||||
<label>UI:DashletGroupBy:Order:asc</label>
|
||||
</value>
|
||||
<value id="desc">
|
||||
<label>UI:DashletGroupBy:Order:desc</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
<property_type id="DashletGroupByBars" xsi:type="Combodo-PropertyType">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<label>UI:DashletGroupBy:Title</label>
|
||||
<nodes>
|
||||
<node id="title" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:DashletGroupBy:Prop-Title</label>
|
||||
</node>
|
||||
<node id="query" xsi:type="Combodo-ValueType-OQL">
|
||||
<label>UI:DashletGroupBy:Prop-Query</label>
|
||||
</node>
|
||||
<node id="group_by" xsi:type="Combodo-ValueType-ClassAttributeGroupBy">
|
||||
<label>UI:DashletGroupBy:Prop-GroupBy</label>
|
||||
<class>{{query.selected_class}}</class>
|
||||
</node>
|
||||
<node id="style" xsi:type="Combodo-ValueType-Choice"> <!-- Possible de le cacher, etc celui-ci nous met dedans -->
|
||||
<label>UI:DashletGroupBy:Prop-Style</label>
|
||||
<values>
|
||||
<value id="bars">
|
||||
<label>UI:DashletGroupByBars:Label</label>
|
||||
</value>
|
||||
<value id="pie">
|
||||
<label>UI:DashletGroupByPie:Label</label>
|
||||
</value>
|
||||
<value id="table">
|
||||
<label>UI:DashletGroupByTable:Label</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
<node id="aggregation_function" xsi:type="Combodo-ValueType-AggregateFunction">
|
||||
<label>UI:DashletGroupBy:Prop-Function</label>
|
||||
<class>{{query.selected_class}}</class> <!-- pour savoir si il y a des attributs additionnables -->
|
||||
</node>
|
||||
<node id="aggregation_attribute" xsi:type="Combodo-ValueType-ClassAttribute">
|
||||
<label>UI:DashletGroupBy:Prop-FunctionAttribute</label>
|
||||
<relevance-condition>{{aggregation_function.value != 'count'}}</relevance-condition>
|
||||
<class>{{query.selected_class}}</class>
|
||||
<category>numeric</category>
|
||||
</node>
|
||||
<node id="order_by" xsi:type="Combodo-ValueType-ChoiceFromInput">
|
||||
<label>UI:DashletGroupBy:Prop-OrderField</label>
|
||||
<values>
|
||||
<value id="attribute">
|
||||
<label>{{aggregation_attribute.label}}</label>
|
||||
</value>
|
||||
<value id="function">
|
||||
<label>{{aggregation_function.label}}</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
<node id="limit" xsi:type="Combodo-ValueType-Integer">
|
||||
<label>UI:DashletGroupBy:Prop-Limit</label>
|
||||
<relevance-condition>{{order_by.value = 'function'}}</relevance-condition>
|
||||
</node>
|
||||
<node id="order_direction" xsi:type="Combodo-ValueType-Choice">
|
||||
<label>UI:DashletGroupBy:Prop-OrderDirection</label>
|
||||
<values>
|
||||
<value id="asc">
|
||||
<label>UI:DashletGroupBy:Order:asc</label>
|
||||
</value>
|
||||
<value id="desc">
|
||||
<label>UI:DashletGroupBy:Order:desc</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
<property_type id="DashletGroupByPie" xsi:type="Combodo-PropertyType">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<label>UI:DashletGroupBy:Title</label>
|
||||
<nodes>
|
||||
<node id="title" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:DashletGroupBy:Prop-Title</label>
|
||||
</node>
|
||||
<node id="query" xsi:type="Combodo-ValueType-OQL">
|
||||
<label>UI:DashletGroupBy:Prop-Query</label>
|
||||
</node>
|
||||
<node id="group_by" xsi:type="Combodo-ValueType-ClassAttributeGroupBy">
|
||||
<label>UI:DashletGroupBy:Prop-GroupBy</label>
|
||||
<class>{{query.selected_class}}</class>
|
||||
</node>
|
||||
<node id="style" xsi:type="Combodo-ValueType-Choice"> <!-- Possible de le cacher, etc celui-ci nous met dedans -->
|
||||
<label>UI:DashletGroupBy:Prop-Style</label>
|
||||
<values>
|
||||
<value id="bars">
|
||||
<label>UI:DashletGroupByBars:Label</label>
|
||||
</value>
|
||||
<value id="pie">
|
||||
<label>UI:DashletGroupByPie:Label</label>
|
||||
</value>
|
||||
<value id="table">
|
||||
<label>UI:DashletGroupByTable:Label</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
<node id="aggregation_function" xsi:type="Combodo-ValueType-AggregateFunction">
|
||||
<label>UI:DashletGroupBy:Prop-Function</label>
|
||||
<class>{{query.selected_class}}</class> <!-- pour savoir si il y a des attributs additionnables -->
|
||||
</node>
|
||||
<node id="aggregation_attribute" xsi:type="Combodo-ValueType-ClassAttribute">
|
||||
<label>UI:DashletGroupBy:Prop-FunctionAttribute</label>
|
||||
<relevance-condition>{{aggregation_function.value != 'count'}}</relevance-condition>
|
||||
<class>{{query.selected_class}}</class>
|
||||
<category>numeric</category>
|
||||
</node>
|
||||
<node id="order_by" xsi:type="Combodo-ValueType-ChoiceFromInput">
|
||||
<label>UI:DashletGroupBy:Prop-OrderField</label>
|
||||
<values>
|
||||
<value id="attribute">
|
||||
<label>{{aggregation_attribute.label}}</label>
|
||||
</value>
|
||||
<value id="function">
|
||||
<label>{{aggregation_function.label}}</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
<node id="limit" xsi:type="Combodo-ValueType-Integer">
|
||||
<label>UI:DashletGroupBy:Prop-Limit</label>
|
||||
<relevance-condition>{{order_by.value = 'function'}}</relevance-condition>
|
||||
</node>
|
||||
<node id="order_direction" xsi:type="Combodo-ValueType-Choice">
|
||||
<label>UI:DashletGroupBy:Prop-OrderDirection</label>
|
||||
<values>
|
||||
<value id="asc">
|
||||
<label>UI:DashletGroupBy:Order:asc</label>
|
||||
</value>
|
||||
<value id="desc">
|
||||
<label>UI:DashletGroupBy:Order:desc</label>
|
||||
</value>
|
||||
</values>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
<property_type id="DashletBadge" xsi:type="Combodo-PropertyType">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<nodes>
|
||||
<node id="class" xsi:type="Combodo-ValueType-Class">
|
||||
<label>UI:DashletBadge:Prop-Class</label>
|
||||
<categories-csv>bizmodel</categories-csv>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
<property_type id="DashletHeaderDynamic" xsi:type="Combodo-PropertyType">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<label>UI:DashletHeaderDynamic:Title</label>
|
||||
<nodes>
|
||||
<node id="title" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:DashletHeaderDynamic:Prop-Title</label>
|
||||
</node>
|
||||
<node id="icon" xsi:type="Combodo-ValueType-Icon">
|
||||
<label>UI:DashletHeaderDynamic:Prop-Icon</label>
|
||||
</node>
|
||||
<node id="subtitle" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:DashletHeaderDynamic:Prop-Subtitle</label>
|
||||
</node>
|
||||
<node id="query" xsi:type="Combodo-ValueType-OQL">
|
||||
<label>UI:DashletHeaderDynamic:Prop-Query</label>
|
||||
</node>
|
||||
<node id="group_by" xsi:type="Combodo-ValueType-ClassAttribute">
|
||||
<label>UI:DashletHeaderDynamic:Prop-GroupBy</label>
|
||||
<class>{{query.selected_class}}</class>
|
||||
<category>enum</category>
|
||||
</node>
|
||||
<node id="values" xsi:type="Combodo-ValueType-CollectionOfValues">
|
||||
<label>UI:DashletHeaderDynamic:Prop-Values</label>
|
||||
<xml-format xsi:type="Combodo-XMLFormat-CSV"/>
|
||||
<value-type xsi:type="Combodo-ValueType-ClassAttributeValue">
|
||||
<class>{{query.selected_class}}</class>
|
||||
<attribute>{{group_by.attribute}}</attribute>
|
||||
</value-type>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
<property_type id="DashletHeaderStatic" xsi:type="Combodo-PropertyType">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<nodes>
|
||||
<node id="title" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:DashletHeaderStatic:Prop-Title</label>
|
||||
</node>
|
||||
<node id="icon" xsi:type="Combodo-ValueType-Icon">
|
||||
<label>UI:DashletHeaderStatic:Prop-Icon</label>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
<property_type id="DashletObjectList" xsi:type="Combodo-PropertyType">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<nodes>
|
||||
<node id="title" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:DashletObjectList:Prop-Title</label>
|
||||
</node>
|
||||
<node id="query" xsi:type="Combodo-ValueType-OQL">
|
||||
<label>UI:DashletObjectList:Prop-Query</label>
|
||||
</node>
|
||||
<node id="menu" xsi:type="Combodo-ValueType-Boolean">
|
||||
<label>UI:DashletObjectList:Prop-Menu</label>
|
||||
<on>
|
||||
<!-- not so cute, but matches exactly 3.2 implementation of boolean fields -->
|
||||
<label>UI:UserManagement:ActionAllowed:Yes</label>
|
||||
<value>true</value>
|
||||
</on>
|
||||
<off>
|
||||
<label>UI:UserManagement:ActionAllowed:No</label>
|
||||
<value>false</value>
|
||||
</off>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
<property_type id="DashletPlainText" xsi:type="Combodo-PropertyType">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<nodes>
|
||||
<node id="text" xsi:type="Combodo-ValueType-Text">
|
||||
<label>UI:DashletPlainText:Prop-Text</label>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
</property_types>
|
||||
</meta>
|
||||
</itop_design>
|
||||
|
||||
@@ -984,7 +984,7 @@ JS
|
||||
$aFunctions = [$sFctVar => $oFctExpr];
|
||||
}
|
||||
|
||||
if (!empty(trim($sAggregationAttr))) {
|
||||
if (!empty($sAggregationAttr)) {
|
||||
$sClass = $this->m_oFilter->GetClass();
|
||||
$sAggregationAttr = MetaModel::GetLabel($sClass, $sAggregationAttr);
|
||||
}
|
||||
@@ -1608,9 +1608,10 @@ JS
|
||||
$iTotalCount = 0;
|
||||
$aURLs = [];
|
||||
|
||||
foreach ($aRes as $aRow) {
|
||||
foreach ($aRes as $iRow => $aRow) {
|
||||
$sValue = $aRow['grouped_by_1'];
|
||||
$sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
|
||||
$iTotalCount += $aRow['_itop_count_'];
|
||||
$aValues[] = [
|
||||
'label' => html_entity_decode(strip_tags($sHtmlValue), ENT_QUOTES, 'UTF-8'),
|
||||
'label_html' => $sHtmlValue,
|
||||
|
||||
@@ -243,12 +243,15 @@ class LoginTwigRenderer
|
||||
|
||||
public function GetDefaultVars()
|
||||
{
|
||||
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
|
||||
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
|
||||
$sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl();
|
||||
|
||||
$aVars = [
|
||||
'sAppRootUrl' => utils::GetAbsoluteUrlAppRoot(),
|
||||
'aPluginFormData' => $this->GetPluginFormData(),
|
||||
'sItopVersion' => ITOP_VERSION,
|
||||
'sVersionShort' => $sVersionShort,
|
||||
'sIconUrl' => $sIconUrl,
|
||||
'sDisplayIcon' => $sDisplayIcon,
|
||||
];
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\PageContent\PageContentFactory;
|
||||
use Combodo\iTop\Application\WebPage\ErrorPage;
|
||||
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
@@ -1219,6 +1218,7 @@ class NewObjectMenuNode extends MenuNode
|
||||
}
|
||||
}
|
||||
|
||||
require_once(APPROOT.'application/dashboard.class.inc.php');
|
||||
/**
|
||||
* This class defines a menu item which content is based on XML dashboard.
|
||||
*/
|
||||
@@ -1279,14 +1279,13 @@ class DashboardMenuNode extends MenuNode
|
||||
if ($oDashboard != null) {
|
||||
WebResourcesHelper::EnableC3JSToWebPage($oPage);
|
||||
|
||||
// TODO 3.3 this works for dashboard menu, what about other places ?
|
||||
$oPageLayout = PageContentFactory::MakeForDashboard();
|
||||
$oPage->SetContentLayout($oPageLayout, $oPage);
|
||||
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
|
||||
$oPage->add('<div id="'.$sDivId.'" class="ibo-dashboard" data-role="ibo-dashboard">');
|
||||
$aExtraParams['dashboard_div_id'] = $sDivId;
|
||||
$aExtraParams['from_dashboard_page'] = true;
|
||||
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
|
||||
$oDashboard->Render($oPage, false, $aExtraParams);
|
||||
$oPage->add('</div>');
|
||||
|
||||
$bEdit = utils::ReadParam('edit', false);
|
||||
if ($bEdit) {
|
||||
@@ -1312,6 +1311,37 @@ class DashboardMenuNode extends MenuNode
|
||||
$oPage->p("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WebPage $oPage
|
||||
* @throws CoreException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function RenderEditor(WebPage $oPage)
|
||||
{
|
||||
$oDashboard = $this->GetDashboard();
|
||||
if ($oDashboard != null) {
|
||||
$oDashboard->RenderEditor($oPage);
|
||||
} else {
|
||||
$oPage->p("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $oDashlet
|
||||
* @throws Exception
|
||||
*/
|
||||
public function AddDashlet($oDashlet)
|
||||
{
|
||||
$oDashboard = $this->GetDashboard();
|
||||
if ($oDashboard != null) {
|
||||
$oDashboard->AddDashlet($oDashlet);
|
||||
$oDashboard->Save();
|
||||
} else {
|
||||
throw new Exception("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1520,7 +1520,7 @@ class utils
|
||||
$sUploadDashboardTransactId = utils::GetNewTransactionId();
|
||||
$aResult = [
|
||||
new SeparatorPopupMenuItem(),
|
||||
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?route=dashboard.export&id='.$sDashboardId.'&file='.$sDashboardFileURL),
|
||||
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sDashboardId.'&file='.$sDashboardFileURL),
|
||||
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'), "UploadDashboard({dashboard_id: '$sDashboardId', file: '$sDashboardFileJS', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn', transaction: '$sUploadDashboardTransactId' })"),
|
||||
];
|
||||
if ($oDashboard->GetReloadURL()) {
|
||||
@@ -1900,12 +1900,6 @@ SQL;
|
||||
return $response;
|
||||
}
|
||||
|
||||
public static function QuoteForPHP(string $sValue): string
|
||||
{
|
||||
$sEscaped = str_replace(['\\', "'"], ['\\\\', "\\'"], $sValue);
|
||||
return "'$sEscaped'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a standard list of character sets
|
||||
*
|
||||
@@ -2988,12 +2982,6 @@ TXT
|
||||
return $sAcronym;
|
||||
}
|
||||
|
||||
public static function IsTrue(mixed $value): bool
|
||||
{
|
||||
$bVal = (is_string($value) ? filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) : (bool) $value);
|
||||
return ($bVal === null ? false : $bVal);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
// Text manipulation
|
||||
//----------------------------------------------
|
||||
|
||||
@@ -42,20 +42,6 @@ define('ITOP_DEFAULT_ENV', 'production');
|
||||
define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance');
|
||||
define('READONLY_MODE_FILE', APPROOT.'data/.readonly');
|
||||
|
||||
// TODO 3.3 To deprecate
|
||||
/**
|
||||
* Exclude the parent class from the list
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
define('ENUM_CHILD_CLASSES_EXCLUDETOP', 1);
|
||||
/**
|
||||
* Include the parent class in the list
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
define('ENUM_CHILD_CLASSES_ALL', 2);
|
||||
|
||||
$fItopStarted = microtime(true);
|
||||
$iItopInitialMemory = memory_get_usage(true);
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
"symfony/mailer": "^6.4",
|
||||
"symfony/security-csrf": "^6.4",
|
||||
"symfony/twig-bundle": "~6.4.0",
|
||||
"symfony/validator" : "^6.4",
|
||||
"symfony/yaml": "~6.4.0",
|
||||
"tecnickcom/tcpdf": "^6.6.0",
|
||||
"thenetworg/oauth2-azure": "^2.0"
|
||||
|
||||
161
composer.lock
generated
161
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "3e627286597661542dd598499c2bcc36",
|
||||
"content-hash": "26fa7aa920057d080bcc0948bf052fda",
|
||||
"packages": [
|
||||
{
|
||||
"name": "apereo/phpcas",
|
||||
@@ -1721,16 +1721,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/cache",
|
||||
"version": "v6.4.12",
|
||||
"version": "v6.4.24",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/cache.git",
|
||||
"reference": "a463451b7f6ac4a47b98dbfc78ec2d3560c759d8"
|
||||
"reference": "d038cd3054aeaf1c674022a77048b2ef6376a175"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/cache/zipball/a463451b7f6ac4a47b98dbfc78ec2d3560c759d8",
|
||||
"reference": "a463451b7f6ac4a47b98dbfc78ec2d3560c759d8",
|
||||
"url": "https://api.github.com/repos/symfony/cache/zipball/d038cd3054aeaf1c674022a77048b2ef6376a175",
|
||||
"reference": "d038cd3054aeaf1c674022a77048b2ef6376a175",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1797,7 +1797,7 @@
|
||||
"psr6"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/cache/tree/v6.4.12"
|
||||
"source": "https://github.com/symfony/cache/tree/v6.4.24"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1808,12 +1808,16 @@
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-16T16:01:33+00:00"
|
||||
"time": "2025-07-30T09:32:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/cache-contracts",
|
||||
@@ -3000,16 +3004,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
"version": "v6.4.29",
|
||||
"version": "v6.4.25",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-foundation.git",
|
||||
"reference": "b03d11e015552a315714c127d8d1e0f9e970ec88"
|
||||
"reference": "6bc974c0035b643aa497c58d46d9e25185e4b272"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/b03d11e015552a315714c127d8d1e0f9e970ec88",
|
||||
"reference": "b03d11e015552a315714c127d8d1e0f9e970ec88",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/6bc974c0035b643aa497c58d46d9e25185e4b272",
|
||||
"reference": "6bc974c0035b643aa497c58d46d9e25185e4b272",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3057,7 +3061,7 @@
|
||||
"description": "Defines an object-oriented layer for the HTTP specification",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v6.4.29"
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v6.4.25"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3077,7 +3081,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-08T16:40:12+00:00"
|
||||
"time": "2025-08-20T06:48:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-kernel",
|
||||
@@ -4529,16 +4533,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
"version": "v3.6.1",
|
||||
"version": "v3.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/service-contracts.git",
|
||||
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
|
||||
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
|
||||
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4592,7 +4596,7 @@
|
||||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.6.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4603,16 +4607,12 @@
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-07-15T11:30:57+00:00"
|
||||
"time": "2025-04-25T09:37:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
@@ -4983,107 +4983,6 @@
|
||||
],
|
||||
"time": "2025-07-10T08:14:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/validator",
|
||||
"version": "v6.4.29",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/validator.git",
|
||||
"reference": "99df8a769e64e399f510166141ea74f450e8dd1d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/validator/zipball/99df8a769e64e399f510166141ea74f450e8dd1d",
|
||||
"reference": "99df8a769e64e399f510166141ea74f450e8dd1d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/polyfill-ctype": "~1.8",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/polyfill-php83": "^1.27",
|
||||
"symfony/translation-contracts": "^2.5|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/annotations": "<1.13",
|
||||
"doctrine/lexer": "<1.1",
|
||||
"symfony/dependency-injection": "<5.4",
|
||||
"symfony/expression-language": "<5.4",
|
||||
"symfony/http-kernel": "<5.4",
|
||||
"symfony/intl": "<5.4",
|
||||
"symfony/property-info": "<5.4",
|
||||
"symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3",
|
||||
"symfony/yaml": "<5.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^1.13|^2",
|
||||
"egulias/email-validator": "^2.1.10|^3|^4",
|
||||
"symfony/cache": "^5.4|^6.0|^7.0",
|
||||
"symfony/config": "^5.4|^6.0|^7.0",
|
||||
"symfony/console": "^5.4|^6.0|^7.0",
|
||||
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
|
||||
"symfony/expression-language": "^5.4|^6.0|^7.0",
|
||||
"symfony/finder": "^5.4|^6.0|^7.0",
|
||||
"symfony/http-client": "^5.4|^6.0|^7.0",
|
||||
"symfony/http-foundation": "^5.4|^6.0|^7.0",
|
||||
"symfony/http-kernel": "^5.4|^6.0|^7.0",
|
||||
"symfony/intl": "^5.4|^6.0|^7.0",
|
||||
"symfony/mime": "^5.4|^6.0|^7.0",
|
||||
"symfony/property-access": "^5.4|^6.0|^7.0",
|
||||
"symfony/property-info": "^5.4|^6.0|^7.0",
|
||||
"symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3",
|
||||
"symfony/yaml": "^5.4|^6.0|^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Validator\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/",
|
||||
"/Resources/bin/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides tools to validate values",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/validator/tree/v6.4.29"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-06T20:26:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
"version": "v6.4.26",
|
||||
@@ -5174,16 +5073,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-exporter",
|
||||
"version": "v6.4.26",
|
||||
"version": "v6.4.25",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-exporter.git",
|
||||
"reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc"
|
||||
"reference": "4ff50a1b7c75d1d596aca50899d0c8c7e3de8358"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/466fcac5fa2e871f83d31173f80e9c2684743bfc",
|
||||
"reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc",
|
||||
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/4ff50a1b7c75d1d596aca50899d0c8c7e3de8358",
|
||||
"reference": "4ff50a1b7c75d1d596aca50899d0c8c7e3de8358",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5231,7 +5130,7 @@
|
||||
"serialize"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/var-exporter/tree/v6.4.26"
|
||||
"source": "https://github.com/symfony/var-exporter/tree/v6.4.25"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5251,7 +5150,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-11T09:57:09+00:00"
|
||||
"time": "2025-08-18T13:06:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
@@ -5715,5 +5614,5 @@
|
||||
"platform-overrides": {
|
||||
"php": "8.1.0"
|
||||
},
|
||||
"plugin-api-version": "2.9.0"
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ MetaModel::IncludeModule('application/user.dashboard.class.inc.php');
|
||||
MetaModel::IncludeModule('application/audit.rule.class.inc.php');
|
||||
MetaModel::IncludeModule('application/audit.domain.class.inc.php');
|
||||
MetaModel::IncludeModule('application/query.class.inc.php');
|
||||
MetaModel::IncludeModule('setup/moduleinstallation.class.inc.php');
|
||||
MetaModel::IncludeModule('setup/moduleinstallation/moduleinstallation.class.inc.php');
|
||||
|
||||
MetaModel::IncludeModule('core/event.class.inc.php');
|
||||
MetaModel::IncludeModule('core/action.class.inc.php');
|
||||
|
||||
@@ -1954,6 +1954,11 @@ class Config
|
||||
*/
|
||||
protected $m_sDefaultLanguage;
|
||||
|
||||
/**
|
||||
* @var string Type of login process allowed: form|basic|url|external
|
||||
*/
|
||||
protected $m_sAllowedLoginTypes;
|
||||
|
||||
/**
|
||||
* @var string Name of the PHP variable in which external authentication information is passed by the web server
|
||||
*/
|
||||
@@ -2027,6 +2032,7 @@ class Config
|
||||
$this->m_iFastReloadInterval = DEFAULT_FAST_RELOAD_INTERVAL;
|
||||
$this->m_bSecureConnectionRequired = DEFAULT_SECURE_CONNECTION_REQUIRED;
|
||||
$this->m_sDefaultLanguage = 'EN US';
|
||||
$this->m_sAllowedLoginTypes = DEFAULT_ALLOWED_LOGIN_TYPES;
|
||||
$this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE;
|
||||
$this->m_aCharsets = [];
|
||||
$this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED;
|
||||
@@ -2173,6 +2179,7 @@ class Config
|
||||
$this->m_aModuleSettings = isset($MyModuleSettings) ? $MyModuleSettings : [];
|
||||
|
||||
$this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US';
|
||||
$this->m_sAllowedLoginTypes = isset($MySettings['allowed_login_types']) ? trim($MySettings['allowed_login_types']) : DEFAULT_ALLOWED_LOGIN_TYPES;
|
||||
$this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE;
|
||||
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : $this->m_sEncryptionKey;
|
||||
$this->m_sEncryptionLibrary = isset($MySettings['encryption_library']) ? trim($MySettings['encryption_library']) : $this->m_sEncryptionLibrary;
|
||||
@@ -2332,7 +2339,7 @@ class Config
|
||||
|
||||
public function GetAllowedLoginTypes()
|
||||
{
|
||||
return explode('|', $this->m_aSettings['allowed_login_types']['value']);
|
||||
return explode('|', $this->m_sAllowedLoginTypes);
|
||||
}
|
||||
|
||||
public function GetExternalAuthenticationVariable()
|
||||
@@ -2410,6 +2417,7 @@ class Config
|
||||
|
||||
public function SetAllowedLoginTypes($aAllowedLoginTypes)
|
||||
{
|
||||
$this->m_sAllowedLoginTypes = implode('|', $aAllowedLoginTypes);
|
||||
$this->Set('allowed_login_types', implode('|', $aAllowedLoginTypes));
|
||||
}
|
||||
|
||||
@@ -2487,6 +2495,7 @@ class Config
|
||||
$aSettings['fast_reload_interval'] = $this->m_iFastReloadInterval;
|
||||
$aSettings['secure_connection_required'] = $this->m_bSecureConnectionRequired;
|
||||
$aSettings['default_language'] = $this->m_sDefaultLanguage;
|
||||
$aSettings['allowed_login_types'] = $this->m_sAllowedLoginTypes;
|
||||
$aSettings['ext_auth_variable'] = $this->m_sExtAuthVariable;
|
||||
$aSettings['encryption_key'] = $this->m_sEncryptionKey;
|
||||
$aSettings['encryption_library'] = $this->m_sEncryptionLibrary;
|
||||
@@ -2590,6 +2599,7 @@ class Config
|
||||
// Old fashioned remaining values
|
||||
$aOtherValues = [
|
||||
'default_language' => $this->m_sDefaultLanguage,
|
||||
'allowed_login_types' => $this->m_sAllowedLoginTypes,
|
||||
'ext_auth_variable' => $this->m_sExtAuthVariable,
|
||||
'encryption_key' => $this->m_sEncryptionKey,
|
||||
'encryption_library' => $this->m_sEncryptionLibrary,
|
||||
@@ -2675,14 +2685,13 @@ class Config
|
||||
*
|
||||
* @param array $aParamValues
|
||||
* @param ?string $sModulesDir
|
||||
* @param bool $bPreserveModuleSettings
|
||||
*
|
||||
* @return void The current object is modified directly
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function UpdateFromParams($aParamValues, $sModulesDir = null, $bPreserveModuleSettings = false)
|
||||
public function UpdateFromParams($aParamValues, $sModulesDir = null)
|
||||
{
|
||||
if (isset($aParamValues['application_path'])) {
|
||||
$this->Set('app_root_url', $aParamValues['application_path']);
|
||||
@@ -2730,7 +2739,10 @@ class Config
|
||||
} else {
|
||||
$aSelectedModules = null;
|
||||
}
|
||||
$this->UpdateIncludes($sModulesDir, $aSelectedModules);
|
||||
|
||||
if (! is_null($sModulesDir)) {
|
||||
$this->UpdateIncludes($sModulesDir, $aSelectedModules);
|
||||
}
|
||||
|
||||
if (isset($aParamValues['source_dir'])) {
|
||||
$this->Set('source_dir', $aParamValues['source_dir']);
|
||||
@@ -2748,17 +2760,13 @@ class Config
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function UpdateIncludes($sModulesDir, $aSelectedModules = null)
|
||||
public function UpdateIncludes(string $sModulesDir, $aSelectedModules = null)
|
||||
{
|
||||
if ($sModulesDir === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the arrays below with default values for the application...
|
||||
$oEmptyConfig = new Config('dummy_file', false); // Do NOT load any config file, just set the default values
|
||||
$aAddOns = $oEmptyConfig->GetAddOns();
|
||||
|
||||
$aModules = ModuleDiscovery::GetAvailableModules([APPROOT.$sModulesDir]);
|
||||
$aModules = ModuleDiscovery::GetModulesOrderedByDependencies([APPROOT.$sModulesDir]);
|
||||
foreach ($aModules as $sModuleId => $aModuleInfo) {
|
||||
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||
if (is_null($aSelectedModules) || in_array($sModuleName, $aSelectedModules)) {
|
||||
|
||||
@@ -41,7 +41,7 @@ use utils;
|
||||
/**
|
||||
* Class \Combodo\iTop\DesignDocument
|
||||
*
|
||||
* A design document is the DOM tree that models behaviors. One of its
|
||||
* A design document is the DOM tree that modelize behaviors. One of its
|
||||
* characteristics is that it can be altered by the mean of the same kind of document.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -259,18 +259,13 @@ class InlineImage extends DBObject
|
||||
* that refer to an InlineImage (detected via the attribute data-img-id="") so that
|
||||
* the URL is consistent with the current URL of the application.
|
||||
*
|
||||
N°8681 * @param string|null $sHtml The HTML fragment to process
|
||||
* @param string $sHtml The HTML fragment to process
|
||||
*
|
||||
* @return string The modified HTML
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 3.3.0 N°8681 Add type hint for parameters and return value
|
||||
*/
|
||||
public static function FixUrls(string|null $sHtml): string
|
||||
public static function FixUrls($sHtml)
|
||||
{
|
||||
// N°8681 - Ensure to have a string value
|
||||
$sHtml = $sHtml ?? '';
|
||||
|
||||
$aNeedles = [];
|
||||
$aReplacements = [];
|
||||
// Find img tags with an attribute data-img-id
|
||||
@@ -394,7 +389,7 @@ JS
|
||||
* Resize an image so that it fits the maximum width/height defined in the config file
|
||||
* @param ormDocument $oImage The original image stored as an array (content / mimetype / filename)
|
||||
* @return ormDocument The resampled image (or the original one if it already fit)
|
||||
* @deprecated since 3.3.0 Replaced by ormDocument::ResizeImageToFit
|
||||
* @deprecated Replaced by ormDocument::ResizeImageToFit
|
||||
*/
|
||||
public static function ResizeImageToFit(ormDocument $oImage, &$aDimensions = null)
|
||||
{
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\EventRegister\ApplicationEvents;
|
||||
use Combodo\iTop\Core\Kpi\KpiLogData;
|
||||
use Combodo\iTop\Service\Events\EventService;
|
||||
use Combodo\iTop\Service\Events\iEventServiceSetup;
|
||||
use Combodo\iTop\Service\Module\ModuleService;
|
||||
|
||||
/**
|
||||
* Measures operations duration, memory usage, etc. (and some other KPIs)
|
||||
*/
|
||||
class ExecutionKPI implements iEventServiceSetup
|
||||
|
||||
class ExecutionKPI
|
||||
{
|
||||
protected static $m_bEnabled_Duration = false;
|
||||
protected static $m_bEnabled_Memory = false;
|
||||
@@ -25,18 +23,15 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
|
||||
protected static $m_aStats = []; // Recurrent operations
|
||||
protected static $m_aExecData = []; // One shot operations
|
||||
/** @var true */
|
||||
private static bool $bMetamodelStarted = false;
|
||||
/**
|
||||
* @var array[ExecutionKPI]
|
||||
*/
|
||||
protected static $m_aExecutionStack = []; // embedded execution stats
|
||||
|
||||
private static ?float $fLastReportTime = null;
|
||||
private static ?float $iLastReportMemory = null;
|
||||
|
||||
// For stats
|
||||
protected $m_fStarted = null;
|
||||
protected $m_fChildrenDuration = 0; // Count embedded
|
||||
protected $m_iInitialMemory = null;
|
||||
|
||||
private static array $aBootstrapOperations = [];
|
||||
|
||||
public static function EnableDuration($iLevel)
|
||||
{
|
||||
if ($iLevel > 0) {
|
||||
@@ -76,7 +71,6 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -103,7 +97,7 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
$sFor = self::$m_sAllowedUser == '*' ? 'EVERYBODY' : "'".trim(self::$m_sAllowedUser)."'";
|
||||
$sSlowQueries = '';
|
||||
if (self::$m_fSlowQueries > 0) {
|
||||
$sSlowQueries = '. Slow Queries: '.self::$m_fSlowQueries.'s';
|
||||
$sSlowQueries = ". Slow Queries: ".self::$m_fSlowQueries."s";
|
||||
}
|
||||
|
||||
$aExtensions = [];
|
||||
@@ -133,7 +127,7 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
$sRequest .= ' operation: '.$_POST['operation'];
|
||||
}
|
||||
|
||||
$fStop = microtime(true);
|
||||
$fStop = MyHelpers::getmicrotime();
|
||||
if (($fStop - $fItopStarted) > self::$m_fSlowQueries) {
|
||||
// Invoke extensions to log the KPI operation
|
||||
/** @var \iKPILoggerExtension $oExtensionInstance */
|
||||
@@ -157,17 +151,17 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
|
||||
$sTableStyle = 'background-color: #ccc; margin: 10px;';
|
||||
|
||||
$sHtml = '<hr/>';
|
||||
$sHtml = "<hr/>";
|
||||
$sHtml .= "<div style=\"background-color: grey; padding: 10px;\">";
|
||||
$sHtml .= "<h3><a name=\"".md5($sExecId)."\">KPIs</a> - $sRequest</h3>";
|
||||
$oStarted = DateTime::createFromFormat('U.u', $fItopStarted);
|
||||
$sHtml .= '<p>'.$oStarted->format('Y-m-d H:i:s.u').'</p>';
|
||||
$sHtml .= '<p>log_kpi_user_id: '.UserRights::GetUserId().'</p>';
|
||||
$sHtml .= '<div>';
|
||||
$sHtml .= "<p>log_kpi_user_id: ".UserRights::GetUserId()."</p>";
|
||||
$sHtml .= "<div>";
|
||||
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
||||
$sHtml .= '<thead>';
|
||||
$sHtml .= ' <th>Operation</th><th>Begin</th><th>End</th><th>Duration</th><th>Memory start</th><th>Memory end</th><th>Memory peak</th>';
|
||||
$sHtml .= '</thead>';
|
||||
$sHtml .= "<thead>";
|
||||
$sHtml .= " <th>Operation</th><th>Begin</th><th>End</th><th>Duration</th><th>Memory start</th><th>Memory end</th><th>Memory peak</th>";
|
||||
$sHtml .= "</thead>";
|
||||
foreach (self::$m_aExecData as $aOpStats) {
|
||||
$sOperation = $aOpStats['op'];
|
||||
$sBegin = round($aOpStats['time_begin'], 3);
|
||||
@@ -186,12 +180,12 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
}
|
||||
}
|
||||
|
||||
$sHtml .= '<tr>';
|
||||
$sHtml .= "<tr>";
|
||||
$sHtml .= " <td>$sOperation</td><td>$sBegin</td><td>$sEnd</td><td>$sDuration</td><td>$sMemBegin</td><td>$sMemEnd</td><td>$sMemPeak</td>";
|
||||
$sHtml .= '</tr>';
|
||||
$sHtml .= "</tr>";
|
||||
}
|
||||
$sHtml .= '</table>';
|
||||
$sHtml .= '</div>';
|
||||
$sHtml .= "</table>";
|
||||
$sHtml .= "</div>";
|
||||
|
||||
$aConsolidatedStats = [];
|
||||
foreach (self::$m_aStats as $sOperation => $aOpStats) {
|
||||
@@ -214,20 +208,20 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
}
|
||||
}
|
||||
$aConsolidatedStats[$sOperation] = [
|
||||
'count' => $iTotalOp,
|
||||
'count' => $iTotalOp,
|
||||
'duration' => $fTotalOp,
|
||||
'min' => $fMinOp,
|
||||
'max' => $fMaxOp,
|
||||
'avg' => $fTotalOp / $iTotalOp,
|
||||
'min' => $fMinOp,
|
||||
'max' => $fMaxOp,
|
||||
'avg' => $fTotalOp / $iTotalOp,
|
||||
'max_args' => $sMaxOpArguments,
|
||||
];
|
||||
}
|
||||
|
||||
$sHtml .= '<div>';
|
||||
$sHtml .= "<div>";
|
||||
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
||||
$sHtml .= '<thead>';
|
||||
$sHtml .= ' <th>Operation</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th><th>Avg</th>';
|
||||
$sHtml .= '</thead>';
|
||||
$sHtml .= "<thead>";
|
||||
$sHtml .= " <th>Operation</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th><th>Avg</th>";
|
||||
$sHtml .= "</thead>";
|
||||
foreach ($aConsolidatedStats as $sOperation => $aOpStats) {
|
||||
$sOperation = '<a href="#'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
|
||||
$sCount = $aOpStats['count'];
|
||||
@@ -236,14 +230,14 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
$sMax = '<a href="#'.md5($sExecId.$aOpStats['max_args']).'">'.round($aOpStats['max'], 3).'</a>';
|
||||
$sAvg = round($aOpStats['avg'], 3);
|
||||
|
||||
$sHtml .= '<tr>';
|
||||
$sHtml .= "<tr>";
|
||||
$sHtml .= " <td>$sOperation</td><td>$sCount</td><td>$sDuration</td><td>$sMin</td><td>$sMax</td><td>$sAvg</td>";
|
||||
$sHtml .= '</tr>';
|
||||
$sHtml .= "</tr>";
|
||||
}
|
||||
$sHtml .= '</table>';
|
||||
$sHtml .= '</div>';
|
||||
$sHtml .= "</table>";
|
||||
$sHtml .= "</div>";
|
||||
|
||||
$sHtml .= '</div>';
|
||||
$sHtml .= "</div>";
|
||||
|
||||
$sHtml .= "<p><a href=\"#end-".md5($sExecId)."\">Next page stats</a></p>";
|
||||
|
||||
@@ -293,18 +287,18 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
$sOperationHtml = '<a name="'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
|
||||
$sHtml .= "<h4>$sOperationHtml</h4>";
|
||||
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
||||
$sHtml .= '<thead>';
|
||||
$sHtml .= ' <th>Operation details (+ blame caller if log_kpi_duration = 2)</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th>';
|
||||
$sHtml .= '</thead>';
|
||||
$sHtml .= "<thead>";
|
||||
$sHtml .= " <th>Operation details (+ blame caller if log_kpi_duration = 2)</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th>";
|
||||
$sHtml .= "</thead>";
|
||||
$bDisplayHeader = false;
|
||||
}
|
||||
$sHtml .= '<tr>';
|
||||
$sHtml .= "<tr>";
|
||||
$sHtml .= " <td>$sHtmlArguments</td><td>$iCountInter</td><td>$sTotalInter</td><td>$sMinInter</td><td>$sMaxInter</td>";
|
||||
$sHtml .= '</tr>';
|
||||
$sHtml .= "</tr>";
|
||||
}
|
||||
}
|
||||
if (!$bDisplayHeader) {
|
||||
$sHtml .= '</table>';
|
||||
$sHtml .= "</table>";
|
||||
$sHtml .= "<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>";
|
||||
}
|
||||
self::Report($sHtml);
|
||||
@@ -339,50 +333,39 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
|
||||
$aNewEntry = null;
|
||||
|
||||
if (is_null(static::$fLastReportTime)) {
|
||||
static::$fLastReportTime = $fItopStarted;
|
||||
}
|
||||
|
||||
if (is_null(static::$iLastReportMemory)) {
|
||||
global $iItopInitialMemory;
|
||||
static::$iLastReportMemory = $iItopInitialMemory;
|
||||
}
|
||||
|
||||
$fStarted = static::$fLastReportTime;
|
||||
$fStopped = microtime(true);
|
||||
$fStarted = $this->m_fStarted;
|
||||
$fStopped = $this->m_fStarted;
|
||||
if (self::$m_bEnabled_Duration) {
|
||||
$fStopped = MyHelpers::getmicrotime();
|
||||
$aNewEntry = [
|
||||
'op' => $sOperationDesc,
|
||||
'time_begin' => $fStarted - $fItopStarted,
|
||||
'time_begin' => $this->m_fStarted - $fItopStarted,
|
||||
'time_end' => $fStopped - $fItopStarted,
|
||||
];
|
||||
// Reset for the next operation (if the object is recycled)
|
||||
$this->m_fStarted = $fStopped;
|
||||
}
|
||||
static::$fLastReportTime = $fStopped;
|
||||
|
||||
$iInitialMemory = static::$iLastReportMemory;
|
||||
$iCurrentMemory = $iInitialMemory;
|
||||
$iPeakMemory = $iInitialMemory;
|
||||
$iInitialMemory = is_null($this->m_iInitialMemory) ? 0 : $this->m_iInitialMemory;
|
||||
$iCurrentMemory = 0;
|
||||
$iPeakMemory = 0;
|
||||
if (self::$m_bEnabled_Memory) {
|
||||
$iCurrentMemory = self::memory_get_usage();
|
||||
if (is_null($aNewEntry)) {
|
||||
$aNewEntry = ['op' => $sOperationDesc];
|
||||
}
|
||||
$aNewEntry['mem_begin'] = $iInitialMemory;
|
||||
$aNewEntry['mem_begin'] = $this->m_iInitialMemory;
|
||||
$aNewEntry['mem_end'] = $iCurrentMemory;
|
||||
$iPeakMemory = self::memory_get_peak_usage();
|
||||
$aNewEntry['mem_peak'] = $iPeakMemory;
|
||||
// Reset for the next operation (if the object is recycled)
|
||||
static::$iLastReportMemory = $iCurrentMemory;
|
||||
$this->m_iInitialMemory = $iCurrentMemory;
|
||||
}
|
||||
|
||||
if (self::$m_bEnabled_Duration || self::$m_bEnabled_Memory) {
|
||||
$aCallstack = ['callstack' => $this->GetCallStack()];
|
||||
if (static::$bMetamodelStarted) {
|
||||
foreach (static::$aBootstrapOperations as $oLog) {
|
||||
$this->LogOperation($oLog);
|
||||
}
|
||||
static::$aBootstrapOperations = [];
|
||||
// Invoke extensions to log the KPI operation
|
||||
// Invoke extensions to log the KPI operation
|
||||
/** @var \iKPILoggerExtension $oExtensionInstance */
|
||||
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
|
||||
$sExtension = ModuleService::GetInstance()->GetModuleNameFromCallStack(1);
|
||||
$oKPILogData = new KpiLogData(
|
||||
KpiLogData::TYPE_REPORT,
|
||||
@@ -393,24 +376,9 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
$sExtension,
|
||||
$iInitialMemory,
|
||||
$iCurrentMemory,
|
||||
$iPeakMemory,
|
||||
$aCallstack
|
||||
$iPeakMemory
|
||||
);
|
||||
$this->LogOperation($oKPILogData);
|
||||
} else {
|
||||
$oKPILogData = new KpiLogData(
|
||||
KpiLogData::TYPE_REPORT,
|
||||
'Step',
|
||||
$sOperationDesc,
|
||||
$fStarted,
|
||||
$fStopped,
|
||||
'',
|
||||
$iInitialMemory,
|
||||
$iCurrentMemory,
|
||||
$iPeakMemory,
|
||||
$aCallstack
|
||||
);
|
||||
static::$aBootstrapOperations[] = $oKPILogData;
|
||||
$oExtensionInstance->LogOperation($oKPILogData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,21 +388,13 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
$this->ResetCounters();
|
||||
}
|
||||
|
||||
private function LogOperation(KpiLogData $oKPILogData): void
|
||||
{
|
||||
/** @var \iKPILoggerExtension $oExtensionInstance */
|
||||
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
|
||||
$oExtensionInstance->LogOperation($oKPILogData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute statistics for a call to an extension
|
||||
* Note: not working in dev mode (with links to env-production)
|
||||
*
|
||||
* @param object|string $object object called
|
||||
* @param string $sMethod method called on the object
|
||||
* @param string $sMessage additional message
|
||||
* @param string $sMethod method called on the object
|
||||
* @param string $sMessage additional message
|
||||
*
|
||||
* @return bool true if an extension was found for this object::method
|
||||
* @throws \ReflectionException
|
||||
@@ -463,23 +423,21 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
|
||||
$fDuration = 0;
|
||||
if (self::$m_bEnabled_Duration) {
|
||||
$fStopped = microtime(true);
|
||||
$fStopped = MyHelpers::getmicrotime();
|
||||
$fDuration = $fStopped - $this->m_fStarted;
|
||||
$aCallstack = [];
|
||||
if (self::$m_bGenerateLegacyReport) {
|
||||
if (self::$m_bBlameCaller) {
|
||||
$aCallstack = MyHelpers::get_callstack(1);
|
||||
self::$m_aStats[$sOperation][$sArguments][] = [
|
||||
'time' => $fDuration,
|
||||
'callers' => $aCallstack,
|
||||
'time' => $fDuration,
|
||||
'callers' => $aCallstack,
|
||||
];
|
||||
} else {
|
||||
self::$m_aStats[$sOperation][$sArguments][] = [
|
||||
'time' => $fDuration,
|
||||
'time' => $fDuration,
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$aCallstack = ['callstack' => $this->GetCallStack()];
|
||||
}
|
||||
|
||||
$iInitialMemory = is_null($this->m_iInitialMemory) ? 0 : $this->m_iInitialMemory;
|
||||
@@ -490,45 +448,33 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
$iPeakMemory = self::memory_get_peak_usage();
|
||||
}
|
||||
|
||||
if (static::$bMetamodelStarted) {
|
||||
foreach (static::$aBootstrapOperations as $oLog) {
|
||||
$this->LogOperation($oLog);
|
||||
}
|
||||
static::$aBootstrapOperations = [];
|
||||
// Invoke extensions to log the KPI operation
|
||||
/** @var \iKPILoggerExtension $oExtensionInstance */
|
||||
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
|
||||
//$sExtension = ModuleService::GetInstance()->GetModuleNameFromCallStack(1);
|
||||
$sExtension = '';
|
||||
$oKPILogData = new KpiLogData(
|
||||
KpiLogData::TYPE_STATS,
|
||||
$sOperation,
|
||||
$sArguments,
|
||||
$this->m_fStarted,
|
||||
$fStopped,
|
||||
'',
|
||||
$sExtension,
|
||||
$iInitialMemory,
|
||||
$iCurrentMemory,
|
||||
$iPeakMemory,
|
||||
$aCallstack
|
||||
);
|
||||
$this->LogOperation($oKPILogData);
|
||||
} else {
|
||||
$oKPILogData = new KpiLogData(
|
||||
KpiLogData::TYPE_STATS,
|
||||
$sOperation,
|
||||
$sArguments,
|
||||
$this->m_fStarted,
|
||||
$fStopped,
|
||||
'',
|
||||
$iInitialMemory,
|
||||
$iCurrentMemory,
|
||||
$iPeakMemory,
|
||||
$aCallstack
|
||||
);
|
||||
static::$aBootstrapOperations[] = $oKPILogData;
|
||||
$oExtensionInstance->LogOperation($oKPILogData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function ResetCounters()
|
||||
{
|
||||
$this->m_fStarted = microtime(true);
|
||||
if (self::$m_bEnabled_Duration) {
|
||||
$this->m_fStarted = microtime(true);
|
||||
}
|
||||
|
||||
if (self::$m_bEnabled_Memory) {
|
||||
$this->m_iInitialMemory = self::memory_get_usage();
|
||||
@@ -557,33 +503,7 @@ class ExecutionKPI implements iEventServiceSetup
|
||||
if (function_exists('memory_get_peak_usage')) {
|
||||
return memory_get_peak_usage($bRealUsage);
|
||||
}
|
||||
|
||||
// PHP > 5.2.1 - this verb depends on a compilation option
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ModuleHandlerApiInterface methods
|
||||
*/
|
||||
|
||||
public static function OnMetaModelStarted()
|
||||
{
|
||||
static::$bMetamodelStarted = true;
|
||||
}
|
||||
|
||||
public function RegisterEventsAndListeners()
|
||||
{
|
||||
EventService::RegisterListener(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED, [$this, 'OnMetaModelStarted']);
|
||||
}
|
||||
|
||||
private function GetCallStack(): string
|
||||
{
|
||||
$aCallStack = MyHelpers::get_callstack(2);
|
||||
$sCallStack = "Call stack:\n";
|
||||
foreach ($aCallStack as $index => $aLine) {
|
||||
$sCallStack .= "#$index ".$aLine['File'].'('.$aLine['Line'].'): '.$aLine['Function']."\n";
|
||||
}
|
||||
|
||||
return $sCallStack;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,28 +691,6 @@ abstract class LogAPI
|
||||
static::$m_oMockMetaModelConfig = $oMetaModelConfig;
|
||||
}
|
||||
|
||||
public static function Exception(string $sMessage, throwable $oException, string $sChannel = null, array $aContext = []): void
|
||||
{
|
||||
$aErrorLogs = [];
|
||||
$aErrorLogs[] = static::PrepareErrorLog($sMessage, $oException, $aContext);
|
||||
$oException = $oException->getPrevious();
|
||||
while ($oException !== null) {
|
||||
$aErrorLogs[] = static::PrepareErrorLog($oException->getMessage(), $oException, $aContext, true);
|
||||
$oException = $oException->getPrevious();
|
||||
}
|
||||
$aErrorLogs = array_reverse($aErrorLogs);
|
||||
foreach ($aErrorLogs as $aErrorLog) {
|
||||
static::Error($aErrorLog['message'], $sChannel, $aErrorLog['context']);
|
||||
}
|
||||
}
|
||||
|
||||
private static function PrepareErrorLog(string $sMessage, throwable $oException, array $aContext, bool $isPrevious = false): array
|
||||
{
|
||||
$aContext['Error Message'] = $oException->getMessage();
|
||||
$aContext['Stack Trace'] = $oException->getTraceAsString();
|
||||
return ['message' => ($isPrevious ? "Previous " : '')."Exception: $sMessage", 'context' => $aContext];
|
||||
}
|
||||
|
||||
public static function Error($sMessage, $sChannel = null, $aContext = [])
|
||||
{
|
||||
static::Log(self::LEVEL_ERROR, $sMessage, $sChannel, $aContext);
|
||||
|
||||
@@ -22,7 +22,8 @@ use Combodo\iTop\Application\EventRegister\ApplicationEvents;
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
use Combodo\iTop\Service\Events\EventData;
|
||||
use Combodo\iTop\Service\Events\EventService;
|
||||
use Combodo\iTop\Service\ServiceLocator\ServiceLocator;
|
||||
use Combodo\iTop\Setup\ModuleDependency\Module;
|
||||
use Combodo\iTop\Setup\ModuleDiscovery\ModuleFileReader;
|
||||
|
||||
require_once APPROOT.'core/modulehandler.class.inc.php';
|
||||
require_once APPROOT.'core/querymodifier.class.inc.php';
|
||||
@@ -143,8 +144,6 @@ abstract class MetaModel
|
||||
*/
|
||||
protected static array $m_aReentranceProtection = [];
|
||||
|
||||
private static ServiceLocator $oServiceLocator;
|
||||
|
||||
/**
|
||||
* MetaModel constructor.
|
||||
*/
|
||||
@@ -465,6 +464,43 @@ abstract class MetaModel
|
||||
return call_user_func([$sClass, 'GetClassDescription'], $sClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return string
|
||||
* @throws \CoreException
|
||||
*/
|
||||
final public static function GetModuleName($sClass)
|
||||
{
|
||||
try {
|
||||
$oReflectionClass = new ReflectionClass($sClass);
|
||||
$sDir = realpath(dirname($oReflectionClass->getFileName()));
|
||||
$sApproot = realpath(APPROOT);
|
||||
while (($sDir !== $sApproot) && (str_contains($sDir, $sApproot))) {
|
||||
$aFiles = glob("$sDir/module.*.php");
|
||||
if (count($aFiles) > 1) {
|
||||
return 'core';
|
||||
}
|
||||
|
||||
if (count($aFiles) == 0) {
|
||||
$sDir = realpath(dirname($sDir));
|
||||
continue;
|
||||
}
|
||||
|
||||
$sModuleFilePath = $aFiles[0];
|
||||
$aModuleInfo = ModuleFileReader::GetInstance()->ReadModuleFileInformation($sModuleFilePath);
|
||||
$sModuleId = $aModuleInfo[ModuleFileReader::MODULE_INFO_ID];
|
||||
list($sModuleName, ) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||
|
||||
return $sModuleName;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
throw new CoreException("Cannot find class module", ['class' => $sClass], '', $e);
|
||||
}
|
||||
|
||||
return 'core';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
*
|
||||
@@ -7029,46 +7065,6 @@ abstract class MetaModel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (Re)Init the global service locator with a configuration file
|
||||
*
|
||||
* @param string|null $sRelativeConfigFileName default to the runtime config file when null
|
||||
*
|
||||
* @return void
|
||||
* @api
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public static function InitServiceLocator(string $sRelativeConfigFileName = null): void
|
||||
{
|
||||
if (!isset(self::$oServiceLocator)) {
|
||||
self::$oServiceLocator = new ServiceLocator();
|
||||
}
|
||||
|
||||
// Read the runtime service locator configuration
|
||||
self::$oServiceLocator->Init($sRelativeConfigFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configured service using a service locator
|
||||
*
|
||||
* Example: $oModelReflection = \MetaModel::GetService('ModelReflexion');
|
||||
*
|
||||
* @param string $sServiceName Name of the service to get
|
||||
*
|
||||
* @return mixed The service object instance corresponding to the service name
|
||||
* @throws \Combodo\iTop\Service\ServiceLocator\ServiceLocatorException
|
||||
* @api
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public static function GetService(string $sServiceName): mixed
|
||||
{
|
||||
if (!isset(self::$oServiceLocator)) {
|
||||
// Read the runtime service locator configuration
|
||||
self::InitServiceLocator();
|
||||
}
|
||||
return self::$oServiceLocator->get($sServiceName);
|
||||
}
|
||||
}
|
||||
|
||||
// Standard attribute lists
|
||||
|
||||
@@ -24,6 +24,19 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exclude the parent class from the list
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
define('ENUM_CHILD_CLASSES_EXCLUDETOP', 1);
|
||||
/**
|
||||
* Include the parent class in the list
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
define('ENUM_CHILD_CLASSES_ALL', 2);
|
||||
|
||||
abstract class ModelReflection
|
||||
{
|
||||
abstract public function GetClassIcon($sClass, $bImgTag = true);
|
||||
@@ -42,11 +55,6 @@ abstract class ModelReflection
|
||||
abstract public function GetFiltersList($sClass);
|
||||
abstract public function IsValidFilterCode($sClass, $sFilterCode);
|
||||
|
||||
/**
|
||||
* @since 3.3.0
|
||||
*/
|
||||
abstract public function IsAbstract($sClass): bool;
|
||||
|
||||
/**
|
||||
* @param string $sOQL
|
||||
*
|
||||
@@ -76,17 +84,9 @@ abstract class ModelReflection
|
||||
* @param string $defaultValue
|
||||
*
|
||||
* @return \RunTimeIconSelectionField
|
||||
* @deprecated since 3.3.0 replaced by GetAvailableIcons
|
||||
*/
|
||||
abstract public function GetIconSelectionField($sCode, $sLabel = '', $defaultValue = '');
|
||||
|
||||
/**
|
||||
* Find available icons for the current context
|
||||
*
|
||||
* @return array of ['value', 'label', 'icon'] where 'value' is the relative path on disk, 'label' the name to display and 'icon' is the URL to get the image
|
||||
*/
|
||||
abstract public function GetAvailableIcons(): array;
|
||||
|
||||
abstract public function GetRootClass($sClass);
|
||||
abstract public function EnumChildClasses($sClass, $iOption = ENUM_CHILD_CLASSES_EXCLUDETOP);
|
||||
}
|
||||
@@ -104,8 +104,6 @@ abstract class QueryReflection
|
||||
|
||||
class ModelReflectionRuntime extends ModelReflection
|
||||
{
|
||||
private static array $aAllIcons = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
@@ -150,7 +148,7 @@ class ModelReflectionRuntime extends ModelReflection
|
||||
$sAttributeClass = get_class($oAttDef);
|
||||
if ($aScope != null) {
|
||||
foreach ($aScope as $sScopeClass) {
|
||||
if (is_a($sAttributeClass, $sScopeClass, true)) {
|
||||
if (($sAttributeClass == $sScopeClass) || is_subclass_of($sAttributeClass, $sScopeClass)) {
|
||||
$aAttributes[$sAttCode] = $sAttributeClass;
|
||||
break;
|
||||
}
|
||||
@@ -232,11 +230,6 @@ class ModelReflectionRuntime extends ModelReflection
|
||||
return MetaModel::IsValidFilterCode($sClass, $sFilterCode);
|
||||
}
|
||||
|
||||
public function IsAbstract($sClass): bool
|
||||
{
|
||||
return MetaModel::IsAbstract($sClass);
|
||||
}
|
||||
|
||||
public function GetQuery($sOQL)
|
||||
{
|
||||
return new QueryReflectionRuntime($sOQL, $this);
|
||||
@@ -252,52 +245,6 @@ class ModelReflectionRuntime extends ModelReflection
|
||||
return new RunTimeIconSelectionField($sCode, $sLabel, $defaultValue);
|
||||
}
|
||||
|
||||
public function GetAvailableIcons(): array
|
||||
{
|
||||
$aFolderList = [
|
||||
APPROOT.'env-'.utils::GetCurrentEnvironment() => utils::GetAbsoluteUrlModulesRoot(),
|
||||
APPROOT.'images/icons' => utils::GetAbsoluteUrlAppRoot().'images/icons',
|
||||
];
|
||||
if (count(self::$aAllIcons) == 0) {
|
||||
foreach ($aFolderList as $sFolderPath => $sUrlPrefix) {
|
||||
$aIcons = self::FindIconsOnDisk($sFolderPath);
|
||||
ksort($aIcons);
|
||||
|
||||
foreach ($aIcons as $sFilePath) {
|
||||
self::$aAllIcons[] = ['value' => $sFilePath, 'label' => basename($sFilePath), 'icon' => $sUrlPrefix.$sFilePath];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::$aAllIcons;
|
||||
}
|
||||
|
||||
private static function FindIconsOnDisk(string $sBaseDir, string $sDir = '', array &$aFilesSpecs = []): array
|
||||
{
|
||||
$aResult = [];
|
||||
// Populate automatically the list of icon files
|
||||
if ($hDir = @opendir($sBaseDir.'/'.$sDir)) {
|
||||
while (($sFile = readdir($hDir)) !== false) {
|
||||
$aMatches = [];
|
||||
if (($sFile != '.') && ($sFile != '..') && ($sFile != 'lifecycle') && is_dir($sBaseDir.'/'.$sDir.'/'.$sFile)) {
|
||||
$sDirSubPath = ($sDir == '') ? $sFile : $sDir.'/'.$sFile;
|
||||
$aResult = array_merge($aResult, self::FindIconsOnDisk($sBaseDir, $sDirSubPath, $aFilesSpecs));
|
||||
}
|
||||
$sSize = filesize($sBaseDir.'/'.$sDir.'/'.$sFile);
|
||||
if (isset($aFilesSpecs[$sFile]) && $aFilesSpecs[$sFile] == $sSize) {
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/\.(png|jpg|jpeg|gif|svg)$/i', $sFile, $aMatches)) { // png, jp(e)g, gif and svg are considered valid
|
||||
$aResult[$sFile.'_'.$sDir] = $sDir.'/'.$sFile;
|
||||
$aFilesSpecs[$sFile] = $sSize;
|
||||
}
|
||||
}
|
||||
closedir($hDir);
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function GetRootClass($sClass)
|
||||
{
|
||||
return MetaModel::GetRootClass($sClass);
|
||||
|
||||
@@ -2103,18 +2103,12 @@ class VariableExpression extends UnaryExpression
|
||||
|
||||
/**
|
||||
* Evaluate the value of the expression
|
||||
*
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \MissingQueryArgument
|
||||
*/
|
||||
* @throws \Exception if terms cannot be evaluated as scalars
|
||||
*/
|
||||
public function Evaluate(array $aArgs)
|
||||
{
|
||||
if (!isset($aArgs[$this->m_sName])) {
|
||||
throw new MissingQueryArgument('Missing variable expression argument', array('expecting'=>$this->m_sName));
|
||||
}
|
||||
return $aArgs[$this->m_sName];
|
||||
throw new Exception('not implemented yet');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -72,15 +72,9 @@ class OQLException extends CoreException
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMessage = "$sIssue - found '{$this->m_sUnexpected}' at $iCol in '$sInput'";
|
||||
if (count($this->m_aExpecting) < 30) {
|
||||
$sExpectations = '{'.implode(', ', $this->m_aExpecting).'}';
|
||||
$sMessage .= ', expecting '.json_encode($sExpectations);
|
||||
}
|
||||
$sExpectations = '{'.implode(', ', $this->m_aExpecting).'}';
|
||||
$sSuggest = self::FindClosestString($this->m_sUnexpected, $this->m_aExpecting);
|
||||
if (strlen($sSuggest) > 0) {
|
||||
$sMessage .= ", I would suggest to use ".json_encode($sSuggest);
|
||||
}
|
||||
$sMessage = "$sIssue - found '{$this->m_sUnexpected}' at $iCol in '$sInput', expecting $sExpectations, I would suggest to use '$sSuggest'";
|
||||
}
|
||||
|
||||
// make sure everything is assigned properly
|
||||
@@ -161,3 +155,5 @@ class OQLException extends CoreException
|
||||
return $sRet;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -57,15 +57,15 @@ class OqlName
|
||||
{
|
||||
return $this->m_iPos;
|
||||
}
|
||||
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->m_sValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Store hexadecimal values as strings so that we can support 64-bit values
|
||||
*
|
||||
*/
|
||||
@@ -77,12 +77,12 @@ class OqlHexValue
|
||||
{
|
||||
$this->m_sValue = $sValue;
|
||||
}
|
||||
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->m_sValue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class OqlJoinSpec
|
||||
@@ -109,7 +109,6 @@ class OqlJoinSpec
|
||||
{
|
||||
return $this->m_oClass->GetValue();
|
||||
}
|
||||
|
||||
public function GetClassAlias()
|
||||
{
|
||||
return $this->m_oClassAlias->GetValue();
|
||||
@@ -119,7 +118,6 @@ class OqlJoinSpec
|
||||
{
|
||||
return $this->m_oClass;
|
||||
}
|
||||
|
||||
public function GetClassAliasDetails()
|
||||
{
|
||||
return $this->m_oClassAlias;
|
||||
@@ -129,12 +127,10 @@ class OqlJoinSpec
|
||||
{
|
||||
return $this->m_oLeftField;
|
||||
}
|
||||
|
||||
public function GetRightField()
|
||||
{
|
||||
return $this->m_oRightField;
|
||||
}
|
||||
|
||||
public function GetOperator()
|
||||
{
|
||||
return $this->m_sOperator;
|
||||
@@ -150,9 +146,8 @@ interface CheckableExpression
|
||||
* @param ModelReflection $oModelReflection MetaModel to consider
|
||||
* @param array $aAliases Aliases to class names (for the current query)
|
||||
* @param string $sSourceQuery For the reporting
|
||||
*
|
||||
* @throws OqlNormalizeException
|
||||
*/
|
||||
*/
|
||||
public function Check(ModelReflection $oModelReflection, $aAliases, $sSourceQuery);
|
||||
}
|
||||
|
||||
@@ -173,11 +168,13 @@ class MatchOqlExpression extends MatchExpression implements CheckableExpression
|
||||
$this->m_oRightExpr->Check($oModelReflection, $aAliases, $sSourceQuery);
|
||||
|
||||
// Only field MATCHES scalar is allowed
|
||||
if (!$this->m_oLeftExpr instanceof FieldExpression) {
|
||||
if (!$this->m_oLeftExpr instanceof FieldExpression)
|
||||
{
|
||||
throw new OqlNormalizeException('Only "field MATCHES string" syntax is allowed', $sSourceQuery, new OqlName($this->m_oLeftExpr->RenderExpression(true), 0));
|
||||
}
|
||||
// Only field MATCHES scalar is allowed
|
||||
if (!$this->m_oRightExpr instanceof ScalarExpression && !$this->m_oRightExpr instanceof VariableOqlExpression) {
|
||||
if (!$this->m_oRightExpr instanceof ScalarExpression && !$this->m_oRightExpr instanceof VariableOqlExpression)
|
||||
{
|
||||
throw new OqlNormalizeException('Only "field MATCHES string" syntax is allowed', $sSourceQuery, new OqlName($this->m_oRightExpr->RenderExpression(true), 0));
|
||||
}
|
||||
}
|
||||
@@ -201,7 +198,7 @@ class NestedQueryOqlExpression extends NestedQueryExpression implements Checkabl
|
||||
*
|
||||
* @param OQLObjectQuery $oOQLObjectQuery
|
||||
*/
|
||||
public function __construct($oOQLObjectQuery)
|
||||
public function __construct($oOQLObjectQuery )
|
||||
{
|
||||
parent::__construct($oOQLObjectQuery->ToDBSearch(""));
|
||||
$this->m_oOQLObjectQuery = $oOQLObjectQuery;
|
||||
@@ -235,7 +232,8 @@ class FieldOqlExpression extends FieldExpression implements CheckableExpression
|
||||
|
||||
public function __construct($oName, $oParent = null)
|
||||
{
|
||||
if (is_null($oParent)) {
|
||||
if (is_null($oParent))
|
||||
{
|
||||
$oParent = new OqlName('', 0);
|
||||
}
|
||||
$this->m_oParent = $oParent;
|
||||
@@ -258,28 +256,37 @@ class FieldOqlExpression extends FieldExpression implements CheckableExpression
|
||||
{
|
||||
$sClassAlias = $this->GetParent();
|
||||
$sFltCode = $this->GetName();
|
||||
if (empty($sClassAlias)) {
|
||||
if (empty($sClassAlias))
|
||||
{
|
||||
// Try to find an alias
|
||||
// Build an array of field => array of aliases
|
||||
$aFieldClasses = array();
|
||||
foreach ($aAliases as $sAlias => $sReal) {
|
||||
foreach ($oModelReflection->GetFiltersList($sReal) as $sAnFltCode) {
|
||||
foreach($aAliases as $sAlias => $sReal)
|
||||
{
|
||||
foreach($oModelReflection->GetFiltersList($sReal) as $sAnFltCode)
|
||||
{
|
||||
$aFieldClasses[$sAnFltCode][] = $sAlias;
|
||||
}
|
||||
}
|
||||
if (!array_key_exists($sFltCode, $aFieldClasses)) {
|
||||
if (!array_key_exists($sFltCode, $aFieldClasses))
|
||||
{
|
||||
throw new OqlNormalizeException('Unknown filter code', $sSourceQuery, $this->GetNameDetails(), array_keys($aFieldClasses));
|
||||
}
|
||||
if (count($aFieldClasses[$sFltCode]) > 1) {
|
||||
if (count($aFieldClasses[$sFltCode]) > 1)
|
||||
{
|
||||
throw new OqlNormalizeException('Ambiguous filter code', $sSourceQuery, $this->GetNameDetails());
|
||||
}
|
||||
$sClassAlias = $aFieldClasses[$sFltCode][0];
|
||||
} else {
|
||||
if (!array_key_exists($sClassAlias, $aAliases)) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!array_key_exists($sClassAlias, $aAliases))
|
||||
{
|
||||
throw new OqlNormalizeException('Unknown class [alias]', $sSourceQuery, $this->GetParentDetails(), array_keys($aAliases));
|
||||
}
|
||||
$sClass = $aAliases[$sClassAlias];
|
||||
if (!$oModelReflection->IsValidFilterCode($sClass, $sFltCode)) {
|
||||
if (!$oModelReflection->IsValidFilterCode($sClass, $sFltCode))
|
||||
{
|
||||
throw new OqlNormalizeException('Unknown filter code', $sSourceQuery, $this->GetNameDetails(), $oModelReflection->GetFiltersList($sClass));
|
||||
}
|
||||
}
|
||||
@@ -298,7 +305,8 @@ class ListOqlExpression extends ListExpression implements CheckableExpression
|
||||
{
|
||||
public function Check(ModelReflection $oModelReflection, $aAliases, $sSourceQuery)
|
||||
{
|
||||
foreach ($this->GetItems() as $oItemExpression) {
|
||||
foreach ($this->GetItems() as $oItemExpression)
|
||||
{
|
||||
$oItemExpression->Check($oModelReflection, $aAliases, $sSourceQuery);
|
||||
}
|
||||
}
|
||||
@@ -308,7 +316,8 @@ class FunctionOqlExpression extends FunctionExpression implements CheckableExpre
|
||||
{
|
||||
public function Check(ModelReflection $oModelReflection, $aAliases, $sSourceQuery)
|
||||
{
|
||||
foreach ($this->GetArgs() as $oArgExpression) {
|
||||
foreach ($this->GetArgs() as $oArgExpression)
|
||||
{
|
||||
$oArgExpression->Check($oModelReflection, $aAliases, $sSourceQuery);
|
||||
}
|
||||
}
|
||||
@@ -341,7 +350,6 @@ abstract class OqlQuery
|
||||
* Determine the class
|
||||
*
|
||||
* @param ModelReflection $oModelReflection MetaModel to consider
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
@@ -384,7 +392,6 @@ class OqlObjectQuery extends OqlQuery
|
||||
* Determine the class
|
||||
*
|
||||
* @param ModelReflection $oModelReflection MetaModel to consider
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
@@ -408,7 +415,6 @@ class OqlObjectQuery extends OqlQuery
|
||||
{
|
||||
return $this->m_oClass;
|
||||
}
|
||||
|
||||
public function GetClassAliasDetails()
|
||||
{
|
||||
return $this->m_oClassAlias;
|
||||
@@ -418,7 +424,6 @@ class OqlObjectQuery extends OqlQuery
|
||||
{
|
||||
return $this->m_aJoins;
|
||||
}
|
||||
|
||||
public function GetCondition()
|
||||
{
|
||||
return $this->m_oCondition;
|
||||
@@ -427,37 +432,44 @@ class OqlObjectQuery extends OqlQuery
|
||||
/**
|
||||
* Recursively check the validity of the expression with regard to the data model
|
||||
* and the query in which it is used
|
||||
*
|
||||
* @param ModelReflection $oModelReflection MetaModel to consider
|
||||
*
|
||||
*
|
||||
* @param ModelReflection $oModelReflection MetaModel to consider
|
||||
* @throws OqlNormalizeException
|
||||
*/
|
||||
*/
|
||||
public function Check(ModelReflection $oModelReflection, $sSourceQuery, $aParentAliases = array())
|
||||
{
|
||||
$sClass = $this->GetClass($oModelReflection);
|
||||
$sClassAlias = $this->GetClassAlias();
|
||||
|
||||
if (!$oModelReflection->IsValidClass($sClass)) {
|
||||
if (!$oModelReflection->IsValidClass($sClass))
|
||||
{
|
||||
throw new UnknownClassOqlException($sSourceQuery, $this->GetClassDetails(), $oModelReflection->GetClasses());
|
||||
}
|
||||
|
||||
$aAliases = array_merge(array($sClassAlias => $sClass), $aParentAliases);
|
||||
$aAliases = array_merge(array($sClassAlias => $sClass),$aParentAliases);
|
||||
|
||||
$aJoinSpecs = $this->GetJoins();
|
||||
if (is_array($aJoinSpecs)) {
|
||||
foreach ($aJoinSpecs as $oJoinSpec) {
|
||||
if (is_array($aJoinSpecs))
|
||||
{
|
||||
foreach ($aJoinSpecs as $oJoinSpec)
|
||||
{
|
||||
$sJoinClass = $oJoinSpec->GetClass();
|
||||
$sJoinClassAlias = $oJoinSpec->GetClassAlias();
|
||||
if (!$oModelReflection->IsValidClass($sJoinClass)) {
|
||||
if (!$oModelReflection->IsValidClass($sJoinClass))
|
||||
{
|
||||
throw new UnknownClassOqlException($sSourceQuery, $oJoinSpec->GetClassDetails(), $oModelReflection->GetClasses());
|
||||
}
|
||||
if (array_key_exists($sJoinClassAlias, $aAliases)) {
|
||||
if ($sJoinClassAlias != $sJoinClass) {
|
||||
if (array_key_exists($sJoinClassAlias, $aAliases))
|
||||
{
|
||||
if ($sJoinClassAlias != $sJoinClass)
|
||||
{
|
||||
throw new OqlNormalizeException('Duplicate class alias', $sSourceQuery, $oJoinSpec->GetClassAliasDetails());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OqlNormalizeException('Duplicate class name', $sSourceQuery, $oJoinSpec->GetClassDetails());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assumption: ext key on the left only !!!
|
||||
// normalization should take care of this
|
||||
@@ -468,74 +480,85 @@ class OqlObjectQuery extends OqlQuery
|
||||
$oRightField = $oJoinSpec->GetRightField();
|
||||
$sToClass = $oRightField->GetParent();
|
||||
$sPKeyDescriptor = $oRightField->GetName();
|
||||
if ($sPKeyDescriptor != 'id') {
|
||||
if ($sPKeyDescriptor != 'id')
|
||||
{
|
||||
throw new OqlNormalizeException('Wrong format for Join clause (right hand), expecting an id', $sSourceQuery, $oRightField->GetNameDetails(), array('id'));
|
||||
}
|
||||
|
||||
$aAliases[$sJoinClassAlias] = $sJoinClass;
|
||||
|
||||
if (!array_key_exists($sFromClass, $aAliases)) {
|
||||
if (!array_key_exists($sFromClass, $aAliases))
|
||||
{
|
||||
throw new OqlNormalizeException('Unknown class in join condition (left expression)', $sSourceQuery, $oLeftField->GetParentDetails(), array_keys($aAliases));
|
||||
}
|
||||
if (!array_key_exists($sToClass, $aAliases)) {
|
||||
if (!array_key_exists($sToClass, $aAliases))
|
||||
{
|
||||
throw new OqlNormalizeException('Unknown class in join condition (right expression)', $sSourceQuery, $oRightField->GetParentDetails(), array_keys($aAliases));
|
||||
}
|
||||
$aExtKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], \Combodo\iTop\Core\AttributeDefinition\AttributeExternalKey::class);
|
||||
$aObjKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], \Combodo\iTop\Core\AttributeDefinition\AttributeObjectKey::class);
|
||||
$aAllKeys = array_merge($aExtKeys, $aObjKeys);
|
||||
if (!array_key_exists($sExtKeyAttCode, $aAllKeys)) {
|
||||
if (!array_key_exists($sExtKeyAttCode, $aAllKeys))
|
||||
{
|
||||
throw new OqlNormalizeException('Unknown key in join condition (left expression)', $sSourceQuery, $oLeftField->GetNameDetails(), array_keys($aAllKeys));
|
||||
}
|
||||
|
||||
if ($sFromClass == $sJoinClassAlias) {
|
||||
if ($sFromClass == $sJoinClassAlias)
|
||||
{
|
||||
if (array_key_exists($sExtKeyAttCode, $aExtKeys)) // Skip that check for object keys
|
||||
{
|
||||
$sTargetClass = $oModelReflection->GetAttributeProperty($aAliases[$sFromClass], $sExtKeyAttCode, 'targetclass');
|
||||
if (!$oModelReflection->IsSameFamilyBranch($aAliases[$sToClass], $sTargetClass)) {
|
||||
if(!$oModelReflection->IsSameFamilyBranch($aAliases[$sToClass], $sTargetClass))
|
||||
{
|
||||
throw new OqlNormalizeException("The joined class ($aAliases[$sFromClass]) is not compatible with the external key, which is pointing to $sTargetClass", $sSourceQuery, $oLeftField->GetNameDetails());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$sOperator = $oJoinSpec->GetOperator();
|
||||
switch ($sOperator) {
|
||||
switch($sOperator)
|
||||
{
|
||||
case '=':
|
||||
$iOperatorCode = TREE_OPERATOR_EQUALS;
|
||||
break;
|
||||
$iOperatorCode = TREE_OPERATOR_EQUALS;
|
||||
break;
|
||||
case 'BELOW':
|
||||
$iOperatorCode = TREE_OPERATOR_BELOW;
|
||||
break;
|
||||
$iOperatorCode = TREE_OPERATOR_BELOW;
|
||||
break;
|
||||
case 'BELOW_STRICT':
|
||||
$iOperatorCode = TREE_OPERATOR_BELOW_STRICT;
|
||||
break;
|
||||
$iOperatorCode = TREE_OPERATOR_BELOW_STRICT;
|
||||
break;
|
||||
case 'NOT_BELOW':
|
||||
$iOperatorCode = TREE_OPERATOR_NOT_BELOW;
|
||||
break;
|
||||
$iOperatorCode = TREE_OPERATOR_NOT_BELOW;
|
||||
break;
|
||||
case 'NOT_BELOW_STRICT':
|
||||
$iOperatorCode = TREE_OPERATOR_NOT_BELOW_STRICT;
|
||||
break;
|
||||
$iOperatorCode = TREE_OPERATOR_NOT_BELOW_STRICT;
|
||||
break;
|
||||
case 'ABOVE':
|
||||
$iOperatorCode = TREE_OPERATOR_ABOVE;
|
||||
break;
|
||||
$iOperatorCode = TREE_OPERATOR_ABOVE;
|
||||
break;
|
||||
case 'ABOVE_STRICT':
|
||||
$iOperatorCode = TREE_OPERATOR_ABOVE_STRICT;
|
||||
break;
|
||||
$iOperatorCode = TREE_OPERATOR_ABOVE_STRICT;
|
||||
break;
|
||||
case 'NOT_ABOVE':
|
||||
$iOperatorCode = TREE_OPERATOR_NOT_ABOVE;
|
||||
break;
|
||||
$iOperatorCode = TREE_OPERATOR_NOT_ABOVE;
|
||||
break;
|
||||
case 'NOT_ABOVE_STRICT':
|
||||
$iOperatorCode = TREE_OPERATOR_NOT_ABOVE_STRICT;
|
||||
break;
|
||||
$iOperatorCode = TREE_OPERATOR_NOT_ABOVE_STRICT;
|
||||
break;
|
||||
}
|
||||
if (array_key_exists($sExtKeyAttCode, $aExtKeys)) // Skip that check for object keys
|
||||
{
|
||||
$sTargetClass = $oModelReflection->GetAttributeProperty($aAliases[$sFromClass], $sExtKeyAttCode, 'targetclass');
|
||||
if (!$oModelReflection->IsSameFamilyBranch($aAliases[$sToClass], $sTargetClass)) {
|
||||
if(!$oModelReflection->IsSameFamilyBranch($aAliases[$sToClass], $sTargetClass))
|
||||
{
|
||||
throw new OqlNormalizeException("The joined class ($aAliases[$sToClass]) is not compatible with the external key, which is pointing to $sTargetClass", $sSourceQuery, $oLeftField->GetNameDetails());
|
||||
}
|
||||
}
|
||||
$aAttList = $oModelReflection->ListAttributes($aAliases[$sFromClass]);
|
||||
$sAttType = $aAttList[$sExtKeyAttCode];
|
||||
if (($iOperatorCode != TREE_OPERATOR_EQUALS) && !is_a($sAttType, \Combodo\iTop\Core\AttributeDefinition\AttributeHierarchicalKey::class, true)) {
|
||||
if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !is_subclass_of($sAttType, \Combodo\iTop\Core\AttributeDefinition\AttributeHierarchicalKey::class) && ($sAttType != \Combodo\iTop\Core\AttributeDefinition\AttributeHierarchicalKey::class))
|
||||
{
|
||||
throw new OqlNormalizeException("The specified tree operator $sOperator is not applicable to the key", $sSourceQuery, $oLeftField->GetNameDetails());
|
||||
}
|
||||
}
|
||||
@@ -544,23 +567,26 @@ class OqlObjectQuery extends OqlQuery
|
||||
|
||||
// Check the select information
|
||||
//
|
||||
foreach ($this->GetSelectedClasses() as $oClassDetails) {
|
||||
foreach ($this->GetSelectedClasses() as $oClassDetails)
|
||||
{
|
||||
$sClassToSelect = $oClassDetails->GetValue();
|
||||
if (!array_key_exists($sClassToSelect, $aAliases)) {
|
||||
if (!array_key_exists($sClassToSelect, $aAliases))
|
||||
{
|
||||
throw new OqlNormalizeException('Unknown class [alias]', $sSourceQuery, $oClassDetails, array_keys($aAliases));
|
||||
}
|
||||
}
|
||||
|
||||
// Check the condition tree
|
||||
//
|
||||
if ($this->m_oCondition instanceof Expression) {
|
||||
if ($this->m_oCondition instanceof Expression)
|
||||
{
|
||||
$this->m_oCondition->Check($oModelReflection, $aAliases, $sSourceQuery);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the relevant DBSearch instance (FromOQL)
|
||||
*/
|
||||
*/
|
||||
public function ToDBSearch($sQuery)
|
||||
{
|
||||
$sClass = $this->GetClass(new ModelReflectionRuntime());
|
||||
@@ -568,7 +594,6 @@ class OqlObjectQuery extends OqlQuery
|
||||
|
||||
$oSearch = new DBObjectSearch($sClass, $sClassAlias);
|
||||
$oSearch->InitFromOqlQuery($this, $sQuery);
|
||||
|
||||
return $oSearch;
|
||||
}
|
||||
}
|
||||
@@ -581,15 +606,19 @@ class OqlUnionQuery extends OqlQuery
|
||||
{
|
||||
parent::__construct();
|
||||
$this->aQueries[] = $oLeftQuery;
|
||||
if ($oRightQueryOrUnion instanceof OqlUnionQuery) {
|
||||
foreach ($oRightQueryOrUnion->GetQueries() as $oSingleQuery) {
|
||||
if ($oRightQueryOrUnion instanceof OqlUnionQuery)
|
||||
{
|
||||
foreach ($oRightQueryOrUnion->GetQueries() as $oSingleQuery)
|
||||
{
|
||||
$this->aQueries[] = $oSingleQuery;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->aQueries[] = $oRightQueryOrUnion;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function GetQueries()
|
||||
{
|
||||
return $this->aQueries;
|
||||
@@ -598,54 +627,66 @@ class OqlUnionQuery extends OqlQuery
|
||||
/**
|
||||
* Check the validity of the expression with regard to the data model
|
||||
* and the query in which it is used
|
||||
*
|
||||
* @param ModelReflection $oModelReflection MetaModel to consider
|
||||
*
|
||||
*
|
||||
* @param ModelReflection $oModelReflection MetaModel to consider
|
||||
* @throws OqlNormalizeException
|
||||
*/
|
||||
*/
|
||||
public function Check(ModelReflection $oModelReflection, $sSourceQuery)
|
||||
{
|
||||
$aColumnToClasses = array();
|
||||
foreach ($this->aQueries as $iQuery => $oQuery) {
|
||||
foreach ($this->aQueries as $iQuery => $oQuery)
|
||||
{
|
||||
$oQuery->Check($oModelReflection, $sSourceQuery);
|
||||
|
||||
$aAliasToClass = array($oQuery->GetClassAlias() => $oQuery->GetClass($oModelReflection));
|
||||
$aJoinSpecs = $oQuery->GetJoins();
|
||||
if (is_array($aJoinSpecs)) {
|
||||
foreach ($aJoinSpecs as $oJoinSpec) {
|
||||
if (is_array($aJoinSpecs))
|
||||
{
|
||||
foreach ($aJoinSpecs as $oJoinSpec)
|
||||
{
|
||||
$aAliasToClass[$oJoinSpec->GetClassAlias()] = $oJoinSpec->GetClass();
|
||||
}
|
||||
}
|
||||
|
||||
$aSelectedClasses = $oQuery->GetSelectedClasses();
|
||||
if ($iQuery != 0) {
|
||||
if (count($aSelectedClasses) < count($aColumnToClasses)) {
|
||||
if ($iQuery != 0)
|
||||
{
|
||||
if (count($aSelectedClasses) < count($aColumnToClasses))
|
||||
{
|
||||
$oLastClass = end($aSelectedClasses);
|
||||
throw new OqlNormalizeException('Too few selected classes in the subquery', $sSourceQuery, $oLastClass);
|
||||
}
|
||||
if (count($aSelectedClasses) > count($aColumnToClasses)) {
|
||||
if (count($aSelectedClasses) > count($aColumnToClasses))
|
||||
{
|
||||
$oLastClass = end($aSelectedClasses);
|
||||
throw new OqlNormalizeException('Too many selected classes in the subquery', $sSourceQuery, $oLastClass);
|
||||
}
|
||||
}
|
||||
foreach ($aSelectedClasses as $iColumn => $oClassDetails) {
|
||||
foreach ($aSelectedClasses as $iColumn => $oClassDetails)
|
||||
{
|
||||
$sAlias = $oClassDetails->GetValue();
|
||||
$sClass = $aAliasToClass[$sAlias];
|
||||
$aColumnToClasses[$iColumn][] = array(
|
||||
'alias' => $sAlias,
|
||||
'class' => $sClass,
|
||||
'alias' => $sAlias,
|
||||
'class' => $sClass,
|
||||
'class_name' => $oClassDetails,
|
||||
);
|
||||
}
|
||||
}
|
||||
foreach ($aColumnToClasses as $iColumn => $aClasses) {
|
||||
foreach ($aColumnToClasses as $iColumn => $aClasses)
|
||||
{
|
||||
$sRootClass = null;
|
||||
foreach ($aClasses as $iQuery => $aData) {
|
||||
if ($iQuery == 0) {
|
||||
foreach ($aClasses as $iQuery => $aData)
|
||||
{
|
||||
if ($iQuery == 0)
|
||||
{
|
||||
// Establish the reference
|
||||
$sRootClass = $oModelReflection->GetRootClass($aData['class']);
|
||||
} else {
|
||||
if ($oModelReflection->GetRootClass($aData['class']) != $sRootClass) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($oModelReflection->GetRootClass($aData['class']) != $sRootClass)
|
||||
{
|
||||
$aSubclasses = $oModelReflection->EnumChildClasses($sRootClass, ENUM_CHILD_CLASSES_ALL);
|
||||
throw new OqlNormalizeException('Incompatible classes: could not find a common ancestor', $sSourceQuery, $aData['class_name'], $aSubclasses);
|
||||
}
|
||||
@@ -658,21 +699,21 @@ class OqlUnionQuery extends OqlQuery
|
||||
* Determine the class
|
||||
*
|
||||
* @param ModelReflection $oModelReflection MetaModel to consider
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function GetClass(ModelReflection $oModelReflection)
|
||||
{
|
||||
$aFirstColClasses = array();
|
||||
foreach ($this->aQueries as $iQuery => $oQuery) {
|
||||
foreach ($this->aQueries as $iQuery => $oQuery)
|
||||
{
|
||||
$aFirstColClasses[] = $oQuery->GetClass($oModelReflection);
|
||||
}
|
||||
$sClass = self::GetLowestCommonAncestor($oModelReflection, $aFirstColClasses);
|
||||
if (is_null($sClass)) {
|
||||
if (is_null($sClass))
|
||||
{
|
||||
throw new Exception('Could not determine the class of the union query. This issue should have been detected earlier by calling OqlQuery::Check()');
|
||||
}
|
||||
|
||||
return $sClass;
|
||||
}
|
||||
|
||||
@@ -685,7 +726,6 @@ class OqlUnionQuery extends OqlQuery
|
||||
public function GetClassAlias()
|
||||
{
|
||||
$sAlias = $this->aQueries[0]->GetClassAlias();
|
||||
|
||||
return $sAlias;
|
||||
}
|
||||
|
||||
@@ -695,25 +735,29 @@ class OqlUnionQuery extends OqlQuery
|
||||
*
|
||||
* @param ModelReflection $oModelReflection MetaModel to consider
|
||||
* @param array $aClasses Flat list of classes
|
||||
*
|
||||
* @return string the lowest common ancestor amongst classes, null if none has been found
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function GetLowestCommonAncestor(ModelReflection $oModelReflection, $aClasses)
|
||||
{
|
||||
$sAncestor = null;
|
||||
foreach ($aClasses as $sClass) {
|
||||
if (is_null($sAncestor)) {
|
||||
foreach($aClasses as $sClass)
|
||||
{
|
||||
if (is_null($sAncestor))
|
||||
{
|
||||
// first loop
|
||||
$sAncestor = $sClass;
|
||||
} elseif ($oModelReflection->GetRootClass($sClass) != $oModelReflection->GetRootClass($sAncestor)) {
|
||||
}
|
||||
elseif ($oModelReflection->GetRootClass($sClass) != $oModelReflection->GetRootClass($sAncestor))
|
||||
{
|
||||
$sAncestor = null;
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAncestor = self::LowestCommonAncestor($oModelReflection, $sAncestor, $sClass);
|
||||
}
|
||||
}
|
||||
|
||||
return $sAncestor;
|
||||
}
|
||||
|
||||
@@ -722,32 +766,37 @@ class OqlUnionQuery extends OqlQuery
|
||||
*/
|
||||
protected static function LowestCommonAncestor(ModelReflection $oModelReflection, $sClassA, $sClassB)
|
||||
{
|
||||
if ($sClassA == $sClassB) {
|
||||
if ($sClassA == $sClassB)
|
||||
{
|
||||
$sRet = $sClassA;
|
||||
} elseif (in_array($sClassA, $oModelReflection->EnumChildClasses($sClassB))) {
|
||||
}
|
||||
elseif (in_array($sClassA, $oModelReflection->EnumChildClasses($sClassB)))
|
||||
{
|
||||
$sRet = $sClassB;
|
||||
} elseif (in_array($sClassB, $oModelReflection->EnumChildClasses($sClassA))) {
|
||||
}
|
||||
elseif (in_array($sClassB, $oModelReflection->EnumChildClasses($sClassA)))
|
||||
{
|
||||
$sRet = $sClassA;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Recurse
|
||||
$sRet = self::LowestCommonAncestor($oModelReflection, $sClassA, $oModelReflection->GetParentClass($sClassB));
|
||||
}
|
||||
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the relevant DBSearch instance (FromOQL)
|
||||
*/
|
||||
*/
|
||||
public function ToDBSearch($sQuery)
|
||||
{
|
||||
$aSearches = array();
|
||||
foreach ($this->aQueries as $oQuery) {
|
||||
foreach ($this->aQueries as $oQuery)
|
||||
{
|
||||
$aSearches[] = $oQuery->ToDBSearch($sQuery);
|
||||
}
|
||||
|
||||
$oSearch = new DBUnionSearch($aSearches);
|
||||
|
||||
return $oSearch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,9 +98,9 @@ class ormPassword
|
||||
$bResult = false;
|
||||
$aInfo = password_get_info($this->m_sHashed);
|
||||
if (is_null($aInfo["algo"]) || $aInfo["algo"] === 0) {
|
||||
// - Unknown algorithm, assume it's a legacy password
|
||||
//unknown, assume it's a legacy password
|
||||
$sHashedPwd = $this->ComputeHash($sClearTextPassword);
|
||||
$bResult = hash_equals($this->m_sHashed, $sHashedPwd);
|
||||
$bResult = ($this->m_sHashed == $sHashedPwd);
|
||||
} else {
|
||||
$bResult = password_verify($sClearTextPassword, $this->m_sHashed);
|
||||
}
|
||||
|
||||
@@ -415,7 +415,12 @@ abstract class User extends cmdbAbstractObject
|
||||
$this->m_aCheckIssues[] = Dict::S('Class:User/Error:CurrentProfilesHaveInsufficientRights');
|
||||
}
|
||||
$oAddon->ResetCache();
|
||||
Session::Set('profile_list', $aCurrentProfiles);
|
||||
|
||||
if (is_null($aCurrentProfiles)) {
|
||||
Session::IsSet('profile_list');
|
||||
} else {
|
||||
Session::Set('profile_list', $aCurrentProfiles);
|
||||
}
|
||||
}
|
||||
// Prevent an administrator to remove their own admin profile
|
||||
if (UserRights::IsAdministrator($this)) {
|
||||
|
||||
@@ -20,213 +20,4 @@ $ibo-dashlet-within-dashboard--dashlet-header-static--margin-top--is-not-first-d
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 3.3: This css is for dashboard editor demo purpose and needs to be updated
|
||||
|
||||
ibo-dashboard[data-edit-mode="edit"]{
|
||||
ibo-dashlet .ibo-dashlet{
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ibo-dashlet{
|
||||
// do not apply to this dashlets
|
||||
container-type: inline-size;
|
||||
|
||||
&:not([data-dashlet-type="DashletBadge"]):not([data-dashlet-type="DashletHeaderStatic"]){
|
||||
border: 1px solid #ccd4db;
|
||||
border-radius: 5px;
|
||||
background-color: white;
|
||||
padding: 16px;
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
background-color: $ibo-color-blue-800;
|
||||
content: "";
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
// Make the dashlet body take all the available height to allow scrollbars when needed
|
||||
.ibo-dashlet > .ibo-content-block{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
row-gap: 10px;
|
||||
.ibo-panel--header{
|
||||
align-items: flex-start;
|
||||
}
|
||||
> .ibo-panel--body{
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ibo-dashlet[data-dashlet-type="DashletBadge"] {
|
||||
.ibo-dashlet-badge{
|
||||
max-width: unset;
|
||||
}
|
||||
.ibo-dashlet-badge--body{
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@container (width < 175px) {
|
||||
.ibo-dashlet-badge--action-list-label, .ibo-dashlet-badge--action-create-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ibo-dashboard[data-edit-mode="edit"] ibo-dashlet[data-dashlet-type="DashletHeaderStatic"]{
|
||||
border: 1px solid #ccd4db;
|
||||
background-color: $ibo-color-grey-100;
|
||||
border-radius: 3px;
|
||||
> .ibo-content-block{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> .ibo-dashlet-header-static{
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ibo-dashlet[data-dashlet-type="DashletHeaderDynamic"] {
|
||||
> .ibo-content-block > .ibo-content-block{
|
||||
.ibo-panel--body{
|
||||
border: none;
|
||||
padding: 0;
|
||||
&:before{
|
||||
display: none;
|
||||
}
|
||||
.ibo-panel-boy{
|
||||
flex-grow: 1;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ibo-dashlet[data-dashlet-type="DashletObjectList"] {
|
||||
overflow-y: hidden!important;
|
||||
|
||||
> .ibo-dashlet > .ibo-content-block > .ibo-content-block{
|
||||
display: flex;
|
||||
max-height: 100%;
|
||||
flex-direction: column;
|
||||
|
||||
.dataTables_wrapper{
|
||||
height: 100%;
|
||||
|
||||
.dataTables_scroll{
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.dataTables_scrollHead{
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
border: 0px;
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dataTables_scrollBody{
|
||||
max-height: unset!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-panel--body{
|
||||
margin: 0 -16px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
padding-top: 16px;
|
||||
&:before{
|
||||
display: none;
|
||||
}
|
||||
.ibo-datatable{
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ibo-dashlet[data-dashlet-type="DashletGroupByTable"] {
|
||||
overflow-y: hidden!important;
|
||||
|
||||
> .ibo-dashlet > .ibo-content-block > .ibo-content-block{
|
||||
display: flex;
|
||||
max-height: 100%;
|
||||
flex-direction: column;
|
||||
|
||||
.dataTables_wrapper{
|
||||
height: 100%;
|
||||
|
||||
.dataTables_scroll{
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.dataTables_scrollHead{
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dataTables_scrollBody{
|
||||
max-height: unset!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-panel--body{
|
||||
margin: 0 -16px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
padding-top: 16px;
|
||||
&:before{
|
||||
display: none;
|
||||
}
|
||||
.ibo-datatable{
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ibo-dashlet[data-dashlet-type="DashletGroupByPie"] {
|
||||
.ibo-panel--body {
|
||||
border: none;
|
||||
padding: 0;
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ibo-dashlet[data-dashlet-type="DashletGroupByBars"] {
|
||||
.ibo-panel--body {
|
||||
border: none;
|
||||
padding: 0;
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
$ibo-field--spacing-top--with-same-block: $ibo-spacing-500 !default;
|
||||
|
||||
.ibo-field + .ibo-field:not(:empty) {
|
||||
.ibo-field + .ibo-field {
|
||||
margin-top: $ibo-field--spacing-top--with-same-block;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,96 +6,4 @@
|
||||
.ibo-prop-header {
|
||||
@extend %ibo-font-size-150;
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
|
||||
.help-text{
|
||||
padding: 1px 5px;
|
||||
background-color: #d7e3f8;
|
||||
border: 1px solid #c6e7f5;
|
||||
border-radius: 5px;
|
||||
margin: 5px 0;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.form-error ul{
|
||||
padding: 1px 5px;
|
||||
background-color: #f8d7da;
|
||||
border: 1px solid #f5c6cb;
|
||||
border-radius: 5px;
|
||||
margin: 5px 0;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.subform{
|
||||
background-color: #efefef;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.form-buttons{
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.form select{
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.form select option{
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.turbo-refreshing{
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.ibo-field legend{
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
collection-entry-element {
|
||||
margin-top: 8px;
|
||||
display: block;
|
||||
padding: 10px 10px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.ts-control{
|
||||
height: auto;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.ibo-form-actions > .ibo-button > span{
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.ibo-form textarea{
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.ibo-form-compact{
|
||||
|
||||
.ibo-field{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.ibo-field--label{
|
||||
min-width: 100px;
|
||||
max-width: unset;
|
||||
width: unset;
|
||||
}
|
||||
|
||||
.ibo-input-type-checkbox{
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.ibo-input-type-date{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,10 +19,7 @@ $ibo-dashlet-blocker--height: 100% !default;
|
||||
.ibo-dashlet {
|
||||
position: relative;
|
||||
width: calc(#{$ibo-dashlet--width} - #{$ibo-dashlet--elements-spacing-x});
|
||||
//margin: calc(#{$ibo-dashlet--elements-spacing-y} / 2) calc(#{$ibo-dashlet--elements-spacing-x} / 2);
|
||||
|
||||
height: 100% !important;
|
||||
width: 100% !important;
|
||||
margin: calc(#{$ibo-dashlet--elements-spacing-y} / 2) calc(#{$ibo-dashlet--elements-spacing-x} / 2);
|
||||
|
||||
&.dashlet-selected {
|
||||
position: relative;
|
||||
@@ -41,21 +38,4 @@ $ibo-dashlet-blocker--height: 100% !default;
|
||||
width: $ibo-dashlet-blocker--width;
|
||||
height: $ibo-dashlet-blocker--height;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.ibo-dashlet--actions {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
display: none;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
|
||||
background-color: $ibo-color-white-100;
|
||||
@extend %ibo-elevation-100;
|
||||
}
|
||||
|
||||
ibo-dashlet[data-edit-mode="edit"] {
|
||||
z-index: 3;
|
||||
}
|
||||
@@ -54,32 +54,3 @@ $ibo-input-select-icon--menu--icon--margin-right: 10px !default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ts-control > .ibo-input-select-icon--menu--item{
|
||||
|
||||
display: flex;
|
||||
column-gap: 5px;
|
||||
align-items: center;
|
||||
padding: 5px 0;
|
||||
|
||||
> img{
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
&:hover{
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.ts-dropdown > .ts-dropdown-content > .ibo-input-select-icon--menu--item{
|
||||
|
||||
display: flex;
|
||||
column-gap: 5px;
|
||||
align-items: center;
|
||||
|
||||
> img{
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,4 +15,3 @@
|
||||
@import "wizard-container/wizard-container";
|
||||
@import "object/all";
|
||||
@import "activity-panel/all";
|
||||
@import "dashlet-panel/all";
|
||||
|
||||
@@ -175,78 +175,3 @@ input:checked + .ibo-dashboard--slider:before {
|
||||
input:checked + .ibo-dashboard--slider:after {
|
||||
content: $ibo-dashboard--slider--before--content;
|
||||
}
|
||||
|
||||
// TODO 3.3 Cleanup variables
|
||||
// TODO 3.3 Move to vendor what's from gridstack
|
||||
|
||||
|
||||
.grid-stack {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ibo-dashboard[data-edit-mode="edit"] .grid-stack{
|
||||
background-size: calc(100% / 12) var(--gs-cell-height);
|
||||
background-color: $ibo-color-white-100;
|
||||
background-image: linear-gradient(to right, $ibo-color-white-200 8px, transparent 8px), linear-gradient(to bottom, $ibo-color-white-200 8px, transparent 8px);
|
||||
--gs-item-margin-top: 8px;
|
||||
--gs-item-margin-bottom: 0;
|
||||
--gs-item-margin-right: 0;
|
||||
--gs-item-margin-left: 8px;
|
||||
}
|
||||
|
||||
ibo-dashboard[data-edit-mode="view"] {
|
||||
.ibo-dashboard--form {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-dashboard--form {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
height: 55px;
|
||||
background-color: $ibo-color-blue-200;
|
||||
margin: -16px -36px 24px -36px;
|
||||
padding: 0 36px;
|
||||
}
|
||||
|
||||
.ibo-dashboard--form--inputs {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
@extend %common-font-ral-med-250;
|
||||
|
||||
> [name="dashboard_title"] {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.ibo-dashboard[data-edit-mode="edit"] ibo-dashlet:not([data-edit-mode="edit"]):hover .ibo-dashlet--actions {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ibo-dashboard[data-edit-mode="error"] .grid-stack{
|
||||
background-image: url($approot-relative + '/images/alpha-fatal-error.gif');
|
||||
}
|
||||
|
||||
// Our edit mode dashboard already has its own header, so we hide the standard one
|
||||
#ibo-page-header:has(+ ibo-dashboard[data-edit-mode="edit"]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ibo-dashboard[data-edit-mode="edit"] .ibo-dashboard--grid:has(ibo-dashboard-grid-slot > ibo-dashlet[data-edit-mode="edit"]) .ibo-dashboard--grid--backdrop {
|
||||
|
||||
position: absolute;
|
||||
height: calc(100% + 24px);
|
||||
// 36px is $ibo-page-container--elements-padding-x, handle variable resolution
|
||||
width: calc(100% + 36px + 36px);
|
||||
margin: -24px -#{36px} 0 -#{36px};
|
||||
background-color: $ibo-color-grey-400;
|
||||
z-index: 2;
|
||||
opacity: 60%;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
@import "dashlet-entry";
|
||||
@import "dashlet-panel";
|
||||
@@ -1,51 +0,0 @@
|
||||
// TODO 3.3 Cleanup variables
|
||||
|
||||
.ibo-dashlet-entry {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
|
||||
|
||||
border: 1px solid $ibo-color-grey-300;
|
||||
border-radius: 5px;
|
||||
padding: 12px;
|
||||
background-color: $ibo-color-grey-100;
|
||||
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
|
||||
&:hover {
|
||||
background-color: $ibo-color-grey-200;
|
||||
border-color: $ibo-color-grey-400;
|
||||
}
|
||||
&:active {
|
||||
background-color: $ibo-color-grey-50;
|
||||
border-color: $ibo-color-grey-500;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-dashlet-entry--icon {
|
||||
flex-shrink: 0;
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
}
|
||||
|
||||
.ibo-dashlet-entry--content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
overflow-x: hidden;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.ibo-dashlet-entry--title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: $ibo-color-grey-900;
|
||||
}
|
||||
|
||||
.ibo-dashlet-entry--description {
|
||||
font-size: 12px;
|
||||
color: $ibo-color-grey-700;
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
// TODO 3.3 Cleanup variables
|
||||
|
||||
.ibo-dashlet-panel {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 326px;
|
||||
background-color: $ibo-color-white-100;
|
||||
}
|
||||
|
||||
.ibo-dashlet-panel--title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
height: 55px;
|
||||
background-color: $ibo-color-white-200;
|
||||
padding: 0 16px;
|
||||
flex-grow: 0;
|
||||
@extend %common-font-ral-med-300;
|
||||
}
|
||||
|
||||
.ibo-dashlet-panel--entries, .ibo-dashlet-panel--form-container {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
|
||||
padding: 16px;
|
||||
gap: 12px;
|
||||
&.ibo-is-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-center-container:has(ibo-dashboard[data-edit-mode="view"]) .ibo-dashlet-panel{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ibo-dashlet-panel--form-container turbo-frame {
|
||||
height: 100%;
|
||||
}
|
||||
.ibo-dashlet-panel--form-container .ibo-form {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
> .form {
|
||||
overflow: auto;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-dashlet-panel--form-container--buttons {
|
||||
display: flex;
|
||||
flex-direction: row !important;
|
||||
justify-content: end;
|
||||
align-items: center;
|
||||
|
||||
margin: 0 -16px -16px -16px;
|
||||
padding: 0 16px;
|
||||
min-height: 60px;
|
||||
|
||||
background-color: $ibo-color-grey-50;
|
||||
border-top: solid 1px $ibo-color-grey-400;
|
||||
}
|
||||
@@ -5,11 +5,9 @@
|
||||
|
||||
$ibo-multi-column--margin-x: -$ibo-spacing-500 !default; /* This is to compensate columns padding and make the whole multicolumn align with the parent borders (cf. Bootstrap rows / cols) */
|
||||
$ibo-multi-column--margin-y: $ibo-spacing-0 !default;
|
||||
$ibo-multi-column--row-gap: $ibo-spacing-800 !default;
|
||||
|
||||
.ibo-multi-column {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: $ibo-multi-column--margin-y $ibo-multi-column--margin-x;
|
||||
row-gap: $ibo-multi-column--row-gap;
|
||||
}
|
||||
3
css/backoffice/vendors/_tomselect.scss
vendored
3
css/backoffice/vendors/_tomselect.scss
vendored
@@ -1,3 +0,0 @@
|
||||
@import "../../../node_modules/tom-select/dist/scss/tom-select.scss";
|
||||
|
||||
$select-color-item-active-border: $ibo-input--focus--border-color;
|
||||
File diff suppressed because one or more lines are too long
@@ -605,6 +605,7 @@ body {
|
||||
color:#a00000;
|
||||
}
|
||||
.setup-extension-tag {
|
||||
display: inline-flex;
|
||||
background-color: grey;
|
||||
border-radius: 8px;
|
||||
padding-left: 3px;
|
||||
@@ -681,9 +682,6 @@ body {
|
||||
overflow: auto;
|
||||
text-align: center;
|
||||
}
|
||||
#installation_progress {
|
||||
display: none;
|
||||
}
|
||||
#fresh_content{
|
||||
border: 0;
|
||||
min-height: 300px;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<module_parameters>
|
||||
<parameters id="authent-local" _delta="define">
|
||||
<password_validation.pattern>^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{12,}$</password_validation.pattern>
|
||||
<password_validation.pattern>^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$</password_validation.pattern>
|
||||
<password_validation.message type="hash"/>
|
||||
</parameters>
|
||||
</module_parameters>
|
||||
|
||||
@@ -29,7 +29,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Heslo nemůže uživatel změnit.',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Heslo bylo obnoveno',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Termín, kdy bylo heslo změneno',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Heslo musí obsahovat minimálně 12 znaků a musí obsahovat minimálně jedno velké písmeno, jedno malé písmeno, jedno číslo a speciální znak.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Heslo musí obsahovat minimálně 8 znaků a musí obsahovat minimálně jedno velké písmeno, jedno malé písmeno, jedno číslo a speciální znak.',
|
||||
'UserLocal:password:expiration' => 'Níže uvedená pole vyžadují rozšíření',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Nastavení exspirace "Jednorázového hesla" nelze u vlastního účtu uživatele.',
|
||||
]);
|
||||
|
||||
@@ -28,7 +28,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||
]);
|
||||
|
||||
@@ -28,7 +28,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Letzte Passworterneuerung',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Letztes Änderungsdatum',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Das Passwort muss mindestens 12 Zeichen lang sein und Großbuchstaben, Kleinbuchstaben, Zahlen und Sonderzeichen enthalten.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Das Passwort entspricht nicht dem in den Konfigurationsregeln hinterlegten RegEx-Ausdruck',
|
||||
'UserLocal:password:expiration' => 'Die folgenden Felder benötigen eine '.ITOP_APPLICATION_SHORT.' Erweiterung',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Das setzen des Passwortablaufs auf "Einmalpasswort" ist für den eigenen Benutzer nicht erlaubt.',
|
||||
]);
|
||||
|
||||
@@ -55,7 +55,7 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed',
|
||||
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User',
|
||||
]);
|
||||
|
||||
@@ -55,7 +55,7 @@ Dict::Add('EN GB', 'British English', 'British English', [
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed',
|
||||
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User',
|
||||
]);
|
||||
|
||||
@@ -25,7 +25,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'El usuario no puede cambiar la contraseña.',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Renovación de contraseña',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Cuando fue el último cambio de contraseña',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'La contraseña debe ser de al menos 12 caracteres e incluir mayúsculas, minúsculas, números y caracteres especiales.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'La contraseña debe ser de al menos 8 caracteres e incluír mayúsculas, minúsculas, números y caracteres especiales.',
|
||||
'UserLocal:password:expiration' => 'El siguiente campo requiere una extensión',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Configurar expiración de contraseña para "ontraseña de un solo uso" no está permitido para su propio Usuario',
|
||||
]);
|
||||
|
||||
@@ -27,7 +27,7 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Mot de passe changé le',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Dernière date à laquelle le mot de passe a été changé',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Le mot de passe doit contenir au moins 12 caractères, avec minuscule, majuscule, nombre et caractère spécial.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Le mot de passe doit contenir au moins 8 caractères, avec minuscule, majuscule, nombre et caractère spécial.',
|
||||
'UserLocal:password:expiration' => 'Les champs ci-dessous nécessitent une extension',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Impossible de mettre "Usage unique" comme validité du mot de passe pour son propre utilisateur.',
|
||||
]);
|
||||
|
||||
@@ -27,7 +27,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'A felhasználó nem változtathat jelszót.',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Jelszó megújítás ideje',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'A jelszó legutóbbi módosításának időpontja',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'A jelszónak legalább 12 karakterből kell állnia, és tartalmaznia kell nagybetűket, kisbetűket, numerikus és speciális karaktereket.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'A jelszónak legalább 8 karakterből kell állnia, és tartalmaznia kell nagybetűket, kisbetűket, numerikus és speciális karaktereket.',
|
||||
'UserLocal:password:expiration' => 'Az alábbi mezőkhöz egy bővítmény szükséges',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'A jelszó lejárati idejének beállítása "Egyszeri jelszóra" nem engedélyezett a saját Felhasználó számára.',
|
||||
]);
|
||||
|
||||
@@ -27,7 +27,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'La password non può essere cambiata dall\'utente.',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Rinnovo della password',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Quando è stata cambiata l\'ultima volta la password',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'La password deve essere di almeno 12 caratteri e includere lettere maiuscole, minuscole, numeri e caratteri speciali.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'La password deve essere di almeno 8 caratteri e includere lettere maiuscole, minuscole, numeri e caratteri speciali.',
|
||||
'UserLocal:password:expiration' => 'I campi sottostanti richiedono un\'estensione',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Impostare la scadenza della password su "Password monouso" non è consentito per il proprio utente',
|
||||
]);
|
||||
|
||||
@@ -28,7 +28,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||
]);
|
||||
|
||||
@@ -28,7 +28,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'De gebruiker kan dit wachtwoord niet veranderen.',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Wachtwoord laatst aangepast',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Tijdstip waarop het wachtwoord het laatst aangepast werd.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Het wachtwoord bestaat uit minstens 12 tekens en bestaat uit een mix van minstens 1 hoofdletter, kleine letter, cijfer en speciaal teken.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Het wachtwoord bestaat uit minstens 8 tekens en bestaat uit een mix van minstens 1 hoofdletter, kleine letter, cijfer en speciaal teken.',
|
||||
'UserLocal:password:expiration' => 'De velden hieronder vereisen een extensie.',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Je kan geen eenmalig wachtwoord instellen voor je eigen gebruiker.',
|
||||
]);
|
||||
|
||||
@@ -27,7 +27,7 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Hasło nie może być zmienione przez użytkownika.',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Odnowienie hasła',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Kiedy ostatnio zmieniano hasło',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Hasło musi mieć co najmniej 12 znaków i zawierać duże, małe litery, cyfry i znaki specjalne.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Hasło musi mieć co najmniej 8 znaków i zawierać duże, małe litery, cyfry i znaki specjalne.',
|
||||
'UserLocal:password:expiration' => 'Poniższe pola wymagają rozszerzenia',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Ustawienie wygaśnięcia hasła "Hasło jednorazowe" nie jest dozwolone dla własnego użytkownika',
|
||||
]);
|
||||
|
||||
@@ -28,7 +28,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Дата изменения пароля',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Когда пароль был изменен в последний раз',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Пароль должен содержать не менее 12 символов и включать прописные, строчные, числовые и специальные символы.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Пароль должен содержать не менее 8 символов и включать прописные, строчные, числовые и специальные символы.',
|
||||
'UserLocal:password:expiration' => 'Поля требуют наличия доп. расширения',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||
]);
|
||||
|
||||
@@ -27,7 +27,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||
]);
|
||||
|
||||
@@ -28,7 +28,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||
]);
|
||||
|
||||
@@ -51,7 +51,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '用户不允许修改密码.',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => '密码更新',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => '上次修改密码的时间',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => '密码必须至少12个字符, 包含大小写, 数字和特殊字符.',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => '密码必须至少8个字符, 包含大小写, 数字和特殊字符.',
|
||||
'UserLocal:password:expiration' => '下面的区域需要插件扩展',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => '不允许用户为自己设置 "一次性密码" 的失效期限',
|
||||
]);
|
||||
|
||||
12
datamodels/2.x/combodo-data-feature-removal/.idea/combodo-data-feature-removal.iml
generated
Normal file
12
datamodels/2.x/combodo-data-feature-removal/.idea/combodo-data-feature-removal.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="Combodo\iTop\DataFeatureRemoval\" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/NoNamespace" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
8
datamodels/2.x/combodo-data-feature-removal/.idea/modules.xml
generated
Normal file
8
datamodels/2.x/combodo-data-feature-removal/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/combodo-data-feature-removal.iml" filepath="$PROJECT_DIR$/.idea/combodo-data-feature-removal.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
24
datamodels/2.x/combodo-data-feature-removal/.idea/php.xml
generated
Normal file
24
datamodels/2.x/combodo-data-feature-removal/.idea/php.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MessDetectorOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PHPCSFixerOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PHPCodeSnifferOptionsConfiguration">
|
||||
<option name="highlightLevel" value="WARNING" />
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PhpIncludePathManager">
|
||||
<include_path>
|
||||
<path value="$PROJECT_DIR$/vendor/composer" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="7.4">
|
||||
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
||||
</component>
|
||||
<component name="PsalmOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
6
datamodels/2.x/combodo-data-feature-removal/.idea/vcs.xml
generated
Normal file
6
datamodels/2.x/combodo-data-feature-removal/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
53
datamodels/2.x/combodo-data-feature-removal/.idea/workspace.xml
generated
Normal file
53
datamodels/2.x/combodo-data-feature-removal/.idea/workspace.xml
generated
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="0556f797-a2a3-4617-8eb0-c7985d4d9530" name="Changes" comment="" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ComposerSettings" synchronizationState="SYNCHRONIZE">
|
||||
<pharConfigPath>$PROJECT_DIR$/composer.json</pharConfigPath>
|
||||
<execution />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="MarkdownSettingsMigration">
|
||||
<option name="stateVersion" value="1" />
|
||||
</component>
|
||||
<component name="PhpWorkspaceProjectConfiguration" interpreter_name="PHP 7.2">
|
||||
<include_path>
|
||||
<path value="$PROJECT_DIR$/vendor/composer" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"customColor": "",
|
||||
"associatedIndex": 1
|
||||
}</component>
|
||||
<component name="ProjectId" id="38XKfHC46lRTrwwYc7IxUdzfXo1" />
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="autoscrollFromSource" value="true" />
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"last_opened_file_path": "/home/combodo/workspaceHUB/HubInstallation",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* CSS of the template page
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Javascript file loaded in template page
|
||||
*/
|
||||
|
||||
17
datamodels/2.x/combodo-data-feature-removal/composer.json
Normal file
17
datamodels/2.x/combodo-data-feature-removal/composer.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"config": {
|
||||
"classmap-authoritative": true
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Combodo\\iTop\\DataFeatureRemoval\\": "src",
|
||||
"": "src/NoNamespace"
|
||||
}
|
||||
},
|
||||
"name": "combodo/combodo-data-feature-removal",
|
||||
"type": "itop-extension",
|
||||
"description": "iTop Data Feature Removal",
|
||||
"require": {
|
||||
"composer-runtime-api": "^2.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<classes>
|
||||
<class id="DataFeatureRemoverExtension" _delta="define">
|
||||
<properties>
|
||||
<category>grant_by_profile</category>
|
||||
<db_table>data_feature_removal_extension</db_table>
|
||||
<naming>
|
||||
<attributes/>
|
||||
</naming>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="extension_code"/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
<uniqueness_rules/>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="extension_code" xsi:type="AttributeString">
|
||||
<sql>extension_code</sql>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="label" xsi:type="AttributeString">
|
||||
<sql>label</sql>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="version" xsi:type="AttributeString">
|
||||
<sql>version</sql>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="module_names" xsi:type="AttributeText">
|
||||
<sql>module_names</sql>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeString">
|
||||
<sql>status</sql>
|
||||
<default_value>none</default_value>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
</fields>
|
||||
<presentation>
|
||||
<list>
|
||||
<items>
|
||||
<item id="extension_code">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
<search>
|
||||
<item id="extension_code">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</search>
|
||||
<details>
|
||||
<item id="extension_code">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</details>
|
||||
</presentation>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="DataFeatureRemoverAuditRule" _delta="define">
|
||||
<properties>
|
||||
<category>grant_by_profile</category>
|
||||
<db_table>data_feature_removal_auditrule</db_table>
|
||||
<naming>
|
||||
<attributes/>
|
||||
</naming>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="rule_name"/>
|
||||
<attribute id="extension_code"/>
|
||||
<attribute id="class_name"/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
<uniqueness_rules/>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="rule_name" xsi:type="AttributeString">
|
||||
<sql>rule_name</sql>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="extension_code" xsi:type="AttributeString">
|
||||
<sql>extension_code</sql>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="class_name" xsi:type="AttributeText">
|
||||
<sql>class_name</sql>
|
||||
<default_value>none</default_value>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="count" xsi:type="AttributeInteger">
|
||||
<sql>count</sql>
|
||||
<default_value>0</default_value>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
</fields>
|
||||
<presentation>
|
||||
<list>
|
||||
<items>
|
||||
<item id="rule_name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="extension_code">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="class_name">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
<search>
|
||||
<item id="rule_name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="extension_code">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="class_name">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</search>
|
||||
<details>
|
||||
<item id="rule_name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="extension_code">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="class_name">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</details>
|
||||
</presentation>
|
||||
<methods/>
|
||||
</class>
|
||||
</classes>
|
||||
<menus>
|
||||
<menu id="DataFeatureRemovalMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>30</rank>
|
||||
<parent>SystemTools</parent>
|
||||
<url>$pages/exec.php?exec_module=combodo-data-feature-removal&exec_page=index.php&c[menu]=DataFeatureRemovalMenu</url>
|
||||
<enable_admin_only>1</enable_admin_only>
|
||||
</menu>
|
||||
</menus>
|
||||
</itop_design>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Localized data
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
'Menu:DataFeatureRemovalMenu' => 'Features Removal',
|
||||
'combodo-data-feature-removal/Operation:Main/Title' => 'Features Removal',
|
||||
|
||||
'DataFeatureRemoval:Main:Title' => 'Features Removal',
|
||||
'DataFeatureRemoval:Main:SubTitle' => 'Prepare features you want to enable/disable in a future setup',
|
||||
'DataFeatureRemoval:Failure:Title' => 'Feature dry removal errors',
|
||||
'DataFeatureRemoval:Helper:Title' => 'This utilitary allows you to enable or disable features that are installed in your iTop.',
|
||||
'DataFeatureRemoval:Helper:Desc1' => 'It will prepare the setup step that proceeds to feature enabling or disabling.',
|
||||
'DataFeatureRemoval:Helper:Desc2' => 'You will need to analyze if there are any data or dependency preventing you from enabling/disabling a feature.',
|
||||
|
||||
'DataFeatureRemoval:Features:Title' => 'Features',
|
||||
'DataFeatureRemoval:Analysis:Title' => 'Analysis result',
|
||||
'DataFeatureRemoval:Analysis:SubTitle' => '%1$s element(s) to clean before continuing',
|
||||
|
||||
'DataFeatureRemoval:Table:Analysis:ClassName' => 'Element to remove',
|
||||
'DataFeatureRemoval:Table:Analysis:RemovalType' => 'Type of element',
|
||||
'DataFeatureRemoval:Table:Analysis:FeatureName' => 'Feature name',
|
||||
'DataFeatureRemoval:Table:Analysis:Occurence' => 'Occurence',
|
||||
|
||||
'UI:Button:Analyze' => 'Analyze',
|
||||
'UI:Button:ModifyChoices' => 'Modify Choices',
|
||||
'UI:Button:AnalyzeAndSetup' => 'Analyze and go to setup',
|
||||
|
||||
'UI:Action:ForceUninstall' => 'Force uninstall',
|
||||
'UI:Action:MoreInfo' => 'More information',
|
||||
|
||||
'DataFeatureRemoval:Table:Analysis:RemovalType:FINAL_CLASS' => 'Final class',
|
||||
|
||||
]);
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Localized data
|
||||
*/
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Menu:DataFeatureRemovalMenu' => 'Features Removal',
|
||||
'combodo-data-feature-removal/Operation:Main/Title' => 'Features Removal',
|
||||
|
||||
'DataFeatureRemoval:Main:Title' => 'Features Removal',
|
||||
'DataFeatureRemoval:Main:SubTitle' => 'Prepare features you want to enable/disable in a future setup',
|
||||
'DataFeatureRemoval:Failure:Title' => 'Feature dry removal errors',
|
||||
'DataFeatureRemoval:Helper:Title' => 'This utilitary allows you to enable or disable features that are installed in your iTop.',
|
||||
'DataFeatureRemoval:Helper:Desc1' => 'It will prepare the setup step that proceeds to feature enabling or disabling.',
|
||||
'DataFeatureRemoval:Helper:Desc2' => 'You will need to analyze if there are any data or dependency preventing you from enabling/disabling a feature.',
|
||||
|
||||
'DataFeatureRemoval:Features:Title' => 'Features',
|
||||
'DataFeatureRemoval:Analysis:Title' => 'Analysis result',
|
||||
'DataFeatureRemoval:Analysis:SubTitle' => '%1$s element(s) to clean before continuing',
|
||||
|
||||
'DataFeatureRemoval:Table:Analysis:ClassName' => 'Element to remove',
|
||||
'DataFeatureRemoval:Table:Analysis:RemovalType' => 'Type of element',
|
||||
'DataFeatureRemoval:Table:Analysis:FeatureName' => 'Feature name',
|
||||
'DataFeatureRemoval:Table:Analysis:Occurence' => 'Occurence',
|
||||
|
||||
'UI:Button:Analyze' => 'Analyze',
|
||||
'UI:Button:ModifyChoices' => 'Modify Choices',
|
||||
'UI:Button:AnalyzeAndSetup' => 'Analyze and go to setup',
|
||||
|
||||
'UI:Action:ForceUninstall' => 'Force uninstall',
|
||||
'UI:Action:MoreInfo' => 'More information',
|
||||
|
||||
'DataFeatureRemoval:Table:Analysis:RemovalType:FINAL_CLASS' => 'Final class',
|
||||
]);
|
||||
20
datamodels/2.x/combodo-data-feature-removal/index.php
Normal file
20
datamodels/2.x/combodo-data-feature-removal/index.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval;
|
||||
|
||||
use Combodo\iTop\DataFeatureRemoval\Controller\DataFeatureRemovalController;
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
|
||||
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
|
||||
DataFeatureRemovalLog::Enable();
|
||||
|
||||
$oController = new DataFeatureRemovalController(MODULESROOT.DataFeatureRemovalHelper::MODULE_NAME.'/templates', DataFeatureRemovalHelper::MODULE_NAME);
|
||||
$oController->SetDefaultOperation('Main');
|
||||
$oController->HandleOperation();
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
// PHP Data Model definition file
|
||||
|
||||
// WARNING - WARNING - WARNING
|
||||
// DO NOT EDIT THIS FILE (unless you know what you are doing)
|
||||
//
|
||||
// If you provide a datamodel.xxxx.xml file with your module,
|
||||
// this file WILL BE overwritten by the compilation of the
|
||||
// module (during the setup) if the datamodel.xxxx.xml file
|
||||
// contains the definition of new classes or menus.
|
||||
//
|
||||
// The recommended way to define new classes (for iTop 2.0 and later) is via the XML definition.
|
||||
// This file remains in the module's template only for the cases where there is:
|
||||
// - either no new class or menu defined in the XML file
|
||||
// - or no XML file at all supplied by the module
|
||||
@@ -1,38 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
//
|
||||
// iTop module definition file
|
||||
//
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-container-mgmt/3.3.0',
|
||||
'combodo-data-feature-removal/3.3.0',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Container management',
|
||||
'label' => 'iTop Data Feature Removal',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => [
|
||||
'itop-virtualization-mgmt/3.3.0',
|
||||
|
||||
],
|
||||
'mandatory' => false,
|
||||
'visible' => true,
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => [
|
||||
|
||||
],
|
||||
'webservice' => [
|
||||
|
||||
'vendor/autoload.php',
|
||||
'model.combodo-data-feature-removal.php', // Contains the PHP code generated by the "compilation" of datamodel.combodo-data-feature-removal.xml
|
||||
],
|
||||
'webservice' => [],
|
||||
'data.struct' => [
|
||||
// add your 'structure' definition XML files here,
|
||||
'data/en_us.data.itop-container-type.xml',
|
||||
'data/en_us.data.itop-container-image-type.xml',
|
||||
],
|
||||
'data.sample' => [
|
||||
// add your sample data XML files here,
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Controller;
|
||||
|
||||
require_once APPROOT.'setup/feature_removal/SetupAudit.php';
|
||||
require_once APPROOT.'setup/feature_removal/DryRemovalRuntimeEnvironment.php';
|
||||
|
||||
use Combodo\iTop\Application\TwigBase\Controller\Controller;
|
||||
use Combodo\iTop\AuthentToken\Helper\TokenAuthLog;
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
|
||||
use Combodo\iTop\DataFeatureRemoval\Model\DataFeatureRemoverAuditRuleService;
|
||||
use Combodo\iTop\DataFeatureRemoval\Model\DataFeatureRemoverExtensionService;
|
||||
use Combodo\iTop\Setup\FeatureRemoval\DryRemovalRuntimeEnvironment;
|
||||
use Combodo\iTop\Setup\FeatureRemoval\SetupAudit;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use utils;
|
||||
|
||||
class DataFeatureRemovalController extends Controller
|
||||
{
|
||||
private array $aSelectedExtensionsForCheck = [];
|
||||
|
||||
public function OperationMain($sErrorMessage = null)
|
||||
{
|
||||
$aParams = [];
|
||||
|
||||
$this->AddLinkedStylesheet(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/css/DataFeatureRemoval.css');
|
||||
$this->AddLinkedScript(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/js/DataFeatureRemoval.js');
|
||||
|
||||
$aParams['sTransactionId'] = utils::GetNewTransactionId();
|
||||
$this->AddFeatureParams($aParams);
|
||||
$this->AddAnalyzeParams($aParams);
|
||||
$aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage;
|
||||
$this->DisplayPage($aParams);
|
||||
}
|
||||
|
||||
public function AddFeatureParams(array &$aParams)
|
||||
{
|
||||
$aParams['aExtensions'] = $this->GetExtensionsTable();
|
||||
$aParams['sModule'] = DataFeatureRemovalHelper::MODULE_NAME;
|
||||
}
|
||||
|
||||
public function AddAnalyzeParams(array &$aParams)
|
||||
{
|
||||
$iTotalCount = 0;
|
||||
$aData = [];
|
||||
$aColumns = [];
|
||||
foreach (DataFeatureRemoverAuditRuleService::GetInstance()->ReadCheckRules() as $oRule) {
|
||||
$sContent = $oRule->Get('class_name');
|
||||
$sModuleName = MetaModel::GetModuleName($sContent);
|
||||
$aExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetIncludingExtensions($sModuleName);
|
||||
$sExtensions = implode(' ', $aExtensions);
|
||||
$sTypeName = $oRule->Get('rule_name');
|
||||
$sTypeDesc = \Dict::S("DataFeatureRemoval:Table:Analysis:RemovalType:$sTypeName");
|
||||
$iCount = $oRule->Get('count');
|
||||
$iTotalCount += $iCount;
|
||||
$aColumns = ['ClassName', 'RemovalType','FeatureName','Occurence'];
|
||||
$aData[] = [
|
||||
<<<HTML
|
||||
<label>$sContent</label>
|
||||
HTML,
|
||||
<<<HTML
|
||||
<label>$sTypeDesc</label>
|
||||
HTML,
|
||||
<<<HTML
|
||||
<label title="$sModuleName">$sExtensions</label>
|
||||
HTML,
|
||||
<<<HTML
|
||||
<label>$iCount</label>
|
||||
HTML,
|
||||
];
|
||||
}
|
||||
|
||||
$aParams['aCheckRules'] = $this->GetTableData('Analysis', $aColumns, $aData);
|
||||
$aParams['rule_count'] = $iTotalCount;
|
||||
}
|
||||
|
||||
public function OperationAnalyze()
|
||||
{
|
||||
$aSelectedExtensionsFromUI = utils::ReadPostedParam('aExtensions', []);
|
||||
$this->aSelectedExtensionsForCheck = [];
|
||||
foreach ($aSelectedExtensionsFromUI as $sCode => $aData) {
|
||||
$sValue = $aData['enable'] ?? 'off';
|
||||
if (($sValue) === 'on') {
|
||||
$this->aSelectedExtensionsForCheck[] = $sCode;
|
||||
}
|
||||
}
|
||||
|
||||
$this->m_sOperation = 'Main';
|
||||
|
||||
try {
|
||||
$this->Analyze();
|
||||
$this->OperationMain();
|
||||
} catch (Exception $e) {
|
||||
\IssueLog::Error(__METHOD__, null, ['stack' => $e->getTraceAsString(), 'exception' => $e->getMessage()]);
|
||||
$this->OperationMain($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function GetExtensionsTable(): array
|
||||
{
|
||||
$aExtensions = [];
|
||||
$aColumns = ['', 'Version', 'Name', 'Code'];
|
||||
$this->aSelectedExtensionsForCheck = DataFeatureRemoverExtensionService::GetInstance()->ReadAuditedExtensions();
|
||||
|
||||
foreach (DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions() as $sCode => $oExtension) {
|
||||
/** @var \iTopExtension $oExtension */
|
||||
|
||||
$sChecked = "checked";
|
||||
$sDisabledHtml = '';
|
||||
if ($oExtension->bRemovedFromDisk) {
|
||||
$sDisabledHtml = 'disabled=""';
|
||||
} elseif (! array_key_exists($sCode, $this->aSelectedExtensionsForCheck)) {
|
||||
$sChecked = "";
|
||||
}
|
||||
|
||||
$sLabel = $oExtension->sLabel;
|
||||
$sVersion = $oExtension->sVersion;
|
||||
$sIdEnable = "aExtensions[$sCode][enable]";
|
||||
|
||||
$aExtensions[] = [
|
||||
<<<HTML
|
||||
<input type="checkbox" $sDisabledHtml class="extension_check" $sChecked id="$sIdEnable" name="$sIdEnable"/>
|
||||
HTML,
|
||||
<<<HTML
|
||||
<label>$sVersion</label>
|
||||
HTML,
|
||||
<<<HTML
|
||||
<label for="$sIdEnable">$sLabel</label>
|
||||
HTML,
|
||||
<<<HTML
|
||||
<label for="$sIdEnable">$sCode</label>
|
||||
HTML,
|
||||
];
|
||||
}
|
||||
|
||||
return $this->GetTableData('Extensions', $aColumns, $aExtensions);
|
||||
|
||||
}
|
||||
|
||||
public function GetTableData(string $sTableName, array $aColumns, array $aData): array
|
||||
{
|
||||
if (empty($aData)) {
|
||||
return [
|
||||
'Type' => 'Table',
|
||||
'Columns' => [['label' => '']],
|
||||
'Data' => [[ Dict::S('DbCleaner:Table:Empty')]],
|
||||
];
|
||||
}
|
||||
|
||||
$aNewColumns = [];
|
||||
foreach ($aColumns as $sColumn) {
|
||||
$aNewColumns[] = ['label' => Dict::S("DataFeatureRemoval:Table:$sTableName:$sColumn", $sColumn)];
|
||||
}
|
||||
$aColumns = $aNewColumns;
|
||||
|
||||
return [
|
||||
'Type' => 'Table',
|
||||
'Columns' => $aColumns,
|
||||
'Data' => $aData,
|
||||
];
|
||||
}
|
||||
|
||||
private function Analyze()
|
||||
{
|
||||
DataFeatureRemoverExtensionService::GetInstance()->SaveExtensions($this->aSelectedExtensionsForCheck);
|
||||
|
||||
$sSourceEnvt = \MetaModel::GetEnvironment();
|
||||
$oDryRemovalRuntimeEnvironment = new DryRemovalRuntimeEnvironment();
|
||||
$oDryRemovalRuntimeEnvironment->Prepare($sSourceEnvt, $this->aSelectedExtensionsForCheck);
|
||||
$oDryRemovalRuntimeEnvironment->CompileFrom($sSourceEnvt);
|
||||
|
||||
$oSetupAudit = new SetupAudit($sSourceEnvt, DryRemovalRuntimeEnvironment::DRY_REMOVAL_AUDIT_ENV);
|
||||
$this->Save($oSetupAudit->GetIssues());
|
||||
}
|
||||
|
||||
private function Save(array $aGetRemovedClasses)
|
||||
{
|
||||
\IssueLog::Debug(__METHOD__, null, ['aGetRemovedClasses' => $aGetRemovedClasses]);
|
||||
|
||||
DataFeatureRemoverAuditRuleService::GetInstance()->SaveChecks($aGetRemovedClasses);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Helper;
|
||||
|
||||
use Exception;
|
||||
use Throwable;
|
||||
|
||||
class DataFeatureRemovalException extends Exception
|
||||
{
|
||||
public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null, array $aContext = [])
|
||||
{
|
||||
if (!is_null($previous)) {
|
||||
$sStack = $previous->getTraceAsString();
|
||||
$sError = $previous->getMessage();
|
||||
} else {
|
||||
$sStack = $this->getTraceAsString();
|
||||
$sError = '';
|
||||
}
|
||||
|
||||
$aContext['error'] = $sError;
|
||||
$aContext['stack'] = $sStack;
|
||||
DataFeatureRemovalLog::Error($message, null, $aContext);
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Helper;
|
||||
|
||||
class DataFeatureRemovalHelper
|
||||
{
|
||||
public const MODULE_NAME = 'combodo-data-feature-removal';
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Helper;
|
||||
|
||||
use LogAPI;
|
||||
|
||||
class DataFeatureRemovalLog extends LogAPI
|
||||
{
|
||||
public const CHANNEL_DEFAULT = 'DataFeatureRemoval';
|
||||
|
||||
protected static $m_oFileLog = null;
|
||||
|
||||
public static function Enable($sTargetFile = null)
|
||||
{
|
||||
if (empty($sTargetFile)) {
|
||||
$sTargetFile = APPROOT.'log/error.log';
|
||||
}
|
||||
parent::Enable($sTargetFile);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Model;
|
||||
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException;
|
||||
use DataFeatureRemoverAuditRule;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use Exception;
|
||||
|
||||
class DataFeatureRemoverAuditRuleService
|
||||
{
|
||||
private static DataFeatureRemoverAuditRuleService $oInstance;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
final public static function GetInstance(): DataFeatureRemoverAuditRuleService
|
||||
{
|
||||
if (!isset(self::$oInstance)) {
|
||||
self::$oInstance = new DataFeatureRemoverAuditRuleService();
|
||||
}
|
||||
|
||||
return self::$oInstance;
|
||||
}
|
||||
|
||||
final public static function SetInstance(?DataFeatureRemoverAuditRuleService $oInstance): void
|
||||
{
|
||||
self::$oInstance = $oInstance;
|
||||
}
|
||||
|
||||
public function SaveChecks(array $aGetRemovedClasses)
|
||||
{
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT DataFeatureRemoverAuditRule', []);
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
|
||||
while (null != ($oObj = $oSet->Fetch())) {
|
||||
$oObj->DBDelete();
|
||||
}
|
||||
|
||||
foreach ($aGetRemovedClasses as $sClass => $iCount) {
|
||||
$oObj = new DataFeatureRemoverAuditRule();
|
||||
$oObj->Set('rule_name', 'FINAL_CLASS');
|
||||
$oObj->Set('extension_code', $sClass);
|
||||
$oObj->Set('class_name', $sClass);
|
||||
$oObj->Set('count', $iCount);
|
||||
$oObj->DBWrite();
|
||||
}
|
||||
}
|
||||
|
||||
public function ReadCheckRules(): array
|
||||
{
|
||||
try {
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT DataFeatureRemoverAuditRule', []);
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
|
||||
$aRes = [];
|
||||
while (null != ($oObj = $oSet->Fetch())) {
|
||||
$aRes[] = $oObj;
|
||||
}
|
||||
|
||||
return $aRes;
|
||||
} catch (Exception $e) {
|
||||
throw new DataFeatureRemovalException(__FUNCTION__.' failed', 0, $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Model;
|
||||
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException;
|
||||
use DataFeatureRemoverExtension;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use Exception;
|
||||
use iTopExtension;
|
||||
use iTopExtensionsMap;
|
||||
use MetaModel;
|
||||
|
||||
class DataFeatureRemoverExtensionService
|
||||
{
|
||||
private static DataFeatureRemoverExtensionService $oInstance;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
final public static function GetInstance(): DataFeatureRemoverExtensionService
|
||||
{
|
||||
if (!isset(self::$oInstance)) {
|
||||
self::$oInstance = new DataFeatureRemoverExtensionService();
|
||||
}
|
||||
|
||||
return self::$oInstance;
|
||||
}
|
||||
|
||||
final public static function SetInstance(?DataFeatureRemoverExtensionService $oInstance): void
|
||||
{
|
||||
self::$oInstance = $oInstance;
|
||||
}
|
||||
|
||||
public function SaveExtensions(array $aSelectedExtensionsForCheck)
|
||||
{
|
||||
$this->ReadItopExtensions();
|
||||
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT DataFeatureRemoverExtension', []);
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
|
||||
while (null != ($oObj = $oSet->Fetch())) {
|
||||
$oObj->DBDelete();
|
||||
}
|
||||
|
||||
foreach ($aSelectedExtensionsForCheck as $i => $sCode) {
|
||||
$oObj = new DataFeatureRemoverExtension();
|
||||
$oObj->Set('extension_code', $sCode);
|
||||
/** @var iTopExtension $oExtension */
|
||||
$oExtension = $this->aItopExtensions[$sCode];
|
||||
$oObj->Set('module_names', json_encode($oExtension->aModules));
|
||||
$oObj->Set('label', $oExtension->sLabel);
|
||||
$oObj->Set('version', $oExtension->sVersion);
|
||||
$oObj->DBWrite();
|
||||
}
|
||||
}
|
||||
|
||||
private array $aSelectedExtensions = [];
|
||||
private array $aItopExtensions = [];
|
||||
private array $aIncludingExtensionsByModuleName = [];
|
||||
public function ReadAuditedExtensions(): array
|
||||
{
|
||||
if (count($this->aSelectedExtensions) == 0) {
|
||||
try {
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT DataFeatureRemoverExtension', []);
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
|
||||
while (null != ($oObj = $oSet->Fetch())) {
|
||||
$sCode = $oObj->Get('extension_code');
|
||||
$sLabel = $oObj->Get('label');
|
||||
$sVersion = $oObj->Get('version');
|
||||
|
||||
$sModuleNames = $oObj->Get('module_names');
|
||||
$aModuleNames = json_decode($sModuleNames, true);
|
||||
if (is_array($aModuleNames) && count($aModuleNames) > 0) {
|
||||
foreach ($aModuleNames as $sModuleName) {
|
||||
$aExtensions = $this->aIncludingExtensionsByModuleName[$sModuleName] ?? [];
|
||||
$aExtensions[] = "$sLabel / $sVersion";
|
||||
$this->aIncludingExtensionsByModuleName[$sModuleName] = $aExtensions;
|
||||
|
||||
}
|
||||
}
|
||||
$this->aSelectedExtensions[$sCode] = $oObj;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
throw new DataFeatureRemovalException(__FUNCTION__.' failed', 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
\IssueLog::Debug(__METHOD__, null, ['aSelectedExtensionsForCheck' => $this->aSelectedExtensions]);
|
||||
\IssueLog::Debug(__METHOD__, null, ['aIncludingExtensionsByModuleName' => $this->aIncludingExtensionsByModuleName]);
|
||||
|
||||
return $this->aSelectedExtensions;
|
||||
}
|
||||
|
||||
public function GetIncludingExtensions(string $sModuleName): array
|
||||
{
|
||||
$this->ReadAuditedExtensions();
|
||||
return $this->aIncludingExtensionsByModuleName[$sModuleName] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iTopExtension[]
|
||||
*/
|
||||
public function ReadItopExtensions(): array
|
||||
{
|
||||
if (count($this->aItopExtensions) == 0) {
|
||||
$oExtensionsMap = new iTopExtensionsMap();
|
||||
$oExtensionsMap->LoadInstalledExtensionsFromDatabase(MetaModel::GetConfig());
|
||||
$this->aItopExtensions = $oExtensionsMap->GetAllExtensionsToDisplayInSetup(true);
|
||||
|
||||
uasort($this->aItopExtensions, function (iTopExtension $oiTopExtension1, iTopExtension $oiTopExtension2) {
|
||||
return strcmp($oiTopExtension1->sLabel, $oiTopExtension2->sLabel);
|
||||
});
|
||||
}
|
||||
|
||||
return $this->aItopExtensions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{# @copyright Copyright (C) 2010-2024 Combodo SAS #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
{% UIForm Standard {} %}
|
||||
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Analysis:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Analysis:SubTitle'|dict_format(rule_count) } %}
|
||||
{% UIDataTable ForForm { sRef:'aCheckRules', aColumns:aCheckRules.Columns, aData:aCheckRules.Data} %}{% EndUIDataTable %}
|
||||
{% EndUIPanel %}
|
||||
{% EndUIForm %}
|
||||
@@ -0,0 +1,18 @@
|
||||
{# @copyright Copyright (C) 2010-2024 Combodo SAS #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
|
||||
{% UIForm Standard {} %}
|
||||
{% UIInput ForHidden {sName:'operation', sValue:'Analyze'} %}
|
||||
{% UIInput ForHidden {sName:'transaction_id', sValue:sTransactionId} %}
|
||||
|
||||
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:Features:Title'|dict_s} %}
|
||||
{% UIDataTable ForForm { sRef:'aExtensions', aColumns:aExtensions.Columns, aData:aExtensions.Data} %}{% EndUIDataTable %}
|
||||
{% EndUIFieldSet %}
|
||||
|
||||
|
||||
{% UIToolbar ForButton {} %}
|
||||
{% UIButton ForPrimaryAction {sLabel:'UI:Button:Analyze'|dict_s, sName:'btn_apply', sId:'btn_apply', bIsSubmit:true} %}
|
||||
{% EndUIToolbar %}
|
||||
|
||||
{% EndUIForm %}
|
||||
@@ -0,0 +1,28 @@
|
||||
{# @copyright Copyright (C) 2010-2025 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
{# Usable variables: #}
|
||||
{# * sTitle => page title #}
|
||||
{# * sMessage => success message #}
|
||||
{# * sError => error message #}
|
||||
|
||||
{# DataFeatureRemoval #}
|
||||
|
||||
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Main:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Main:SubTitle'|dict_s } %}
|
||||
|
||||
{% UIAlert ForInformation { sTitle:'DataFeatureRemoval:Helper:Title'|dict_s } %}
|
||||
{{ 'DataFeatureRemoval:Helper:Desc1'|dict_s }}<BR>
|
||||
{{ 'DataFeatureRemoval:Helper:Desc2'|dict_s }}
|
||||
{% EndUIAlert %}
|
||||
|
||||
|
||||
{% if null != DataFeatureRemovalErrorMessage %}
|
||||
<div id="feature_removal_error_msg_div" style="display:block">
|
||||
{% UIAlert ForFailure { sTitle:'DataFeatureRemoval:Failure:Title'|dict_s, sId: 'feature_removal_error_msg', sContent:DataFeatureRemovalErrorMessage } %}
|
||||
{% EndUIAlert %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% include 'FeaturesTab.html.twig' %}
|
||||
{% include 'ExtensionRemovalDataTab.html.twig' %}
|
||||
{% EndUIPanel %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{# @copyright Copyright (C) 2010-2024 Combodo SAS #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
$(document).on('click', '#checkAllExtensions', function() {
|
||||
var bChecked = this.checked;
|
||||
$('.extension_check').each( function() { this.checked = bChecked });
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
{# @copyright Copyright (C) 2010-2024 Combodo SAS #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
25
datamodels/2.x/combodo-data-feature-removal/vendor/autoload.php
vendored
Normal file
25
datamodels/2.x/combodo-data-feature-removal/vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464::getLoader();
|
||||
579
datamodels/2.x/combodo-data-feature-removal/vendor/composer/ClassLoader.php
vendored
Normal file
579
datamodels/2.x/combodo-data-feature-removal/vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,579 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var string|null */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array<string, list<string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var string|null */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var array<string, self>
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param string|null $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string> Array of classname => path
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||
*
|
||||
* @return array<string, self>
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
Copyright (c) 2010-present Fabien Potencier
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -17,3 +18,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
17
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_classmap.php
vendored
Normal file
17
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => $baseDir . '/src/Controller/DataFeatureRemovalController.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalException' => $baseDir . '/src/Helper/DataFeatureRemovalException.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalHelper' => $baseDir . '/src/Helper/DataFeatureRemovalHelper.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalLog' => $baseDir . '/src/Helper/DataFeatureRemovalLog.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Model\\DataFeatureRemoverAuditRuleService' => $baseDir . '/src/Model/DataFeatureRemoverAuditRuleService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Model\\DataFeatureRemoverExtensionService' => $baseDir . '/src/Model/DataFeatureRemoverExtensionService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\SetupAudit' => $baseDir . '/src/Service/SetupAudit.php',
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
);
|
||||
9
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_namespaces.php
vendored
Normal file
9
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_namespaces.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
11
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_psr4.php
vendored
Normal file
11
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\' => array($baseDir . '/src'),
|
||||
'' => array($baseDir . '/src/NoNamespace'),
|
||||
);
|
||||
37
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_real.php
vendored
Normal file
37
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit4f96a7199e2c0d90e547333758b26464::getInitializer($loader));
|
||||
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
$loader->register(true);
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
48
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_static.php
vendored
Normal file
48
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit4f96a7199e2c0d90e547333758b26464
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'C' =>
|
||||
array (
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\' => 32,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $fallbackDirsPsr4 = array (
|
||||
0 => __DIR__ . '/../..' . '/src/NoNamespace',
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => __DIR__ . '/../..' . '/src/Controller/DataFeatureRemovalController.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalException' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalException.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalHelper' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalHelper.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalLog' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalLog.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Model\\DataFeatureRemoverAuditRuleService' => __DIR__ . '/../..' . '/src/Model/DataFeatureRemoverAuditRuleService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Model\\DataFeatureRemoverExtensionService' => __DIR__ . '/../..' . '/src/Model/DataFeatureRemoverExtensionService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\SetupAudit' => __DIR__ . '/../..' . '/src/Service/SetupAudit.php',
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$prefixDirsPsr4;
|
||||
$loader->fallbackDirsPsr4 = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$fallbackDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ SetupWebPage::AddModule(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Database maintenance tools',
|
||||
'category' => 'Application management',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Combodo\iTop\DBTools\Service;
|
||||
use CMDBSource;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use IssueLog;
|
||||
|
||||
class DBToolsUtils
|
||||
{
|
||||
|
||||
@@ -71,19 +71,6 @@
|
||||
<module>itop-virtualization-mgmt</module>
|
||||
</modules>
|
||||
<default>true</default>
|
||||
<sub_options>
|
||||
<options type="array">
|
||||
<choice>
|
||||
<extension_code>itop-container-mgmt</extension_code>
|
||||
<title>Containerization</title>
|
||||
<description><![CDATA[Manage Container Images, Applications and Hosts]]></description>
|
||||
<modules type="array">
|
||||
<module>itop-container-mgmt</module>
|
||||
</modules>
|
||||
<default>false</default>
|
||||
</choice>
|
||||
</options>
|
||||
</sub_options>
|
||||
</choice>
|
||||
</options>
|
||||
</step>
|
||||
|
||||
@@ -1,205 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<Brand alias="Brand" id="1">
|
||||
<name>Acer</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icon-acer.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmc6c3ZnIHhtbG5zOmlua3NjYXBlPSJodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIiB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiIHhtbG5zOnN2Zz0iaH
|
||||
R0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgaWQ9ImFjZXIiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iODMiIGhlaWdodD0iODMiIHZpZXdCb3g9IjAgMCA4MyA4MyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgc29kaXBvZGk6ZG9jbmFtZT0iaWNvbi1hY2VyLnN2ZyIgaW5rc2NhcGU6dmVyc2lvbj0iMS40LjMgKDBkMTVmNzUwNDIsIDIwMjUtMTItMjUpIj48c3ZnOmRlZnMgaWQ9ImRlZnMxIi8+PHNvZGlwb2RpOm5hbWVkdmlldyBpZD0ibmFtZWR2
|
||||
aWV3MSIgcGFnZWNvbG9yPSIjZmZmZmZmIiBib3JkZXJjb2xvcj0iIzAwMDAwMCIgYm9yZGVyb3BhY2l0eT0iMC4yNSIgaW5rc2NhcGU6c2hvd3BhZ2VzaGFkb3c9IjIiIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiIGlua3NjYXBlOnBhZ2VjaGVja2VyYm9hcmQ9IjAiIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIgc2hvd2d1aWRlcz0idHJ1ZSIgaW5rc2NhcGU6em9vbT0iMTAuNDgzMDcxIiBpbmtzY2FwZTpjeD0iNzUuNzg4ODYiIGlua3NjYXBlOmN5PSIzNS
|
||||
42NzY1NjgiIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMjU2MCIgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iMTM2MCIgaW5rc2NhcGU6d2luZG93LXg9IjAiIGlua3NjYXBlOndpbmRvdy15PSIwIiBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIiBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJhY2VyIj48c29kaXBvZGk6Z3VpZGUgcG9zaXRpb249IjQwLjMwNzkxOSw0MS4yMjAyMTQiIG9yaWVudGF0aW9uPSIwLC0xIiBpZD0iZ3VpZGUxIiBpbmtzY2FwZTpsb2NrZWQ9
|
||||
ImZhbHNlIi8+PC9zb2RpcG9kaTpuYW1lZHZpZXc+Cjxzdmc6cGF0aCBpZD0iYWNlci1sb2dvIiBzdHlsZT0iZmlsbDojODBjMzQzIiBkPSJtIDgyLjg1LDMyLjc2MDg5MyBjIC0wLjI5LC0wLjQyIC0wLjYyLC0wLjcgLTIuMDQsLTAuODEgLTAuMzcsLTAuMDMgLTEuNiwtMC4wNyAtMy42NiwtMC4wNyAtNS40MiwwIC05LjEsMS42NSAtMTAuOTgsNC45MSAwLjUyLC0zLjI4IC0yLjY3LC00LjkyIC05LjU1LC00LjkyIC04LjA5LDAgLTEzLjE0LDMuMjcgLTE1LjE1LDkuOD
|
||||
EgLTAuNzQsMS45MSAtMC44Miw0LjAyIC0wLjIzLDUuOTggbCAtMS45MSwwLjEzIGMgLTEuNDksMC4xMSAtMy40NiwwLjIyIC00LjY2LDAuMjIgLTIuOTYsMCAtNC44LC0wLjUgLTUuNTEsLTEuNSAtMC42NCwtMC45IC0wLjU3LC0yLjU2IDAuMTcsLTQuOTggMS4yMywtNC4wMiA0LjI5LC01LjgyIDkuMTgsLTUuODIgMi41MywwIDUsMC4yNyA1LDAuMjcgMC4zLC0wLjA1IDAuNTEsLTAuMzMgMC40NiwtMC42NCAwLC0wLjAxIDAsLTAuMDIgLTAuMDEsLTAuMDMgbCAtMC4w
|
||||
NSwtMC4zOCAtMC4xNywtMS4zNSBjIC0wLjExLC0wLjg5IC0wLjc3LC0xLjQxIC0xLjk3LC0xLjU3IC0xLjEsLTAuMDcgLTEuOTEsLTAuMTMgLTMuMTIsLTAuMTMgaCAtMC4wNyBjIC02LjM5LDAuMDEgLTEwLjg0LDIuMTIgLTEzLjM2LDYuMzIgMC45MiwtNC4yMSAtMi4wNCwtNi4zMiAtOC44NywtNi4zMiAtMi43MywtMC4wNSAtNS40NiwwLjA2IC04LjE4LDAuMzMgLTEuMDMsLTAuMDMgLTEuOTYsMC42MSAtMi4zMywxLjU3IGwgLTAuNTQsMS43MyBjIC0wLjEsMC4zMi
|
||||
AwLjA1LDAuNDggMC40NiwwLjQ4IGggMC4wMSBjIDAuMywtMC4wNCAxLjQ2LC0wLjE1IDMuNDQsLTAuMzEgMi42MiwtMC4yMSA0LjU1LC0wLjMyIDUuODMsLTAuMzIgMy43NywwIDUuMzUsMC45NSA0Ljc2LDIuODQgLTAuMTEsMC40IC0wLjQ0LDAuNzEgLTAuODUsMC43OCAtMy41NiwwLjU5IC02LjM5LDEuMDIgLTguNDgsMS4yOCAtNS44OSwwLjc1IC05LjI5LDIuNTkgLTEwLjIsNS41MiAtMS4yNSw0LjAzIDEuODksNi4wNCA5LjQ0LDYuMDQgMy4xNywwLjA0IDYuMzQs
|
||||
LTAuMTggOS40OCwtMC42NSAxLjQ3LC0wLjI1IDIuMjIsLTAuNjMgMi41MSwtMS41OCBsIDEuNDEsLTQuNDkgYyAtMC4xNSw0LjQ5IDIuOTksNi43NSA5LjQxLDYuNzUgMi4yMywwLjA0IDQuNDUsLTAuMDYgNi42NiwtMC4zMSAxLjMyLC0wLjIzIDEuOTUsLTAuNTIgMi4yNCwtMS41MSBsIDAuMjgsLTEuNDEgYyAxLjM3LDIuMTQgNC4zNywzLjIxIDkuMDEsMy4yMSA0Ljg5LDAgNy43NCwtMC4xNCA4LjU1LC0wLjQxIDAuNTcsLTAuMTIgMS4wNCwtMC41MiAxLjI1LC0xLj
|
||||
A2IDAuMDMsLTAuMDkgMC4wNSwtMC4xOSAwLjA2LC0wLjI4IGwgMC41OSwtMS45MSBjIDAuMSwtMC4zMyAtMC4wNSwtMC40OSAtMC40NSwtMC40OCBsIC0zLjEzLDAuMTUgYyAtMi4wOSwwLjEyIC0zLjcyLDAuMTggLTQuOSwwLjE3IC0xLjU0LDAuMDggLTMuMDgsLTAuMDcgLTQuNTgsLTAuNDYgLTEuMiwtMC40MSAtMS45NCwtMS42MSAtMS43NywtMi44NiBsIDkuOTEsLTEuMjcgYyA0LjQ0LC0wLjU3IDcuNDIsLTEuOTQgOC45MiwtNC4xMiBsIC0zLjM3LDExLjczIGMg
|
||||
LTAuMDcsMC4xOCAtMC4wNCwwLjM4IDAuMDcsMC41MyAwLjE4LDAuMTcgMC40MSwwLjI1IDAuNjUsMC4yMiBoIDQuMSBjIDAuNDcsMC4wNyAwLjkzLC0wLjIyIDEuMDYsLTAuNjggbCAzLjYyLC0xMi42NyBjIDAuNDgsLTEuNjcgMiwtMi40OCA0LjY3LC0yLjQ4IDIuNDEsMCA0LjIyLDAuMDIgNS4zOCwwLjA3IDAuMDMsMCAwLjA2LDAgMC4wOSwwIDAuMzksMCAwLjc0LC0wLjI2IDAuODQsLTAuNjMgbCAwLjYzLC0xLjc0IGMgMC4xNSwtMC4zIDAuMTIsLTAuNjMgLTAuMD
|
||||
UsLTAuODkgbSAtNjYuMTIsMTUuMjQgYyAtMS44MywwLjIzIC0zLjY4LDAuMzMgLTUuNTIsMC4zIC00LjE3LDAgLTUuOTksLTAuODQgLTUuNDYsLTIuNTMgMC4zOCwtMS4yMSAxLjQ3LC0xLjk0IDMuMjgsLTIuMTkgbCA5LjQ4LC0xLjI4IHogbSA0My44MywtMTAuMjcgYyAtMC40LDEuMyAtMi4yNSwyLjE5IC01LjU2LDIuNjcgbCAtNy45LDEuMTMgMC4yLC0wLjY1IGMgMC4zOSwtMS43NCAxLjM3LC0zLjI4IDIuNzksLTQuMzcgMS4yLC0wLjc3IDMuMTUsLTEuMTYgNS44NiwtMS4xNiAzLjU2LDAgNS4xLDAuOCA0LjYxLDIuMzgiLz4KPC9zdmc6c3ZnPgo=</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Acer</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="2">
|
||||
<name>Apple</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-mac-os.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiMwODgzZDkiIGQ9Ik0zNi4yMzIsMjMuOTg1YzAtNS44NjUsNC43NjYtOC41MSw0Ljk2Ni04LjYzNmMtMi41OTYtMy45OTMtNi43OS00LjQ2Ny
|
||||
04LjM2Mi00LjQ2OCBjLTMuNjQzLDAtNi44NjMsMi4wMjItOC41ODUsMi4wMjJjLTEuNzk3LDAtNC40MTgtMi4xMjEtNy4zNjMtMi4wMjJjLTMuODQzLDAuMDc1LTcuMzYzLDIuMzQ2LTkuMzM0LDUuNjkxIGMtMS4zOTcsMi4zOTYtMS45NDcsNS4yMTctMS44OTYsOC4wODdjMC4wMDIsMC4xMTMsMC4wMTcsMC4yMjgsMC4wMiwwLjM0MUgzNi4zMkMzNi4yNzksMjQuNjcxLDM2LjI0MywyNC4zMzcsMzYuMjMyLDIzLjk4NXoiLz48cGF0aCBmaWxsPSIjMDg4M2Q5IiBkPSJN
|
||||
MzAuNTY1LDcuMDYzQzMyLjI2MSw1LjE5MSwzMy4yMSwyLjYyMSwzMy4wNiwwYy0yLjM0NiwwLTUuMDY2LDEuMzcyLTYuNzg4LDMuMzk0IGMtMS4zNDgsMS42NzItMi43OTUsNC4yOTMtMi4yNzEsNi45MTNDMjYuNDIyLDEwLjYwNywyOS4wNDMsOS4wODUsMzAuNTY1LDcuMDYzeiIvPjxwYXRoIGZpbGw9IiMwMzcwYzgiIGQ9Ik0xNy41MTEsNDVjMi43NzEsMCwzLjc5NC0xLjg0OCw3LjQxMy0xLjg0OGMzLjM3LDAsNC40MTgsMS44NDgsNy4zMzgsMS44NDggYzMuMDcsMCw1LjA5Mi0yLjc5NSw2LjkxMy01LjU2N2MyLjI5NS0zLjIxOCwzLjA3LTYuMjg4LDMuMTY5LTYuNDE0Yy0wLjA5NCwwLTUuMjg3LTIuMTEyLTYuMDI2LTguMDE5SDUuNjc4IGMwLjE1Nyw1LjMxMSwyLjIyOCwxMC43OSw0LjY3MSwxNC4zMDlDMTIuMjcsNDIuMDU1LDE0LjQ0MSw0NSwxNy41MTEsNDV6Ii8+PC9zdmc+Cg==</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Apple</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="3">
|
||||
<name>Asus</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-asus.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIgeG1sbnM9Imh0dHA6Ly93
|
||||
d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwLDAsMjU2LDI1NiIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCIgZmlsbC1ydWxlPSJub256ZXJvIiB2ZXJzaW9uPSIxLjEiIGlkPSJzdmcxMyIgc29kaXBvZGk6ZG9jbmFtZT0iaWNvbnM4LWFzdXMgKDEpLnN2ZyIgaW5rc2NhcGU6dmVyc2lvbj0iMS40LjMgKDBkMTVmNzUwNDIsIDIwMjUtMTItMjUpIj48c29kaXBvZGk6bmFtZWR2aWV3IGlkPS
|
||||
JuYW1lZHZpZXcxMyIgcGFnZWNvbG9yPSIjZmZmZmZmIiBib3JkZXJjb2xvcj0iIzAwMDAwMCIgYm9yZGVyb3BhY2l0eT0iMC4yNSIgaW5rc2NhcGU6c2hvd3BhZ2VzaGFkb3c9IjIiIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiIGlua3NjYXBlOnBhZ2VjaGVja2VyYm9hcmQ9IjAiIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIgaW5rc2NhcGU6em9vbT0iMTcuMTg3NSIgaW5rc2NhcGU6Y3g9IjMxLjk3MDkwOSIgaW5rc2NhcGU6Y3k9IjMyIiBpbmtzY2FwZTp3
|
||||
aW5kb3ctd2lkdGg9IjI1NjAiIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEzNjAiIGlua3NjYXBlOndpbmRvdy14PSIwIiBpbmtzY2FwZTp3aW5kb3cteT0iMCIgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMSIgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0iZzEzIi8+PGRlZnMgaWQ9ImRlZnMxMCI+PHJhZGlhbEdyYWRpZW50IGN4PSIzNC42MjUiIGN5PSIzMS44NzUiIHI9IjIzLjIwNiIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGlkPSJjb2xvci0xIj
|
||||
48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNmNGU5YzMiIGlkPSJzdG9wMSIvPjxzdG9wIG9mZnNldD0iMC4yMTkiIHN0b3AtY29sb3I9IiNmOGVlY2QiIGlkPSJzdG9wMiIvPjxzdG9wIG9mZnNldD0iMC42NDQiIHN0b3AtY29sb3I9IiNmZGY0ZGMiIGlkPSJzdG9wMyIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ZmZjZlMSIgaWQ9InN0b3A0Ii8+PC9yYWRpYWxHcmFkaWVudD48bGluZWFyR3JhZGllbnQgeDE9IjAuMzY1IiB5MT0iMzIuNSIgeDI9
|
||||
IjY0IiB5Mj0iMzIuNSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGlkPSJjb2xvci0yIj48c3RvcCBvZmZzZXQ9IjAuMDUzIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBpZD0ic3RvcDUiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwMDAwMDAiIGlkPSJzdG9wNiIvPjwvbGluZWFyR3JhZGllbnQ+PHJhZGlhbEdyYWRpZW50IGN4PSIzNC42MjUiIGN5PSIzMS44NzUiIHI9IjIzLjIwNiIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGlkPS
|
||||
Jjb2xvci0zIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNmNGU5YzMiIGlkPSJzdG9wNyIvPjxzdG9wIG9mZnNldD0iMC4yMTkiIHN0b3AtY29sb3I9IiNmOGVlY2QiIGlkPSJzdG9wOCIvPjxzdG9wIG9mZnNldD0iMC42NDQiIHN0b3AtY29sb3I9IiNmZGY0ZGMiIGlkPSJzdG9wOSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ZmZjZlMSIgaWQ9InN0b3AxMCIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVs
|
||||
ZT0ibm9uemVybyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIHN0cm9rZS1saW5lY2FwPSJidXR0IiBzdHJva2UtbGluZWpvaW49Im1pdGVyIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IiIgc3Ryb2tlLWRhc2hvZmZzZXQ9IjAiIGZvbnQtZmFtaWx5PSJub25lIiBmb250LXdlaWdodD0ibm9uZSIgZm9udC1zaXplPSJub25lIiB0ZXh0LWFuY2hvcj0ibm9uZSIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOiBub3JtYWwiIGlkPSJnMT
|
||||
MiPjxnIHRyYW5zZm9ybT0ic2NhbGUoNCw0KSIgaWQ9ImcxMiI+PHBhdGggZD0iTTYuMTU2LDI5LjI0M2wtNS43MjMsOS45MTljLTAuMTkyLDAuMzMzIDAuMDQ4LDAuNzUgMC40MzMsMC43NWgyLjc2NGMwLjM1NiwwIDAuNjg2LC0wLjE5IDAuODY1LC0wLjQ5OGw1LjYyOSwtOS43MDF6TTYuMjk5LDI5LjAwNWMwLDAgMC44MTUsLTEuNDg2IDEuNjI1LC0yLjkyYzAuMzU0LC0wLjYyOCAxLjAxOSwtMS4wMTQgMS43NCwtMS4wMTRjMS40MDgsMC4wMDEgMy43NTcsMC4wMDMg
|
||||
NS4wODYsMC4wMDRjMC41NTIsMCAwLjk5NSwwLjQ0OCAwLjk5NSwxLjAwMXYyLjYxYzAsMCAwLjMyMywtMS4zODYgMC44OTEsLTIuMDQzYzAuNTM0LC0wLjYxOSAxLjI0NiwtMS40NzggMi44NzIsLTEuNTkyaDEwLjk2M2MwLjU1MiwwIDEsMC40NDggMSwxdjEuOTU1YzAsMC41NTIgLTAuNDQ4LDEgLTEsMXpNNjQsMjguMDA4di0xLjk1OGMwLC0wLjU1MiAtMC40NDgsLTEgLTEsLTFoLTExLjhjLTEuNjIyLDAuMTE0IC0yLjMzNywwLjk3MiAtMi44NzIsMS41OTJjLTAuNT
|
||||
Y5LDAuNjU3IC0wLjg5LDIuMDQzIC0wLjg5LDIuMDQzdjAuMzE4bDE1LjU2MiwwLjAwNWMwLjU1MiwwIDEsLTAuNDQ4IDEsLTF6TTMzLjA5NSwyNS4wN2gxLjU3OGMwLjU1MiwwIDEsMC40NDggMSwxdjIuOTM1aC0zLjU3OHYtMi45MzVjMCwtMC41NTIgMC40NDgsLTEgMSwtMXpNNDQuODM5LDI1LjA3aDEuNTc0YzAuNTUyLDAgMSwwLjQ0OCAxLDF2Mi45MzVoLTMuNTc0di0yLjkzNWMwLC0wLjU1MiAwLjQ0NywtMSAxLC0xek00Ny40MTMsMzAuNDI1bC0zLjUxNCwtMC4y
|
||||
MzN2NC41NjZjMCwwIC0wLjAxLDEuMzE0IC0xLjE1OCwxLjMxNGMtMS4xMzgsMCAtNi4wMzksMCAtNi4wMzksMGMwLDAgLTEuMDIzLC0wLjA5MyAtMS4wMjMsLTEuMzAzYzAsLTEuMjA3IDAsLTUuMTk2IDAsLTUuMTk2bC0zLjU0OSwtMC4yODV2Ny4wMDFjMC41NzQsMy4zNTkgMy4zMTEsMy42MTcgMy4zMTEsMy42MTdjMCwwIDAuMjc4LDAuMDIyIDAuMzI0LDAuMDI2aDguMTU2YzAsMCAzLjQ5MSwtMC4zMTEgMy40OTEsLTQuMDIzYzAuMDAxLC0zLjcxMyAwLjAwMSwtNS
|
||||
40ODQgMC4wMDEsLTUuNDg0ek0xMy4xMTEsMzkuOTE0aDE1LjczYzIuOTE0LC0wLjY0NyAzLjIxOCwtMy41NzcgMy4yMTgsLTMuNTc3YzAuMTM2LC0wLjg3MSAwLjA1NywtMS41NzQgMC4wNTcsLTEuNTc0Yy0wLjA4OCwtMC41ODggLTEuMDk0LC0zLjE3OCAtMy4yODEsLTMuNDA1Yy0xLjMwNCwtMC4xMzQgLTEyLjkxLC0xLjE1NSAtMTIuOTEsLTEuMTU1YzAuMjI1LDEuMjg4IDAuNzQ4LDEuOTM4IDEuMDk0LDIuMzExYzAuODA1LDAuODU3IDIuMDg3LDEuMDk5IDIuMDg3
|
||||
LDEuMDk5YzAuMzA5LDAuMDMzIDguOTQ1LDAuODI0IDguOTQ1LDAuODI0YzAuMjc0LDAuMDE3IDAuNzk3LDAuMDkzIDAuNzksMC44NDljMCwwLjA5MSAtMC4wNzUsMC43NTcgLTAuNzM4LDAuNzU3aC0xMi4wMTRjLTAuMjc2LDAgLTAuNSwtMC4yMjQgLTAuNSwtMC41di01LjM3M2wtMy40NzgsLTAuMjgxdjkuMDI3YzAsMC41NSAwLjQ0OCwwLjk5OCAxLDAuOTk4ek00Ny40NDQsMzcuMDE3YzAuMDAxLC0wLjU1MiAwLjQ0OCwtMC45OTggMSwtMC45OThoMTEuNDI5YzAuMj
|
||||
g2LDAgMC41OTUsLTAuMTg3IDAuNTk1LC0wLjE4N2MwLjEzLC0wLjEyOSAwLjIzNSwtMC4zNjQgMC4yMzUsLTAuNTkxYzAsLTAuNzUzIC0wLjU2MSwtMC43ODYgLTAuODQzLC0wLjgwM2MwLDAgLTguNzMyLC0wLjgwOCAtOS4wMzYsLTAuODM0YzAsMCAtMS4yMTEsLTAuMjA3IC0yLjAxNywtMS4wNjhjLTAuMzUxLC0wLjM2OSAtMC44MTUsLTAuNzcxIC0xLjE2MSwtMi4wOTljMCwwIDExLjY3MSwwLjc2MyAxMi45NjgsMC44OTdjMi4xODksMC4yMzIgMy4yMTUsMi42MzIgMy4zMDgsMy40M2MwLDAgMC4wOTMsMC43MjIgLTAuMDIsMS42MDdjMCwwIC0wLjQ1NCwzLjM3NCAtMy42NjQsMy41NzloLTExLjc5N2MtMC41NTMsMCAtMS4wMDEsLTAuNDQ5IC0xLC0xLjAwMnoiIGZpbGw9InVybCgjY29sb3ItMikiIGlkPSJwYXRoMTEiLz48L2c+PC9nPjwvc3ZnPgo=</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Asus</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="4">
|
||||
<name>Cisco</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icon-cisco.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIgeG1sbnM9Imh0dHA6Ly93d
|
||||
3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgd2lkdGg9IjEwOCIgaGVpZ2h0PSIxMDgiIHZpZXdCb3g9IjAgMCAxMDggMTA4IiByb2xlPSJpbWciIHZlcnNpb24
|
||||
9IjEuMSIgaWQ9InN2ZzExIiBzb2RpcG9kaTpkb2NuYW1lPSJpY29uLWNpc2NvLnN2ZyIgaW5rc2NhcGU6dmVyc2lvbj0iMS40LjMgKDBkMTVmNzUwNDIsIDIwMjUtMTItMjUpIj48c29kaXBvZGk6bmFtZWR2aWV3IGlkPSJuYW1lZHZpZXcxMSIgcGFnZWNvbG9yPSIjZmZmZmZmIiBib3JkZXJjb2xvcj0iIzAwMDAwMCIgYm9yZGVyb3BhY2l0eT0iMC4yNSIgaW5rc2NhcGU6c2hvd3BhZ2VzaGFkb3c9IjIiIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiIGlua3NjYXBlO
|
||||
nBhZ2VjaGVja2VyYm9hcmQ9IjAiIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIgc2hvd2d1aWRlcz0idHJ1ZSIgaW5rc2NhcGU6em9vbT0iNi44MjI5NjAyIiBpbmtzY2FwZTpjeD0iNDguODc5MDc4IiBpbmtzY2FwZTpjeT0iNTEuNzM3MDc1IiBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjI1NjAiIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEzNjAiIGlua3NjYXBlOndpbmRvdy14PSIwIiBpbmtzY2FwZTp3aW5kb3cteT0iMCIgaW5rc2NhcGU6d2luZG93LW1heGl
|
||||
taXplZD0iMSIgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnMTEiPjxzb2RpcG9kaTpndWlkZSBwb3NpdGlvbj0iMTYuOTM5NTg3LDUzLjM3NjMwMyIgb3JpZW50YXRpb249IjAsLTEiIGlkPSJndWlkZTExIiBpbmtzY2FwZTpsb2NrZWQ9ImZhbHNlIi8+PC9zb2RpcG9kaTpuYW1lZHZpZXc+PHRpdGxlIGlkPSJmdy1jLWhlYWRlcl9fbG9nby10aXRsZSI+Q2lzY28uY29tIEZyYW5jZTwvdGl0bGU+PGRlZnMgaWQ9ImRlZnMxIj48cGF0aCBkPSJtIDAsMjIuNzY5IGEgM
|
||||
i4zNDgsMi4zNDggMCAwIDAgMy45MzUsMS41NDUgYyAwLjQzNCwtMC40MDMgMC43LC0wLjk1NSAwLjc0NCwtMS41NDUgdiAtNS4yIGEgMi4zNCwyLjM0IDAgMCAwIC00LjY3OSwwIHYgNS4yIiBpZD0iYmFyX3Nob3J0IiBjbGFzcz0iYmFyIi8+PHBhdGggZD0ibSAxMi45NSwyMi43NjkgYSAyLjM0OSwyLjM0OSAwIDAgMCAyLjM0LDIuMTcxIDIuMzQ2LDIuMzQ2IDAgMCAwIDIuMzM5LC0yLjE3MSBWIDExLjExMiBhIDIuMzQxLDIuMzQxIDAgMCAwIC00LjY3OSwwIFYgMjI
|
||||
uNzciIGlkPSJiYXJfdGFsbCIgY2xhc3M9ImJhciIvPjxwYXRoIGQ9Im0gMjUuODMyLDI3LjQ2NCBhIDIuMzQ1LDIuMzQ1IDAgMCAwIDQuNjc4LDAgViAyLjI0OSBhIDIuMzQyLDIuMzQyIDAgMCAwIC00LjY3OCwwIHYgMjUuMjE1IiBpZD0iYmFyX2dyYW5kZSIgY2xhc3M9ImJhciIvPjxwYXRoIGQ9Im0gMjQuMDI2LDU2LjI3NyB2IC01LjAwMiBsIC0wLjA5OCwwLjA0MyBhIDkuMjUzLDkuMjUzIDAgMCAxIC0zLjYwNSwwLjkxNSA1LjMwMyw1LjMwMyAwIDAgMSAtMy42M
|
||||
ywtMS4wNyA0LjY0NCw0LjY0NCAwIDAgMSAtMS41OCwtMi4yNDQgNS4zOTUsNS4zOTUgMCAwIDEgLTAuMTA2LC0zIDQuNiw0LjYgMCAwIDEgMS42MDksLTIuNTY2IDQuODIzLDQuODIzIDAgMCAxIDIuNTI4LC0xLjA5IDguMzMyLDguMzMyIDAgMCAxIDQuNzc0LDAuODk1IGwgMC4xMDgsMC4wNTYgdiAtNS4wMyBsIC0wLjIyOCwtMC4wNjEgYSAxMi43OCwxMi43OCAwIDAgMCAtNC41NTIsLTAuNTk2IDEwLjUzNCwxMC41MzQgMCAwIDAgLTQuMDY1LDAuOTMgOS4yOSw5LjI
|
||||
5IDAgMCAwIC0zLjMyOSwyLjU3MiAxMC4wMTQsMTAuMDE0IDAgMCAwIC0wLjE4MiwxMi4xOCA5LjU0Niw5LjU0NiAwIDAgMCA1LjI5MiwzLjQwMyBjIDIuMjExLDAuNTM4IDQuNTI4LDAuNDU2IDYuNjk3LC0wLjIzNCBsIDAuMzY3LC0wLjEwMSIgaWQ9ImNpc2NvX2MiLz48L2RlZnM+PGcgZmlsbD0iIzAyYzhmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBpZD0iZzExIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC4wOTQ2Njg1OSwyNi4yMzQ5NDYpIj48dXNlIGhyZWY9IiNja
|
||||
XNjb19jIiBpZD0idXNlMSIvPjx1c2UgaHJlZj0iI2Npc2NvX2MiIHg9IjQ5LjUiIGlkPSJ1c2UyIi8+PHBhdGggZD0ibSA0MS42OSw1Mi4xMjUgLTAuMDE5LDQuMzA4IDAuMzE1LDAuMDU0IGMgMC45ODksMC4xODUgMS45ODcsMC4zMTMgMi45OSwwLjM4NSBhIDE4LjEsMTguMSAwIDAgMCAyLjY0MiwwLjA1MSBjIDAuODQyLC0wLjA2IDEuNjc1LC0wLjIxOCAyLjQ4LC0wLjQ2OCBhIDYuODYyLDYuODYyIDAgMCAwIDIuNTczLC0xLjM3MSA1LjE5LDUuMTkgMCAwIDAgMS4
|
||||
0OTgsLTIuMTQ4IDUuOTEyLDUuOTEyIDAgMCAwIC0wLjAzLC00LjMyNCA0Ljg1Miw0Ljg1MiAwIDAgMCAtMS4zNDMsLTEuODYyIDUuNTY4LDUuNTY4IDAgMCAwIC0xLjk3LC0xLjE0NyBsIC0zLjI1LC0xLjIwNiBhIDEuNzQyLDEuNzQyIDAgMCAxIC0wLjg4NywtMC44NDUgMS4xMDcsMS4xMDcgMCAwIDEgMC4wMzYsLTAuOTg2IDEuMjksMS4yOSAwIDAgMSAwLjIxNywtMC4yOTEgMS43NSwxLjc1IDAgMCAxIDAuNDgsLTAuMzQ3IGMgMC4zNjMsLTAuMTggMC43NTUsLTAuM
|
||||
jkzIDEuMTU4LC0wLjMzNyBhIDYuNzYsNi43NiAwIDAgMSAyLjA3MiwwLjAyMiBjIDAuODEsMC4wODggMS42MTMsMC4yMzEgMi40MDIsMC40MyBsIDAuMTY4LDAuMDM3IHYgLTMuOTc0IGwgLTAuMzEsLTAuMDY3IGEgMjEuMTQsMjEuMTQgMCAwIDAgLTIuNDQ0LC0wLjQzNSAxMi41NDUsMTIuNTQ1IDAgMCAwIC0zLjIxMywtMC4wMTQgNi45NDUsNi45NDUgMCAwIDAgLTMuNjk5LDEuNDg4IDQuOTA4LDQuOTA4IDAgMCAwIC0xLjU4LDIuMTc4IDUuOTg0LDUuOTg0IDAgMCA
|
||||
wIC0wLjAwMyw0LjA1IGMgMC4yNDIsMC42NSAwLjYzLDEuMjM3IDEuMTM2LDEuNzE0IDAuNDM3LDAuNDIyIDAuOTMyLDAuNzggMS40NywxLjA2NSAwLjcwOCwwLjM4IDEuNDU4LDAuNjc1IDIuMjM1LDAuODc4IDAuMjU3LDAuMDc3IDAuNTEyLDAuMTU4IDAuNzY2LDAuMjQzIGwgMC4zODUsMC4xNDEgMC4xMSwwLjA0NSBjIDAuMzgsMC4xMzYgMC43MjYsMC4zNSAxLjAxOCwwLjYyOCAwLjIwMiwwLjE5IDAuMzU4LDAuNDIzIDAuNDU1LDAuNjgzIDAuMDYsMC4yMzcgMC4wN
|
||||
jEsMC40ODUgMC4wMDMsMC43MjMgYSAxLjUzNiwxLjUzNiAwIDAgMSAtMC43NDQsMC44OTIgMy42OTEsMy42OTEgMCAwIDEgLTEuMjM5LDAuMzg3IDksOSAwIDAgMSAtMS45MiwwLjA5NyAyMS45NzMsMjEuOTczIDAgMCAxIC0yLjUwNywtMC4zMzQgYyAtMC40MzMsLTAuMDkgLTAuODY0LC0wLjE5IC0xLjI5MSwtMC4zMDMgeiBtIC0xMS4xNDQsNC40ODIgaCA0LjczIFYgMzcuODQ2IGggLTQuNzMgeiBNIDg1LjMwNSw0My4zODYgYSA0LjkzNCw0LjkzNCAwIDEgMSA2LjE
|
||||
1Nyw3LjcxMSA0LjkzNCw0LjkzNCAwIDAgMSAtNi4xNTcsLTcuNzEgbSAtNi44NjcsMy44NDggYSA5Ljg3LDkuODcgMCAwIDAgMTIuMDAyLDkuNDg1IDkuNjI5LDkuNjI5IDAgMCAwIDMuMTU3LC0xNy43MjkgOS45MzQsOS45MzQgMCAwIDAgLTE1LjE2LDguMjQ0IiBpZD0icGF0aDIiLz48dXNlIGhyZWY9IiNiYXJfc2hvcnQiIHg9IjAiIGlkPSJ1c2UzIi8+PHVzZSBocmVmPSIjYmFyX3RhbGwiIHg9IjAiIGlkPSJ1c2U0Ii8+PHVzZSBocmVmPSIjYmFyX2dyYW5kZSIge
|
||||
D0iMCIgaWQ9InVzZTUiLz48dXNlIGhyZWY9IiNiYXJfdGFsbCIgeD0iMjUuODc1IiBpZD0idXNlNiIvPjx1c2UgaHJlZj0iI2Jhcl9zaG9ydCIgeD0iNTEuNzUiIGlkPSJ1c2U3Ii8+PHVzZSBocmVmPSIjYmFyX3RhbGwiIHg9IjUxLjc1IiBpZD0idXNlOCIvPjx1c2UgaHJlZj0iI2Jhcl9ncmFuZGUiIHg9IjUxLjc1IiBpZD0idXNlOSIvPjx1c2UgaHJlZj0iI2Jhcl90YWxsIiB4PSI3Ny42MjUiIGlkPSJ1c2UxMCIvPjx1c2UgaHJlZj0iI2Jhcl9zaG9ydCIgeD0iMTAzLjM3NSIgaWQ9InVzZTExIi8+PC9nPjxtZXRhZGF0YSBpZD0ibWV0YWRhdGExMSI+PHJkZjpSREY+PGNjOldvcmsgcmRmOmFib3V0PSIiPjxkYzp0aXRsZT5DaXNjby5jb20gRnJhbmNlPC9kYzp0aXRsZT48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PC9zdmc+Cg==</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Cisco</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="5">
|
||||
<name>Dell</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-dell.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiMwMjg4ZDEiIGQ9Ik0yNCw0QzEyLjk1Niw0LDQsMTIuOTU2LDQsMjRzOC45NTYsMjAsMjAsMjBzMjAtOC45NTYsMjAtMjBTMzUuMDQ0LDQsMjQs
|
||||
NHogTTI0LDQxYy05LjM5MSwwLTE3LTcuNjA5LTE3LTE3UzE0LjYwOSw3LDI0LDdzMTcsNy42MDksMTcsMTdTMzMuMzkxLDQxLDI0LDQxeiIvPjxwYXRoIGZpbGw9IiMwMjg4ZDEiIGQ9Ik0zNS42NDEsMjUuNTYzbDIuODQsMC4wMDRsLTAuMDA0LDIuMzk1bC01LjY5MS0wLjAxMmwwLjAxMi04LjE3MmwyLjg1NSwwLjAwNEwzNS42NDEsMjUuNTYzeiBNMjYuMzQsMjUuMTAybC00LjY5OSwzLjY4NGwtNC4yODUtMy4zNzljLTAuNjIxLDEuNDg0LTIuMTA5LDIuNTItMy44Mz
|
||||
YsMi41MTZsLTMuNjY0LTAuMDA0bDAuMDA4LTguMTcybDMuNjY4LDAuMDA0YzEuOTI2LDAuMDA0LDMuMzA5LDEuMjIzLDMuODI4LDIuNTMxbDQuMjk3LTMuMzY3bDEuNTg2LDEuMjVsLTMuOTM0LDMuMDg2bDAuNzU0LDAuNTk0bDMuOTM0LTMuMDg2bDEuNTksMS4yNTRsLTMuOTM0LDMuMDgybDAuNzUsMC41OTRsMy45NDEtMy4wODJsMC4wMDQtMi44MzZsMi44NTIsMC4wMDRsLTAuMDA4LDUuNzgxbDIuODQsMC4wMDRsLTAuMDA0LDIuMzkxbC01LjY5MS0wLjAwOEwyNi4zNCwyNS4xMDJ6IE0xNS4wMTIsMjMuODRjMC0xLjExMy0wLjczLTEuNzQyLTEuNzctMS43NDJoLTAuNjM3bC0wLjAwNCwzLjQ3N2gwLjYyMUMxNC4xODQsMjUuNTc0LDE1LjAxMiwyNS4wNTEsMTUuMDEyLDIzLjg0Ii8+PC9zdmc+Cg==</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Dell</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="6">
|
||||
<name>HP Inc</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-hp.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0yNCA0QTIwIDIwIDAgMSAwIDI0IDQ0QTIwIDIwIDAgMSAwIDI0IDRaIi8+PHBhdGggZmlsbD0iIzE5NzZkMiIgZD0iTTI0LDQzLj
|
||||
k5N2MtMC4xOTksMC0wLjY1MiwwLjAwNi0wLjg1LDBsNC0xMC45OTloNS42MjVjMC45ODcsMCwyLjA3MS0wLjc1OSwyLjQwOS0xLjY4Nmw0Ljc0OC0xMi42ODdjMC43MjUtMS45OTUtMC40MTctMy42MjYtMi41MzktMy42MjZoLTcuODA0bC02LjUxOCwxOC4yNTdoLTAuMDAybC0zLjcxMiwxMC4xOThDMTAuNTUsNDEuMzYxLDQsMzMuNDQ1LDQsMjMuOTk5YzAtOS4xNzQsNi4xNzgtMTYuOTA1LDE0LjYtMTkuMjYxbC0zLjgzLDEwLjUyNmgtMC4wMDFMOC4xNSwzMi45OTho
|
||||
NC4yMzlsNS41NzYtMTQuOTk5aDMuMTg1bC01LjU3NiwxNC45OTlsMy45MTksMC4wMDFsNS40MzgtMTQuMzc0YzAuNzI2LTEuOTk1LTAuNDE2LTMuNjI2LTIuNTM2LTMuNjI2SDE5LjE1bDMuOTUxLTEwLjk3OEMyMy4zOTksNC4wMDgsMjMuNjk5LDQsMjQsNGMxMS4wNDYsMCwyMCw4Ljk1MywyMCwxOS45OTlTMzUuMDQ2LDQzLjk5NywyNCw0My45OTd6IE0zNi4xNSwxNy45OTloLTMuMTg1bC00LjUwOSwxMS45OTloMy4xODVMMzYuMTUsMTcuOTk5eiIvPjwvc3ZnPgo=</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>HP Inc</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="7">
|
||||
<name>HPE</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icon-hpe.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIgeG1sbnM9Imh0dHA6Ly93d3c
|
||||
udzMub3JnLzIwMDAvc3ZnIiB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjAiIGlkPSJrYXRtYW5fMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCA2MzAgNjMwIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzb2RpcG9kaTpkb2NuYW1lPSJpY29uLWhwZS5zdmciIHdpZHRoPSI2MzAiIGhlaWdodD0iNjMwIiBpbmtzY2FwZTp2ZXJzaW9uPSIxLjQuMyAoMGQxNWY3NTA0MiwgMjAyNS0xMi0yNSkiPjxkZWZzIGlkPSJkZWZzM
|
||||
iIvPjxzb2RpcG9kaTpuYW1lZHZpZXcgaWQ9Im5hbWVkdmlldzIiIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIgYm9yZGVyY29sb3I9IiMwMDAwMDAiIGJvcmRlcm9wYWNpdHk9IjAuMjUiIGlua3NjYXBlOnNob3dwYWdlc2hhZG93PSIyIiBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMC4wIiBpbmtzY2FwZTpwYWdlY2hlY2tlcmJvYXJkPSIwIiBpbmtzY2FwZTpkZXNrY29sb3I9IiNkMWQxZDEiIHNob3dndWlkZXM9InRydWUiIGlua3NjYXBlOnpvb209IjAuNjkwNTUxNSIgaW5rc2N
|
||||
hcGU6Y3g9Ii0yMTcuOTQxNzUiIGlua3NjYXBlOmN5PSIyNzUuMTQyNCIgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIyNTYwIiBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMzYwIiBpbmtzY2FwZTp3aW5kb3cteD0iMCIgaW5rc2NhcGU6d2luZG93LXk9IjAiIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjEiIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9ImthdG1hbl8xIj48c29kaXBvZGk6Z3VpZGUgcG9zaXRpb249IjE5Ny42NjI0NCwzMTQuNDg4NDgiIG9yaWVudGF0a
|
||||
W9uPSIwLC0xIiBpZD0iZ3VpZGUyIiBpbmtzY2FwZTpsb2NrZWQ9ImZhbHNlIi8+PC9zb2RpcG9kaTpuYW1lZHZpZXc+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyIgaWQ9InN0eWxlMSI+Cgkuc3Qwe2ZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MzY7fQoJLnN0MXtmaWxsOm5vbmU7c3Ryb2tlOiMwM0E4ODM7c3Ryb2tlLXdpZHRoOjM2O30KPC9zdHlsZT4KPHBhdGggY2xhc3M9InN0MCIgZD0ibSAxOC41MTE5ODcsNDA1LjkzMDEyIHYgLTE4MCBtIDE
|
||||
1NC4wMDAwMDMsMTgwIHYgLTE4MCBtIC0xNTQuMDAwMDAzLDg5IEggMTU1LjUxMTk5IG0gOTUsOTEgdiAtMTgwIG0gMCwxOCBoIDEwMiBjIDI3LjYsMCA1MCwyMi40IDUwLDUwIDAsMjcuNiAtMjIuNCw1MCAtNTAsNTAgaCAtMTAyIG0gMjIyLC02NyB2IC0zMyBoIDE1OCIgaWQ9InBhdGgxIi8+CjxwYXRoIGNsYXNzPSJzdDEiIGQ9Im0gNjMwLjUxMTk5LDM4Ny45MzAxMiBoIC0xNTggdiAtNzYgaCAxNTgiIGlkPSJwYXRoMiIvPgo8L3N2Zz4K</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>HPE</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="8">
|
||||
<name>IBM</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-ibm.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiMzZjUxYjUiIGQ9Ik00OCAxNkw0OCAxNCA0MC40NjkgMTQgMzkuODA5IDE2ek0zMyAzMUwzMyAyOSAyOSAyOSAyNyAyOSAyNyAzMXpNMzkuNzY2I
|
||||
DI4TDQwLjUxIDI2IDM0LjUxIDI2IDM1LjI2NiAyOHpNMjkgMjZIMzNWMjhIMjl6TTI5IDIzSDMzVjI1SDI5ek00MiAyOUw0MiAzMSA0OCAzMSA0OCAyOSA0NiAyOXpNMzYuMTgxIDE5TDM1LjUyMSAxNyAyNyAxNyAyNyAxOSAyOSAxOXpNMzcuMTcgMjJMMzYuNTEgMjAgMjkgMjAgMjkgMjJ6TTMzLjM3OCAyM0wzNC4xMzMgMjUgNDAuODgzIDI1IDQxLjYyOCAyM3pNNDIgMjNINDZWMjVINDJ6TTI3IDMySDMzVjM0SDI3ek0zNS4xOTEgMTZMMzQuNTMxIDE0IDI3IDE0IDI
|
||||
3IDE2ek0zNi43NzYgMzJMMzcuNTMxIDM0IDM4LjI3NiAzMnpNNDIgMzJINDhWMzRINDJ6TTM5LjQ3OSAxN0wzOC44MTkgMTkgNDYgMTkgNDggMTkgNDggMTd6TTM5LjM5MyAyOUwzNS42NDMgMjkgMzYuMzk4IDMxIDM4LjY0OCAzMXpNNDIgMjZINDZWMjhINDJ6TTM4LjQ5IDIwTDM3LjgzIDIyIDQ2IDIyIDQ2IDIwek0wIDE0SDhWMTZIMHpNMCAxN0g4VjE5SDB6TTIgMjBINlYyMkgyek0yIDIzSDZWMjVIMnpNMiAyNkg2VjI4SDJ6TTAgMjlIOFYzMUgwek0wIDMySDhWM
|
||||
zRIMHpNMTAgMTdIMThWMTlIMTB6TTI0Ljk3NyAxNmMtLjkxMy0xLjIwOC0yLjM0Ny0yLTMuOTc3LTJIMTB2Mmg3LjAyM0gyNC45Nzd6Ii8+PHBhdGggZmlsbD0iIzNmNTFiNSIgZD0iTTI1LjU3OCAxN2gtOS4xMzFDMTYuMTcxIDE3LjYxMyAxNiAxOC4yODMgMTYgMTloMTBDMjYgMTguMjg4IDI1Ljg0NiAxNy42MTMgMjUuNTc4IDE3ek0yMy45NzUgMjNIMTJ2MmgxMS45NzNjLS44MzMtLjYyLTEuODU0LTEtMi45NzMtMUMyMi4xMTkgMjQgMjMuMTQyIDIzLjYyMSAyMy4
|
||||
5NzUgMjN6TTE3LjAyMyAzMkgxMHYyaDExYzEuNjMgMCAzLjA2NS0uNzkyIDMuOTc3LTJIMTcuMDIzek0xOCAyOWgtMi02djJoNi40NDdIMThoNy41NzhDMjUuODQ2IDMwLjM4NyAyNiAyOS43MTIgMjYgMjlIMTh6TTIxIDIwYzAgMCAwIC4wODMgMCAxcy0xIDEtMSAxaDQuOTc5Yy40NDEtLjU4NC43Ny0xLjI1Ny45MjEtMkgyMXpNMTIgMjBIMTdWMjJIMTJ6Ii8+PGc+PHBhdGggZmlsbD0iIzNmNTFiNSIgZD0iTTIxIDI4aDQuODg1Yy0uMTU2LS43MzgtLjQ2Ny0xLjQxOC0uOTA3LTJIMjBjMCAwIDEgLjE2NyAxIDFTMjEgMjggMjEgMjh6TTEyIDI2SDE3VjI4SDEyeiIvPjwvZz48L3N2Zz4K</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>IBM</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="9">
|
||||
<name>Lenovo</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-lenovo.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxyZWN0IHdpZHRoPSI0OCIgaGVpZ2h0PSIxNiIgeT0iMTYiIGZpbGw9IiNmZjE3NDQiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMTEuOTM1LDI2LjA2MmMwLjM3LD
|
||||
AuMzQxLDAuNzgyLDAuNDUsMS4yMjcsMC40NzhjMC42NDUsMC4wMzksMS4yMTctMC4xNTYsMS43MjQtMC41NDYgYzAuMTI0LTAuMDk2LDAuMTYzLTAuMTI2LDAuMTYzLTAuMTI2czAuNzc3LDAuNjA5LDEuMDk3LDAuODU1Yy0wLjI2MSwwLjMwOS0wLjU2NywwLjUyMS0wLjkwMSwwLjY5MiBjLTEuMTAzLDAuNTY1LTIuMjQ5LDAuNjg3LTMuNDI0LDAuMjY0Yy0xLjM0Ni0wLjQ4NS0yLjEzMS0xLjY5My0yLjA1OS0zLjExN2MwLjA3My0xLjQ0MSwxLjAwNS0yLjYwOCwyLjM5
|
||||
Mi0yLjk0NCBjMS4wNjQtMC4yNTcsMi4wODQtMC4xNDMsMi45OCwwLjUzOWMwLjY1MSwwLjQ5NiwxLjAwMSwxLjI4LDEuMTQ3LDIuMDY4YzAsMC0yLjU5NSwxLjExLTMuNzk1LDEuNjA2IEMxMi4zMTMsMjUuOTAzLDEyLjE0MSwyNS45NzUsMTEuOTM1LDI2LjA2MnogTTExLjQ3MiwyNC45MjhjMC45NjktMC40MDEsMS45MzUtMC44MDEsMi45MDEtMS4yMDEgYy0wLjMzNC0wLjcyMi0xLjA5Ni0xLjAxNy0xLjg2Ni0wLjc0OEMxMS43NTgsMjMuMjQsMTEuMjgsMjQuMTI0LD
|
||||
ExLjQ3MiwyNC45Mjh6Ii8+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTI3LjA3NiwyNy45MzRjLTEuNjMyLTAuMDE3LTIuOTU2LTEuMDY4LTMuMjYxLTIuNmMtMC4zNy0xLjg1MiwwLjk2OS0zLjYzMywyLjg2LTMuODA4IGMxLjI4MS0wLjExOCwyLjM3MywwLjI1NCwzLjE1NSwxLjNjMS40NTEsMS45NDEsMC4yMiw0Ljc1Ny0yLjE5Myw1LjA1NUMyNy40NSwyNy45MDUsMjcuMjYzLDI3LjkxNywyNy4wNzYsMjcuOTM0eiBNMjcuMTEsMjYuNDM0IGMwLjkyOSwwLjAwMiwxLjYy
|
||||
Mi0wLjcyMywxLjYyOC0xLjcwNGMwLjAwNi0wLjk3LTAuNzI0LTEuNzQyLTEuNjQ5LTEuNzQ1Yy0wLjkzNi0wLjAwMy0xLjYzMSwwLjczNC0xLjYyOCwxLjcyNiBDMjUuNDY1LDI1LjY3NSwyNi4xODksMjYuNDMyLDI3LjExLDI2LjQzNHoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNNDAuNjI0LDI3LjkzNGMtMS42MzItMC4wMTctMi45NTYtMS4wNjgtMy4yNjEtMi42Yy0wLjM3LTEuODUyLDAuOTY5LTMuNjMzLDIuODYtMy44MDggYzEuMjgxLTAuMTE4LDIuMzczLDAuMj
|
||||
U0LDMuMTU1LDEuM2MxLjQ1MSwxLjk0MSwwLjIyLDQuNzU3LTIuMTkzLDUuMDU1QzQwLjk5OCwyNy45MDUsNDAuODExLDI3LjkxNyw0MC42MjQsMjcuOTM0eiBNNDAuNjU4LDI2LjQzNGMwLjkyOSwwLjAwMiwxLjYyMy0wLjcyMywxLjYyOC0xLjcwNGMwLjAwNi0wLjk3LTAuNzI0LTEuNzQyLTEuNjQ5LTEuNzQ1Yy0wLjkzNi0wLjAwMy0xLjYzMSwwLjczNC0xLjYyOCwxLjcyNiBDMzkuMDEzLDI1LjY3NSwzOS43MzcsMjYuNDMyLDQwLjY1OCwyNi40MzR6Ii8+PHBhdGgg
|
||||
ZmlsbD0iI2ZmZiIgZD0iTTIxLjM3NywyNy45ODdjMC0wLjA5NSwwLjAwMS0yLjU4NywwLTMuNjYzYy0wLjAwMS0wLjc1OS0wLjYwNS0xLjMyNy0xLjQxNC0xLjMzMSBjLTAuNzk0LTAuMDA1LTEuMzgzLDAuNTYtMS4zODQsMS4zMzJjLTAuMDAxLDEuMDc2LDAsMy42NzksMCwzLjY3OWwtMS43NDEsMC4wMDJsMC4wMDctNi4zNzhjMCwwLDEuMTY4LTAuMDE4LDEuNzIyLTAuMDE4IGMwLDAuMjY0LTAuMDA2LDAuODMyLTAuMDA2LDAuODMyczAuMTM4LTAuMTI4LDAuMTgxLT
|
||||
AuMTcxYzEuMTU3LTEuMTc0LDMuMjI2LTAuOTczLDQuMDMxLDAuMzkxIGMwLjIyMywwLjM3OCwwLjMzOCwwLjc4OSwwLjM0LDEuMjIzYzAuMDA4LDEuMjY0LDAuMDAzLDQuMTA0LDAuMDAzLDQuMTA0UzIxLjk2NCwyNy45ODcsMjEuMzc3LDI3Ljk4N3oiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMzAuMTY0LDIxLjYwOGMwLjY0MiwwLDEuOTY0LDAuMDE1LDEuOTY0LDAuMDE1czEuNDc4LDQuMDI0LDEuNTI2LDQuMTQ5IGMwLjExNS0wLjMxMSwxLjIwOC0zLjI5LDEuNTIx
|
||||
LTQuMTc0YzAuNjQ2LDAuMDE4LDEuMjg4LDAuMDEsMS45NywwLjAxYy0wLjAyOSwwLjA4NC0yLjU2Miw2LjM5OC0yLjU2Miw2LjM5OGwtMS44NzYtMC4wMDMgQzMxLjkwNSwyNi4wNDIsMzAuMTkxLDIxLjY5MiwzMC4xNjQsMjEuNjA4eiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik01Ljc2NywyNi4zOTNjMC4xMDQsMCwzLjg2OCwwLjAxMSwzLjg2OCwwLjAxMWwtMC4wMDIsMS41ODFMNCwyNy45ODl2LTguMDczaDEuNzcgQzUuNzcsMTkuOTE2LDUuNzY3LDI2LjI4NCw1Ljc2NywyNi4zOTN6Ii8+PC9zdmc+Cg==</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Lenovo</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="10">
|
||||
<name>Razer</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-razer.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiM2NGRkMTciIGQ9Ik0yNiwyMGMwLjEsMCwwLjIsMCwwLjMsMGMwLjMtMC4xLDAuNS0wLjMsMC42LTAuNWMwLjEtMC4yLDAuMS0wLjUsMC4xLTA
|
||||
uOGMtMC4yLTAuNi0xLTEuOC0yLTIuNCBjMCwwLjcsMCwxLjMsMCwxLjljMCwwLjUsMCwxLDAsMS4yYzAuMSwwLjIsMC4zLDAuNCwwLjUsMC42QzI1LjcsMjAsMjUuOCwyMCwyNiwyMCBNMjkuNCwyM2MwLjcsMCwxLjYtMC4xLDIuMy0wLjUgYy0wLjUtMC4zLTEtMC42LTEuNS0wLjljLTAuNC0wLjMtMC45LTAuNi0xLjEtMC42YzAsMC0wLjEsMC0wLjEsMGMtMC4yLDAtMC40LDAuMS0wLjYsMC4yYy0wLjIsMC4xLTAuNCwwLjQtMC40LDAuNiBjLTAuMSwwLjUsMC4zLDEuM
|
||||
SwwLjgsMS4yQzI5LDIzLDI5LjIsMjMsMjkuNCwyMyBNMjMsMjQuOWMwLjUtMC4yLDEtMC40LDEuNS0wLjZjMC41LTAuMiwxLTAuNCwxLjItMC41YzAuMi0wLjIsMC4zLTAuNCwwLjMtMC43IGMwLTAuMy0wLjEtMC41LTAuMy0wLjdDMjUuNiwyMi4xLDI1LjMsMjIsMjUsMjJjLTAuMiwwLTAuNSwwLjEtMC43LDAuM0MyMy45LDIyLjYsMjMuMiwyMy44LDIzLDI0LjkgTTQxLjUsMSBjLTAuNywwLTEuNCwwLjUtMS41LDEuM2MwLDAsMCwwLDAsMEMzOS43LDIuMSwzOS40LDI
|
||||
sMzksMmMtMS43LDAtMi45LDAuMi0zLjYsMC43QzM0LjUsMy4yLDM0LDQuMSwzNCw1YzAsMC4xLDAsMC4xLDAsMC4yIEMzMy42LDUuMSwzMy4xLDUsMzIuNyw1Yy0xLjMsMC0yLjQsMC43LTMuMSwyQzI5LjIsNy43LDI5LDguNCwyOSw5LjJjMCwyLjYsMi4yLDQuNiw0LjUsNi42YzIuNywyLjQsMy45LDMuOCwzLjMsNC44IGMtMC4yLDAuNC0wLjQsMC40LTAuNCwwLjRjLTAuMSwwLTAuMiwwLTAuMywwYy0wLjEsMC0wLjMsMC0wLjUtMC4xYzAtMC42LTAuMS0xLjEtMC4yL
|
||||
TEuNmMtMC4yLTAuNi0wLjUtMS4yLTEtMS43IGMtMC40LTAuNS0xLTAuNy0xLjUtMC45Yy0wLjEsMC0wLjItMC4xLTAuNC0wLjFjLTAuMywwLTAuNywwLjItMC44LDAuNWMtMC4zLDAuNC0wLjIsMC45LDAuMiwxLjNjMC4yLDAuMiwwLjQsMC40LDAuNSwwLjYgYzAuMSwwLjIsMC4xLDAuMywwLjEsMC41Yy0wLjItMC4xLTAuNS0wLjMtMC43LTAuNGMtMC44LTAuNS0xLjQtMC45LTEuOS0xYzAtMC4xLTAuMS0wLjItMC4xLTAuM2MtMC41LTEuNS0yLjEtMy43LTQuMy00LjU
|
||||
gYy0xLTMuNS0zLjMtNC4zLTUuMS00LjNjLTQuNiwwLTUuNCw0LjktNiw4LjVjLTAuMiwxLjQtMC43LDQtMS4zLDQuNWMwLTAuMi0wLjEtMC41LTAuMS0xQzEzLDE5LjksMTIuNywxNywxMCwxNyBjLTEuNiwwLTIuNCwxLjEtMi44LDEuN2MtMC4yLTAuMi0wLjMtMC40LTAuNC0wLjZjLTAuMy0wLjYtMS0xLjEtMS43LTEuMUM1LjEsMTYuOSw1LDE2LjcsNSwxNi41QzUsMTUuNyw0LjMsMTUsMy41LDE1IGMtMC43LDAtMS4yLDAuNC0xLjQsMS4xQzEuNCwxNi4zLDEsMTYuO
|
||||
CwxLDE3LjVDMSwxOC4zLDEuNywxOSwyLjUsMTljMC4xLDAsMC4yLDAsMC4zLDBDMi45LDE5LjEsMywxOS4xLDMsMTkuMiBjMCwwLjIsMC4xLDAuNSwwLjIsMC43YzEsMS45LDIuNSwyLjcsMywyLjlDNi42LDIyLjksNywyMyw3LjQsMjNjMC43LDAsMS4zLTAuMiwxLjgtMC41QzkuNSwyNCwxMC4zLDI2LDEzLDI2IGM0LjEsMCw0LjktNC42LDUuNC03LjljMC42LTMuNCwxLTUuMSwyLTUuMWMwLjMsMCwwLjcsMCwxLjEsMC45Yy0wLjQsMC4yLTAuNywwLjUtMSwwLjhjLTA
|
||||
uNSwwLjUtMC44LDEuMS0xLDEuNyBjLTAuMiwwLjYtMC4xLDEuMi0wLjEsMS43YzAuMSwwLjUsMC41LDAuOCwwLjksMC45YzAsMCwwLDAsMC4xLDBjMC41LDAsMC45LTAuMywxLTAuOGMwLjEtMC4zLDAuMi0wLjYsMC4zLTAuOCBjMC4xLTAuMSwwLjItMC4yLDAuMy0wLjNjMCwwLjMsMCwwLjYsMCwwLjljMCwwLjksMCwxLjUsMC4xLDJjLTEsMS0yLjIsMy0yLjIsNS4yYy0xLjMsMC45LTIuMiwxLjktMi43LDNjLTAuNSwxLjItMC41LDIuNSwwLjEsMy43IGMwLjgsMS45L
|
||||
DIuNSwyLjksNC45LDIuOWMxLjgsMCwzLjgtMC41LDUuNy0xLjFjMS43LTAuNSwzLjMtMC45LDQuMy0wLjljMC4yLDAsMC40LDAsMC42LDAuMWMtMC4yLDAuMS0wLjUsMC4zLTEsMC42IGMtMS4xLDAuNi0zLjYsMi0yLjUsNC41YzAuNywxLjYsMi41LDEuOCwzLjYsMS44bDAuMSwwYzAsMCwwLDAsMCwwYy0wLjEsMC4yLTAuMiwwLjMtMC40LDAuNmMtMC40LDAuNC0wLjYsMC44LTAuNiwxLjMgYy0wLjEsMC0wLjMsMC4xLTAuNSwwLjFjLTAuOCwwLTEuNSwwLjctMS41LDE
|
||||
uNWMwLDAuNywwLjQsMS4yLDEuMSwxLjRjMC4yLDAuNiwwLjgsMS4xLDEuNCwxLjFjMC44LDAsMS41LTAuNywxLjUtMS41bDAtMC4zIGMwLjEtMC4xLDAuMS0wLjEsMC4yLTAuMmMwLjUsMCwwLjktMC4yLDEuMi0wLjZjMS43LTEuNywxLjYtMy4zLDEuNi00LjFjMC0xLjMtMC45LTIuNC0yLTIuOWMxLjMtMC45LDIuNy0yLjUsMS42LTQuOCBjLTAuOC0xLjctMi4yLTIuNi00LjQtMi42Yy0xLjcsMC0zLjUsMC41LTUuMywxYy0xLjgsMC41LTMuNCwwLjktNC42LDAuOWMtM
|
||||
SwwLTEuMS0wLjMtMS4yLTAuNUMyMSwzMC4xLDIxLDI5LjksMjEsMjkuOCBjMC4xLTAuMiwwLjMtMC41LDAuOC0wLjljMC40LDAuNCwwLjksMC42LDEuMywwLjhjMC40LDAuMiwwLjksMC4zLDEuNCwwLjNjMC4yLDAsMC40LDAsMC42LTAuMWMwLjYtMC4xLDEuMi0wLjQsMS42LTAuNyBjMC40LTAuMywwLjYtMC44LDAuNC0xLjJjLTAuMS0wLjQtMC41LTAuNi0wLjktMC42Yy0wLjEsMC0wLjEsMC0wLjIsMGMtMC4yLDAtMC40LDAuMS0wLjYsMC4xYy0wLjEsMC0wLjIsMC0
|
||||
wLjIsMCBjLTAuMiwwLTAuMy0wLjEtMC40LTAuMmMwLjItMC4xLDAuNS0wLjIsMC43LTAuM2MxLTAuNCwxLjYtMC42LDItMWMwLjEtMC4xLDAuMS0wLjEsMC4yLTAuMmMwLjEsMCwwLjMsMC4xLDAuNCwwLjEgQzI4LjYsMjYsMjksMjYsMjkuNCwyNmMwLjksMCwyLjktMC4xLDQuNS0xLjRjMC44LDAuMiwxLjUsMC40LDIuMiwwLjRjMC40LDAsMC45LTAuMSwxLjMtMC4yYzEuMi0wLjMsMi4zLTEuMSwyLjktMi4zIGMyLjItMy45LTEuMy03LjEtNC4yLTkuN0MzNC45LDExL
|
||||
jcsMzMsMTAsMzMsOS4xYzAsMCwwLDAsMC0wLjFjMC4yLDAuMSwwLjQsMC4xLDAuOCwwLjNjMC42LDAuMiwxLjUsMC42LDIuNCwwLjYgYzEuMSwwLDEuOS0wLjUsMi41LTEuNWMwLjYtMSwwLjQtMS45LDAuMS0yLjVjMC4xLDAsMC4yLDAsMC4zLDBjMC42LDAsMS4yLTAuMywxLjYtMC44QzQxLjMsNS4xLDQyLDUsNDIuNSw1QzQzLjMsNSw0NCw0LjMsNDQsMy41IGMwLTAuNy0wLjQtMS4yLTEuMS0xLjRDNDIuNywxLjQsNDIuMiwxLDQxLjUsMUw0MS41LDF6Ii8+PHBhdGg
|
||||
gZD0iTTEzLDI1Yy0yLjYsMC0yLjgtMi41LTIuOS0zLjhjMC0wLjMtMC4xLTAuOS0wLjItMS4xYy0wLjEsMC4xLTAuMSwwLjItMC4yLDAuM2MtMC4xLDAuMS0wLjIsMC4zLTAuMywwLjUgYy0wLjYsMS0xLjksMS40LTIuOSwxYy0wLjgtMC4zLTEuOC0xLjEtMi41LTIuNGMtMC4yLTAuNSwwLTEuMSwwLjQtMS4zYzAuNS0wLjIsMS4xLDAsMS4zLDAuNGMwLjQsMC43LDEsMS4zLDEuNCwxLjQgYzAuMiwwLjEsMC40LDAsMC41LTAuMmMwLjEtMC4xLDAuMi0wLjMsMC4yLTAuN
|
||||
GMwLjMtMC42LDAuOC0xLjQsMi0xLjRjMS44LDAsMiwxLjksMi4xLDNjMC4yLDEuOCwwLjQsMiwwLjksMiBjMS41LDAsMS45LTIuMSwyLjUtNS40YzAuNi0zLjQsMS4zLTcuNiw1LTcuNmMyLjcsMCwzLjgsMS45LDQuMiw0LjFjMi4xLDAuNCwzLjcsMi43LDQuMSw0YzAuMiwwLjgsMC4yLDEuNi0wLjIsMi4zcy0xLDEuMi0xLjcsMS41IGMtMC44LDAuMi0xLjYsMC4yLTIuMy0wLjJjLTAuNy0wLjQtMS4yLTEtMS41LTEuN0MyMywxOS42LDIzLDE5LjEsMjMsMTguMmMwLTM
|
||||
uNy0wLjQtNi4yLTIuNi02LjJjLTEuOSwwLTIuNCwyLjQtMyw2IEMxNi45LDIxLjMsMTYuMywyNSwxMywyNXogTTI1LDE2LjNjMCwwLjcsMCwxLjMsMCwxLjljMCwwLjUsMCwxLDAsMS4yYzAuMSwwLjIsMC4zLDAuNCwwLjUsMC42YzAuMiwwLjEsMC41LDAuMSwwLjgsMC4xIGMwLjMtMC4xLDAuNS0wLjMsMC42LTAuNWMwLjEtMC4yLDAuMS0wLjUsMC4xLTAuOEMyNi44LDE4LjEsMjYsMTYuOSwyNSwxNi4zeiIvPjxwYXRoIGQ9Ik0yNCAxNmMtLjMtLjEtLjctLjEtMS4xL
|
||||
S4xLS40IDAtLjcuMS0xLjEuMi0uMy4xLS42LjQtLjkuNy0uMy4zLS40LjctLjUgMS4xLS4xLS40LS4xLS45IDAtMS40LjEtLjUuNC0uOS43LTEuMy40LS40LjgtLjcgMS4yLS45LjUtLjIuOS0uNCAxLjUtLjVsLjEgMGMuNi0uMSAxLjEuMyAxLjIuOFMyNSAxNS45IDI0LjUgMTZDMjQuMyAxNiAyNC4xIDE2IDI0IDE2ek0zLjUgMTguMWMtLjEgMC0uMSAwLS4yIDBDMy4xIDE4IDIuOCAxOCAyLjUgMTggMi4yIDE4IDIgMTcuOCAyIDE3LjVTMi4yIDE3IDIuNSAxN2MuNSA
|
||||
wIC44IDAgMS4yLjJDNCAxNy4zIDQuMSAxNy42IDQgMTcuOCAzLjkgMTggMy43IDE4LjEgMy41IDE4LjF6Ii8+PHBhdGggZD0iTTQuNSAxOWMtLjEgMC0uMSAwLS4yLS4xLS4xIDAtMS4zLS43LTEuMy0yLjRDMyAxNi4yIDMuMiAxNiAzLjUgMTZTNCAxNi4yIDQgMTYuNWMwIDEuMS43IDEuNS43IDEuNi4yLjEuMy40LjIuN0M0LjkgMTguOSA0LjcgMTkgNC41IDE5ek0zNCA0M2MtLjMgMC0uNS0uMS0uNy0uMy0uNC0uNC0uNC0xIDAtMS40LjctLjcuNy0xLjQuNy0xLjggM
|
||||
C0uMi0uMi0uMy0uNC0uNC0uMiAwLS40IDAtLjctLjEtMS0uMS0yLjMtLjItMi44LTEuMi0uNy0xLjcgMS0yLjYgMi4xLTMuMiAxLjctLjkgMS45LTEuMiAxLjYtMS44LS42LTEuMy0yLjgtLjgtNi4yLjEtMy43IDEtNy44IDIuMi05LjMtMS4zLS40LTEtLjUtMi0uMS0yLjkuNS0xLjIgMS42LTIuMSAyLjgtMi44LS4zLTIuMSAxLTQuMyAyLTUuMSAxLjItMS4xIDMuMS0xIDQuMi4yIDEuMSAxLjIgMSAzLjEtLjIgNC4yLS4zLjMtLjguNS0xLjcuOS0uNi4zLTEuNS42LTI
|
||||
uMyAxLS4xLjEtLjIuMi0uMy4yLS4xIDAtLjEuMS0uMi4xLTEgLjYtMiAxLjMtMi4zIDIuMS0uMi40LS4yLjkuMSAxLjQuOCAxLjcgMy4zIDEuMiA3IC4yIDMuNC0uOSA3LjItMiA4LjYgMSAxIDIuMy0xLjIgMy42LTIuNSA0LjMtLjMuMi0uOC40LTEgLjYuMyAwIC42LjEuOS4xLjMgMCAuNiAwIC44LjEgMS4yLjIgMi4xIDEuMiAyLjEgMi4zIDAgLjYuMSAyLTEuMyAzLjNDMzQuNSA0Mi45IDM0LjMgNDMgMzQgNDN6TTI1IDIyYy0uMiAwLS41LjEtLjcuMy0uNC40LTEuM
|
||||
iAxLjUtMS4zIDIuNi41LS4yIDEtLjQgMS41LS42LjUtLjIgMS0uNCAxLjItLjUuNC0uMy40LTEgMC0xLjRDMjUuNSAyMi4xIDI1LjMgMjIgMjUgMjJ6Ii8+PHBhdGggZD0iTTIzLjIgMjYuMWMwIC4zLjIuNy4zIDEgLjIuMy4zLjYuNi45LjIuMy42LjQgMSAuNS40LjEuOC4xIDEuMiAwLS40LjItLjguNS0xLjIuNS0uNS4xLTEgMC0xLjUtLjItLjUtLjItLjktLjUtMS4zLS44LS40LS40LS43LS43LTEtMS4ybC0uMS0uMWMtLjMtLjUtLjEtMS4xLjQtMS40LjUtLjMgMS4
|
||||
xLS4xIDEuNC40QzIzLjIgMjUuOCAyMy4yIDI1LjkgMjMuMiAyNi4xek0zMi41IDQ1Yy0uMyAwLS41LS4yLS41LS41bDAtLjVjMC0uMiAwLS40IDAtLjYgMC0uMy4zLS41LjUtLjUuMyAwIC41LjIuNS41IDAgLjIgMCAuMyAwIC41bDAgLjVDMzMgNDQuOCAzMi44IDQ1IDMyLjUgNDV6Ii8+PHBhdGggZD0iTTMxLjUgNDRjLS4zIDAtLjUtLjItLjUtLjVzLjItLjUuNS0uNWMxLjEgMCAxLjUtLjcgMS42LS43LjEtLjIuNC0uMy43LS4yLjIuMS4zLjQuMi43QzMzLjkgNDIuO
|
||||
CAzMy4zIDQ0IDMxLjUgNDR6TTI5LjQgMjVjLS40IDAtLjcgMC0xLS4xLTEuNi0uMy0yLjctMS45LTIuNC0zLjUuMi0uOC42LTEuNSAxLjMtMS45LjctLjQgMS41LS42IDIuMy0uNS40LjEuOC4zIDEuNy45LjYuNCAxLjQuOCAyLjIgMS4yIDAgMCAwIDAgMCAwIC4yIDAgLjMgMCAuNS4xLjEuMS4yLjEuMy4yLjkuNCAxLjguNiAyLjQuNC40LS4xLjgtLjQgMS4xLS45IDEtMS43LS44LTMuNS0zLjUtNkMzMiAxMy4xIDMwIDExLjMgMzAgOS4yYzAtLjYuMS0xLjIuNC0xLjd
|
||||
DMzEuMSA2LjMgMzIgNiAzMi43IDZjLjggMCAxLjYuMyAyLjMuNi4yLjEuNi4yLjguMyAwIDAgMCAwIDAgMC0uMi0uMi0uMy0uNC0uNS0uN0MzNS4xIDUuOCAzNSA1LjQgMzUgNWMwLS42LjMtMS4xLjktMS41QzM2LjYgMy4xIDM4LjEgMyAzOSAzYy42IDAgMSAuNCAxIDFzLS40IDEtMSAxYy0uOCAwLTEuNi4xLTIgLjIgMCAwIDAgMCAwIDAgLjEuMi4yLjQuMy41QzM3LjggNi4yIDM4LjMgNyAzNy44IDhjLS45IDEuNi0yLjUuOS0zLjYuNEMzMy43IDguMiAzMy4xIDggM
|
||||
zIuNyA4Yy0uMSAwLS4zIDAtLjYuNEMzMiA4LjYgMzIgOC45IDMyIDkuMWMwIDEuMyAxLjggMi45IDMuNSA0LjQgMi43IDIuNCA1LjcgNS4yIDQgOC40LS41IDEtMS4zIDEuNi0yLjMgMS45LTEuMS4zLTIuMy4xLTMuNC0uNEMzMi42IDI0LjYgMzAuOCAyNSAyOS40IDI1ek0yOSAyMWMtLjIgMC0uNC4xLS42LjItLjIuMS0uNC40LS40LjYtLjEuNS4zIDEuMS44IDEuMi41LjEgMS45LjEgMi45LS41LS41LS4zLTEtLjYtMS41LS45LS40LS4zLS45LS42LTEuMS0uNkMyOS4
|
||||
xIDIxIDI5LjEgMjEgMjkgMjF6Ii8+PHBhdGggZD0iTTMyLjYgMjEuN2MuMi0uMi40LS42LjYtLjkuMi0uMy4zLS43LjMtMS4xIDAtLjQgMC0uNy0uMi0xLjEtLjEtLjQtLjQtLjctLjgtMSAuNC4yLjguMyAxLjIuNy4zLjMuNi44LjggMS4zLjEuNS4yIDEgLjIgMS41IDAgLjUtLjEgMS0uMyAxLjVsMCAuMWMtLjIuNS0uOC44LTEuMy42cy0uOC0uOC0uNi0xLjNDMzIuNCAyMS45IDMyLjUgMjEuOCAzMi42IDIxLjd6TTQwLjggNC4xYy0uMiAwLS40LS4yLS41LS40IDAtL
|
||||
jMuMS0uNS40LS42LjEgMCAuMi0uMi4yLS42QzQxIDIuMiA0MS4yIDIgNDEuNSAyUzQyIDIuMiA0MiAyLjVDNDIgMy4zIDQxLjUgNCA0MC44IDQuMSA0MC45IDQuMSA0MC45IDQuMSA0MC44IDQuMXoiLz48cGF0aCBkPSJNMzksNC41Yy0wLjIsMC0wLjQtMC4yLTAuNS0wLjRjLTAuMS0wLjMsMC4xLTAuNSwwLjQtMC42QzM5LDMuNSw0MSwzLDQyLjUsM0M0Mi44LDMsNDMsMy4yLDQzLDMuNVM0Mi44LDQsNDIuNSw0IGMtMS40LDAtMy40LDAuNS0zLjQsMC41QzM5LjEsNC41LDM5LDQuNSwzOSw0LjV6Ii8+PC9zdmc+Cg==</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Razer</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="11">
|
||||
<name>Samsung</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-samsung.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiMwZDQ3YTEiIGQ9Ik00Ny45NywxOS44MjZjMC42NTQsMy43NDctOS41NDcsOC42NTUtMjIuNzg4LDEwLjk2Yy0xMy4yMzgsMi4zMDYtMjQuN
|
||||
SwxLjEzNi0yNS4xNTMtMi42MTMgYy0wLjY1My0zLjc0Nyw5LjU1MS04LjY1NCwyMi43OS0xMC45NThDMzYuMDU5LDE0LjkwNyw0Ny4zMTgsMTYuMDc4LDQ3Ljk3LDE5LjgyNnoiLz48cG9seWdvbiBmaWxsPSIjZmFmYWZhIiBwb2ludHM9IjM1LjUxLDI1LjM4OCAzNS40NDIsMjEuNDkyIDM2LjY3MSwyMS40OTIgMzYuNjcxLDI2LjQwMyAzNC45MDUsMjYuNDAzIDMzLjY3OCwyMi4zNzMgMzMuNjUyLDIyLjM3MyAzMy43MiwyNi40MDMgMzIuNDk5LDI2LjQwMyAzMi40OTk
|
||||
sMjEuNDkyIDM0LjM0MiwyMS40OTIgMzUuNDgzLDI1LjM4OCIvPjxwb2x5Z29uIGZpbGw9IiNmYWZhZmEiIHBvaW50cz0iMTMuMTc3LDIxLjk1MiAxMi40OTcsMjYuNDU1IDExLjE1NywyNi40NTUgMTIuMDc2LDIxLjQ5MiAxNC4yODQsMjEuNDkyIDE1LjIwMSwyNi40NTUgMTMuODY1LDI2LjQ1NSAxMy4yMDQsMjEuOTUyIi8+PHBvbHlnb24gZmlsbD0iI2ZhZmFmYSIgcG9pbnRzPSIxOC45NjQsMjUuMjg2IDE5LjU3NywyMS40OTIgMjEuNjAxLDIxLjQ5MiAyMS43MDgsM
|
||||
jYuNDU1IDIwLjQ2OCwyNi40NTUgMjAuNDM1LDIxLjk5MyAyMC40MDksMjEuOTkzIDE5LjU4LDI2LjQ1NSAxOC4zMjEsMjYuNDU1IDE3LjQ5LDIxLjk5MyAxNy40NjQsMjEuOTkzIDE3LjQzMywyNi40NTUgMTYuMTksMjYuNDU1IDE2LjMsMjEuNDkyIDE4LjMyNSwyMS40OTIgMTguOTM3LDI1LjI4NiIvPjxwYXRoIGZpbGw9IiNmYWZhZmEiIGQ9Ik05LjA2NywyNS4wNTVjMC4wNDksMC4xMiwwLjAzNCwwLjI3NSwwLjAxMSwwLjM2OGMtMC4wNDIsMC4xNjUtMC4xNTQsMC4
|
||||
zMzMtMC40ODMsMC4zMzMgYy0wLjMxMiwwLTAuNS0wLjE3OS0wLjUtMC40NXYtMC40OEg2Ljc2M0w2Ljc2MiwyNS4yMWMwLDEuMTA2LDAuODcxLDEuNDQxLDEuODA1LDEuNDQxYzAuODk4LDAsMS42MzctMC4zMDcsMS43NTQtMS4xMzQgYzAuMDYxLTAuNDI5LDAuMDE1LTAuNzA5LTAuMDA1LTAuODE2Yy0wLjIwOS0xLjAzOS0yLjA5My0xLjM0OS0yLjIzMy0xLjkzYy0wLjAyNC0wLjA5OS0wLjAxNy0wLjIwNS0wLjAwNS0wLjI2MiBjMC4wMzUtMC4xNTgsMC4xNDMtMC4zM
|
||||
zIsMC40NTMtMC4zMzJjMC4yOSwwLDAuNDYxLDAuMTgsMC40NjEsMC40NWMwLDAuMDkxLDAsMC4zMDcsMCwwLjMwN2gxLjIzN3YtMC4zNDggYzAtMS4wODEtMC45Ny0xLjI1LTEuNjczLTEuMjVjLTAuODgzLDAtMS42MDQsMC4yOTItMS43MzYsMS4wOTljLTAuMDM2LDAuMjIzLTAuMDQxLDAuNDIyLDAuMDExLDAuNjcxIEM3LjA0OSwyNC4xMTgsOC44MTEsMjQuNDEyLDkuMDY3LDI1LjA1NXoiLz48cGF0aCBmaWxsPSIjZmFmYWZhIiBkPSJNMjUuMjA0LDI1LjA0NmMwLjA
|
||||
0OSwwLjExOSwwLjAzMywwLjI3LDAuMDExLDAuMzYzYy0wLjA0MSwwLjE2NS0wLjE1MiwwLjMzLTAuNDc5LDAuMzMgYy0wLjMwNywwLTAuNDk0LTAuMTc5LTAuNDk0LTAuNDQ0bC0wLjAwMS0wLjQ3NmgtMS4zMThsLTAuMDAyLDAuMzc5YzAsMS4wOTUsMC44NjMsMS40MjYsMS43ODcsMS40MjYgYzAuODg4LDAsMS42Mi0wLjMwMywxLjczNi0xLjEyMmMwLjA2MS0wLjQyNiwwLjAxOC0wLjcwMi0wLjAwNC0wLjgwN2MtMC4yMDgtMS4wMjktMi4wNzMtMS4zMzYtMi4yMTEtM
|
||||
S45MTIgYy0wLjAyNC0wLjA5OS0wLjAxNy0wLjIwMy0wLjAwNS0wLjI1N2MwLjAzNi0wLjE2LDAuMTQyLTAuMzI5LDAuNDQ5LTAuMzI5YzAuMjg4LDAsMC40NTUsMC4xNzUsMC40NTUsMC40NDQgYzAsMC4wOSwwLDAuMzA0LDAsMC4zMDRoMS4yMjh2LTAuMzQ1YzAtMS4wNy0wLjk2Mi0xLjIzNy0xLjY1OS0xLjIzN2MtMC44NzMsMC0xLjU4OCwwLjI4OC0xLjcxNywxLjA5IGMtMC4wMzYsMC4yMi0wLjA0LDAuNDE1LDAuMDEyLDAuNjYzQzIzLjIwNiwyNC4xMTgsMjQuOTU
|
||||
xLDI0LjQxLDI1LjIwNCwyNS4wNDZ6Ii8+PHBhdGggZmlsbD0iI2ZhZmFmYSIgZD0iTTI5LjM3MiwyNS43MTNjMC4zNDQsMCwwLjQ1MS0wLjIzOCwwLjQ3NS0wLjM2YzAuMDEtMC4wNTQsMC4wMTMtMC4xMjUsMC4wMTItMC4xOVYyMS40OWgxLjI1NSB2My41NmMwLjAwMywwLjA5MS0wLjAwNiwwLjI3OS0wLjAxMSwwLjMyNWMtMC4wODgsMC45MjctMC44MjEsMS4yMjctMS43MzIsMS4yMjdjLTAuOTEzLDAtMS42NDYtMC4zMDEtMS43MzMtMS4yMjcgYy0wLjAwNC0wLjA0N
|
||||
y0wLjAxMy0wLjIzNS0wLjAxMS0wLjMyNXYtMy41NmgxLjI1NHYzLjY3MmMwLDAuMDY0LDAuMDAyLDAuMTM3LDAuMDEyLDAuMTkgQzI4LjkyMSwyNS40NzMsMjkuMDI1LDI1LjcxMywyOS4zNzIsMjUuNzEzeiIvPjxwYXRoIGZpbGw9IiNmYWZhZmEiIGQ9Ik0zOS43MjUsMjUuNjZjMC4zNTksMCwwLjQ4NS0wLjIyNywwLjUwOC0wLjM1OWMwLjAwOS0wLjA1NywwLjAxMi0wLjEyNiwwLjAxMS0wLjE4OXYtMC43MiBoLTAuNTA5di0wLjcyNGgxLjc2VjI1Yy0wLjAwMSwwLjA
|
||||
5My0wLjAwMywwLjE2Mi0wLjAxOCwwLjMyN2MtMC4wODIsMC45MDMtMC44NjYsMS4yMjUtMS43NDUsMS4yMjUgYy0wLjg4MSwwLTEuNjYzLTAuMzIyLTEuNzQ3LTEuMjI1Yy0wLjAxNC0wLjE2Ni0wLjAxNi0wLjIzNC0wLjAxOC0wLjMyN2wwLjAwMS0yLjA4OWMwLTAuMDg4LDAuMDExLTAuMjQ0LDAuMDIxLTAuMzI3IGMwLjExLTAuOTI4LDAuODYyLTEuMjI2LDEuNzQzLTEuMjI2YzAuODgsMCwxLjY1MSwwLjI5NywxLjc0MiwxLjIyNmMwLjAxNiwwLjE1OCwwLjAxMSwwL
|
||||
jMyNywwLjAxMSwwLjMyN3YwLjE2NmgtMS4yNTF2LTAuMjc4IGMwLjAwMSwwLjAwMS0wLjAwMi0wLjExOC0wLjAxNi0wLjE4OWMtMC4wMjEtMC4xMS0wLjExNi0wLjM2Mi0wLjQ5NS0wLjM2MmMtMC4zNjIsMC0wLjQ2NywwLjIzOC0wLjQ5NCwwLjM2MiBjLTAuMDE1LDAuMDY1LTAuMDIxLDAuMTU0LTAuMDIxLDAuMjM0djIuMjdjLTAuMDAxLDAuMDYzLDAuMDAzLDAuMTMyLDAuMDEzLDAuMTg5QzM5LjI0MSwyNS40MzMsMzkuMzY2LDI1LjY2LDM5LjcyNSwyNS42NnoiLz48L3N2Zz4K</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Samsung</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="12">
|
||||
<name>Sony</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icon-sony.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmc6c3ZnIHhtbG5zOmlua3NjYXBlPSJodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIiB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiIHhtbG5zOnN2Zz0iaH
|
||||
R0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjgwIDEyODAiIHZlcnNpb249IjEuMSIgaWQ9InN2ZzEiIHNvZGlwb2RpOmRvY25hbWU9Imljb24tc29ueS5zdmciIGlua3NjYXBlOnZlcnNpb249IjEuNC4zICgwZDE1Zjc1MDQyLCAyMDI1LTEyLTI1KSIgd2lkdGg9IjEyODAiIGhlaWdodD0iMTI4MCI+PHNvZGlwb2RpOm5hbWVkdmlldyBpZD0ibmFtZWR2aWV3MSIgcGFnZWNvbG9yPSIjZmZmZmZmIiBib3JkZXJjb2xvcj0iIzAwMDAwMCIgYm9y
|
||||
ZGVyb3BhY2l0eT0iMC4yNSIgaW5rc2NhcGU6c2hvd3BhZ2VzaGFkb3c9IjIiIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiIGlua3NjYXBlOnBhZ2VjaGVja2VyYm9hcmQ9IjAiIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIgaW5rc2NhcGU6em9vbT0iMC42MzQxODYzOSIgaW5rc2NhcGU6Y3g9Ii00NjIuNzk3NjkiIGlua3NjYXBlOmN5PSIyMjUuNDg1NzYiIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMjU2MCIgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iMTM2MC
|
||||
IgaW5rc2NhcGU6d2luZG93LXg9IjAiIGlua3NjYXBlOndpbmRvdy15PSIwIiBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIiBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJnNCIgc2hvd2d1aWRlcz0idHJ1ZSI+PHNvZGlwb2RpOmd1aWRlIHBvc2l0aW9uPSIxNzMuMzcxMDgsNjQxLjg5MDI0IiBvcmllbnRhdGlvbj0iMCwtMSIgaWQ9Imd1aWRlMSIgaW5rc2NhcGU6bG9ja2VkPSJmYWxzZSIvPjwvc29kaXBvZGk6bmFtZWR2aWV3Pjxzdmc6ZGVmcyBpZD0iZGVmczEi
|
||||
Lz48c3ZnOmcgaWQ9IkxheWVyXzIiPjxzdmc6ZyBpZD0iZzQiIGlua3NjYXBlOmxhYmVsPSJsb2dvIj48c3ZnOnBhdGggZD0ibSA0NTYuMDEyOSw3NTEuNzQ2ODcgYyAtNDYuNDEyNzksMCAtODkuNDIwNzksLTEzLjgyMzk5IC0xMTguMDkyNzksLTM5LjYwMzE5IGEgOTYuODk1OTg5LDk2Ljg5NTk4OSAwIDAgMSAtMzIuMTI3OTksLTczLjE5MDM5IDk4LjMyOTU4OCw5OC4zMjk1ODggMCAwIDEgMzIuMTI3OTksLTcyLjkzNDQgYyAyNi42MjQsLTI0LjE5MTk5IDczLjcyOC
|
||||
wtMzkuNTUxOTkgMTE4LjA5Mjc5LC0zOS41NTE5OSA0OS4wNzUxOSwwIDg4LjM3MTE5LDEyLjM2NDggMTE4LjM5OTk5LDM5LjYwMzE5IGEgOTcuNDA3OTg5LDk3LjQwNzk4OSAwIDAgMSAzMS42OTI3OSw3Mi44ODMyIDEwMS41Mjk1OSwxMDEuNTI5NTkgMCAwIDEgLTMxLjY5Mjc5LDczLjE5MDM5IGMgLTI3Ljk4MDgsMjUuOTMyOCAtNzEuOTEwNCwzOS42MDMxOSAtMTE4LjM5OTk5LDM5LjYwMzE5IHYgLTI5LjY0NDc5IGMgMjQuNjAxNiwwIDQ3LjQzNjc5LC04LjQ5OTIg
|
||||
NjMuMzg1NTksLTI0LjM3MTIgMTUuOTQ4OCwtMTUuODcyIDIzLjE5MzYsLTM1LjEyMzIgMjMuMTkzNiwtNTguODc5OTkgMCwtMjIuNjgxNiAtNy45NjE2LC00My44Nzg0IC0yMy4xOTM2LC01OC44OCAtMTUuNzQ0LC0xNS40ODc5OSAtMzkuMTE2NzksLTI0LjIxNzU5IC02My4zODU1OSwtMjQuMjE3NTkgLTI0LjI2ODgsMCAtNDcuNzQzOTksOC42NTI4IC02My40ODc5OSwyNC4yMTc1OSAtMTUuMTgwOCwxNS4wMjcyIC0yMy4wNCwzNi4zMDA4IC0yMy4wNCw1OC44OCBhID
|
||||
gyLjM1NTE5LDgyLjM1NTE5IDAgMCAwIDIzLjA0LDU4Ljg3OTk5IGMgMTUuNzQ0LDE1LjY5MjggMzkuMDY1NTksMjQuMzcxMiA2My40ODc5OSwyNC4zNzEyIHogTSAxMTcuMTIwMTQsNTI2LjQ2NjkgYyAtMjQuODA2MzkyLDAgLTUyLjk5MTk4OSw0LjY1OTIgLTc2Ljc5OTk4NiwxNS4zNiBDIDE4LjA5OTM1NSw1NTEuNzU5NyAxLjU3NWUtNCw1NjcuNzA4NDkgMS41NzVlLTQsNTk0LjE1MzI5IGEgNTQuMjIwNzk0LDU0LjIyMDc5NCAwIDAgMCAxNC43MTk5OTg1LDM3LjI3
|
||||
MzYgYyA2LjQyNTU5OSw1LjkzOTIgMTYuNzkzNTk5LDE2LjAyNTYgNDMuODc4Mzk2LDIxLjk2NDggMTIuMTA4Nzk4LDIuNTU5OTkgMzcuOTkwMzk1LDYuNjgxNTkgNjMuNzY5NTg4LDkuMzk1MTkgMjUuNzc5MiwyLjcxMzYgNTAuNzY0OCw1LjEyIDYxLjAwNDgsNy44NTkyIDguMTQwOCwyLjA3MzYgMjEuODM2NzksNC44ODk2IDIxLjgzNjc5LDIwLjI0OTYgMCwxNS4zNiAtMTQuNDEyNzksMTkuOTY4IC0xNi45MjE1OSwyMC45NjY0IC0yLjUwODgsMC45OTg0IC0xOS44MT
|
||||
Q0LDguOTM0NCAtNTAuODkyOCw4LjkzNDQgYSAyMTYuNDIyMzcsMjE2LjQyMjM3IDAgMCAxIC02MC41OTUxOSwtMTAuNDE5MiBjIC0xMS41OTY3OTksLTQuMTQ3MiAtMjMuNzU2Nzk3LC05LjYgLTM1LjA5NzU5NiwtMjMuNDQ5NiBhIDQwLjI2ODc5NSw0MC4yNjg3OTUgMCAwIDEgLTcuMjk1OTk5LC0yMi4yMjA4IEggNi4yNDY1NTY3IHYgNzguODQ3OTkgSCAzNy41Mjk3NTQgdiAtMTAuNjc1MTkgYSA0LjQ1NDM5OTUsNC40NTQzOTk1IDAgMCAxIDYuNzU4NCwtMy44NCAy
|
||||
NDYuNDI1NTcsMjQ2LjQyNTU3IDAgMCAwIDQ1Ljc3Mjc5NCwxNC43OTY3OSBjIDE2LjQzNTIwMiwzLjQzMDQgMjcuMDU5MTkyLDUuOTEzNiA0Ny40ODc5OTIsNS45MTM2IGEgMjAyLjYyMzk4LDIwMi42MjM5OCAwIDAgMCA2My42NDE2LC04Ljk4NTYgMTExLjA3ODM5LDExMS4wNzgzOSAwIDAgMCAzNy44MTExOSwtMTguNjYyMzkgNTEuODE0Mzk0LDUxLjgxNDM5NCAwIDAgMCAyMC4yNDk1OSwtNDEuNDk3NiA1OC4wNjA3OTMsNTguMDYwNzkzIDAgMCAwIC0xNi4zNTgzOS
|
||||
wtNDAuODA2MzkgNzIuMDEyNzkyLDcyLjAxMjc5MiAwIDAgMCAtMjAuMTcyOCwtMTMuNzk4NCAxNDguNjA3OTgsMTQ4LjYwNzk4IDAgMCAwIC0yNC44ODMxOSwtOC42Nzg0IGMgLTE2LjIzMDQsLTMuOTY4IC01Mi42ODQ4LC04LjkzNDQgLTcwLjExODQsLTEwLjY3NTIgLTE4LjI3ODM5LC0xLjg5NDQgLTQ5Ljk5Njc5LC00LjUzMTIgLTYyLjY2ODc4OSwtOC40NDggLTMuODM5OTk5LC0xLjIwMzIgLTExLjY3MzU5OSwtNC45MTUyIC0xMS42NzM1OTksLTE0LjAwMzIgMCwt
|
||||
Ni40NzY4IDMuNTg0LC0xMS45NTUyIDEwLjY0OTU5OSwtMTYuMzg0IEMgNzUuMjY0MTUsNTYwLjc3MDkgOTcuOTQ1NzQ3LDU1Ni4zOTMzIDEyMS42MDAxNCw1NTYuMzkzMyBhIDE2Ni45ODg3OCwxNjYuOTg4NzggMCAwIDEgNjYuNzEzNiwxMy4wMzAzOSA3Mi44NTc1OTEsNzIuODU3NTkxIDAgMCAxIDE1Ljg3MTk5LDkuNDcyIDQ3LjcxODM5NCw0Ny43MTgzOTQgMCAwIDEgMTUuNjQxNiwyNi4xNjMyIGggMjUuMjY3MiBWIDUzNi40MjUzIGggLTI4LjE2IHYgNy45NjE2IG
|
||||
MgMCwyLjU2IC0yLjU2LDUuOTM5MiAtNy42OCwzLjE0ODggLTEyLjY5NzU5LC02LjYwNDggLTQ4LjM4Mzk5LC0yMC44ODk2IC05Mi4xMzQzOSwtMjEuMDY4OCB6IG0gNjE4LjIxNDMzLDEyLjU5NTIgMTM3LjYyNTU4LDEyNC4xODU1OCAtMS40MDgsLTgzLjYwOTU5IGMgLTAuMTUzNiwtMTAuOTgyNCAtMi4xNTA0LC0xNS41NjQ3OSAtMTQuMDI4OCwtMTUuNTY0NzkgaCAtMjUuODU1OTkgdiAtMjUuMDExMiBoIDExNy43NTk5OCB2IDI1LjAxMTIgaCAtMjUuMjY3MTkgYyAt
|
||||
MTIuMDgzMiwwIC0xMi44LDMuODkxMTkgLTEzLjAwNDgsMTUuNTY0NzkgbCAyLjEyNDgsMTU5Ljc2OTU5IGggLTQwLjMyIEwgNzE0LjQxOTI3LDU5Ny45NDIwOSB2IDEwMC4zNzc1OSBjIDAuMTI4LDEwLjkzMTIgMC42NCwxNi4wNzY4IDExLjg3ODQsMTYuMDc2OCBoIDI4LjE2IHYgMjUuMDExMiBIIDYzOS4wMjcyOCB2IC0yNS4wMTEyIGggMjcuMDMzNiBjIDEwLjA4NjM5LDAgOS42NzY3OSwtOS42MjU2IDkuNjc2NzksLTE2LjY0IFYgNTgwLjU4NTI5IGMgMCwtNy42OC
|
||||
AtMS4wNzUyLC0xNi40ODYzOSAtMTYuODk1OTksLTE2LjQ4NjM5IGggLTIxLjkxMzYgViA1MzkuMDYyMSBaIE0gMTA4My43NzYsNzE0LjM0NTI4IGEgNTUuODU5MTkzLDU1Ljg1OTE5MyAwIDAgMCA2Ljk2MzIsLTAuNDM1MiA4LjYyNzE5OSw4LjYyNzE5OSAwIDAgMCA1LjQyNzIsLTQuODEyOCAyOC4wMDYzOTcsMjguMDA2Mzk3IDAgMCAwIDAuNTM3NiwtNS40MDE2IHYgLTM5LjU1MiBjIDAsLTEuMzMxMiAwLC0xLjM1NjggLTEuNjg5NiwtMy40NTYgLTEuNjg5NiwtMi4w
|
||||
OTkyIC03Mi4wODk2LC04MS45MTk5OSAtNzUuMjg5NiwtODUuNTAzOTkgLTMuOTkzNiwtNC4zNTIgLTExLjAwOCwtMTEuMDg0NzkgLTIxLjY4MzIsLTExLjA4NDc5IGggLTI0LjQ0Nzk2IHYgLTI1LjAzNjggaCAxMzcuOTgzOTYgdiAyNC45ODU2IGggLTE2LjY0IGMgLTMuODQsMCAtNi40LDMuNjYwNzkgLTMuMTIzMiw3LjY3OTk5IDAsMCA0Ni40Mzg0LDU1LjU1MiA0Ni44NzM2LDU2LjE0MDggMC40MzUyLDAuNTg4OCAwLjgxOTIsMC43MTY4IDEuNDA4LDAuMTc5MiAwLj
|
||||
U4ODgsLTAuNTM3NiA0Ny41OTA0LC01NS44MDggNDcuOTQ4OCwtNTYuMzIgYSA0Ljc4NzE5OTQsNC43ODcxOTk0IDAgMCAwIC00LjA5NiwtNy42Nzk5OSBoIC0xNy4wNzUyIFYgNTM5LjA2MjEgSCAxMjgwIHYgMjUuMDM2OCBoIC0yNS4yNjcyIGMgLTkuMTY0OCwwIC0xMi44LDEuNjg5NTkgLTE5Ljc4ODgsOS40NzE5OSBsIC03Ni4xNiw4Ni44ODYzOSBhIDUuMzc1OTk5NCw1LjM3NTk5OTQgMCAwIDAgLTAuOTIxNiwzLjY4NjQgdiAzOS41MjY0IGEgMjguMTU5OTk3LDI4
|
||||
LjE1OTk5NyAwIDAgMCAwLjU2MzIsNS40MDE2IDguNTI0Nzk5LDguNTI0Nzk5IDAgMCAwIDUuNDAxNiw0LjgxMjggNTAuNjExMTk0LDUwLjYxMTE5NCAwIDAgMCA2LjkxMiwwLjQzNTIgaCAyNS44MzA0IHYgMjUuMDM2OCBoIC0xMzcuMjY3MiB2IC0yNS4wMzY4IHoiIGlkPSJwYXRoMSIgZmlsbD0iIzAwMDAwMCIgc3R5bGU9InN0cm9rZS13aWR0aDoyLjU2Ii8+PC9zdmc6Zz48L3N2ZzpnPjwvc3ZnOnN2Zz4K</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Sony</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="13">
|
||||
<name>Toshiba</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>logo-toshiba.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmc6c3ZnIHhtbG5zOmlua3NjYXBlPSJodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIiB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiIHhtbG5zOnN2Zz0
|
||||
iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHdpZHRoPSI4MDAiIGhlaWdodD0iODAwIiB2ZXJzaW9uPSIxLjAiIHZpZXdCb3g9IjAgMCA4MDAgODAwLjAxOTY5IiBpZD0ic3ZnMSIgc29kaXBvZGk6ZG9jbmFtZT0ibG9nby10b3NoaWJhLnN2ZyIgaW5rc2NhcGU6dmVyc2lvbj0iMS40LjMgKDBkMTVmNzUwNDIsIDIwMjUtMTItMjUpIj48c3ZnOmRlZnMgaWQ9ImRlZnMxIi8+PHNvZGlwb2RpOm5hbWVkdmlldyBpZD0ibmFtZWR2a
|
||||
WV3MSIgcGFnZWNvbG9yPSIjZmZmZmZmIiBib3JkZXJjb2xvcj0iIzAwMDAwMCIgYm9yZGVyb3BhY2l0eT0iMC4yNSIgaW5rc2NhcGU6c2hvd3BhZ2VzaGFkb3c9IjIiIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiIGlua3NjYXBlOnBhZ2VjaGVja2VyYm9hcmQ9IjAiIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIgc2hvd2d1aWRlcz0idHJ1ZSIgaW5rc2NhcGU6em9vbT0iMS41MzgxMjUiIGlua3NjYXBlOmN4PSIzNzguNzA3ODQiIGlua3NjYXBlOmN5PSIyODg
|
||||
uMDEzIiBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjI1NjAiIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEzNjAiIGlua3NjYXBlOndpbmRvdy14PSIwIiBpbmtzY2FwZTp3aW5kb3cteT0iMCIgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMSIgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnMSI+PHNvZGlwb2RpOmd1aWRlIHBvc2l0aW9uPSIyMjcuMzE3MTYsMzk5LjM4NTQyIiBvcmllbnRhdGlvbj0iMCwtMSIgaWQ9Imd1aWRlMSIgaW5rc2NhcGU6bG9ja2VkPSJmY
|
||||
WxzZSIvPjwvc29kaXBvZGk6bmFtZWR2aWV3PgogIDxzdmc6cGF0aCBmaWxsPSIjZTYxZTFlIiBkPSJtIDc2Ni4xMDAxNiw0NTkuNzEzNiBoIDM0LjU1IGwgLTM1LjY1LC0xMTcuNjYgLTQ5LjEsLTAuMDAyIC0zNS42NSwxMTcuNjYgaCAzNC41NiBsIDYuMywtMjEuNzggaCAzOC42NiBsIDYuMzMsMjEuNzggbSAtMzcuNTEsLTQ3Ljk0MyAxMS43NiwtNDAuNjUxIGggMC4yIGwgMTEuNzYsNDAuNjUxIHogbSAtNTU1LjQ2LDUwLjA1NSBjIDM1LjQ4LDAgNTIuNjMsLTYuMjU
|
||||
gNTUuMDYsLTM4LjI2NSAwLjU4LC03LjYxOCAwLjY5LC0xNS40MzkgMC42OSwtMjIuNjg5IDAuMDEsLTcuMjI1IC0wLjExLC0xNS4wNTQgLTAuNjksLTIyLjY3MSAtMi40MywtMzIuMDI1IC0xOS41OCwtMzguMjY1IC01NS4wNiwtMzguMjY1IC0zNS40OCwwIC01Mi42Miw2LjI0IC01NS4wNCwzOC4yNjUgLTAuNTksNy42MTcgLTAuNzEsMTUuNDQ2IC0wLjcxLDIyLjY3MSAwLjAxLDcuMjUgMC4xMiwxNS4wNzEgMC43MSwyMi42ODkgMi40MiwzMi4wMTUgMTkuNTYsMzguMjY1IDU1LjA0LDM4LjI2NSBtIC0yMi4zMSwtNjAuOTU0IGMgMCwtNi40NjEgMC4xNiwtMTAuMjggMC4zLC0xMy4xMTQgMC45LC0xOC4xNjEgOC4wNywtMjAuMjc4IDIyLjAxLC0yMC4yNzggMTMuOTUsMCAyMS4xMiwyLjExNyAyMi4wMSwyMC4yNzggMC4xNCwyLjgzMyAwLjMxLDYuNjUyIDAuMzEsMTMuMTE0IDAsNi40ODIgLTAuMTcsMTAuMzA4IC0wLjMxLDEzLjEzNSAtMC44OSwxOC4xNjQgLTguMDYsMjAuMjg1IC0yMi4wMSwyMC4yODUgLTEzLjk0LDAgLTIxLjExLC0yLjEyMSAtMjIuMDEsLTIwLjI4NSAtMC4xNCwtMi44MjcgLTAuMywtNi42NTMgLTAuMywtMTMuMTM1IHogTSAwLjY1MDE1ODIyLDM0Mi4xMDU2IHYgMjkuMzMxIEggMzUuODIyMTU4IHYgODguMzI3IGggMzUuMTg1IHYgLTg4LjMyNyBoIDM1LjE3MzAwMiB2IC0yOS4zMzEgSCAwLjY1MDE1ODIyIE0gNTQwLjUwMDE2LDQ1OS43MTM2IHYgLTExNy42NjIgaCAtMzMuMzkgdiAxMTcuNjYyIGggMzMuMzkgbSAtMTM0LjM1LC03NC43MDMgdiAtNDIuOTU5IGggLTMzLjIgdiAxMTcuNjYyIGggMzMuMiB2IC00NS4zNzIgaCAzOC41OCB2IDQ1LjM3MiBoIDMzLjE5IHYgLTExNy42NjIgaCAtMzMuMTkgdiA0Mi45NTkgaCAtMzguNTggbSAyNDQuMTcsMTMuMjA2IGMgMTQuNzksLTMuNzgxIDE5LjEzLC0xMi42MTYgMTkuMTMsLTI1LjM4NiAwLC0yNS44NTkgLTE2LjI3LC0zMC43OCAtMzkuNCwtMzAuNzggaCAtNTkuOTUgdiAxMTcuNjYgaCA2Mi45MiBjIDI4Ljk3LDAgMzguNzEsLTEyLjQ4IDM4LjcxLC0zMS42NzUgMCwtMTMuMzgzIC0zLjA2LC0yNS4xOTEgLTIxLjQxLC0yOS44MjIgbSAtNDcuMDMsMTMuMTY5IGggMjMuMDIgYyA5LjMsMCAxMS4yNCw0LjA3NCAxMS4yNCwxMC43IDAsNi42MzIgLTMuNjQsMTAuNzE3IC0xMS4yNCwxMC43MTcgaCAtMjMuMDIgeiBtIDAsLTQyLjQyNSBoIDIzLjAyIGMgNi4wMSwwIDkuNzMsMi44NTEgOS43Myw5LjcwOCAwLDUuODc4IC0zLjY4LDkuNDk2IC05LjczLDkuNDk2IGggLTIzLjAyIHogbSAtMzU1LjA2LDUyLjE0MyBoIDMxLjY1IGMgMC4wMyw1LjcwOCAwLjc2LDkuNTIzIDMuNTMsMTEuNjMgMy4xNSwyLjM3NCA1Ljk3LDMuMTU4IDE1LjMyLDMuMTU4IDksMCAxOC44NiwwIDE4Ljg2LC0xMS4wODUgMCwtOC43NDIgLTUuNTEsLTEwLjczNyAtMTUuNjgsLTExLjI3OSAtMjUuMjIsLTEuMzM2IC0zNC4zNCwtMi4wNDkgLTQzLjczLC05LjAyNSAtNi40LC00Ljc1NyAtOS43MiwtMTQuMDE4IC05LjcyLC0yNi41NDIgMCwtMjEuMjk3IDcuNDMsLTI4Ljc2OCAxOC4xNSwtMzMuOTgxIDExLjA2LC01LjM4MSA1NC40NywtNS4zODEgNjYuMTUsMCAxNC42OSw2Ljc2OCAxNS4xMiwyMS40MiAxNS4xMiwzNS4wMTEgaCAtMzEuNTcgYyAtMC4wNiwtNi45MjkgLTEuNjIsLTguODg2IC0yLjg5LC0xMC4xNzUgLTMuMjgsLTIuOTA4IC03Ljk1LC0zLjUyMiAtMTQuNjksLTMuNTIyIC04LjE2LDAgLTE3LjYsMC4zNjggLTE3LjYsMTAuMjc3IDAsNy41NiAzLjI3LDEwLjcyIDExLjg1LDExLjI3NiAxMS43OSwwLjc1NCAzNS4wMiwxLjQ5NyA0My4zLDYuMzgzIDExLjYxLDYuODY3IDE0LjYyLDE2LjE1OSAxNC42MiwzMS4zMTkgMCwyMS45MDggLTcuODQsMjguMzM4IC0xOC43NSwzMy4xNTggLTEyLjU5LDUuNTYgLTU0LjY0LDUuNTYgLTY4LjMxLC0wLjQzIC0xNS4zLC02LjY3IC0xNS42MSwtMTkuOTY0IC0xNS42MSwtMzYuMTczIiBpZD0icGF0aDEiLz4KPC9zdmc6c3ZnPgo=</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>Brand</finalclass>
|
||||
<friendlyname>Toshiba</friendlyname>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="1">
|
||||
<name>Acer</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="2">
|
||||
<name>Apple</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="3">
|
||||
<name>Asus</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="4">
|
||||
<name>Cisco</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="5">
|
||||
<name>Dell</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="6">
|
||||
<name>HP Inc</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="7">
|
||||
<name>HPE</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="8">
|
||||
<name>IBM</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="9">
|
||||
<name>Lenovo</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="10">
|
||||
<name>Razer</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="11">
|
||||
<name>Samsung</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="12">
|
||||
<name>Sony</name>
|
||||
</Brand>
|
||||
<Brand alias="Brand" id="13">
|
||||
<name>Toshiba</name>
|
||||
</Brand>
|
||||
</Set>
|
||||
|
||||
|
||||
@@ -1,116 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<OSFamily alias="OSFamily" id="1">
|
||||
<name>Arch</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-arch-linux.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCwwLDI1NiwyNTYiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIGZpbGwtcnVsZT0ibm9uemVybyI+PGcgZmlsbD0iIzAwODhjYyIgZmlsbC1ydWxlPSJub256ZXJvIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWxpbmVjYXA9ImJ1dHQiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLWRhc2hhcnJheT0iIiBzdHJva2UtZGFzaG9mZnNldD0iMCIgZm9udC1mYW1pbHk9Im5vbmUiIGZvbnQtd2VpZ2h0PSJub25lIiBmb250LXNpemU9Im5vbmUiIHRleHQtYW5jaG9yPSJub25lIiBzdHlsZT0ibWl4LWJsZW5kLW1vZGU6IG5vcm1hbCI+PGcgdHJhbnNmb3JtPSJzY2FsZSg1LjMzMzMzLDUuMzMzMzMpIj48cGF0aCBkPSJNMjguNDY1LDM4LjYxMWMwLjQxOSwtMS4xMDUgMC42NjQsLTIuMzY1IDAuNjY0LC0zLjcxNGMwLC00LjEzMyAtMi4yMTEsLTcuNDk0IC00LjkyOSwtNy40OTRjLTIuNzQxLDAgLTQuOTUxLDMuMzYxIC00Ljk1MSw3LjQ5NGMwLDEuMzI2IDAuMjIxLDIuNTg2IDAuNjQxLDMuNjY5Yy05LjA0MSwwLjk1MSAtMTUuNDA3LDQuNzMxIC0xNy45OTMsNi40MzJjNC4zNTUsLTYuMjc4IDguOTA5LC0xMy42MzggMTMuMjYyLC0yMi4xMDVjMS4wODMsLTIuMTAxIDIuMTAxLC00LjE3OCAzLjA1LC02LjIxMWMwLjM3NSwwLjI0MyAwLjc1MSwwLjUwOSAxLjE3MSwwLjc3NWMxLjk0NSwxLjIxNSAzLjc1OSwxLjg3OSA1LjA4NCwyLjIzM2MtMC45NzMsLTAuNzMgLTIuMDMzLC0xLjYxMyAtMy4xMTYsLTIuNjk3Yy0wLjgxNywtMC44MTcgLTEuNTQ3LC0xLjYzNyAtMi4xNjcsLTIuNDMzYzEuODM1LC00LjAyMiAzLjQyNywtNy44OTEgNC44MTksLTExLjU2YzIuMzIsNi4xNDQgNS4yMTcsMTIuODQyIDguODQxLDE5Ljg5M2MyLjM0Myw0LjUzMSA0LjczMSw4Ljc1NCA3LjExNywxMi42NDRjLTAuNjg1LC0wLjM3NSAtMS40MzcsLTAuNzMgLTIuMjMzLC0xLjAzOWMtMS4zNzEsLTAuNTMgLTIuNjUyLC0wLjg2MiAtMy43NTksLTEuMDZjMS41MDMsMC43NTEgMy4yNSwxLjc0NyA1LjA4NCwzLjA3M2MxLjE5NCwwLjg4NSAyLjI1NCwxLjc2OSAzLjE2MSwyLjYzMWMwLjAyMSwwLjAyMSAwLjAyMSwwLjAyMSAwLjA0NSwwLjA0NWMxLjI2LDIuMDU2IDIuNTY1LDMuOTU3IDMuODQ2LDUuODEzYy0yLjU0MSwtMS42ODEgLTguNzk2LC01LjM5NSAtMTcuNjM3LC02LjM4OXoiLz48L2c+PC9nPjwvc3ZnPgo=</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Arch</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="2">
|
||||
<name>Debian</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-debian.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiNFOTFFNjMiIGQ9Ik0yNi43NjMsMjQuNTQ4Yy0wLjYxNCwwLjAxLDAuMTE3LDAuMzE3LDAuOTE4LDAuNDRjMC4yMi0wLjE3MiwwLjQxOS0wLj
|
||||
M0OCwwLjYtMC41MTVDMjcuNzgxLDI0LjU5MiwyNy4yNzQsMjQuNTk0LDI2Ljc2MywyNC41NDggTTMwLjA1NCwyMy43MjdjMC4zNjQtMC41LDAuNjMxLTEuMDU1LDAuNzIzLTEuNjI0Yy0wLjA4MiwwLjQwNS0wLjMwMywwLjc1NS0wLjUxLDEuMTI4Yy0xLjE0NiwwLjcyMS0wLjEwOC0wLjQzLDAtMC44NjVDMjkuMDM1LDIzLjkxMywzMC4wOTgsMjMuMjkzLDMwLjA1NCwyMy43MjcgTTMxLjI2OSwyMC41NjhjMC4wNzMtMS4xMDUtMC4yMTktMC43NTYtMC4zMTctMC4zMzZD
|
||||
MzEuMDY4LDIwLjI5NCwzMS4xNTYsMjEuMDEzLDMxLjI2OSwyMC41NjggTTI0LjQzOSw1LjQ3OGMwLjMyNywwLjA1OCwwLjcwNiwwLjEwNCwwLjY1MywwLjE4M0MyNS40NDksNS41ODIsMjUuNTMxLDUuNTEsMjQuNDM5LDUuNDc4IE0yNS4wOTMsNS42NmwtMC4yMzIsMC4wNDdsMC4yMTUtMC4wMTdMMjUuMDkzLDUuNjYgTTM1LjI5NCwyMC45ODZjMC4wMzgsMC45OTEtMC4yOSwxLjQ3Mi0wLjU4NSwyLjMyMmwtMC41MjksMC4yNjZjLTAuNDM1LDAuODQxLDAuMDQxLDAuNT
|
||||
M1LTAuMjY4LDEuMjAyYy0wLjY3OSwwLjYwMy0yLjA1NSwxLjg4My0yLjQ5NiwyLjAwNGMtMC4zMjEtMC4wMDksMC4yMTgtMC4zODIsMC4yODktMC41MjZjLTAuOTA2LDAuNjItMC43MjgsMC45MzQtMi4xMTMsMS4zMTNsLTAuMDQxLTAuMDljLTMuNDE5LDEuNjA3LTguMTY2LTEuNTc2LTguMTAzLTUuOTI4Yy0wLjAzNywwLjI3NS0wLjEwNCwwLjIwOS0wLjE4LDAuMzJjLTAuMTc1LTIuMjM3LDEuMDMzLTQuNDg2LDMuMDczLTUuNDAzYzEuOTk1LTAuOTg3LDQuMzM1LTAu
|
||||
NTgsNS43NjMsMC43NWMtMC43ODUtMS4wMjgtMi4zNDgtMi4xMTktNC4xOTktMi4wMTdjLTEuODE0LDAuMDI5LTMuNTEsMS4xODItNC4wNzcsMi40MzRjLTAuOTI5LDAuNTg1LTEuMDM4LDIuMjU2LTEuNDQxLDIuNTYzYy0wLjU0NSw0LjAwMywxLjAyNCw1LjczMywzLjY4LDcuNzY4YzAuNDE3LDAuMjgyLDAuMTE4LDAuMzI2LDAuMTc1LDAuNTQxYy0wLjg4My0wLjQxMi0xLjY5LTEuMDM3LTIuMzU0LTEuODAxYzAuMzUzLDAuNTE3LDAuNzMzLDEuMDE3LDEuMjIzLDEuND
|
||||
FjLTAuODMxLTAuMjc5LTEuOTQyLTIuMDEzLTIuMjY3LTIuMDg0YzEuNDM1LDIuNTY3LDUuODE4LDQuNTAyLDguMTEzLDMuNTQxYy0xLjA2MiwwLjA0LTIuNDEyLDAuMDIxLTMuNjA0LTAuNDJjLTAuNTAxLTAuMjU3LTEuMTgzLTAuNzkxLTEuMDYyLTAuODkzYzMuMTMzLDEuMTcxLDYuMzY5LDAuODg3LDkuMDc4LTEuMjg2YzAuNjg5LTAuNTM3LDEuNDQzLTEuNDQ5LDEuNjYyLTEuNDY0Yy0wLjMyNywwLjQ5MywwLjA1NywwLjIzOS0wLjE5NywwLjY3NGMwLjY4OC0xLjEw
|
||||
OS0wLjI5OS0wLjQ0OSwwLjcxMS0xLjkxM2wwLjM3MywwLjUxMmMtMC4xMzktMC45MTcsMS4xNDMtMi4wMzMsMS4wMTItMy40ODljMC4yOTEtMC40NDUsMC4zMjYsMC40NzgsMC4wMTUsMS41MDJjMC40MzQtMS4xMzYsMC4xMTMtMS4zMTcsMC4yMjQtMi4yNTRjMC4xMjEsMC4zMTUsMC4yNzksMC42NDgsMC4zNTksMC45ODFjLTAuMjgxLTEuMDk3LDAuMjg5LTEuODQ4LDAuNDMzLTIuNDg1Yy0wLjE0Mi0wLjA2My0wLjQzNSwwLjQ4NS0wLjUwMy0wLjgxMmMwLjAxLTAuNT
|
||||
YyLDAuMTU2LTAuMjk1LDAuMjE0LTAuNDM1Yy0wLjExMS0wLjA2NC0wLjQtMC40OTYtMC41NzctMS4zMjNjMC4xMjctMC4xOTMsMC4zNDIsMC41MDYsMC41MTYsMC41MzNjLTAuMTEyLTAuNjU1LTAuMzA0LTEuMTU5LTAuMzEzLTEuNjY1Yy0wLjUxLTEuMDYxLTAuMTgxLDAuMTQzLTAuNTkyLTAuNDU4Yy0wLjU0My0xLjY4NywwLjQ0OS0wLjM5LDAuNTE0LTEuMTU2YzAuODIsMS4xODgsMS4yODksMy4wMjksMS41MDQsMy43OTJjLTAuMTY0LTAuOTMtMC40MjgtMS44MzIt
|
||||
MC43NTItMi43MDRjMC4yNDksMC4xMDgtMC40MDEtMS45MTEsMC4zMjQtMC41NzVjLTAuNzcyLTIuODQ4LTMuMzE0LTUuNTExLTUuNjUtNi43NmMwLjI4NiwwLjI2MiwwLjY0NiwwLjU5MSwwLjUxNywwLjY0MmMtMS4xNjMtMC42OS0wLjk1OS0wLjc0NS0xLjEyNC0xLjA0MWMtMC45NDYtMC4zODMtMS4wMSwwLjAzNC0xLjYzNiwwYy0xLjc4Ni0wLjk0My0yLjEyOS0wLjg0NS0zLjc3Mi0xLjQzN2wwLjA3OCwwLjM0OWMtMS4xODQtMC4zOTQtMS4zNzksMC4xNDYtMi42NT
|
||||
csMC4wMDJjLTAuMDc4LTAuMDYyLDAuNDEtMC4yMTksMC44MTEtMC4yNzhjLTEuMTQzLDAuMTUtMS4wOS0wLjIyOC0yLjIwOCwwLjA0MmMwLjI3Ny0wLjE5NywwLjU2Ni0wLjMyMiwwLjg2MS0wLjQ4NmMtMC45MzIsMC4wNTktMi4yMjYsMC41NDItMS44MjUsMC4xMDNjLTEuNTIxLDAuNjc2LTQuMjIsMS42My01LjczNSwzLjA1MWwtMC4wNDctMC4zMjJjLTAuNjk0LDAuODM1LTMuMDI4LDIuNDkyLTMuMjE1LDMuNTdsLTAuMTg1LDAuMDQzYy0wLjM2MSwwLjYxMy0wLjU5
|
||||
NSwxLjMwNS0wLjg4MSwxLjkzNWMtMC40NzQsMC44MDYtMC42OTIsMC4zMTEtMC42MjYsMC40MzZjLTAuOTI5LDEuODgzLTEuMzksMy40NjctMS43OSw0Ljc2OGMwLjI4NCwwLjQyNCwwLjAwNywyLjU1OCwwLjExMyw0LjI2NGMtMC40NjcsOC40MjksNS45MTYsMTYuNjA5LDEyLjg5MSwxOC41YzEuMDIzLDAuMzY1LDIuNTQyLDAuMzU0LDMuODM2LDAuMzljLTEuNTI1LTAuNDM4LTEuNzIyLTAuMjMyLTMuMjA5LTAuNzQ5Yy0xLjA3NC0wLjUwNi0xLjMwOC0xLjA4Mi0yLj
|
||||
A2Ni0xLjc0bDAuMywwLjUzYy0xLjQ5LTAuNTI2LTAuODY3LTAuNjUyLTIuMDc4LTEuMDM0bDAuMzIxLTAuNDI0Yy0wLjQ4Mi0wLjAzMi0xLjI3OS0wLjgxMS0xLjQ5Ny0xLjI0MWwtMC41MjgsMC4wMjFjLTAuNjM0LTAuNzgzLTAuOTcyLTEuMzQ4LTAuOTQ4LTEuNzg1bC0wLjE3LDAuMzA1Yy0wLjE5NC0wLjMzMi0yLjMzNS0yLjkzNy0xLjIyNC0yLjMzYy0wLjIwNy0wLjE4OC0wLjQ4MS0wLjMwNy0wLjc3OS0wLjg1bDAuMjI3LTAuMjU4Yy0wLjUzNS0wLjY4Ni0wLjk4
|
||||
My0xLjU2OC0wLjk0OS0xLjg2YzAuMjg0LDAuMzg0LDAuNDgyLDAuNDU0LDAuNjc5LDAuNTIyYy0xLjM1MS0zLjM0OS0xLjQyNi0wLjE4Ny0yLjQ0OC0zLjQwOWwwLjIxNi0wLjAxOWMtMC4xNjYtMC4yNDYtMC4yNjUtMC41MjEtMC4zOTktMC43ODVsMC4wOTQtMC45MzhjLTAuOTcyLTEuMTI1LTAuMjcyLTQuNzgxLTAuMTMyLTYuNzgzYzAuMDk3LTAuODE2LDAuODExLTEuNjg0LDEuMzU0LTMuMDQ1bC0wLjMzMi0wLjA1NWMwLjYzMi0xLjEwNCwzLjYxMi00LjQzMyw0Lj
|
||||
k5LTQuMjZjMC42NjktMC44NDEtMC4xMzItMC4wMDItMC4yNjMtMC4yMTVjMS40NjktMS41MiwxLjkzLTEuMDczLDIuOTItMS4zNDljMS4wNjgtMC42MzMtMC45MTcsMC4yNTEtMC40MS0wLjIzOWMxLjg0OC0wLjQ3MywxLjMxLTEuMDczLDMuNzE4LTEuMzExYzAuMjU0LDAuMTQ1LTAuNTksMC4yMjMtMC44LDAuNDFjMS41MzgtMC43NTMsNC44Ny0wLjU4NCw3LjAzNCwwLjQxN2MyLjUxMSwxLjE3Myw1LjMzLDQuNjQyLDUuNDQzLDcuOTA0bDAuMTI2LDAuMDM1Yy0wLjA2
|
||||
MywxLjI5OCwwLjE5OCwyLjc5OC0wLjI1Nyw0LjE3NUwzNS4yOTQsMjAuOTg2IE0yMC4wNzIsMjUuMzg5bC0wLjA4NiwwLjQzMWMwLjQwMywwLjU0NywwLjcyNCwxLjE0MiwxLjIzNywxLjU2N0MyMC44NTMsMjYuNjY0LDIwLjU3NywyNi4zNjQsMjAuMDcyLDI1LjM4OSBNMjEuMDIzLDI1LjM1M2MtMC4yMTMtMC4yMzctMC4zNC0wLjUxOC0wLjQ4LTAuODAyYzAuMTM1LDAuNDk1LDAuNDExLDAuOTIyLDAuNjY5LDEuMzU3TDIxLjAyMywyNS4zNTMgTTM3Ljg3NywyMS42OD
|
||||
hsLTAuMDg4LDAuMjI2Yy0wLjE2NiwxLjE3NC0wLjUyMywyLjMzMi0xLjA2OCwzLjQxMkMzNy4zMjQsMjQuMTg5LDM3LjcxNCwyMi45NDcsMzcuODc3LDIxLjY4OCBNMjQuNTYsNS4xODVDMjQuOTc0LDUuMDMxLDI1LjU3OSw1LjEwMSwyNi4wMTksNWMtMC41NzMsMC4wNDgtMS4xNDQsMC4wNzktMS43MDYsMC4xNTFMMjQuNTYsNS4xODUgTTEwLjAwNywxMi45MjNjMC4wOTUsMC44ODItMC42NjcsMS4yMjksMC4xNjcsMC42NDRDMTAuNjIzLDEyLjU2MiwxMCwxMy4yODYsMTAuMDA3LDEyLjkyMyBNOS4wMjgsMTcuMDE2YzAuMTkxLTAuNTkyLDAuMjI2LTAuOTQzLDAuMy0xLjI4NUM4Ljc5NywxNi40MSw5LjA4NCwxNi41NTMsOS4wMjgsMTcuMDE2Ii8+PC9zdmc+Cg==</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Debian</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="3">
|
||||
<name>Oracle Linux</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icon-oracle-linux.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIgeG1sbnM9Imh0dH
|
||||
A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjMxIDIzMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pbllNaWQiIHZlcnNpb249IjEuMSIgaWQ9InN2ZzQiIHhtbDpzcGFjZT0icHJlc2VydmUiIHdpZHRoPSIyMzEiIGhlaWdodD0iMjMxIiBzb2RpcG9kaTpkb2NuYW1lPSJpY29uLW9yYWNsZS1saW51eC5zdmciIGlua3NjYXBlOnZlcnNpb249IjEuNC4zICgwZDE1Zjc1MDQyLCAy
|
||||
MDI1LTEyLTI1KSI+PHNvZGlwb2RpOm5hbWVkdmlldyBpZD0ibmFtZWR2aWV3MSIgcGFnZWNvbG9yPSIjZmZmZmZmIiBib3JkZXJjb2xvcj0iIzAwMDAwMCIgYm9yZGVyb3BhY2l0eT0iMC4yNSIgaW5rc2NhcGU6c2hvd3BhZ2VzaGFkb3c9IjIiIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiIGlua3NjYXBlOnBhZ2VjaGVja2VyYm9hcmQ9IjAiIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIgc2hvd2d1aWRlcz0idHJ1ZSIgaW5rc2NhcGU6em9vbT0iNy41MzMyOD
|
||||
kxIiBpbmtzY2FwZTpjeD0iMTA3LjA1ODE1IiBpbmtzY2FwZTpjeT0iOTAuNzk2OTkzIiBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjI1NjAiIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEzNjAiIGlua3NjYXBlOndpbmRvdy14PSIwIiBpbmtzY2FwZTp3aW5kb3cteT0iMCIgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMSIgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnNCI+PHNvZGlwb2RpOmd1aWRlIHBvc2l0aW9uPSI0MS43NjM1ODksMTE1LjQ2OCIgb3JpZW50
|
||||
YXRpb249IjAsLTEiIGlkPSJndWlkZTEiIGlua3NjYXBlOmxvY2tlZD0iZmFsc2UiLz48L3NvZGlwb2RpOm5hbWVkdmlldz48ZGVmcyBpZD0iZGVmczgiPjxyZWN0IHg9Ii0xMzguMjQ2NDEiIHk9IjgxLjU2NzIzOCIgd2lkdGg9IjM4Mi4zNjc0IiBoZWlnaHQ9IjI0MC4yMTE1NiIgaWQ9InJlY3Q0OTUiLz48cmVjdCB4PSItMTcuNjEyNjIzIiB5PSIxMDQuMzU4OTgiIHdpZHRoPSIxNzEuMDUyMzgiIGhlaWdodD0iMTk3LjMxNDQ0IiBpZD0icmVjdDI5MSIvPjwvZGVmcz
|
||||
48ZyBpZD0iZzE0MDciIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAuNjEzMjE1NDIsNzYuODM1NTMzKSI+PHBhdGggZD0ibSA5OS41OSwxOS41MiBoIDE1LjI0IEwgMTA2Ljc4LDYuNTIgOTEuOTgsMzAgaCAtNi43MyBsIDE4LC0yOC4xNyBhIDQuMjksNC4yOSAwIDAgMSA3LC0wLjA1IEwgMTI4LjMsMzAgaCAtNi43MyBsIC0zLjE3LC01LjI1IGggLTE1LjQyIGwgLTMuMzYsLTUuMjMgbSA2OS45Myw1LjIzIFYgMC4yOCBoIC01LjcyIHYgMjYuODggYSAyLjc2LDIuNzYgMCAw
|
||||
IDAgMC44NSwyIDIuODksMi44OSAwIDAgMCAyLjA4LDAuODcgaCAyNiBsIDMuMzksLTUuMjUgaCAtMjYuNjMgbSAtOTQuNTQsLTQuNCBhIDEwLjA1LDEwLjA1IDAgMCAwIDAsLTIwLjEgaCAtMjUgViAzMCBoIDUuNzEgViA1LjU0IGggMTguOTQgYSA0LjgxLDQuODEgMCAwIDEgMCw5LjYyIEggNTguNTIgTCA3NS41OCwzMCBoIDguMjkgTCA3Mi40MSwyMC4zOCBoIDIuNTcgTSAxNC44NiwzMCBoIDE3LjI3IGEgMTQuODYsMTQuODYgMCAwIDAgMCwtMjkuNzEgSCAxNC44Ni
|
||||
BhIDE0Ljg2LDE0Ljg2IDAgMSAwIDAsMjkuNzEgbSAxNi44OCwtNS4yMyBoIC0xNi41IGEgOS42Miw5LjYyIDAgMCAxIDAsLTE5LjIzIGggMTYuNSBhIDkuNjIsOS42MiAwIDEgMSAwLDE5LjIzIE0gMTQwLjIzLDMwIGggMTcuNjMgbCAzLjM0LC01LjIzIGggLTIwLjU4IGEgOS42Miw5LjYyIDAgMSAxIDAsLTE5LjIzIGggMTYuNzUgbCAzLjM4LC01LjI1IGggLTIwLjUyIGEgMTQuODYsMTQuODYgMCAxIDAgMCwyOS43MSBtIDY5Ljg3LC01LjIzIGEgOS42Miw5LjYyIDAg
|
||||
MCAxIC05LjI2LC03IGggMjQuNDIgbCAzLjM2LC01LjI0IGggLTI3Ljc4IGEgOS42MSw5LjYxIDAgMCAxIDkuMjYsLTcgaCAxNi43NiBsIDMuMzUsLTUuMjUgaCAtMjAuNSBhIDE0Ljg2LDE0Ljg2IDAgMCAwIDAsMjkuNzEgaCAxNy42MyBsIDMuMzUsLTUuMjMgaCAtMjAuNiIgc3R5bGU9ImZpbGw6I2M3NDYzNCIgaWQ9InBhdGgyIi8+PHBhdGggaWQ9InJlY3Q3NDkiIHN0eWxlPSJmaWxsOiNjNzQ2MzQ7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlLXdpZHRoOjUuMjUxOTtzdH
|
||||
Jva2UtbGluZWNhcDpzcXVhcmU7cGFpbnQtb3JkZXI6c3Ryb2tlIGZpbGwgbWFya2VycyIgZD0ibSAyNS4zOTE1MTcsNDcuOTMwODcxIGggNC45ODA4NjMgdiAzLjgzMDAyNSBoIC00Ljk4MDg2MyB6IG0gNjEuNTAwOCwxOC41NTcwNjEgLTcuMjQsLTEwLjI0MDAwMiBoIDQuOTYgbCA0LjY0LDcuMDgwMDAyIGggMC4yNCBsIDQuNzYsLTcuMDgwMDAyIGggNC43MiBsIC03LjI4LDEwLjE2MDAwMiA3LjY0LDEwLjg4IGggLTQuOTYgbCAtNS4wOCwtNy43MiBoIC0wLjI0IGwg
|
||||
LTUuMTIsNy43MiBoIC00LjcyIHogbSAtMjEuNTk5OTk4LDExLjI4IHEgLTYuNjgsMCAtNi42OCwtNy4yNCBWIDU2LjI0NzkzIGggNC4xMiB2IDEzLjc2MDAwMiBxIDAsMi4zNiAxLjA0LDMuMzIgMS4wOCwwLjkyIDMuMTIsMC45MiAxLjQsMCAyLjYsLTAuNjggMS4yLC0wLjcyIDEuODgsLTIgMC43MiwtMS4yOCAwLjcyLC0yLjk2IFYgNTYuMjQ3OTMgaCA0LjEyIHYgMjEuMDQwMDAyIGggLTMuMzIgbCAtMC40LC0yLjggaCAtMC4yOCBxIC0xLjE2LDEuNiAtMi45MiwyLj
|
||||
Q0IC0xLjc2LDAuODQgLTQsMC44NCB6IE0gMzUuODEyMzIsNTYuMjQ3OTMgaCAzLjMyMDAwMSBsIDAuNCwyLjgwMDAwMiBoIDAuMjggcSAxLjEyLC0xLjYwMDAwMiAyLjg4LC0yLjQ0MDAwMiAxLjgsLTAuODQgNC4wNCwtMC44NCA2LjY4LDAgNi42OCw3LjI0MDAwMiB2IDE0LjI4IGggLTQuMTIgdiAtMTMuNzYgcSAwLC0yLjM2IC0xLjA4LC0zLjI4IC0xLjA0LC0wLjk2IC0zLjA4LC0wLjk2IC0xLjQsMCAtMi42LDAuNzIgLTEuMiwwLjY4IC0xLjkyLDEuOTYgLTAuNjgsMS4yOCAtMC42OCwyLjk2IHYgMTIuMzYgSCAzNS44MTIzMiBaIE0gMy42MTIzOSw0Ny45MzA4NzEgaCA0LjQ0IHYgMjUuNTE3MDYxIGggMTQuMjggdiAzLjg0IGggLTE4LjcyIHogTSAyNi4yNTY3NjgsNTkuNDYzOTUgViA3Ny4yODc5MzIgSCAzMC4zNzIzOCBWIDU2LjI3NTQ2NCBoIC02LjM4NzYxMiB2IDEuODI1NjgxIHoiLz48L2c+PC9zdmc+Cg==</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Oracle Linux</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="4">
|
||||
<name>Red Hat</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-red-hat.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiMzNzQ3NEYiIGQ9Ik0yNy44MTMsMzQuODg4Yy0wLjMxOSwwLjM1My0wLjc1NSwwLjM3OC0xLjI4NCwwLjA3NWMtMC40OTctMC4yODItMS4yN
|
||||
zYtMC4yODItMS41MS0wLjAwMSBjLTAuMjY5LDAuMzIzLTAuMDc1LDAuNjgxLDAuMzY3LDAuNjgxYzAuMjA3LDAsMC42MDQsMC4xMzcsMC44NzQsMC4zMDNjMC4yNzEsMC4xNjcsMC42NTMsMC4zMDMsMC44NDcsMC4zMDMgYzAuNDc1LDAuMDAyLDEuMjM0LTAuNzgyLDEuMjM0LTEuMjczQzI4LjM0MiwzNC41MDYsMjguMTgyLDM0LjQ4LDI3LjgxMywzNC44ODh6IE00MywyNS45NzFjMCwzLjIyMS0wLjUzNSw1LjYwMi0xLjg4Nyw4LjM4NiBjLTAuOTgsMi4wMjItMC44NDY
|
||||
sMS45Mi0yLjI3MiwxLjc0Yy0xLjI5My0wLjE2My0yLjk4OS0wLjAyNi00LjA3NSwwLjMzMWMtMC40ODQsMC4xNi0wLjYxNywwLjI4My0wLjY4MSwwLjY0MyBjLTAuMDY1LDAuMzc5LTAuMjA2LDAuNDkzLTAuOTc5LDAuNzkzYy0wLjY1MiwwLjI1My0wLjk3NywxLjAzMy0xLjY4NiwxLjcyOGMtMC41NDMsMC41My0xLjEyMSwxLjAzLTEuMjg4LDEuMTEzIEMyOS43NDIsNDAuODk0LDI5LDQxLjA2OSwyOSw0MC45NzRjMC0wLjA3MSwwLjk4Ni0yLjI1MSwyLjM1Ny00LjIxO
|
||||
GMwLjQ5LTAuNzA0LDAuNjYxLTEuMTA0LDAuNzA5LTEuNjYxIGMwLjAzNi0wLjQwNSwwLjIxMS0xLjIyOSwwLjM4OS0xLjgzYzAuMTc5LTAuNjAzLDAuMjg5LTEuMTMsMC4yNDYtMS4xNzNzLTAuMzcsMC4wMjUtMC43MjYsMC4xNDggYy0wLjc3OSwwLjI3NS0xLjI5MywwLjI4Ni0yLjE3NywwLjA1MWMtMC41NjMtMC4xNTEtMC43NzEtMC4xMzktMS4zNDQsMC4wOGMtMC42MzksMC4yNDYtMC43MTksMC4yNDYtMS4zMTMsMC4wMDYgYy0wLjU5NS0wLjIzNy0wLjcyNS0wLjI
|
||||
zNy0yLjE0NiwwLjAxNGMtMi42NTUsMC40NjYtMy41MTMsMC4yMDYtNS4yODQtMS42MDljLTEuMDk4LTEuMTI1LTEuNTA4LTEuMzcyLTEuNzE3LTEuMDMgYy0wLjA1MSwwLjA4My0wLjI1MywwLjE1MS0wLjQ0NiwwLjE1MWMtMC4yNTgsMC0wLjQ4NC0wLjIwMy0wLjg0MS0wLjc2Yy0wLjI2Ny0wLjQxNS0wLjY3Ny0wLjg5My0wLjkwOS0xLjA1OCBjLTEuMjc0LTAuOTA2LTIuNzE1LTAuMjUtMi43MTUsMS4yNGMwLDAuNjE0LDEuMjI4LDIuNDY1LDEuODQ3LDIuNzg2YzAuO
|
||||
DE4LDAuNDIzLDAuMzU3LDEuMDU3LTAuNjcxLDAuOTE5IGMtMC41MzItMC4wNzItMC43NjctMC4yMzEtMS40ODItMS4wMDNjLTAuNzY0LTAuODI2LTAuOTA3LTAuOTE2LTEuNDQzLTAuOTE0Yy0wLjMyOCwwLjAwMi0wLjg3NSwwLjEzMS0xLjIxNSwwLjI4NCBjLTAuODc3LDAuMzk5LTIuMDIyLDAuNjItMy4yMjEsMC42Mkg1Ljg2NUw1LjYzLDMxLjE0NkM1LjA5MywyOS4xNzEsNSwyOC40LDUsMjUuOTcxYzAtMS44NTcsMC4wNzEtMi44MjEsMC4yNzktMy43NzkgYzEuMTI
|
||||
0LTUuMTcyLDMuOTg0LTkuMzUzLDguMzIzLTEyLjE2OWMyLjEyOC0xLjM4Miw0LjA4NC0yLjE5Miw2LjU3OS0yLjcyOWMxLjc4My0wLjM4Myw1Ljc3Ni0wLjM5NCw3LjUxLTAuMDIxIGM1LjkwMiwxLjI3MywxMC43OTQsNC45OTYsMTMuMzM5LDEwLjE2QzQyLjQ1NywyMC4zMjUsNDMsMjIuNjc3LDQzLDI1Ljk3MXoiLz48cGF0aCBmaWxsPSIjRkYzRDAwIiBkPSJNMzguMDgyLDIyLjMxMmMtMC43MTEtMC41MzktMi41MjktMS4zMjctMy4wNjMtMS4zMjdjLTAuMTQ2LDAtM
|
||||
C40LDAuMjczLTAuNTk4LDAuNjQzIGMtMC4yOTcsMC41NTktMS4xMzEsMS4zMjItMS40NDQsMS4zMjJjLTAuMDU4LDAsMC4xMDEtMC4zODQsMC4zNS0wLjg1MmMwLjExLTAuMjA1LDAuMjA0LTAuNDIzLDAuMjgtMC42MzEgYzAuMTA5LTAuMzAzLDAuMTc4LTAuNTg0LDAuMTc4LTAuNzc2YzAtMC45NTgtMC42NzYtMy4xMTctMS40OTctNS4wNDljLTAuNDM1LTEuMDI0LTAuOTExLTEuOTg1LTEuMzUxLTIuNjY5IGMtMC4yMTUtMC4zMzUtMC4zOTMtMC41ODktMC41NTktMC4
|
||||
3OTJjLTAuMjktMC4zNTEtMC41NTktMC41NTQtMC45NzUtMC43NzljLTAuMjgzLTAuMTUyLTAuNTgtMC4yNy0wLjg5MS0wLjM1NiBjLTAuMDA2LDAtMC4wMTItMC4wMDMtMC4wMTYtMC4wMDNjLTAuMDczLTAuMDIxLTAuMTQ1LTAuMDM5LTAuMjE5LTAuMDU1Yy0wLjAxMi0wLjAwMy0wLjAyMy0wLjAwNS0wLjAzNS0wLjAwOSBjLTAuMDctMC4wMTQtMC4xMzktMC4wMjYtMC4yMTItMC4wMzljLTAuMDE1LTAuMDAzLTAuMDI4LTAuMDAzLTAuMDQ0LTAuMDA2Yy0wLjA3Mi0wL
|
||||
jAxMi0wLjE0Mi0wLjAyMS0wLjIxNS0wLjAzIGMtMC4wMTItMC4wMDEtMC4wMjUtMC4wMDEtMC4wMzctMC4wMDNjLTAuMTYtMC4wMTYtMC4zMjUtMC4wMjctMC40OTUtMC4wMjdjLTAuMDE3LDAtMC4wMzYsMC0wLjA1MywwIGMtMC4xMiwwLTAuMjM5LDAuMDA2LTAuMzYyLDAuMDE0Yy0wLjAzOSwwLjAwMS0wLjA3NiwwLjAwNC0wLjExNCwwLjAwNWMtMC4xMzIsMC4wMTEtMC4yNjcsMC4wMjQtMC40MDIsMC4wNDIgYy0wLjA0OCwwLjAwNi0wLjA5NSwwLjAxMy0wLjE0NCw
|
||||
wLjAxOWMtMC4xMzQsMC4wMTktMC4yNywwLjA0MS0wLjQwOCwwLjA2OGMtMC4wNTUsMC4wMS0wLjExMiwwLjAyNC0wLjE3LDAuMDM2IGMtMC4xMDYsMC4wMjItMC4yMTgsMC4wNDgtMC4zMjksMC4wNzVjLTAuMDQzLDAuMDEtMC4wODMsMC4wMTctMC4xMjYsMC4wMjdjLTEuMDYzLDAuMjcyLTEuNTU4LDAuMzE5LTIuNTY2LDAuMjQ1IGMtNC4xMTctMC4yOTctMy45NTEtMC4zLTQuNjMsMC4wNDdjLTAuMzY4LDAuMTg4LTAuNjI4LDAuMzktMC44NDgsMC43M2MtMC4yOTgsM
|
||||
C40NjItMC41MiwxLjE3Mi0wLjgyOSwyLjQ1MSBjLTAuNTgyLDIuNDAzLTAuNTk1LDMuMTQ2LTAuMDY4LDMuNzczYzAuNTM2LDAuNjM5LDIuMjY1LDEuNDMxLDMuOTksMS44MjdjMi4wNjMsMC40NzQsMy40NjksMC44OTIsMy44NTksMS4xNDkgYzAuMDk3LDAuMDYzLDAuMjA1LDAuMTc4LDAuMzAxLDAuMzEzYzAuMDkxLDAuMTI1LDAuMTcsMC4yNjYsMC4yMTgsMC4zOTRjMC40MzQsMS4xNTcsMC42NjcsMS42MjcsMC45MzEsMS44NjQgYzAuMDY1LDAuMDYsMC4xMjUsMC4
|
||||
xMzEsMC4xNzQsMC4xOTdjMC4wNjYsMC4wOTIsMC4xMDcsMC4xODMsMC4xMDcsMC4yMzljMCwxLjA5Ny03LjgwMy0xLjMzMy05LjgxNC0zLjA1NCBjLTAuNTM4LTAuNDYyLTAuODM3LTAuODQ2LTAuOTY1LTEuMjg4Yy0wLjA3Ny0wLjI3NC0wLjA4Ny0wLjU3MS0wLjA0Ni0wLjkyMmwwLjAyNC0wLjIxMWwwLjA2My0wLjUzNGgtMC4wMDF2LTAuMDAybC0xLjk5OCwwLjA2NiBjLTEuNjg4LDAuMDU2LTIuMTA5LDAuMTE4LTIuNzE1LDAuNDEyYy0yLjA4NiwxLjAwNS0xLjk4N
|
||||
SwyLjY5LDAuMjg4LDQuODVjMS42MzQsMS41NTQsNC4xMTMsMy4wODUsNi44NTMsNC4zMzQgYzIuODI4LDEuMjkzLDUuOTM2LDIuMjgzLDguNjgxLDIuNjg2YzEuMTg4LDAuMTc1LDIuNzEyLDAuMjM3LDQuMTEzLDAuMTkzYzAuNzkxLTAuMDI0LDEuNTQzLTAuMDg0LDIuMTctMC4xOCBjMy4zNjUtMC41MTMsNS42OTUtMS44ODYsNi42NjgtMy45MzRjMC4xMDUtMC4yMjIsMC4xODktMC40MzgsMC4yNTgtMC42NTJDMzkuODE4LDI0LjY1NCwzOS4zNzcsMjMuMjk3LDM4LjA
|
||||
4MiwyMi4zMTJ6IE0yMi4xMjIsMTYuMDE1Yy0xLjQzOCwwLjE1OS0yLjE0MSwwLjM1NS0yLjQwMywwLjY3MWMtMC4xMDEsMC4xMjEtMC4yMDQsMC4xODgtMC4zMjcsMC4xOTdjLTAuMjQ5LDAuMDE3LTAuNTctMC4yMTUtMS4wODktMC43NDIgYy0wLjM2MS0wLjM3MS0wLjU2Ny0wLjYzNy0wLjY2Ny0wLjg2N2MtMC4wNS0wLjExNS0wLjA3My0wLjIyNi0wLjA3My0wLjMzMmMwLTAuMDYxLDAuMDA0LTAuMTIsMC4wMS0wLjE3OCBjMC4wMDEtMC4wMDgsMC4wMDMtMC4wMTYsM
|
||||
C4wMDMtMC4wMjNjMC4wMDctMC4wNDcsMC4wMTYtMC4wOTMsMC4wMjgtMC4xMzljMC4wMDEtMC4wMDksMC4wMDMtMC4wMTUsMC4wMDUtMC4wMjMgYzAuMDE0LTAuMDQ4LDAuMDI5LTAuMDk0LDAuMDQ5LTAuMTM3YzAuMDAzLTAuMDA3LDAuMDA1LTAuMDEzLDAuMDEtMC4wMTljMC4wMTctMC4wMzIsMC4wMzItMC4wNjMsMC4wNTEtMC4wOTMgYzAuMDA3LTAuMDEzLDAuMDE1LTAuMDI0LDAuMDIzLTAuMDM1YzAuMDE0LTAuMDI0LDAuMDMyLTAuMDQ2LDAuMDUtMC4wNjdjMC4
|
||||
wMDctMC4wMDksMC4wMTUtMC4wMTcsMC4wMjMtMC4wMjcgYzAuMDI1LTAuMDI0LDAuMDUxLTAuMDQ3LDAuMDc3LTAuMDY1YzAuMDEyLTAuMDA3LDAuMDIzLTAuMDE1LDAuMDM2LTAuMDJjMC4wMTktMC4wMTQsMC4wMzgtMC4wMjEsMC4wNTgtMC4wMyBjMC4wMTItMC4wMDYsMC4wMjUtMC4wMTEsMC4wMzctMC4wMTVjMC4wMjktMC4wMDgsMC4wNTctMC4wMTYsMC4wODgtMC4wMTljMC4wMDMsMCwwLjAwNi0wLjAwMSwwLjAxLTAuMDAxIGMwLjAzMi0wLjAwMywwLjA2NC0wL
|
||||
jAwMiwwLjA5NywwLjAwM2MwLjAwNywwLjAwMSwwLjAxNSwwLjAwMywwLjAyMywwLjAwNGMwLjAyNiwwLjAwNiwwLjA1MywwLjAxMiwwLjA3OSwwLjAyMSBjMC4wMDcsMC4wMDMsMC4wMTQsMC4wMDYsMC4wMjEsMC4wMDljMC4wMzEsMC4wMTQsMC4wNjIsMC4wMzEsMC4wOTEsMC4wNTFjMC4wMDIsMC4wMDIsMC4wMDQsMC4wMDMsMC4wMDcsMC4wMDYgYzAuMDM2LDAuMDIzLDAuMDcxLDAuMDUsMC4xMDQsMC4wODNjMC42NjgsMC42NTMsMC45LDAuNzE0LDIuMzk0LDAuNjE
|
||||
1YzAuNTQ2LTAuMDM3LDEuMDEyLTAuMDM4LDEuMzk0LTAuMDA3IGMwLjcwOSwwLjA2LDEuMTMxLDAuMjMsMS4yNCwwLjUxNWMwLjAzOCwwLjA5OSwwLjA1LDAuMTgsMC4wMjUsMC4yNUMyMy41MjIsMTUuODA5LDIzLjEyMiwxNS45MDQsMjIuMTIyLDE2LjAxNXogTTI5LjAwMSwxMy4zOCBjLTAuMDEsMC4wMDctMC4wMTksMC4wMTMtMC4wMzEsMC4wMTljMCwwLjAwMS0wLjAwMywwLjAwMy0wLjAwNiwwLjAwNGMtMC41MTEsMC4yNjktMS4zMjUsMC40MjktMi4xNzEsMC4zN
|
||||
TggYy0wLjM0NC0wLjAyNy0wLjUyNi0wLjA4Ny0wLjU0My0wLjE2NGMtMC4wMTItMC4wNTIsMC4wNTUtMC4xMTEsMC4xOTctMC4xNzFjMC4wNy0wLjAzLDAuMTUzLTAuMDYxLDAuMjU2LTAuMDg5IGMwLjU4NC0wLjE2OSwwLjkxLTAuNjA4LDAuNTk0LTAuODA1Yy0wLjMzNy0wLjIxMi0xLjQ5Mi0wLjM0NS0yLjAwNC0wLjIzMWMtMC4yMTcsMC4wNDktMC4zNDIsMC4wNTEtMC4zNzQsMC4wMTMgYy0wLjAwMS0wLjAwMS0wLjAwNC0wLjAwMy0wLjAwNS0wLjAwNmMtMC4wMDk
|
||||
tMC4wMTUtMC4wMDQtMC4wMzUsMC4wMTEtMC4wNjJjMC4wMTItMC4wMTYsMC4wMjYtMC4wMzEsMC4wNDctMC4wNDggYzAsMCwwLjAwMSwwLDAuMDAyLDBjMC4wMTktMC4wMTgsMC4wNDUtMC4wMzIsMC4wNzItMC4wNDZjMC4wMDItMC4wMDMsMC4wMDYtMC4wMDMsMC4wMS0wLjAwNmMwLjAyNy0wLjAxNCwwLjA1Ny0wLjAyNywwLjA5Mi0wLjA0MSBjMC4wMDUtMC4wMDIsMC4wMDgtMC4wMDMsMC4wMTEtMC4wMDVjMC4wMzctMC4wMTQsMC4wNzctMC4wMjgsMC4xMjEtMC4wN
|
||||
DJjMC4wMDEsMCwwLjAwMy0wLjAwMiwwLjAwNS0wLjAwMiBjMC4yNzYtMC4wOSwwLjY4Mi0wLjE2NCwxLjEtMC4yMTNjMC4wMDgtMC4wMDMsMC4wMTQtMC4wMDMsMC4wMjEtMC4wMDNjMC4wNjEtMC4wMDksMC4xMjMtMC4wMTQsMC4xODYtMC4wMiBjMC4wMDktMC4wMDIsMC4wMTktMC4wMDIsMC4wMjctMC4wMDNjMC4wNjEtMC4wMDQsMC4xMTktMC4wMDksMC4xOC0wLjAxM2MwLjAwOSwwLDAuMDE5LTAuMDAyLDAuMDI3LTAuMDAyIGMwLjA2NS0wLjAwMywwLjEzMS0wLjAwNywwLjE5My0wLjAwOWMwLjAwNCwwLDAuMDA2LDAsMC4wMDYsMGMwLjIwNi0wLjAwOCwwLjQtMC4wMDIsMC41NzEsMC4wMTIgYzAuOTQ4LDAuMDg2LDEuNzE2LDAuNDIxLDEuODY4LDAuODEzYzAuMDE1LDAuMDQsMC4wMjQsMC4wOCwwLjAyNywwLjEyM0MyOS41MSwxMi45NzksMjkuMzIsMTMuMjAxLDI5LjAwMSwxMy4zOHoiLz48L3N2Zz4K</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Red Hat</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="5">
|
||||
<name>Ubuntu</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-ubuntu.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik00MCwyNGMwLDguOC03LjIsMTYtMTYsMTZTOCwzMi44LDgsMjRTMTUuMiw4LDI0LDhTNDAsMTUuMiw0MCwyNHoiLz48cGF0aC
|
||||
BmaWxsPSIjZTY0YTE5IiBkPSJNMzAgMjRjMCAzLjMtMi43IDYtNiA2LTMuMyAwLTYtMi43LTYtNnMyLjctNiA2LTZDMjcuMyAxOCAzMCAyMC43IDMwIDI0ek0xMiAyMS41YzEuNCAwIDIuNSAxLjEgMi41IDIuNXMtMS4xIDIuNS0yLjUgMi41UzkuNSAyNS40IDkuNSAyNCAxMC42IDIxLjUgMTIgMjEuNU0xMiAyMC41Yy0xLjkgMC0zLjUgMS42LTMuNSAzLjVzMS42IDMuNSAzLjUgMy41IDMuNS0xLjYgMy41LTMuNVMxMy45IDIwLjUgMTIgMjAuNXpNMzAgMzEuNWMxLjQg
|
||||
MCAyLjUgMS4xIDIuNSAyLjVzLTEuMSAyLjUtMi41IDIuNS0yLjUtMS4xLTIuNS0yLjVTMjguNiAzMS41IDMwIDMxLjVNMzAgMzAuNWMtMS45IDAtMy41IDEuNi0zLjUgMy41czEuNiAzLjUgMy41IDMuNSAzLjUtMS42IDMuNS0zLjVTMzEuOSAzMC41IDMwIDMwLjV6Ii8+PHBhdGggZmlsbD0iI2U2NGExOSIgZD0iTTI0LDRDMTMsNCw0LDEzLDQsMjRzOSwyMCwyMCwyMHMyMC05LDIwLTIwUzM1LDQsMjQsNHogTTMyLjUsMzRjMCwxLjQtMS4xLDIuNS0yLjUsMi41IHMtMi
|
||||
41LTEuMS0yLjUtMi41YzAtMC4yLDAtMC41LDAuMS0wLjdDMjYuNSwzMy44LDI1LjMsMzQsMjQsMzRjLTUuMSwwLTkuMi0zLjgtOS45LTguN2MtMC40LDAuNy0xLjIsMS4yLTIuMSwxLjIgYy0xLjQsMC0yLjUtMS4xLTIuNS0yLjVzMS4xLTIuNSwyLjUtMi41YzAuOSwwLDEuNywwLjUsMi4xLDEuMmMwLjctNC45LDQuOC04LjcsOS45LTguN2MxLjMsMCwyLjUsMC4yLDMuNiwwLjcgYy0wLjEtMC4yLTAuMS0wLjQtMC4xLTAuN2MwLTEuNCwxLjEtMi41LDIuNS0yLjVzMi41
|
||||
LDEuMSwyLjUsMi41YzAsMS4yLTAuOCwyLjItMiwyLjRDMzIuNywxOC4zLDM0LDIxLDM0LDI0cy0xLjMsNS43LTMuNSw3LjYgQzMxLjcsMzEuOCwzMi41LDMyLjgsMzIuNSwzNHoiLz48cGF0aCBmaWxsPSIjZTY0YTE5IiBkPSJNMzAgMTEuNWMxLjQgMCAyLjUgMS4xIDIuNSAyLjUgMCAxLjQtMS4xIDIuNS0yLjUgMi41cy0yLjUtMS4xLTIuNS0yLjVDMjcuNSAxMi42IDI4LjYgMTEuNSAzMCAxMS41TTMwIDEwLjVjLTEuOSAwLTMuNSAxLjYtMy41IDMuNXMxLjYgMy41ID
|
||||
MuNSAzLjUgMy41LTEuNiAzLjUtMy41UzMxLjkgMTAuNSAzMCAxMC41ek0yNCAyNGMtMi42LTQuMS01LjItOC4xLTcuOC0xMi4yIi8+PHBhdGggZmlsbD0iI2U2NGExOSIgZD0iTTE5LjEgMTAuN0gyMS4xVjI1LjFIMTkuMXoiIHRyYW5zZm9ybT0icm90YXRlKC0zMi40NjcgMjAuMTI3IDE3LjkxMSkiLz48cGF0aCBmaWxsPSIjZTY0YTE5IiBkPSJNMjQgMjNIMzguNFYyNUgyNHoiLz48Zz48cGF0aCBmaWxsPSIjZTY0YTE5IiBkPSJNMjQsMjRjLTIuNyw0LTUuMyw4LTgsMTIiLz48cGF0aCBmaWxsPSIjZTY0YTE5IiBkPSJNMTIuOCAyOUgyNy4yMDAwMDAwMDAwMDAwMDNWMzFIMTIuOHoiIHRyYW5zZm9ybT0icm90YXRlKC01Ni4zMTIgMTkuOTk4IDMwLjAwNikiLz48L2c+PC9zdmc+Cg==</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Ubuntu</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="6">
|
||||
<name>Ubuntu server</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-ubuntu.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik00MCwyNGMwLDguOC03LjIsMTYtMTYsMTZTOCwzMi44LDgsMjRTMTUuMiw4LDI0LDhTNDAsMTUuMiw0MCwyNHoiLz48cGF0aC
|
||||
BmaWxsPSIjZTY0YTE5IiBkPSJNMzAgMjRjMCAzLjMtMi43IDYtNiA2LTMuMyAwLTYtMi43LTYtNnMyLjctNiA2LTZDMjcuMyAxOCAzMCAyMC43IDMwIDI0ek0xMiAyMS41YzEuNCAwIDIuNSAxLjEgMi41IDIuNXMtMS4xIDIuNS0yLjUgMi41UzkuNSAyNS40IDkuNSAyNCAxMC42IDIxLjUgMTIgMjEuNU0xMiAyMC41Yy0xLjkgMC0zLjUgMS42LTMuNSAzLjVzMS42IDMuNSAzLjUgMy41IDMuNS0xLjYgMy41LTMuNVMxMy45IDIwLjUgMTIgMjAuNXpNMzAgMzEuNWMxLjQg
|
||||
MCAyLjUgMS4xIDIuNSAyLjVzLTEuMSAyLjUtMi41IDIuNS0yLjUtMS4xLTIuNS0yLjVTMjguNiAzMS41IDMwIDMxLjVNMzAgMzAuNWMtMS45IDAtMy41IDEuNi0zLjUgMy41czEuNiAzLjUgMy41IDMuNSAzLjUtMS42IDMuNS0zLjVTMzEuOSAzMC41IDMwIDMwLjV6Ii8+PHBhdGggZmlsbD0iI2U2NGExOSIgZD0iTTI0LDRDMTMsNCw0LDEzLDQsMjRzOSwyMCwyMCwyMHMyMC05LDIwLTIwUzM1LDQsMjQsNHogTTMyLjUsMzRjMCwxLjQtMS4xLDIuNS0yLjUsMi41IHMtMi
|
||||
41LTEuMS0yLjUtMi41YzAtMC4yLDAtMC41LDAuMS0wLjdDMjYuNSwzMy44LDI1LjMsMzQsMjQsMzRjLTUuMSwwLTkuMi0zLjgtOS45LTguN2MtMC40LDAuNy0xLjIsMS4yLTIuMSwxLjIgYy0xLjQsMC0yLjUtMS4xLTIuNS0yLjVzMS4xLTIuNSwyLjUtMi41YzAuOSwwLDEuNywwLjUsMi4xLDEuMmMwLjctNC45LDQuOC04LjcsOS45LTguN2MxLjMsMCwyLjUsMC4yLDMuNiwwLjcgYy0wLjEtMC4yLTAuMS0wLjQtMC4xLTAuN2MwLTEuNCwxLjEtMi41LDIuNS0yLjVzMi41
|
||||
LDEuMSwyLjUsMi41YzAsMS4yLTAuOCwyLjItMiwyLjRDMzIuNywxOC4zLDM0LDIxLDM0LDI0cy0xLjMsNS43LTMuNSw3LjYgQzMxLjcsMzEuOCwzMi41LDMyLjgsMzIuNSwzNHoiLz48cGF0aCBmaWxsPSIjZTY0YTE5IiBkPSJNMzAgMTEuNWMxLjQgMCAyLjUgMS4xIDIuNSAyLjUgMCAxLjQtMS4xIDIuNS0yLjUgMi41cy0yLjUtMS4xLTIuNS0yLjVDMjcuNSAxMi42IDI4LjYgMTEuNSAzMCAxMS41TTMwIDEwLjVjLTEuOSAwLTMuNSAxLjYtMy41IDMuNXMxLjYgMy41ID
|
||||
MuNSAzLjUgMy41LTEuNiAzLjUtMy41UzMxLjkgMTAuNSAzMCAxMC41ek0yNCAyNGMtMi42LTQuMS01LjItOC4xLTcuOC0xMi4yIi8+PHBhdGggZmlsbD0iI2U2NGExOSIgZD0iTTE5LjEgMTAuN0gyMS4xVjI1LjFIMTkuMXoiIHRyYW5zZm9ybT0icm90YXRlKC0zMi40NjcgMjAuMTI3IDE3LjkxMSkiLz48cGF0aCBmaWxsPSIjZTY0YTE5IiBkPSJNMjQgMjNIMzguNFYyNUgyNHoiLz48Zz48cGF0aCBmaWxsPSIjZTY0YTE5IiBkPSJNMjQsMjRjLTIuNyw0LTUuMyw4LTgsMTIiLz48cGF0aCBmaWxsPSIjZTY0YTE5IiBkPSJNMTIuOCAyOUgyNy4yMDAwMDAwMDAwMDAwMDNWMzFIMTIuOHoiIHRyYW5zZm9ybT0icm90YXRlKC01Ni4zMTIgMTkuOTk4IDMwLjAwNikiLz48L2c+PC9zdmc+Cg==</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Ubuntu server</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="7">
|
||||
<name>vCenter Server</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-vmware.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNTAgNTAiIHdpZHRoPSI1MHB4IiBoZWlnaHQ9IjUwcHgiPjxwYXRoIGQ9Ik0gNDIuNDE0MDYzIDE1IEMgMzguODI0MjE5IDE1IDM2LjU3NDIxOSAxNy41IDM2LjU3NDIxOSAxNy41IEMgMzUuMzc4OTA2IDE1Ljk0MTQwNiAzMy43MzA0NjkgMTUuMDAzOTA2IDMwLjk0MTQwNiAxNS4wMDM5MDYgQyAyNy45OTYwOTQgMTUuMDAzOTA2IDI2LjA0Mjk2OSAxNy41IDI2LjA0Mjk2OSAxNy41IEMgMjQuODQ3NjU2IDE1Ljk0MTQwNiAyMi42ODc1IDE1IDIxIDE1IEMgMTguMzkwNjI1IDE1IDE2LjMyMDMxMyAxNi4xNTIzNDQgMTUuMDU0Njg4IDE5LjA1ODU5NCBMIDEwLjgyMDMxMyAyOC4zMjAzMTMgTCA2LjAzMTI1IDE2LjU1ODU5NCBDIDUuNDI1NzgxIDE1LjIyNjU2MyAzLjkzMzU5NCAxNC42MjUgMi41NDI5NjkgMTUuMjQ2MDk0IEMgMS4xNDg0MzggMTUuODcxMDk0IDAuNjM2NzE5IDE3LjQyNTc4MSAxLjI2NTYyNSAxOC43NTc4MTMgTCA3LjExMzI4MSAzMS45NDUzMTMgQyA4LjAzMTI1IDMzLjk0OTIxOSA5LjAwMzkwNiAzNSAxMC44MjAzMTMgMzUgQyAxMi43NjU2MjUgMzUgMTMuNjA5Mzc1IDMzLjg1NTQ2OSAxNC41MzEyNSAzMS45NDUzMTMgQyAxNC41MzEyNSAzMS45NDUzMTMgMTguNTExNzE5IDIzLjA2MjUgMTkgMjIgQyAxOS40ODgyODEgMjAuOTM3NSAyMC4zMDA3ODEgMjAgMjEuNSAyMCBDIDIyLjg3NSAyMCAyNCAyMS4xMjUgMjQgMjIuNSBMIDI0IDMyLjM3NSBDIDI0IDMzLjgyMDMxMyAyNS4wODU5MzggMzUgMjYuNTIzNDM4IDM1IEMgMjcuOTU3MDMxIDM1IDI5IDMzLjgyMDMxMyAyOSAzMi4zNzUgTCAyOSAyMi41IEMgMjkgMjEuMTI1IDMwLjEyNSAyMCAzMS41IDIwIEMgMzIuODc1IDIwIDM0IDIxLjEyNSAzNCAyMi41IEwgMzQgMzIuNSBDIDM0IDMzLjg3NSAzNS4xMjUgMzUgMzYuNSAzNSBDIDM3Ljg3NSAzNSAzOSAzMy44NzUgMzkgMzIuNSBMIDM5IDIyLjUgQyAzOSAyMS4xMjUgNDAuMTI1IDIwIDQxLjUgMjAgQyA0Mi44NzUgMjAgNDQgMjEuMTI1IDQ0IDIyLjUgTCA0NCAzMi41IEMgNDQgMzMuODc1IDQ1LjEyNSAzNSA0Ni41IDM1IEMgNDcuODc1IDM1IDQ5IDMzLjg3NSA0OSAzMi41IEwgNDkgMjEuMzU1NDY5IEMgNDkgMTcuNjE3MTg4IDQ2LjAxMTcxOSAxNSA0Mi40MTQwNjMgMTUgWiIvPjwvc3ZnPgo=</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>vCenter Server</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="8">
|
||||
<name>Windows</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-windows.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiMxOTc2ZDIiIGQ9Ik02LDZoMTd2MTdINlY2eiIvPjxwYXRoIGZpbGw9IiMxOTc2ZDIiIGQ9Ik0yNS4wNDIsMjIuOTU4VjZINDJ2MTYuOTU4SDI1LjA0MnoiLz48cGF0aCBmaWxsPSIjMTk3NmQyIiBkPSJNNiwyNWgxN3YxN0g2VjI1eiIvPjxwYXRoIGZpbGw9IiMxOTc2ZDIiIGQ9Ik0yNSw0MlYyNWgxN3YxN0gyNXoiLz48L3N2Zz4K</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Windows</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="9">
|
||||
<name>Windows server</name>
|
||||
<logo><mimetype>image/svg+xml</mimetype><filename>icons8-windows-server.svg</filename><data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiPjxwYXRoIGZpbGw9IiMwMGIwZmYiIGQ9Ik0yMCAyNS4wMjZMNS4wMTEgMjUgNS4wMTIgMzcuNzQ0IDIwIDM5LjgxOHpNMjIgMjUuMDNMMjIgNDAuMDk1IDQyLjk5NSA0MyA0MyAyNS4wNjZ6TTIwIDguMjU2TDUgMTAuMzggNS4wMTQgMjMgMjAgMjN6TTIyIDcuOTczTDIyIDIzIDQyLjk5NSAyMyA0Mi45OTUgNXoiLz48L3N2Zz4K</data><downloads_count>0</downloads_count></logo>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Windows server</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="1">
|
||||
<name>Arch</name>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Arch</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="2">
|
||||
<name>Debian</name>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Debian</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="3">
|
||||
<name>Oracle Linux</name>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Oracle Linux</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="4">
|
||||
<name>Red Hat</name>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Red Hat</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="5">
|
||||
<name>Ubuntu</name>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Ubuntu</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="6">
|
||||
<name>Ubuntu server</name>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Ubuntu server</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="7">
|
||||
<name>vCenter Server</name>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>vCenter Server</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="8">
|
||||
<name>Windows</name>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Windows</friendlyname>
|
||||
</OSFamily>
|
||||
<OSFamily alias="OSFamily" id="9">
|
||||
<name>Windows server</name>
|
||||
<finalclass>OS Family</finalclass>
|
||||
<friendlyname>Windows server</friendlyname>
|
||||
</OSFamily>
|
||||
</Set>
|
||||
|
||||
|
||||
|
||||
@@ -4461,9 +4461,6 @@
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<fields_semantic>
|
||||
<image_attribute>logo</image_attribute>
|
||||
</fields_semantic>
|
||||
<style>
|
||||
<icon/>
|
||||
</style>
|
||||
@@ -4473,15 +4470,7 @@
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="logo" xsi:type="AttributeImage">
|
||||
<display_max_width>96</display_max_width>
|
||||
<display_max_height>96</display_max_height>
|
||||
<storage_max_width>128</storage_max_width>
|
||||
<storage_max_height>128</storage_max_height>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
</fields>
|
||||
<fields/>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<details>
|
||||
@@ -4489,9 +4478,6 @@
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="logo">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
@@ -4506,9 +4492,6 @@
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="logo">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
</presentation>
|
||||
@@ -4591,9 +4574,6 @@
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="logo">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
<summary>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user