Compare commits

..

278 Commits

Author SHA1 Message Date
Eric Espié
f1af3d5c5f N°9711 - Block user from going back to the setup (#944) 2026-06-22 17:12:57 +02:00
v-dumas
614d3586c8 N°9656 - remove useless old sample data files 2026-06-22 15:37:19 +02:00
Vincent Dumas
f9dc3ee73a N°9656 enrich sample data (#942) 2026-06-22 14:41:51 +02:00
Molkobain
99a9c8ef40 Merge remote-tracking branch 'origin/support/3.2' into develop 2026-06-20 13:19:49 +02:00
Molkobain
ff2357473b Add comment on dictionary tests to explain how uncomplete they are compared to whet they seem to do 2026-06-20 10:27:58 +02:00
Molkobain
9a93bcb06f PHP Code Styles: Fix composer.lock to be compatible with platform requirements (PHP 8.1) 2026-06-20 10:11:45 +02:00
Anne-Catherine
9b4f3290e8 N°7914 - REST: Allow class based output fields + Allow OQL with multiclass result (#708) 2026-06-19 17:07:14 +02:00
Eric Espié
67792155dd N°9710 - Add fast setup button at the beginning of Setup (#941) 2026-06-19 15:28:03 +02:00
Eric Espie
a23b9aa596 N°9709 - XML load failing on empty one way password 2026-06-19 11:53:02 +02:00
Anne-Cath
017481af21 ci: fix setup css 2026-06-18 17:48:42 +02:00
Eric Espie
4f70441618 N°9678 - Fix extension map initialization 2026-06-18 17:31:13 +02:00
Eric Espie
fb6a332bd0 N°9684 - Add setup page class inclusion in Controller.php 2026-06-18 17:22:05 +02:00
Timmy38
a9af4fc060 N°9701 Add id to badges 2026-06-18 11:05:09 +02:00
odain
6a8dc159c1 revert 75433d3390: Enhance unattended CLI to log fatal error 2026-06-17 15:38:22 +02:00
odain
2930a122c6 N°9144 - fix commit operation rmdir conf/production-build failed as not always empty 2026-06-17 15:21:30 +02:00
odain
75433d3390 Enhance unattended CLI to log fatal error just like setup wizardinstead of silent failure 2026-06-17 15:12:46 +02:00
odain
d4d6fa149d N°9412 - revert fresh-install.xml changes 2026-06-17 14:31:50 +02:00
odain-cbd
207ac373d0 N°9678 - Datamodel not added after extension management setup (#936)
* N°9678 - Datamodel not added after extension management setup

* N°9678 - fix selecting extensions from extensions folder in extension mgt view

* cleanup: remove cached stuff in runtimeenv

* N°9678 - Refactor iTopExtensionsMap instantiation to use GetExtensionsMap method

* N°9678 - Refactor data model compilation and improve directory scanning logic

* N°9678 - Handle MySQLException in ModuleInstallationRepository and remove unnecessary error logging in WizStepModulesChoice

---------

Co-authored-by: Eric Espie <eric.espie@combodo.com>
2026-06-17 10:22:05 +02:00
Timmy38
0240d12007 N°9690 Fix multiple added_extensions 2026-06-16 10:13:22 +02:00
odain
1123a83490 💚 Fix PHP code styles 2026-06-15 22:23:19 +02:00
Molkobain
8ccf832bdd 💚 Fix PHP code styles 2026-06-15 19:10:25 +02:00
Anne-Cath
caa1b8652d FIxes unit tests 2026-06-15 16:51:02 +02:00
Anne-Catherine
ed1cfc3b08 N°7289 - Read-only attribute, dynamically read-write, entry silently ignored on submission (#724) 2026-06-15 16:01:06 +02:00
Anne-Catherine
dd6b03cccc N°3789 - Bulk actions on replicas: (Resync, Force Update, Delete,...) (#546) 2026-06-15 15:58:36 +02:00
Timmy38
3e38e349e5 N°9690 Fix code style 2026-06-15 11:53:14 +02:00
Timmy38
65b58ec4e2 N°9690 Removed and added modules/extensions are now read from GET parameters 2026-06-15 11:49:52 +02:00
Timmy38
6a20e36434 N°9683 Fix Code Style 2026-06-12 11:23:35 +02:00
Vincent Dumas
3805a322c1 N°9160 Copy log entry from parent ticket (#927)
* N°9160 - Refactor UpdateChildxxxxxLog and add test
2026-06-12 09:09:02 +02:00
odain
0bf773a23c N°9454 - fix unattended regression when fresh install and no conf yet 2026-06-11 18:47:48 +02:00
Timmy38
28a09068a0 N°9683 Add markdown in UIBlock for behat 2026-06-11 17:14:48 +02:00
lenaick.moreira
db7fd6b3c0 N°9638 - Rollback undesired changes 2026-06-11 09:41:45 +02:00
odain-cbd
cf76c23ac6 N°9670 - Extension management - even if not selected, an extension is analysed during setup check compatibility (#933)
* N°9670 - Extension management - even if not selected, an extension is analysed during setup check compatibility

* N°9670 - enhance log msg

* N°9670 - PR feedback
2026-06-11 07:09:44 +02:00
lenaick.moreira
b36b0de93c N°9654 - fix typo in param name 2026-06-10 16:52:34 +02:00
Lenaick
a95125e8bf N°9638 - Add setup ContextTag for async operation (#934) 2026-06-10 16:03:09 +02:00
lenaick.moreira
6e536e7dbe N°9597 - Fix CI 2026-06-10 10:53:16 +02:00
Lenaick
733eea8a78 N°9654 - Reduce surface attack on config file rights during setup (#932) 2026-06-09 16:56:58 +02:00
Lenaick
f48efbbd03 N°9597 - Switch environment to a build environment must not be available (#925)
* N°9597 - Switch environment to a build environment must not be available

* N°9597 - Switch environment to a build environment must not be available
2026-06-09 16:49:47 +02:00
Lenaick
1a57a427c0 N°9454 - Make MTT compatible with the dry run (#931)
* N°9454 - Make MTT compatible with the dry run

* N°9454 - Make MTT compatible with the dry run

* N°9454 - Cleaning up configuration handling

* N°9454 - Cleanup code

* N°9454 - Remove writable directories

* Update setup/wizardsteps/WizStepLandingBeforeAudit.php

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update setup/runtimeenv.class.inc.php

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* N°9454 - Secure target environment wizard step done form submission

---------

Co-authored-by: Eric Espie <eric.espie@combodo.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-06-09 14:29:06 +02:00
odain
a419914236 N°9412 - fix uninstall option and others when going to setup from extension mgt 2026-06-08 17:13:49 +02:00
jf-cbd
3426b92768 Fix unit test 2026-06-08 14:04:01 +02:00
jf-cbd
7c44c94de1 Fix unit and CS fixer tests 2026-06-08 13:50:14 +02:00
Purple Grape
4371ddfbbd N°9663 - improved translation for zh_cn (#913) 2026-06-08 13:21:12 +02:00
Timmy38
66bf1dc6fa N°9179 Fix tests for unattended install backward compatibility 2026-06-08 11:45:11 +02:00
Eric Espie
6999000d69 N°9179 - Fix CI 2026-06-08 09:01:20 +02:00
Eric Espié
eedcdf32fe N°9169 - adapt itsm designer connector to the new setup (#928)
* N°9169 - Adapt ITSM designer connector to the new setup - Button Back to designer

* N°9169 - Enhance ITSM designer connector with return button functionality

* N°9169 - Adapt ITSM designer connector to the new setup - Button Back to designer (removed URL in post params)

* N°9169 - Enhance ITSM designer connector with return button functionality and update button styles

---------

Co-authored-by: lenaick.moreira <lenaick.moreira@gmail.com>
2026-06-05 09:59:14 +02:00
Timmy38
2321d89981 N°9179 Fix missing optional steps when using older install-xxxx.xml file with unattended install 2026-06-04 09:38:48 +02:00
odain
3bf47d1e8c Merge branch 'support/3.2' into develop 2026-06-02 17:47:33 +02:00
odain
feb89650e4 curl_close deprecated in PHP 8.5 2026-06-02 17:47:10 +02:00
Eric Espie
b672dfc9f2 Fix PHPStan warning 2026-06-02 15:10:28 +02:00
Eric Espie
210e2cefca Merge commit '07afcdcec6c42a5a9c5d56badc50dbc3401a98d3' into develop 2026-06-01 09:01:52 +02:00
Eric Espie
07afcdcec6 remove not meaningful localized data test 2026-05-29 15:38:20 +02:00
Eric Espie
24fa5d3bbd N°9169 - Adapt ITSM designer connector to the new setup (FIX some unit tests) 2026-05-29 10:54:39 +02:00
Timmy38
65de991853 N°9167 Fix visible menu in analysis result 2026-05-29 10:13:29 +02:00
Eric Espie
a1a82a02c8 Merge remote-tracking branch 'origin/develop' into feature/uninstallation 2026-05-29 09:59:51 +02:00
Eric Espie
6266d4ce15 N°9169 - Adapt ITSM designer connector to the new setup (FIX some unit tests) 2026-05-29 09:56:00 +02:00
lenaick.moreira
367ae456eb N°9169 - Adapt ITSM designer connector to the new setup (WIP) 2026-05-28 15:43:54 +02:00
Eric Espie
c80dbf9bb4 N°9169 - Adapt ITSM designer connector to the new setup (FIX some unit tests) 2026-05-28 11:42:59 +02:00
Timmy38
683b075bf5 N°9172 Modify ext mgmt labels 2026-05-28 11:19:30 +02:00
v-dumas
cbbcc489e0 N°9553 - Fix setup issue due to wrong method params testing 2026-05-28 10:49:45 +02:00
Eric Espie
406f688394 N°9169 - Adapt ITSM designer connector to the new setup (FIX CI) 2026-05-28 10:35:29 +02:00
Eric Espie
06bff3f9e4 N°9169 - Adapt ITSM designer connector to the new setup (WIP) 2026-05-27 17:38:19 +02:00
Vincent Dumas
7c49909dd9 N°9553 upload localised structural data (#917)
* Helper for loading XML localized data during Setup
* Refactor existing code
* Add new localized structural data
2026-05-27 16:32:14 +02:00
Vincent Dumas
51180c9529 N°9604 - Add Flux tab on Server, VM and ContainerApplication (#918) 2026-05-27 16:17:23 +02:00
lenaick.moreira
643ec3bc43 N°9169 - Adapt ITSM designer connector to the new setup (WIP) 2026-05-27 14:58:25 +02:00
lenaick.moreira
b3f984b0e1 N°9169 - Adapt ITSM designer connector to the new setup (WIP) 2026-05-27 14:55:41 +02:00
Eric Espie
cbc02dce52 N°9638 - Regression itop-time-tracking due to iBackofficeDictEntriesExtension UI 2026-05-27 11:30:24 +02:00
odain
955ce5fc2c ci: fix setup css 2026-05-25 00:07:56 +02:00
odain
e7ce3fcf8a N°9567 - Make extension mgt to setup work
N°9567 - Make extension mgt to setup work
2026-05-22 14:36:54 +02:00
odain
c156c09be0 N°9567 - ci fix Implicitly marking parameter $oConfig as nullable is deprecated 2026-05-22 07:50:00 +02:00
odain
3df12bba46 Merge branch 'feature/uninstallation2' into feature/uninstallation 2026-05-21 13:56:40 +02:00
odain
0912cc21cf N°9564 - fix WizardChoice test 2026-05-21 13:56:24 +02:00
odain
3aa59ae0b7 N°9564 - fix extension mgt flow from 1st to 2nd screen 2026-05-21 13:54:16 +02:00
odain
a5b5d22e2f N°9564 - enhance simulate testing script to use local settings 2026-05-21 13:52:35 +02:00
odain
08a3044cd1 N°9564 - fix first screen
log cleanup

after merge adaptations
2026-05-21 13:52:30 +02:00
odain
00f1c7498d N°8760 - raise module dependency errors in all setups ecept wizard/unattended 2026-05-21 10:10:10 +02:00
odain
a4345d0311 N°9567 - fix back to setup from extension management - extension screen missing when back after audit
N°9567 - fix again
2026-05-21 10:10:10 +02:00
Timmy38
77a820105f N°9167 Use ExtensionDetails UIBlocks instead of table (#910) 2026-05-21 09:48:33 +02:00
odain
03e1806f9a N°9567 - fix back to setup from extension management - extension screen missing when back after audit 2026-05-20 14:56:55 +02:00
lenaick.moreira
eef06ee032 Merge branch 'support/3.2.3' into support/3.2 2026-05-20 14:20:43 +02:00
Lenaick
d6ce202fa8 N°9614 - Add a specific route to display the icons for an EventNotificationNewsroom (#911)
* N°9614 - Add a specific route to display the icons for an EventNotificationNewsroom

* N°9614 - Display the icon in EventNotificationNewsroom only for events relating to the logged-in user

* N°9614 - Refactor icon download logic in EventNotificationNewsroomService and add unit tests

* Add unit test to verify icon download functionality for users without read access
2026-05-20 14:18:13 +02:00
Eric Espie
b6c48f4bba Removed duplicated itop-flow-map 2026-05-20 13:48:45 +02:00
Eric Espie
e9dd2dc3e6 N°9567 - Fix CI 2026-05-20 10:43:20 +02:00
odain-cbd
ba6cc9dcba N°9567 - Extension Mgmt : Run setup (#912)
* N°9144 - correct next button in audit page

* N°9567 - WIP

code style

* N°9412 - Screen Analysis results wip + test endpoint

* N°9412 - next button label

* N°9412 - Mask CI pbs

* N°9412 - Analysis results screen wip

* N°9412 - Analysis results screen wip

* N°9567 - fix extension map init of installation choices

* N°9567 - fix test

* N°9567 - link from ext mgt to setup WIP

* N°9567 - add enc_type in UIForm to be able to change content type in twigs

* N°9412 - wip

* N°9567 - Extension Mgmt : Run setup

* N°9567 - Extension Mgmt : Run setup

* N°9567 - Extension Mgmt : Run setup (fix post-deletion button inputs)

* N°9567 - Extension Mgmt : Run setup

* N°9567 - Extension Mgmt : Run setup

* N°9567 - Extension Mgmt : Run setup

---------

Co-authored-by: Eric Espie <eric.espie@combodo.com>
2026-05-20 10:16:32 +02:00
Stephen Abello
1c38d989e4 N°9603 - Fix transitions applied when editing only caselog are not working (#908)
* N°9603 - Fix transitions applied when editing only caselog are not working

* Remove unused variable
2026-05-18 17:28:46 +02:00
Lenaick
fb7a38c83f N°9134 Validate extension codes before installation and refine progress message styling (#909)
* N°9134 Validate extension codes before installation and refine progress message styling

* Add test for compile failure when extension code is missing
2026-05-18 10:11:37 +02:00
odain
b29a3b5df8 Merge branch 'develop' into feature/uninstallation 2026-05-15 08:54:38 +02:00
Molkobain
e65542f978 Merge remote-tracking branch 'origin/support/3.2.3' into support/3.2 2026-05-07 18:54:39 +02:00
Stephen Abello
829857ec85 N°9461 - Fix activity panel send options hidden by CKEditor 2026-05-07 15:55:02 +02:00
Lenaick
29502a4297 N°9205 - Show progress messages in setup sequencer (#906)
* N°9205 - Show progress messages in setup sequencer

* N°9205 - Fix unit tests
2026-05-07 10:27:31 +02:00
Eric Espie
c5b678b4cf Merge remote-tracking branch 'origin/feature/uninstallation' into feature/9412-uninstallationchoices 2026-05-06 15:04:24 +02:00
Eric Espie
cb46889e92 N°9412 - Display Choices on extensions in analysis results 2026-05-06 14:35:33 +02:00
odain
2fe487df3c Merge branch 'feature/9412-uninstallationchoices' into feature/uninstallation 2026-05-06 13:30:12 +02:00
odain
ae1f9391f9 N°9144 - PR review feedbacks 2026-05-06 13:22:46 +02:00
Eric Espie
f4a1aca3f9 Changed display of modules and installation choices 2026-05-06 11:54:45 +02:00
odain
4d2722654a N°9144 - no audit in unattended + tests 2026-05-06 10:53:26 +02:00
odain
73ebf663d6 N°9144 - setup robustness 2026-05-06 10:53:19 +02:00
odain
99a5b47899 N°9144 - adapt unattended XMLs 2026-05-06 10:53:10 +02:00
odain
109aa03901 N°9412 - Backend cleanup must work on setup settings that differ from runtime - WIP 2026-05-04 16:16:29 +02:00
Eric Espie
80813dba22 N°9503 - Setup wizard : fix symlinks for data/production-modules 2026-04-30 14:35:29 +02:00
Eric Espie
da282e6c24 N°9009 - fix removing sources of a mandatory module 2026-04-30 12:03:38 +02:00
Eric Espie
c4eaeeeb5f fix setup button in develop mode for page core-update 2026-04-30 11:01:26 +02:00
odain
e605b147d3 fix merge from develop: broken setup style 2026-04-30 10:49:53 +02:00
Molkobain
bfcff9b9c8 Merge remote-tracking branch 'origin/develop' into feature/uninstallation 2026-04-30 10:39:14 +02:00
Eric Espie
cd9a755162 N°9165 - fix greptile mistake 2026-04-30 10:28:25 +02:00
Eric Espie
841ea9bb11 N°9165 - fix greptile mistake 2026-04-30 10:26:34 +02:00
Eric Espié
4582256f01 N°9165 - secure data cleanup 2026-04-30 10:20:25 +02:00
Benjamin DALSASS
0fc7434794 Merge remote-tracking branch 'origin/develop' into feature/uninstallation 2026-04-29 11:08:03 +02:00
Timmy38
42fdffe25b N°9503 Fix phpunit test 2026-04-28 10:43:05 +02:00
odain
309f8f8727 fix merge 2026-04-28 10:27:28 +02:00
odain
16108a80fc Merge branch 'develop' into feature/uninstallation 2026-04-28 10:24:50 +02:00
Timmy38
7e0e357713 N°9503 Fix broken symlink in setup wizard (#881) 2026-04-27 09:14:41 +02:00
Timmy38
d358c41c24 N°9144 Fix code style 2026-04-24 09:12:31 +02:00
Timmy38
d0ddb35f8d N°9144 Fix static analysis issues (#885)
* N°9144 Fix static analysis issues with phpstan
* up to level 1 for all setup files
* up to level 5 for all wizardsteps
2026-04-23 14:08:22 +02:00
Eric Espie
fc2cb86122 Fix CI (PHP8.4) 2026-04-23 08:47:07 +02:00
Eric Espie
467d2755ca N°9169 - Refactor code 2026-04-22 17:30:34 +02:00
odain-cbd
de0e94800a N°8806 - Installation multiple extension with dependence via ITSM Designer (#879)
* N°8806 - Installation multiple extension with dependence via ITSM Designer

* N°8806 - fix tests

* N°8806 - improve GetMFModulesToCompile to handle extensions and installation choices on all setup that use compileFrom (MTP, CoreUpdate, Hub, DryRemoval)

* N°8806 - add log when loading MFModule

* N°8806 - code cleanup + test cover

* N°8806 - typo

* N°8806 - log removal
2026-04-21 10:52:23 +02:00
odain
3b0832781a N°9526 - Message de warning dans le unattended sur une professional 2026-04-21 10:11:19 +02:00
Eric Espie
900bd6956a N°9525 - TagSet Errors 2026-04-20 17:42:35 +02:00
odain
848d869954 N°9434 - remove unecessary code 2026-04-20 16:18:06 +02:00
odain
020d720140 N°9434 - Do not launch dry run on a iTop version upgrade 2026-04-20 16:15:13 +02:00
odain
dc8f186443 N°9144 - fix broken fresh install 2026-04-20 15:44:09 +02:00
Eric Espie
423807d32a N°9144 - Put back Session::IsInitialized() 2026-04-20 11:59:13 +02:00
Eric Espie
7819620013 Fix CI 2026-04-17 15:32:12 +02:00
Eric Espie
0fb15e72d4 N°9501 - Can't connect new itop3.3.0 to Designer 2026-04-17 15:25:45 +02:00
Eric Espie
0b6e7d3258 last step 2026-04-17 15:07:53 +02:00
Eric Espie
8088fdc322 N°9514 - End user device cannot be uninstalled 2026-04-17 14:50:49 +02:00
Eric Espie
d3dbe7b231 N°9514 - End user device cannot be uninstalled (WIP) 2026-04-17 14:18:07 +02:00
Eric Espie
f05d98aba8 Fix CI (To be checked) by simplifying mocks 2026-04-17 10:41:54 +02:00
Eric Espie
999e4de7f1 Fix CI (SessionHandler) 2026-04-17 09:04:08 +02:00
Eric Espie
327c1572a4 fix session 2026-04-16 15:05:20 +02:00
Eric Espie
16cdc80778 fix session 2026-04-16 14:45:13 +02:00
Eric Espie
962a8e68b3 comment 2026-04-16 14:03:12 +02:00
Eric Espie
d61742dffb fix setup updating config file 2026-04-16 14:00:33 +02:00
Eric Espie
9f15385545 fix session 2026-04-16 13:49:36 +02:00
Eric Espie
751ad846a4 Forgot datamodels/1.x 2026-04-16 11:02:46 +02:00
Eric Espie
f3b55a648e Fix CI 2026-04-16 10:17:31 +02:00
Eric Espie
5ff640dfe7 Fix config creation 2026-04-14 17:19:18 +02:00
Eric Espie
662d6e3fb4 Fix config creation 2026-04-14 17:01:54 +02:00
Eric Espie
cbafcccde5 Merge remote-tracking branch 'origin/develop' into feature/uninstallation 2026-04-14 11:38:05 +02:00
Eric Espie
7573b1bfba Fix setup session problems 2026-04-14 11:20:06 +02:00
odain
e7e7664cb8 N°9500 - move STATIC_CALL_AUTOSELECT_WHITELIST from RuntimeEnvironment to ModuleFileReader 2026-04-13 22:56:46 +02:00
odain
1222507205 N°9500 - Designer - Can't mtp - OQL errors 2026-04-13 11:48:18 +02:00
odain
b133f52d83 fix merge
fix merge
2026-04-08 21:10:32 +02:00
odain
e28addfd6d Merge branch 'develop' into odain 2026-04-08 20:24:22 +02:00
odain
2ec0931896 N°8955 - fix Implicitly... again 2026-04-08 20:18:52 +02:00
odain
ca30645d36 N°9144 - fix rebase 2026-04-08 16:03:15 +02:00
odain
bd14a84677 N°8955 - fix Implicitly marking parameter as nullable is deprecated 2026-04-08 15:26:11 +02:00
odain
ad0234a94f N°9144 - setup wizard sequencers test coverage + fixes
N°9144 - ci: fix hub setup test

N°9144 - code style

N°9144 - tests and fixes

N°9144 - ci: fix tests and code style
2026-04-08 15:26:09 +02:00
odain
611f1e66f2 N°9144 - ci revert ITOP_DEFAULT_ENV 2026-04-08 15:24:47 +02:00
odain
82a20c54a9 N°9144 - fix both UI setup wizard and CLI unattended + replace production by ITOP_DEFAULT_ENV 2026-04-08 15:24:42 +02:00
Eric Espie
d36f68e3b0 N°9144 - Fix sessions 2026-04-08 15:24:40 +02:00
odain
9ca0dd643f N°9144 - fix fresh install 2026-04-08 15:24:37 +02:00
odain
e27aca728c N°9144 - WIP: fix unattended 2026-04-08 15:24:35 +02:00
odain
c3824f421b N°9144 - bypass audit in setup wizard sometimes 2026-04-08 15:24:32 +02:00
Eric Espie
ecc07f4575 N°9144 - WIP symbolic links 2026-04-08 15:24:29 +02:00
Eric Espie
bcf2123df0 N°9144 - Fix unattended install 2026-04-08 15:24:27 +02:00
Eric Espie
8dca03f557 N°9144 - Fix runtime env 2026-04-08 15:24:24 +02:00
Eric Espie
2129007512 N°9144 - Setup sequencer side B 2026-04-08 15:24:22 +02:00
Eric Espie
14d01b89a7 N°9144 - Setup sequencer side A 2026-04-08 15:24:12 +02:00
Eric Espie
e2bda81414 N°9144 - Split setup in 2 different step - refactor RuntimeEnv 2026-04-08 15:20:52 +02:00
Eric Espie
6b7d306006 N°9409 - Fix CI 2026-04-08 15:20:49 +02:00
Eric Espie
40feabb866 N°9409 - Fix CI 2026-04-08 15:20:46 +02:00
Eric Espie
e17eaa7430 N°9409 - Fix CI 2026-04-08 15:20:44 +02:00
Eric Espie
deeee08e8c N°9409 - Designer 3.3.0 - PHPStan level 2 2026-04-08 15:20:42 +02:00
Molkobain
b7b01c94e7 N°9161 - Fix unit test which missed a markup change 2026-04-08 15:20:42 +02:00
odain
ba29a41d98 N°9409 - Designer 3.3.0: be able to extend nstallationChoicesToModuleConverter 2026-04-08 15:20:39 +02:00
Eric Espie
073d4f15f5 N°9409 - Designer 3.3.0 - PHPStan level 1 2026-04-08 15:20:36 +02:00
Eric Espie
91915f001b N°9409 - Designer 3.3.0 - PHPStan level 1 wip 2026-04-08 15:20:34 +02:00
Molkobain
9b7c7c0b48 N°9161 - Change UIBlock badges markup from span to div to improve E2E testing 2026-04-08 15:20:34 +02:00
Eric Espie
85b20f34a3 N°9409 - Designer 3.3.0 - edit dashboard fix 2026-04-08 15:20:31 +02:00
odain
7a153c3698 N°8760 - fix setup/cleanup audit on legacy 1.x packages without any
installation.xml
2026-04-08 15:19:34 +02:00
Eric Espie
1be0e61971 N°9409 - Designer 3.3.0 2026-04-08 15:19:32 +02:00
Eric Espie
d53433e62d N°9409 - Designer 3.3.0 2026-04-08 15:19:29 +02:00
Eric Espie
51f4dd7948 N°9409 - Designer 3.3.0 2026-04-08 15:19:25 +02:00
Eric Espie
d2384bb274 N°9409 - Create a package designer 3.3.0 - PHP 8.4 2026-04-08 15:19:16 +02:00
Eric Espie
cedc1ec711 N°9370 - autoload 2026-04-08 15:18:24 +02:00
odain
9cb2d78b48 PR review - move Prepare in DryRemovalRuntimeEnvironment constr 2026-04-08 15:18:24 +02:00
odain
9c32e29e77 code style 2026-04-08 15:18:24 +02:00
odain
c6dd16549c N°9370 - use env-production-build in setup audit sequencer (no more dry-production) 2026-04-08 15:18:24 +02:00
odain
f2b15554bb N°9370 - use env-production-build for dry removal audit
wip
2026-04-08 15:18:24 +02:00
Eric Espie
358c4383f8 Add explanation messages 2026-03-18 14:16:55 +01:00
Eric Espie
890db04fa3 Fix CI 2026-03-18 14:16:54 +01:00
Eric Espie
e1e2da2881 N°8761 - Assist in cleaning up data prior to uninstalling extensions 2026-03-18 14:16:54 +01:00
Eric Espie
cb47ea4316 N°8761 - Assist in cleaning up data prior to uninstalling extensions 2026-03-18 14:16:54 +01:00
Eric Espié
a3e8abe520 N°8761 - Assist in cleaning up data prior to uninstalling extensions (#838)
* N°8761 - Assist in cleaning up data prior to uninstalling extensions - handle transaction ID + add deletion plan screen

* N°8761 - poc of deletion plan screen

* code style

* N°8761 - WIP deletion plan execution

* Delete all parent classes objects + cleanup

* 🌐 translation (EN only)

* remove history

* In case of no leaf class to remove, delete also the child classes

* 🎨 refactor & fix typo

* Analysis not stored anymore in DB

* Analysis for removed modules

* 🌐 dico

* Add spinner to setup button "Go to backoffice"

* Fix count after PR review

* Fix after PR review

* Fix Number of elements to remove

* Fix arrays

---------

Co-authored-by: odain <olivier.dain@combodo.com>
2026-03-18 14:16:54 +01:00
Timmy38
48e58f4323 * N°8955 Add UIBlocks markup in the setup 2026-03-18 14:16:54 +01:00
Timothee
337ccbb921 N°9141 Fix missing bCanBeUninstalled flag for installation.xml choices 2026-03-18 14:16:54 +01:00
Timothee
34930a93cb N°9327 Fix phpunit tests 2026-03-18 14:16:54 +01:00
Timmy38
5f731d9f97 N°9327 Do not enter readonly or maintenance mode when doing data audit 2026-03-18 14:16:54 +01:00
Timmy38
9b7fd7b398 N°9141 Log when extension uninstallation is forced 2026-03-18 14:16:54 +01:00
Timmy38
e0eee6798d N°9088 Allow extension uninstallation from production-modules folder 2026-03-18 14:16:54 +01:00
Timothee
a8f1b6ea35 N°9161 Fix missing href 2026-03-18 14:16:54 +01:00
odain
d49a50da5b ci: code style 2026-03-18 14:16:54 +01:00
odain
6a34fb9a15 phpstan cleanup 2026-03-18 14:16:54 +01:00
Timmy38
3befe469e8 N°9161 Add markup for behat in setup recap screen 2026-03-18 14:16:54 +01:00
Timmy38
add7e7a677 N°8955 add UI block for uninstallation 2026-03-18 14:16:54 +01:00
odain
f80a074135 cleanup 2026-03-18 14:16:53 +01:00
Timothee
113e3bc110 Fix Code Style 2026-03-18 14:16:53 +01:00
Timmy38
c20c4644b1 N°9009 Add phpunit test to GetSelectedModules 2026-03-18 14:16:53 +01:00
Timothee
b77a0e3297 N°9144 Fix backup option presence during install 2026-03-18 14:16:53 +01:00
odain
a237b32115 N°9168 - fix ci 2026-03-18 14:16:53 +01:00
odain
681abc84b9 Merge branch 'feature/9168-moveintocore' into feature/uninstallation 2026-03-18 14:16:53 +01:00
Timothee
7775cfeccc N°9144 Small fixes
> Prevent verification when some dependencies are missing
> Close unclosed div
> Change progress bar title depending on step
> Fix ignored "check uninstall check" flag
> Added phpunit tests to cover "check uninstall check" flag
> Progress bar appropriately reflect error status (red & not animated)
2026-03-18 14:16:53 +01:00
odain
222e08e29b N°9168 - merge data feature removal to iTop core code
N°9168 - phpstan fix

N°9168 - align module version with itop core
2026-03-18 14:16:53 +01:00
Timothee
773501baed N°9144 Fix back from module choice 2026-03-18 14:16:53 +01:00
Timothee
150094341f N°9010 Fix Code Style 2026-03-18 14:16:53 +01:00
Timmy38
e1215733e9 N°9010 fix flags when extension is missing 2026-03-18 14:16:53 +01:00
Timmy38
2b2e431d0a N°9144 Add data audit setup step
N°8864 Fix unneeded char
2026-03-18 14:16:53 +01:00
odain
98312d1c15 N°8760 - fix installation choices db query - read code instead of title + add log 2026-03-18 14:16:53 +01:00
odain
fc08bed218 Merge branch 'feature/8760-audit-squashed' into feature/uninstallation 2026-03-18 14:16:52 +01:00
odain
eb01828f06 N°8764 - enhance setup wizards transition computation/tests 2026-03-18 14:16:52 +01:00
odain
4c0b54a0f7 N°8760 - Audit uninstall of extensions that declare final classes
N°8760 - be able to list modules based on extension choices
refactoring: move some classes in a moduleinstallation folder (coming
namespace)

N°8760 - module dependency check applied before audit

N°8760 - make dependency check work during audit

N°8760 - fix ci

N°8760 - fix ci

N°8760 - add GetCreatedIn to get module name based on DBObject class - everything stored in MetaModel during compilation and autoload

N°8760 - be able to describe from which module a datamodel class comes via MetaModel created_in field

N°8760 - rename GetCreatedIn <- GetModuleName + compute module name live instead having complex stuff in MetaModel/compilation

temp review 1

review: renaming InstallationChoicesToModuleConverter

review: renaming InstallationChoicesToModuleConverter

review: ModuleDiscovery:GetModulesOrderedByDependencies replacing deprecated GetAvailableModules method

ci: fix typo

cleanup

review: rework InstallationChoicesToModuleConverter

N°8760 - review tests
2026-03-18 14:16:52 +01:00
Molkobain
8074643231 N°9106 - Adapt extensions pills so they can be read correctly by Behat 2026-03-18 14:16:52 +01:00
odain
1fb264e630 N°8764 - fix setup wizards transitions - damned missing file 2026-03-18 14:16:52 +01:00
odain
2bfafeffe6 N°8764 - fix setup wizards transitions 2026-03-18 14:16:52 +01:00
odain
324a68df32 N°8764 - fix missing setup wizards titles + cache step computation 2026-03-18 14:16:52 +01:00
odain
14c3dafa4d code style 2026-03-18 14:16:52 +01:00
odain
7e78bd8519 N°8764 - use last working model in case setup wizard to do setup audit - skip if no model available to make setup work 2026-03-18 14:16:52 +01:00
Timothee
54aa56c5a8 N°8763 Add phpunit tests for iTopExtension::CanBeUninstalled 2026-03-18 14:16:52 +01:00
odain
62bd1b8f49 N°8864 - code readability 2026-03-18 14:16:52 +01:00
odain
b5e95f297c N°8760 - Audit uninstall of extensions that declare final classes - refactor extension computations and move them in ExtensionMap
N°8760 - Audit uninstall of extensions that declare final classes - refactor extension computations and move them in ExtensionMap
2026-03-18 14:16:52 +01:00
odain
f89cb71f61 simplify WizardStep::GetTitle 2026-03-18 14:16:52 +01:00
odain
b30ff8b832 N°8981 - reduce log verbosity during setup 2026-03-18 14:16:52 +01:00
Timothee
5254a83327 N°8763 Fix non-uninstallable check in multi-modules extensions 2026-03-18 14:16:52 +01:00
odain
b1f49a1568 Merge branch 'feature/8981-prepare' into feature/uninstallation 2026-03-18 14:16:52 +01:00
odain
336898da98 Merge branch 'feature/8981-prepare' into feature/uninstallation 2026-03-18 14:16:51 +01:00
odain
84803abd36 N°8764 - skip audit when itop reinstalled on top of a backup without env-production to read previous datamodel + phpdoc fix 2026-03-18 14:16:51 +01:00
odain
9370c83a69 setup: phpstan level 2
setup: phpstan level 2
2026-03-18 14:16:51 +01:00
odain
f7dfeafa3f setup: phpstan level 1 2026-03-18 14:16:48 +01:00
odain
5b4030a95f setup: phpstan level 0 2026-03-18 14:16:13 +01:00
odain
fe6ba35ada N°8764 halt setup wizard at data issue - 2nd review 2026-03-18 14:16:13 +01:00
odain
789c4bb5ea N°8764 halt setup wizard at data issue - review
- 2 types of SetupAudit constructors
- setup wizard new step management enhancement
- change SetupAudit GetIssue API behaviour
2026-03-18 14:16:13 +01:00
odain
f5f5334e5f ci: test enhancement => use GetTemporaryFilePath 2026-03-18 14:16:13 +01:00
odain
51f0eea8e3 enhance test sdk: add GetTemporaryFilePath
# Conflicts:
#	tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php
2026-03-18 14:16:10 +01:00
odain
875b2f1f29 N°7629: log changed 2026-03-18 14:15:00 +01:00
odain
36fc0fb0ea N°8981: test ModuleDiscovery filtered by removed extensions 2026-03-18 14:15:00 +01:00
odain
4f9a4dcfa5 N°8764 - fix first install 2026-03-18 14:15:00 +01:00
odain
dfc6189cef N°8764 - stop setup and display data to cleanup message 2026-03-18 14:15:00 +01:00
odain
ad33453860 N°7629: improve InterfaceDiscovery::GetCandidateClasses robustness 2026-03-18 14:15:00 +01:00
odain
f787cf0950 N°8764 - Halt setup if database is not compatible with an uninstallation 2026-03-18 14:15:00 +01:00
odain
cf7a193f7b N°8981: fix broken setup wizard due to invalid array passed 2026-03-18 14:14:59 +01:00
odain
8bbd1ab621 Merge branch 'feature/8981-prepare' into feature/uninstallation 2026-03-18 14:14:59 +01:00
odain
20ae350286 N°8981: ModuleInstallationRepository dedicated to module installation queries
N°8981: ModuleInstallationRepository dedicated to module installation queries

fix renaming
2026-03-18 14:14:59 +01:00
odain
df9d69c70f N°8981: review cleanup on module filtering due to extensoin removal 2026-03-18 14:14:59 +01:00
odain
ba09c624f0 N°8981: be able to remove extension during setup even when present on disk 2026-03-18 14:14:59 +01:00
odain
7611a0e5c8 N°8981 setup wizard: reuse AnalyzeInstallation result in wizard module choice step 2026-03-18 14:14:59 +01:00
odain
19e60ea628 N°8981 setup wizard: optimize IsConnectableToITopHub use (perf)
N°8981: revert IsConnectableToITopHub
2026-03-18 14:14:59 +01:00
odain
5aaae3ad9c N°8981 setup wizard: static removal + cleanup 2026-03-18 14:14:59 +01:00
odain
3b6ead1307 N°8981 : add type in function 2026-03-18 14:14:59 +01:00
odain
4678684ce6 N°8981 setup wizard: cache GetParamForConfigArray 2026-03-18 14:14:59 +01:00
odain
c008483625 N°8981 setup wizard: cleanup main actions + remove static when possible 2026-03-18 14:14:59 +01:00
odain
bfef10d636 N°8981 setup wizard: cleanup config use in setup wizard 2026-03-18 14:14:59 +01:00
odain
d84959ce6c test SDK enhancement: be able to compare moduleinstallation
ci: add log and hopefully fix hub test

ci: fix all test that rely on CustomDataTC
2026-03-18 14:14:59 +01:00
odain
b230623a32 N°8981: repair previous setup cleanup (broken setups) 2026-03-18 14:14:59 +01:00
odain
375c1f3a73 N°8981: prepare hub connector test cover
sdk test enhancement : add call itop api

fix ci

ci: fix broken tests

ci: cover hub setup on compile and launch steps

code style

ci: fix ModuleDiscoveryTest redundant class + add logs to investigate ci setup issues

ci: fix log during setup tests
2026-03-18 14:14:59 +01:00
odain
ab7a737512 N°4789 - do not call empty ModuleInstallerAPI class + logs
code style
2026-03-18 14:14:59 +01:00
Timothee
371819f13f N°8864 Passing array instead of html 2026-03-18 14:14:58 +01:00
odain
56cb3cae4f N°8981 - cleanup/simplify setup
fix RecordInstallation due to previous refactoring
2026-03-18 14:14:58 +01:00
Timothee
11b985aaa7 N°9010 Improve tests readability 2026-03-18 14:14:58 +01:00
odain
59fe11b96e ci: fix broken LoginTest 2026-03-18 14:14:58 +01:00
Timmy38
55b03941e8 N°8864 list extensions installation in setup recap 2026-03-18 14:14:58 +01:00
Timothee
2fcd224ffd N°9010 Setup wizard : manage multiple level extension choice 2026-03-18 14:14:58 +01:00
odain
b26e0c8a90 Merge branch 'develop' into feature/uninstallation 2026-03-18 14:14:58 +01:00
odain
b967fb7f20 Merge branch 'develop' into feature/uninstallation 2025-12-19 16:17:12 +01:00
odain
195038c941 Merge branch 'develop' into feature/uninstallation 2025-12-19 15:48:56 +01:00
odain
9a8d87e2b5 Merge branch 'develop' into feature/uninstallation 2025-12-18 14:02:45 +01:00
odain
385302c44c ci: fix nightly 2025-12-08 10:51:28 +01:00
odain
b563f113d0 add combodo-data-feature-removal 2025-12-08 10:38:30 +01:00
odain
715d9d3b1c less logs during setup 2025-12-05 17:37:09 +01:00
odain
7a6c2bc6a4 ci: fix with package 2025-12-05 17:36:57 +01:00
odain
8919184ef9 ci: adapt test to run also with itop packages 2025-12-05 11:36:19 +01:00
odain
7bfaebe4db ci: fix merge and issues with LoadChoicesFromDatabase 2025-12-04 18:40:21 +01:00
odain
8e10cf9b72 N°8760 : fix broken setup
ci: fix merge
2025-12-04 18:28:47 +01:00
odain
9f3d7d2c36 N°8760: revert dry removal audit and use real file deletion again
code formatting
2025-12-04 17:19:18 +01:00
odain
ae980e365d N°8760 :fix ModuleInstallation db query + refactor query in ModuleInstallationService
extensionmap cleanup

fix setup broken
2025-12-04 17:19:18 +01:00
odain
a2b01b3ed4 N°8760 - setupaudit and dry removal API review with Romain - avoid file deletion
N°8760 - be able to simulate extension removal by oerriding GetExtensionMap

be able to simulate SetupAudit errors in Setups for integration tests

fix rebase
2025-12-04 17:19:18 +01:00
odain
9cdc707bc5 N°8760 - Audit uninstall of extensions that declare classes - first prototype
N°8760 - Audit uninstall of extensions that declare classes - be able to trace DM classes created_in

N°8760 - be able to test with additional extensions installed in test SDK

N°8760 - provide a service dedicated to extension removal

N°8760 - compute all rules by default

add comment

adapt audit to both extension and mtp
2025-12-04 17:19:18 +01:00
odain
76178c16b8 N°8760: code legacy refactoring around module computation (AnalyzeInstallation)
AnalyzeInstallation refactoring

fix ci call to ModuleInstallationService

ci: fix code style

get rid of itop_version

refactoring: make code simpler

get rid of unused name_db

refactoring setup: rename version_db by installed_version

refactoring setup: rename version_code by available_version

code cleanup: avoid useless runtimeenv instanciation
2025-12-04 17:19:18 +01:00
494 changed files with 44223 additions and 10752 deletions

View File

@@ -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');

View File

@@ -97,33 +97,125 @@ class RestUtils
* @throws Exception
* @api
*/
public static function GetFieldList($sClass, $oData, $sParamName)
public static function GetFieldList($sClass, $oData, $sParamName, $bFailIfNotFound = true)
{
$sFields = self::GetOptionalParam($oData, $sParamName, '*');
$aShowFields = [];
if ($sFields == '*') {
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
$aShowFields[$sClass][] = $sAttCode;
}
} elseif ($sFields == '*+') {
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass) {
foreach (MetaModel::ListAttributeDefs($sRefClass) as $sAttCode => $oAttDef) {
$aShowFields[$sRefClass][] = $sAttCode;
}
}
} else {
foreach (explode(',', $sFields) as $sAttCode) {
$sAttCode = trim($sAttCode);
if (($sAttCode != 'id') && (!MetaModel::IsValidAttCode($sClass, $sAttCode))) {
throw new Exception("$sParamName: invalid attribute code '$sAttCode'");
}
$aShowFields[$sClass][] = $sAttCode;
}
}
return $aShowFields;
return match($sFields) {
'*' => self::GetFieldListForClass($sClass),
'*+' => self::GetFieldListForParentClass($sClass),
default => self::GetLimitedFieldListForClass($sClass, $sFields, $sParamName, $bFailIfNotFound),
};
}
/**
* Check if the requested field list asks for an extended output.
*
* Extended output is requested when using '*+' or class-scoped field definitions.
*
* @param string $sFields Requested field specification.
*
* @return bool
*/
public static function HasRequestedExtendedOutput(string $sFields): bool
{
return match($sFields) {
'*' => false,
'*+' => true,
default => substr_count($sFields, ':') > 1,
};
}
/**
* Check if the requested field list asks for all output fields.
*
* @param string $sFields Requested field specification.
*
* @return bool
*/
public static function HasRequestedAllOutputFields(string $sFields): bool
{
return match($sFields) {
'*', '*+' => true,
default => false,
};
}
protected static function GetFieldListForClass(string $sClass): array
{
return [$sClass => array_keys(MetaModel::ListAttributeDefs($sClass))];
}
/**
* Build a field list for all child classes of the given parent class.
*
* @param string $sClass Parent class name.
*
* @return array Array of class => list of attribute codes.
*/
protected static function GetFieldListForParentClass(string $sClass): array
{
$aFieldList = array();
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass) {
$aFieldList = array_merge($aFieldList, self::GetFieldListForClass($sRefClass));
}
return $aFieldList;
}
/**
* Build a restricted field list for one class from a comma-separated attribute list.
*
* @param string $sClass Class name.
* @param string $sFields Comma-separated list of requested attribute codes.
* @param string $sParamName Input parameter name used in error messages.
* @param bool $bFailIfNotFound If true, throws when an attribute code is invalid.
*
* @return array Array containing one class => list of attribute codes.
* @throws Exception When an attribute code is invalid and $bFailIfNotFound is true.
*/
protected static function GetLimitedFieldListForSingleClass(string $sClass, string $sFields, string $sParamName, bool $bFailIfNotFound = true): array
{
$aFieldList = [$sClass => []];
foreach (explode(',', $sFields) as $sAttCode) {
$sAttCode = trim($sAttCode);
if (($sAttCode == 'id') || (MetaModel::IsValidAttCode($sClass, $sAttCode))) {
$aFieldList[$sClass][] = $sAttCode;
} else {
if ($bFailIfNotFound) {
throw new Exception("$sParamName: invalid attribute code '$sAttCode' for class '$sClass'");
}
}
}
return $aFieldList;
}
/**
* Build a restricted field list for one or several classes.
*
* Accepted formats are either "att1,att2" for a single class, or
* "ClassA:att1,att2;ClassB:att3" for class-scoped field definitions.
*
* @param string $sClass Default class name used when no class scope is specified.
* @param string $sFields Requested field specification.
* @param string $sParamName Input parameter name used in error messages.
* @param bool $bFailIfNotFound If true, throws when an attribute code is invalid.
*
* @return array Array of class => list of attribute codes.
* @throws Exception Propagated from GetLimitedFieldListForSingleClass.
*/
protected static function GetLimitedFieldListForClass(string $sClass, string $sFields, string $sParamName, bool $bFailIfNotFound = true): array
{
if (!str_contains($sFields, ':')) {
return self::GetLimitedFieldListForSingleClass($sClass, $sFields, $sParamName, $bFailIfNotFound);
}
$aFieldList = [];
$aFieldListParts = explode(';', $sFields);
foreach ($aFieldListParts as $sClassFields) {
list($sSubClass, $sSubClassFields) = explode(':', $sClassFields);
$aFieldList = array_merge($aFieldList, self::GetLimitedFieldListForSingleClass(trim($sSubClass), trim($sSubClassFields), $sParamName, $bFailIfNotFound));
}
return $aFieldList;
}
/**
* Read and interpret object search criteria from a Rest/Json structure
*

View File

@@ -175,6 +175,11 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
*/
protected $sDisplayMode;
protected $aFieldsMap;
/**
* @var array Store posted values in order to be used in GetAttributeFlags
* @since 3.3.0
*/
protected $aPostedValues = [];
/**
* If true, bypass IsActionAllowedOnAttribute when writing this object
@@ -524,6 +529,12 @@ JS
$sLabel = Dict::S('Tag:Synchronized');
$sSynchroTagId = 'synchro_icon-'.$this->GetKey();
$aTags[$sSynchroTagId] = ['title' => $sTip, 'css_classes' => 'ibo-object-details--tag--synchronized', 'decoration_classes' => 'fas fa-lock', 'label' => $sLabel];
if (UserRights::IsActionAllowed(SynchroReplica::class, UR_ACTION_READ)) {
$oDBSearch = DBObjectSearch::FromOQL('SELECT SynchroReplica WHERE dest_class=:sClass AND dest_id=:id');
$sFilter = rawurlencode($oDBSearch->serialize(false, ['sClass' => get_class($this),'id' => $this->GetKey()]));
$sUrlSearchReplica = 'UI.php?operation=search&filter='.$sFilter;
$oPage->add_ready_script("$('#$sSynchroTagId').on('click',function() {window.location = '$sUrlSearchReplica' });");
}
}
}
@@ -3986,6 +3997,7 @@ HTML;
$aErrors = [];
$aFinalValues = [];
$this->aPostedValues = $aValues; // Store the values for later use (e.g. in GetAttributeFlags)
foreach ($this->GetWriteableAttList(array_keys($aValues), $aErrors, $aAttFlags) as $sAttCode => $oAttDef) {
$aFinalValues[$sAttCode] = $aValues[$sAttCode];
}

View File

@@ -497,7 +497,7 @@ EOF
* @param array $aExtraParams
* @param bool $bCanEdit
*
* @return \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout
* @return null|\Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = [], $bCanEdit = true)
{

View File

@@ -1078,7 +1078,6 @@ JS
if ($aCounts[$sStateValue] == 0) {
$aCounts[$sStateValue] = ['link' => '-', 'label' => $aCounts[$sStateValue]];
;
} else {
$oSingleGroupByValueFilter = $this->m_oFilter->DeepClone();
$oSingleGroupByValueFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
@@ -1947,8 +1946,8 @@ class MenuBlock extends DisplayBlock
$sSelectedClassName = MetaModel::GetName($sSelectedClass);
// Check rights on class
$bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sSelectedClass)) && UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_MODIFY) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject'));
$bIsBulkDeleteAllowed = (bool) UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_DELETE);
$bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sSelectedClass)) && UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_MODIFY) && (($oReflectionClass->IsSubclassOf(cmdbAbstractObject::class) || $sSelectedClass === SynchroReplica::class));
$bIsBulkDeleteAllowed = (bool)UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_DELETE);
// Refine filter on selected class so bullk actions occur on the right class
$oSelectedClassFilter = $this->GetFilter()->DeepClone();
@@ -1958,7 +1957,15 @@ class MenuBlock extends DisplayBlock
// Action label dict code has a specific suffix for "Link" / "Remote" aliases to allow dedicated labels in linksets.
$sActionLabelCodeSuffix = in_array($sSelectedAlias, ['Link', 'Remote']) ? $sSelectedAlias : 'Class';
if ($bIsBulkModifyAllowed) {
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:ModifyAll:'.$sSelectedAlias, Dict::Format('UI:Menu:ModifyAll_'.$sActionLabelCodeSuffix, $sSelectedClassName));
if ($sSelectedClass === SynchroReplica::class) {
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:UnlinkAll:', Dict::S('Class:SynchroReplica/Action:unlink_all'), 'unlink');
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:UnLinkSynchroAll:', Dict::S('Class:SynchroReplica/Action:unlinksynchro_all'), 'unlinksynchro');
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:SynchroAll:', Dict::S('Class:SynchroReplica/Action:synchro_all'), 'synchro');
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:AllowDeleteAll:', Dict::S('Class:SynchroReplica/Action:allowdelete_all'), 'allowdelete');
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:DenyDeleteAll:', Dict::S('Class:SynchroReplica/Action:denydelete_all'), 'denydelete');
} else {
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:ModifyAll:'.$sSelectedAlias, Dict::Format('UI:Menu:ModifyAll_'.$sActionLabelCodeSuffix, $sSelectedClassName));
}
}
if ($bIsBulkDeleteAllowed) {
$this->AddBulkDeleteObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:BulkDelete:'.$sSelectedAlias, Dict::Format('UI:Menu:BulkDelete_'.$sActionLabelCodeSuffix, $sSelectedClassName));
@@ -2478,11 +2485,11 @@ class MenuBlock extends DisplayBlock
* @since 3.1.0
* @internal
*/
protected function AddBulkModifyObjectsMenuAction(array &$aActions, string $sClass, string $sFilter, string $sActionIdentifier = 'UI:Menu:ModifyAll', $sActionLabel = 'UI:Menu:ModifyAll'): void
protected function AddBulkModifyObjectsMenuAction(array &$aActions, string $sClass, string $sFilter, string $sActionIdentifier = 'UI:Menu:ModifyAll', $sActionLabel = 'UI:Menu:ModifyAll', $sOperationName = 'modify'): void
{
$aActions[$sActionIdentifier] = [
'label' => Dict::S($sActionLabel),
'url' => $this->PrepareUrlForStandardMenuAction($sClass, "operation=select_for_modify_all&class=$sClass&filter=".urlencode($sFilter)),
'label' => Dict::S($sActionLabel),
'url' => $this->PrepareUrlForStandardMenuAction($sClass, 'operation=select_for_'.$sOperationName.'_all&class='.$sClass.'&filter='.urlencode($sFilter)),
] + $this->GetDefaultParamsForMenuAction();
}

View File

@@ -14,6 +14,8 @@ class CoreException extends Exception
/**
* CoreException constructor.
*
* ATTENTION: Logging here will break the CI
*
* @param string $sIssue error message
* @param array|null $aContextData key/value array, value MUST implements _toString
* @param string $sImpact

View File

@@ -1387,7 +1387,7 @@ class DesignerIconSelectionField extends DesignerFormField
public function AddAllowedValue($aValue)
{
// Add a null value to the list of allowed values
$this->aAllowedValues = array_merge([$aValue], $this->aAllowedValues);
$this->aAllowedValues = array_merge([$aValue], $this->aAllowedValues ?? [null]);
}
public function EnableUpload($sIconUploadUrl)
{

View File

@@ -17,6 +17,7 @@
// 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\Helper\Session;
use Combodo\iTop\Service\Startup\StartupService;
require_once(APPROOT.'core/cmdbobject.class.inc.php');
require_once(APPROOT.'application/utils.inc.php');
@@ -69,26 +70,7 @@ $oKPI->ComputeAndReport("Session Start");
$sSwitchEnv = utils::ReadParam('switch_env', null);
$bAllowCache = true;
if (($sSwitchEnv != null) && file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE) && (Session::Get('itop_env') !== $sSwitchEnv)) {
Session::Set('itop_env', $sSwitchEnv);
$sEnv = $sSwitchEnv;
$bAllowCache = false;
// Reset the opcache since otherwise the PHP "model" files may still be cached !!
if (function_exists('opcache_reset')) {
// Zend opcode cache
opcache_reset();
}
if (function_exists('apc_clear_cache')) {
// APC(u) cache
apc_clear_cache();
}
// TODO: reset the credentials as well ??
} elseif (Session::IsSet('itop_env')) {
$sEnv = Session::Get('itop_env');
} else {
$sEnv = ITOP_DEFAULT_ENV;
Session::Set('itop_env', ITOP_DEFAULT_ENV);
}
$sEnv = (new StartupService())->SetItopEnvironment($sSwitchEnv, $bAllowCache);
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
try {
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);

View File

@@ -284,9 +284,7 @@ class utils
}
// Read and record the value for switching the archive mode
$iCurrent = self::ReadParam('with-archive', $iDefault);
if (Session::IsInitialized()) {
Session::Set('archive_mode', $iCurrent);
}
Session::Set('archive_mode', $iCurrent);
// Read and use the value for the current page (web services)
$iCurrent = self::ReadParam('with_archive', $iCurrent, true);
self::$bPageMode = ($iCurrent == 1);
@@ -976,7 +974,7 @@ class utils
return self::$oConfig;
}
$sProductionEnvConfigPath = self::GetConfigFilePath('production');
$sProductionEnvConfigPath = self::GetConfigFilePath(ITOP_DEFAULT_ENV);
if (file_exists($sProductionEnvConfigPath)) {
$oProductionEnvDiskConfig = new Config($sProductionEnvConfigPath);
self::SetConfig($oProductionEnvDiskConfig);
@@ -1919,7 +1917,9 @@ SQL;
$aResponseHeaders[$sName] = $sValue;
}
}
curl_close($ch);
if (PHP_VERSION_ID < 80000) {
curl_close($ch);
}
return $response;
}
@@ -3192,4 +3192,30 @@ TXT
}
}
}
/**
* Read memory limit from the php.ini file
*
* @return int Memory limit in bytes
*/
public static function GetMemoryLimit(): int
{
$sLimit = ini_get('memory_limit');
if ($sLimit == '-1') {
return 128 * 1048576;
}
switch (substr($sLimit, -1)) {
case 'M':
case 'm':
return (int)$sLimit * 1048576;
case 'K':
case 'k':
return (int)$sLimit * 1024;
case 'G':
case 'g':
return (int)$sLimit * 1073741824;
default:
return (int)$sLimit;
}
}
}

View File

@@ -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');

View File

@@ -20,9 +20,6 @@
*
*/
use Combodo\iTop\Config\Validator\iTopConfigAstValidator;
use Combodo\iTop\Config\Validator\iTopConfigSyntaxValidator;
define('ITOP_APPLICATION', 'iTop');
define('ITOP_APPLICATION_SHORT', 'iTop');
@@ -1182,8 +1179,8 @@ class Config
'tracking_level_linked_set_default' => [
'type' => 'integer',
'description' => 'Default tracking level if not explicitly set at the attribute level, for AttributeLinkedSet (defaults to NONE in case of a fresh install, LIST otherwise - this to preserve backward compatibility while upgrading from a version older than 2.0.3 - see TRAC #936)',
'default' => LINKSET_TRACKING_LIST,
'value' => LINKSET_TRACKING_LIST,
'default' => LINKSET_TRACKING_NONE,
'value' => LINKSET_TRACKING_NONE,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
@@ -2755,14 +2752,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']);
@@ -2810,7 +2806,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']);
@@ -2828,17 +2827,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)) {

View File

@@ -5108,8 +5108,8 @@ abstract class DBObject implements iDisplay
protected function GetReferencingObjectsForDeletion($bAllowAllData = false)
{
$aDependentObjects = [];
$aRererencingMe = MetaModel::EnumReferencingClasses(get_class($this));
foreach ($aRererencingMe as $sRemoteClass => $aExtKeys) {
$aReferencingMe = MetaModel::EnumReferencingClasses(get_class($this));
foreach ($aReferencingMe as $sRemoteClass => $aExtKeys) {
/** @var \AttributeExternalKey $oExtKeyAttDef */
foreach ($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef) {
// skip if external key doesn't require the deletion cascading

View File

@@ -360,10 +360,10 @@ class DesignElement extends \DOMElement
* @param string $sTagName
* @param string|null $sDefault
*
* @return string
* @return null|string
* @throws \DOMFormatException
*/
public function GetChildText($sTagName, $sDefault = null)
public function GetChildText($sTagName, $sDefault = null): ?string
{
$sRet = $sDefault;
if ($oChild = $this->GetOptionalElement($sTagName)) {

View File

@@ -22,6 +22,7 @@ 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\Setup\ModuleDiscovery\ModuleFileReader;
require_once APPROOT.'core/modulehandler.class.inc.php';
require_once APPROOT.'core/querymodifier.class.inc.php';
@@ -128,7 +129,7 @@ abstract class MetaModel
/** @var array */
private static $m_aClassToFile = [];
/** @var string */
protected static $m_sEnvironment = 'production';
protected static $m_sEnvironment = ITOP_DEFAULT_ENV;
/**
* Objects currently created/updated.
@@ -462,6 +463,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
*
@@ -4621,12 +4659,15 @@ abstract class MetaModel
* @throws \CoreException
* @throws \MySQLException
*/
public static function DBExists($bMustBeComplete = true)
public static function DBExists($bMustBeComplete = true, ?string $sDBName = null)
{
if (!CMDBSource::IsDB(self::$m_sDBName)) {
if (is_null($sDBName)) {
$sDBName = self::$m_sDBName;
}
if (!CMDBSource::IsDB($sDBName)) {
return false;
}
CMDBSource::SelectDB(self::$m_sDBName);
CMDBSource::SelectDB($sDBName);
$aFound = [];
$aMissing = [];
@@ -5709,7 +5750,7 @@ abstract class MetaModel
* @throws \DictExceptionUnknownLanguage
* @throws \Exception
*/
public static function Startup($config, $bModelOnly = false, $bAllowCache = true, $bTraceSourceFiles = false, $sEnvironment = 'production')
public static function Startup($config, $bModelOnly = false, $bAllowCache = true, $bTraceSourceFiles = false, $sEnvironment = ITOP_DEFAULT_ENV)
{
// Startup on a new environment is not supported
static $bStarted = false;

View File

@@ -340,13 +340,14 @@ class ormDocument
* @param string $sContentDisposition Either 'inline' or 'attachment'
* @param string $sSecretField The attcode of the field containing a "secret" to be provided in order to retrieve the file
* @param string $sSecretValue The value of the secret to be compared with the value of the attribute $sSecretField
* @param bool $bAllowAllData If true, no rights filtering is applied
*
* @return void
*/
public static function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachment', $sSecretField = null, $sSecretValue = null)
public static function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachment', $sSecretField = null, $sSecretValue = null, $bAllowAllData = false)
{
try {
$oObj = MetaModel::GetObject($sClass, $id, false, false);
$oObj = MetaModel::GetObject($sClass, $id, false, $bAllowAllData);
if (!is_object($oObj)) {
// If access to the document is not granted, check if the access to the host object is allowed
$oObj = MetaModel::GetObject($sClass, $id, false, true);

View File

@@ -52,7 +52,7 @@ class ormPassword
public function SetPassword($sClearTextPassword)
{
$iHashAlgo = MetaModel::GetConfig()->GetPasswordHashAlgo();
$this->m_sHashed = password_hash($sClearTextPassword, $iHashAlgo);
$this->m_sHashed = password_hash($sClearTextPassword ?? '', $iHashAlgo);
}
/**
@@ -99,10 +99,10 @@ class ormPassword
$aInfo = password_get_info($this->m_sHashed);
if (is_null($aInfo["algo"]) || $aInfo["algo"] === 0) {
// - Unknown algorithm, assume it's a legacy password
$sHashedPwd = $this->ComputeHash($sClearTextPassword);
$sHashedPwd = $this->ComputeHash($sClearTextPassword ?? '');
$bResult = hash_equals($this->m_sHashed, $sHashedPwd);
} else {
$bResult = password_verify($sClearTextPassword, $this->m_sHashed);
$bResult = password_verify($sClearTextPassword ?? '', $this->m_sHashed);
}
return $bResult;
}

View File

@@ -43,24 +43,24 @@ final class ormTagSet extends ormSet
/**
*
* @param array $aTagCodes
* @param array|null $aItems
*
* @throws \CoreException
* @throws \CoreUnexpectedValue when a code is invalid
*/
public function SetValues($aTagCodes)
public function SetValues($aItems)
{
if (is_null($aTagCodes)) {
$aTagCodes = [];
if (is_null($aItems)) {
$aItems = [];
}
if (!is_array($aTagCodes)) {
throw new CoreUnexpectedValue("Wrong value {$aTagCodes} for {$this->sClass}:{$this->sAttCode}");
if (!is_array($aItems)) {
throw new CoreUnexpectedValue("Wrong value {$aItems} for {$this->sClass}:{$this->sAttCode}");
}
$oTags = [];
$iCount = 0;
$bError = false;
foreach ($aTagCodes as $sTagCode) {
foreach ($aItems as $sTagCode) {
$iCount++;
if (($this->iLimit != 0) && ($iCount > $this->iLimit)) {
$bError = true;

View File

@@ -248,6 +248,45 @@ class RestResultWithObjects extends RestResult
}
}
/**
* @package RESTAPI
* @api
*/
class RestResultWithObjectSets extends RestResultWithObjects
{
private $current_object = null;
public function MakeNewObjectSet()
{
$arr = array();
$this->current_object = &$arr;
$this->objects[] = &$arr;
}
/**
* Report the given object
*
* @api
* @param string $sObjectAlias Name of the subobject, usually the OQL class alias
* @param int $iCode An error code (RestResult::OK is no issue has been found)
* @param string $sMessage Description of the error if any, an empty string otherwise
* @param DBObject $oObject The object being reported
* @param array|null $aFieldSpec An array of class => attribute codes (Cf. RestUtils::GetFieldList). List of the attributes to be reported.
* @param boolean $bExtendedOutput Output all of the link set attributes ?
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
public function AppendSubObject($sObjectAlias, $iCode, $sMessage, $oObject, $aFieldSpec = null, $bExtendedOutput = false)
{
$oObjRes = ObjectResult::FromDBObject($oObject, $aFieldSpec, $bExtendedOutput, $iCode, $sMessage);
$this->current_object[$sObjectAlias] = $oObjRes;
}
}
/**
* @package RESTAPI
* @api
@@ -500,15 +539,22 @@ class CoreServices implements iRestServiceProvider, iRestInputSanitizer
break;
case 'core/get':
$sClass = RestUtils::GetClass($aParams, 'class');
$sClassParam = RestUtils::GetMandatoryParam($aParams, 'class');
$key = RestUtils::GetMandatoryParam($aParams, 'key');
$aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
$bExtendedOutput = (RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+');
$sShowFields = RestUtils::GetOptionalParam($aParams, 'output_fields', '*');
$iLimit = (int)RestUtils::GetOptionalParam($aParams, 'limit', 0);
$iPage = (int)RestUtils::GetOptionalParam($aParams, 'page', 1);
$oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key, $iLimit, self::getOffsetFromLimitAndPage($iLimit, $iPage));
$sTargetClass = $oObjectSet->GetFilter()->GetClass();
// Validate the class(es)
$aClass = explode(',', $sClassParam);
foreach ($aClass as $sClass) {
if (!MetaModel::IsValidClass(trim($sClass))) {
throw new Exception("class '$sClass' is not valid");
}
}
$oObjectSet = RestUtils::GetObjectSetFromKey($sClassParam, $key, $iLimit, self::getOffsetFromLimitAndPage($iLimit, $iPage));
$sTargetClass = $oObjectSet->GetFilter()->GetClass();
if (UserRights::IsActionAllowed($sTargetClass, UR_ACTION_READ) != UR_ALLOWED_YES) {
$oResult->code = RestResult::UNAUTHORIZED;
@@ -519,19 +565,67 @@ class CoreServices implements iRestServiceProvider, iRestInputSanitizer
} elseif ($iPage < 1) {
$oResult->code = RestResult::INVALID_PAGE;
$oResult->message = "The request page number is not valid. It must be an integer greater than 0";
} else {
if (!$bExtendedOutput && RestUtils::GetOptionalParam($aParams, 'output_fields', '*') != '*') {
$aFields = $aShowFields[$sClass];
//Id is not a valid attribute to optimize
if (in_array('id', $aFields)) {
unset($aFields[array_search('id', $aFields)]);
}
$aAttToLoad = [$oObjectSet->GetClassAlias() => $aFields];
$oObjectSet->OptimizeColumnLoad($aAttToLoad);
} elseif (count($oObjectSet->GetSelectedClasses()) > 1) {
$oResult = new RestResultWithObjectSets();
$aCache = [];
$aShowFields = [];
foreach ($oObjectSet->GetSelectedClasses() as $sSelectedClass) {
$aShowFields = array_merge( $aShowFields, RestUtils::GetFieldList($sSelectedClass, $aParams, 'output_fields', false));
}
while ($oObjects = $oObjectSet->FetchAssoc()) {
$oResult->MakeNewObjectSet();
foreach ($oObjects as $sAlias => $oObject) {
if (!$oObject) {
continue;
}
if (!array_key_exists($sAlias, $aCache)) {
$sClass = get_class($oObject);
$bExtendedOutput = RestUtils::HasRequestedExtendedOutput($sShowFields);
if (!RestUtils::HasRequestedAllOutputFields($sShowFields)) {
$aFields = $aShowFields[$sClass];
//Id is not a valid attribute to optimize
if ($aFields && in_array('id', $aFields)) {
unset($aFields[array_search('id', $aFields)]);
}
$aAttToLoad = [$sAlias => $aFields];
$oObjectSet->OptimizeColumnLoad($aAttToLoad);
}
$aCache[$sAlias] = [
'aShowFields' => $aShowFields,
'bExtendedOutput' => $bExtendedOutput,
];
} else {
$aShowFields = $aCache[$sAlias]['aShowFields'];
$bExtendedOutput = $aCache[$sAlias]['bExtendedOutput'];
}
$oResult->AppendSubObject($sAlias, 0, '', $oObject, $aShowFields, $bExtendedOutput);
}
}
$oResult->message = "Found: ".$oObjectSet->Count();
} else {
$aShowFields =[];
foreach ($aClass as $sSelectedClass) {
$sSelectedClass = trim($sSelectedClass);
$aShowFields = array_merge($aShowFields, RestUtils::GetFieldList($sSelectedClass, $aParams, 'output_fields', false));
}
if (!RestUtils::HasRequestedAllOutputFields($sShowFields) && count($aShowFields) == 1) {
$aFields = $aShowFields[$sClass];
//Id is not a valid attribute to optimize
if (in_array('id', $aFields)) {
unset($aFields[array_search('id', $aFields)]);
}
$aAttToLoad = [$oObjectSet->GetClassAlias() => $aFields];
$oObjectSet->OptimizeColumnLoad($aAttToLoad);
}
while ($oObject = $oObjectSet->Fetch()) {
$oResult->AddObject(0, '', $oObject, $aShowFields, $bExtendedOutput);
$oResult->AddObject(0, '', $oObject, $aShowFields, RestUtils::HasRequestedExtendedOutput($sShowFields));
}
$oResult->message = "Found: ".$oObjectSet->Count();
}

View File

@@ -22,4 +22,6 @@
@import "medallion-with-blocklist";
@import "field-badge-within-datatable";
@import "jquery-blockui-within-dialog";
@import "jquery-blockui-within-datatable";
@import "jquery-blockui-within-datatable";
@import "badge-with-badge";
@import "extension-details-with-extension-details";

View File

@@ -0,0 +1,10 @@
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-badge--spacing-left--with-same-block: $ibo-spacing-200 !default;
.ibo-badge + .ibo-badge {
margin-left: $ibo-badge--spacing-left--with-same-block;
}

View File

@@ -0,0 +1,11 @@
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-extension-details--margin-top: $ibo-spacing-300 !default;
.ibo-extension-details + .ibo-extension-details,
.ibo-extension-details--information--description .ibo-extension-details {
margin-top: $ibo-extension-details--margin-top;
}

View File

@@ -33,4 +33,5 @@
@import "field-badge";
@import "file-select";
@import "medallion-icon";
@import "toast";
@import "toast";
@import "badge";

View File

@@ -0,0 +1,41 @@
$ibo-badge--padding-x : $ibo-spacing-200 !default;
$ibo-badge--padding-y : $ibo-spacing-100 !default;
$ibo-badge--border-radius : $ibo-border-radius-400 !default;
$ibo-badge-colors: (
'primary': ($ibo-color-primary-100, $ibo-color-primary-900),
'secondary': ($ibo-color-secondary-100, $ibo-color-secondary-900),
'neutral': ($ibo-color-secondary-100, $ibo-color-secondary-900),
'information': ($ibo-color-information-100, $ibo-color-information-900),
'success': ($ibo-color-success-100, $ibo-color-success-900),
'failure': ($ibo-color-danger-100, $ibo-color-danger-900),
'warning': ($ibo-color-warning-100,$ibo-color-warning-900),
'danger': ($ibo-color-danger-100,$ibo-color-danger-900),
'grey' : ($ibo-color-grey-100, $ibo-color-grey-900),
'blue-grey': ($ibo-color-blue-grey-100, $ibo-color-blue-grey-900),
'blue': ($ibo-color-blue-100, $ibo-color-blue-900),
'cyan': ($ibo-color-cyan-100, $ibo-color-cyan-900),
'green': ($ibo-color-green-100, $ibo-color-green-900),
'orange' : ($ibo-color-orange-100, $ibo-color-orange-900),
'red': ($ibo-color-red-100, $ibo-color-red-900),
'pink': ($ibo-color-pink-100, $ibo-color-pink-900),
) !default;
.ibo-badge {
display: inline-block;
white-space: nowrap;
padding : $ibo-badge--padding-y $ibo-badge--padding-x;
border-radius : $ibo-badge--border-radius;
@extend %ibo-font-ral-med-50;
@each $sColor, $aColorValues in $ibo-badge-colors {
$bg-color: nth($aColorValues, 1);
$text-color: nth($aColorValues, 2);
&.ibo-is-#{$sColor} {
background-color: $bg-color;
color: $text-color;
}
}
}

View File

@@ -8,6 +8,7 @@ $ibo-toggler--wrapper--height: 20px !default;
$ibo-toggler--slider--border-radius: $ibo-border-radius-900 !default;
$ibo-toggler--slider--background-color: $ibo-color-secondary-600 !default;
$ibo-toggler--slider--disabled--background-color: $ibo-color-secondary-200 !default;
$ibo-toggler--slider--before--left: 3px !default;
$ibo-toggler--slider--before--bottom: 3px !default;
@@ -17,6 +18,7 @@ $ibo-toggler--slider--before--border-radius: $ibo-border-radius-full !default;
$ibo-toggler--slider--before--background-color: $ibo-color-grey-100 !default;
$ibo-toggler--slider--checked--background-color: $ibo-color-primary-600 !default;
$ibo-toggler--slider--checked-disabled--background-color: $ibo-color-primary-200 !default;
$ibo-toggler--slider--focus--box-shadow: 0 0 1px $ibo-color-primary-600 !default;
$ibo-toggler--label--margin-left: 4px !default;
@@ -61,6 +63,13 @@ $ibo-toggler--label--margin-left: 4px !default;
background-color: $ibo-toggler--slider--checked--background-color;
}
.ibo-toggler--wrapper input:disabled + .ibo-toggler--slider {
background-color: $ibo-toggler--slider--disabled--background-color;
}
.ibo-toggler--wrapper input:checked:disabled + .ibo-toggler--slider {
background-color: $ibo-toggler--slider--checked-disabled--background-color;
}
input:focus + .ibo-toggler--slider {
box-shadow: $ibo-toggler--slider--focus--box-shadow;
}

View File

@@ -15,3 +15,4 @@
@import "wizard-container/wizard-container";
@import "object/all";
@import "activity-panel/all";
@import "extension/all";

View File

@@ -0,0 +1 @@
@import "extension-details";

View File

@@ -0,0 +1,76 @@
$ibo-extension-details--information--metadata--padding: $ibo-spacing-200 !default;
$ibo-extension-details--information--metadata--delimiter: "-" !default;
$ibo-extension-details--information--metadata--color: $ibo-color-grey-700 !default;
$ibo-extension-details--actions--button--padding-y: 3px !default;
$ibo-extension-details--actions--button--padding-x: $ibo-button--padding-x !default;
.ibo-extension-details {
display: inline-flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
}
.ibo-extension-details--information {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.ibo-extension-details--actions {
display: flex;
}
.ibo-extension-details--information--label {
@extend %ibo-font-ral-med-150;
}
.ibo-extension-details--information--metadata {
@extend %ibo-font-ral-med-100;
color: $ibo-extension-details--information--metadata--color;
}
.ibo-extension-details--information--description {
@extend %ibo-font-ral-med-100;
}
.ibo-extension-details--information--metadata span + span:before {
content: $ibo-extension-details--information--metadata--delimiter;
padding-left: $ibo-extension-details--information--metadata--padding;
padding-right: $ibo-extension-details--information--metadata--padding;
}
//ibo-extension-details can have other ibo-extension-details inside its ibo-extension-details--information--description in the setup. We need to only affect direct children
.ibo-extension-details:has(>.ibo-extension-details--actions input:is([type="checkbox"], [type="radio"]):checked){
&>.ibo-extension-details--information>.ibo-extension-details--information--label .ibo-badge.unchecked {
display: none;
}
}
//Merging the two lines below with :is([type="checkbox"], [type="radio"]) will generate a warning in scss compiler
.ibo-extension-details:has(>.ibo-extension-details--actions input[type="checkbox"]:not(:checked)),
.ibo-extension-details:has(>.ibo-extension-details--actions input[type="radio"]:not(:checked)) {
&>.ibo-extension-details--information>.ibo-extension-details--information--label .ibo-badge.checked {
display: none;
}
}
.ibo-extension-details--actions > button {
padding: $ibo-extension-details--actions--button--padding-y $ibo-extension-details--actions--button--padding-x;
}
.ibo-extension-details--actions:has(.toggler-install:not(:disabled)) .ibo-popover-menu--section a[data-resource-id="force_uninstall"] {
display: none;
}
.ibo-extension-details .ibo-popover-menu ~ .ibo-button{
visibility: hidden;
}
.ibo-extension-details .ibo-popover-menu:has(.ibo-popover-menu--item) ~ .ibo-button{
visibility: visible;
}
.ibo-extension-details .ibo-toggler--wrapper:has(.ibo-toggler.ibo-is-hidden){
visibility: hidden;
}

View File

@@ -80,4 +80,14 @@ $ibo-data-synchro-source--synoptics--cell--arrow--border: 2px solid $ibo-data-sy
}
.ibo-data-synchro-source--replicas-status--warning{
margin: $ibo-data-synchro-source--replicas-status--warning--margin;
}
.ibo-page-header--replica-title{
display: table;
width: 100%;
>.ibo-toolbar--button{
display: table-cell;
vertical-align: middle;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -316,29 +316,34 @@ fieldset {
background-color: #F7FAFC;
padding: 10px;
.wiz-choice{
&:checked ~ .description {
#itop-ticket-mgmt-simple-ticket-enhanced-portal:not(:checked),
#itop-ticket-mgmt-itil-enhanced-portal:not(:checked) {
~ .description::after {
content: "Legacy portal is no longer part of iTop, by leaving this option unchecked your portal users won't be able to access iTop anymore.";
display: block;
margin-top: 0.5em;
font-weight: bold;
color: $legacy-portal-removal-text-color;
}
}
}
&:not(:checked) ~ label .setup-extension-tag.checked{
&:not(:checked) ~ label .checked{
display:none;
}
&:checked ~ label .setup-extension-tag.unchecked{
&:checked ~ label .unchecked{
display:none;
}
}
}
.ibo-extension-details:has(>.ibo-extension-details--actions>input:checked) {
.ibo-extension-details:has(#itop-ticket-mgmt-simple-ticket-enhanced-portal:not(:checked), #itop-ticket-mgmt-itil-enhanced-portal:not(:checked)) {
.ibo-extension-details--information--description::after {
content: "Legacy portal is no longer part of iTop, by leaving this option unchecked your portal users won't be able to access iTop anymore.";
display: block;
margin-top: 0.5em;
font-weight: bold;
color: $legacy-portal-removal-text-color;
}
}
}
.ibo-extension-details--information--metadata{
color: $ibo-color-grey-800;
}
.choice-disabled {
color: $ibo-color-grey-700;
}
body {
font-size: 1.17rem;
@@ -522,10 +527,12 @@ body {
}
}
.ibo-setup-summary-title {
font-size: $ibo-font-size-150;
.ibo-setup-summary-title, .ibo-setup-summary-title:visited, .ibo-setup-summary-title:hover {
font-size: $ibo-font-size-150;
color: inherit;
}
#ibo-setup-licenses--components-list {
background-color: $ibo-color-white-200;
padding: 12px;
@@ -605,6 +612,7 @@ body {
color:#a00000;
}
.setup-extension-tag {
display: inline-flex;
background-color: grey;
border-radius: 8px;
padding-left: 3px;
@@ -630,6 +638,21 @@ body {
}
}
.ibo-extension-details {
align-items: flex-start;
}
.ibo-extension-details--actions input{
margin:0.2em 0.5em;
width: 12px;
}
:not(.ibo-badge) ~ .ibo-badge{
margin-left:0.5em;
}
.ibo-extension-details--information--label i{
font-size : 0.9em;
margin-left:0.3em;
}
.setup--wizard-choice--label + .setup--wizard-choice--more-info {
margin-left: 0.5rem;
}
@@ -676,14 +699,10 @@ body {
}
}
#progress_content {
height: 200px;
overflow: auto;
text-align: center;
}
#installation_progress {
display: none;
#progress_content *:not(.message) + .message {
margin-top: 1.5rem;
}
#fresh_content{
border: 0;
min-height: 300px;

View File

@@ -22,5 +22,5 @@
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:darkmoon' => '暗月',
'theme:darkmoon' => 'Dark moon',
]);

View File

@@ -23,5 +23,5 @@
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:fullmoon-high-contrast' => 'Fullmoon (High contrast)~~',
'theme:fullmoon-high-contrast' => 'Fullmoon (高对比度)',
]);

View File

@@ -23,5 +23,5 @@
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:fullmoon-protanopia-deuteranopia' => 'Fullmoon (Protanopia & Deuteranopia)~~',
'theme:fullmoon-protanopia-deuteranopia' => 'Fullmoon (红绿色盲 & 绿色色盲)',
]);

View File

@@ -23,5 +23,5 @@
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:fullmoon-tritanopia' => 'Fullmoon (Tritanopia)~~',
'theme:fullmoon-tritanopia' => 'Fullmoon (蓝黄色盲)',
]);

View File

@@ -0,0 +1,9 @@
/*
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/*
* CSS of the template page
*/

View File

@@ -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
*/

View File

@@ -0,0 +1,16 @@
{
"config": {
"classmap-authoritative": true
},
"autoload": {
"psr-4": {
"Combodo\\iTop\\DataFeatureRemoval\\": "src"
}
},
"name": "combodo/combodo-data-feature-removal",
"type": "itop-extension",
"description": "iTop Data Feature Removal",
"require": {
"composer-runtime-api": "^2.0"
}
}

View File

@@ -0,0 +1,20 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b862a55cbf5448fb99f0905a4db6529b",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"composer-runtime-api": "^2.0"
},
"platform-dev": {},
"plugin-api-version": "2.6.0"
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
<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&amp;exec_page=index.php&amp;c[menu]=DataFeatureRemovalMenu</url>
<enable_admin_only>1</enable_admin_only>
</menu>
</menus>
<module_parameters>
<parameters id="combodo-data-feature-removal">
<max_count_estimation_for_safe_cleanup>100</max_count_estimation_for_safe_cleanup>
</parameters>
</module_parameters>
</itop_design>

View File

@@ -0,0 +1,62 @@
<?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' => 'Extension management',
'combodo-data-feature-removal/Operation:Main/Title' => 'Extension management',
'DataFeatureRemoval:Main:Title' => 'Extension management',
'DataFeatureRemoval:Main:SubTitle' => 'Toggle extensions installed on your iTop',
'DataFeatureRemoval:Failure:Title' => 'Extensions dry removal errors',
'DataFeatureRemoval:Helper:Title' => 'Analyze if there are any data or dependency preventing you from adding/removing an extension.',
'DataFeatureRemoval:Features:Title' => 'Extensions',
'DataFeatureRemoval:Result:Title' => 'Modification requested',
'DataFeatureRemoval:Execution:Title' => 'Deletion Executions',
'DataFeatureRemoval:Analysis:Title' => 'Analysis result',
'DataFeatureRemoval:Analysis:Subtitle' => 'Review all elements requiring attention',
'DataFeatureRemoval:Analysis:SubTitle' => '%1$s element(s) to clean before continuing',
'DataFeatureRemoval:DeletionPlan:Title' => 'Data deletion plan',
'DataFeatureRemoval:DeletionPlan:SubTitle' => '%1$s rows to clean before continuing',
'DataFeatureRemoval:DoDeletion:Title' => 'Do deletion',
'DataFeatureRemoval:DoDeletion:SubTitle' => 'Remove all the entries from the database',
'DataFeatureRemoval:DeletionPlan:Error:Issues' => 'Some objects must be deleted manually prior to cleanup',
'DataFeatureRemoval:Table:Analysis:ClassName' => 'Element to remove',
'DataFeatureRemoval:Table:Analysis:FeatureName' => 'Extension name',
'DataFeatureRemoval:Table:Analysis:Module' => 'Module name',
'DataFeatureRemoval:Table:Analysis:Occurrence' => 'Occurrence',
'DataFeatureRemoval:CleanupComplete:Title' => 'All clear.',
'DataFeatureRemoval:CompilComplete' => 'Compilation successful. No Cleanup needed. You can proceed to setup.',
'UI:Button:Analyze' => 'Analyze',
'UI:Button:ModifyChoices' => 'Change my selection',
'UI:Button:AnalyzeAndSetup' => 'Analyze and go to setup',
'UI:Button:PlanDeletion' => 'Proceed with deletion',
'UI:Button:DoDeletion' => 'Proceed with deletion',
'UI:Button:BackToMain' => 'Change my selection',
'UI:Button:Setup' => 'Run setup',
'UI:Action:ForceUninstall' => 'Force uninstall',
'UI:Action:MoreInfo' => 'More information',
'DataFeatureRemoval:Table:Empty' => 'No data to remove',
'DataFeatureRemoval:Column:Class' => 'Class',
'DataFeatureRemoval:Column:DeleteCount' => 'Entries to delete',
'DataFeatureRemoval:Column:UpdateCount' => 'Entries to update',
'DataFeatureRemoval:Column:IssueCount' => 'Issues found preventing automatic cleanup',
'DataFeatureRemoval:Column:DeletedCount' => 'Deleted entries',
'DataFeatureRemoval:Column:UpdatedCount' => 'Updated entries',
]);

View File

@@ -0,0 +1,62 @@
<?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' => 'Gestion des extensions',
'combodo-data-feature-removal/Operation:Main/Title' => 'Gestion des extensions',
'DataFeatureRemoval:Main:Title' => 'Gestion des extensions',
'DataFeatureRemoval:Main:SubTitle' => 'Sélectionner les extensions à installer sur votre iTop',
'DataFeatureRemoval:Failure:Title' => 'Erreurs lors de la simulation de suppression d\'extensions',
'DataFeatureRemoval:Helper:Title' => 'Activez ou désactivez les extensions installées dans votre iTop.',
'DataFeatureRemoval:Features:Title' => 'Extensions',
'DataFeatureRemoval:Result:Title' => 'Modification demandée',
'DataFeatureRemoval:Execution:Title' => 'Suppressions',
'DataFeatureRemoval:Analysis:Title' => 'Résultat de lanalyse',
'DataFeatureRemoval:Analysis:Subtitle' => 'Vérifier les éléments à nettoyer',
'DataFeatureRemoval:Analysis:SubTitle' => '%1$s élément(s) à nettoyer avant de poursuivre',
'DataFeatureRemoval:DeletionPlan:Title' => 'Plan de suppression des données',
'DataFeatureRemoval:DeletionPlan:SubTitle' => '%1$s ligne(s) à nettoyer avant de poursuivre',
'DataFeatureRemoval:DoDeletion:Title' => 'Exécuter la suppression',
'DataFeatureRemoval:DoDeletion:SubTitle' => 'Supprime toutes les entrées de la base de données',
'DataFeatureRemoval:DeletionPlan:Error:Issues' => 'Certains objets doivent être supprimés manuellement avant le nettoyage',
'DataFeatureRemoval:Table:Analysis:ClassName' => 'Élément à supprimer',
'DataFeatureRemoval:Table:Analysis:FeatureName' => 'Extension',
'DataFeatureRemoval:Table:Analysis:Module' => 'Module',
'DataFeatureRemoval:Table:Analysis:Occurrence' => 'Occurrence',
'DataFeatureRemoval:CleanupComplete:Title' => 'All clear.',
'DataFeatureRemoval:CompilComplete' => 'Compilation successful. No Cleanup needed. You can proceed to setup.',
'UI:Button:Analyze' => 'Analyser',
'UI:Button:ModifyChoices' => 'Modifier la sélection',
'UI:Button:AnalyzeAndSetup' => 'Analyser et ouvrir lassistant de configuration',
'UI:Button:PlanDeletion' => 'Supprimer les données',
'UI:Button:DoDeletion' => 'Supprimer les données',
'UI:Button:BackToMain' => 'Modifier la sélection',
'UI:Button:Setup' => 'Lancer le setup',
'UI:Action:ForceUninstall' => 'Forcer la désinstallation',
'UI:Action:MoreInfo' => 'Plus dinformations',
'DataFeatureRemoval:Table:Empty' => 'Aucune donnée à supprimer',
'DataFeatureRemoval:Column:Class' => 'Classe',
'DataFeatureRemoval:Column:DeleteCount' => 'Entrées à supprimer',
'DataFeatureRemoval:Column:UpdateCount' => 'Entrées à mettre à jour',
'DataFeatureRemoval:Column:IssueCount' => 'Problèmes empêchant le nettoyage automatique',
'DataFeatureRemoval:Column:DeletedCount' => 'Entrées supprimées',
'DataFeatureRemoval:Column:UpdatedCount' => 'Entrées mises à jour',
]);

View 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();

View File

@@ -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

View File

@@ -0,0 +1,54 @@
<?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
'combodo-data-feature-removal/3.3.0',
[
// Identification
//
'label' => 'iTop Data Feature Removal',
'category' => 'business',
// Setup
//
'dependencies' => [
],
'mandatory' => true,
'visible' => false,
// Components
//
'datamodel' => [
'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.sample' => [
// add your sample data XML files here,
],
// Documentation
//
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
'doc.more_information' => '', // hyperlink to more information, if any
// Default settings
//
'settings' => [
// Module specific settings go here, if any
],
]
);

View File

@@ -0,0 +1,461 @@
<?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\Helper\Session;
use Combodo\iTop\Application\TwigBase\Controller\Controller;
use Combodo\iTop\DataFeatureRemoval\Entity\DataCleanupSummaryEntity;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
use Combodo\iTop\DataFeatureRemoval\Service\DataCleanupService;
use Combodo\iTop\DataFeatureRemoval\Service\DataFeatureRemoverExtensionService;
use Combodo\iTop\Setup\FeatureRemoval\DryRemovalRuntimeEnvironment;
use Combodo\iTop\Setup\FeatureRemoval\SetupAudit;
use ContextTag;
use CoreException;
use Dict;
use Exception;
use MetaModel;
use MFCompiler;
use RunTimeEnvironment;
use SetupUtils;
use utils;
class DataFeatureRemovalController extends Controller
{
private ?array $aExtensionsToCheck = null;
private bool $bForcedUninstallation = false;
private array $aCountClassesToCleanup = [];
private array $aAnalysisDataTable = [];
private array $aDeletionExecutionSummary = [];
private ?RuntimeEnvironment $oRuntimeEnvironment = null;
private int $iCount = 0;
private int $iColumnCount = 2;
public function OperationMain($sErrorMessage = null): void
{
$aParams = [];
$this->AddAnalyzeParams();
$aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['iColumnCount'] = $this->iColumnCount;
$aParams['aAvailableExtensions'] = $this->SplitArrayIntoColumns($this->GetAvailableExtensions(), $this->iColumnCount);
$aParams['aAnalysisDataTable'] = $this->aAnalysisDataTable;
$aParams['aClasses'] = array_keys($this->aCountClassesToCleanup);
$aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage;
$aParams['bHasData'] = $this->iCount > 0;
$aParams['sSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup';
$aParams['iCount'] = $this->iCount;
Session::Set('bForceCompilation', true);
$this->AddLinkedStylesheet(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/css/DataFeatureRemoval.css');
$this->AddLinkedScript(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/js/DataFeatureRemoval.js');
$this->DisplayPage($aParams);
}
public function AddAnalyzeParams(): void
{
$aData = [];
$aColumns = [];
$this->iCount = 0;
foreach ($this->aCountClassesToCleanup as $sClass => $iCount) {
$sModuleName = MetaModel::GetModuleName($sClass);
$aExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetIncludingExtensions($sModuleName);
$sExtensions = implode(' ', $aExtensions);
$aColumns = ['ClassName','FeatureName','Module','Occurrence'];
$aData[] = [$sClass,$sExtensions,$sModuleName,$iCount];
$this->iCount += $iCount;
}
$this->aAnalysisDataTable = $this->GetTableData('Analysis', $aColumns, $aData);
}
public function OperationAnalysisResult(): void
{
$aParams = [];
//from setup wizard/mtp
if (!SetupUtils::IsSessionSetupTokenValid()) {
//from same module
$this->ValidateTransactionId();
}
// Display changed extensions
$aHiddenInputNames = [
'selected_extensions' => '[]',
'selected_modules' => '[]',
'display_choices' => '',
'added_extensions' => '[]',
'removed_extensions' => '[]',
'extensions_not_uninstallable' => '[]',
'copy_setup_files' => 1,
'force-uninstall' => '',
'use_symbolic_links' => MFCompiler::UseSymbolicLinks() ? 'on' : '',
'return_application' => '',
'target_env' => ITOP_DEFAULT_ENV,
];
$aHiddenInputs = [];
foreach ($aHiddenInputNames as $sInputName => $defaultValue) {
$aHiddenInputs[$sInputName] = utils::ReadPostedParam($sInputName, $defaultValue, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
}
$aParams['aHiddenInputs'] = $aHiddenInputs;
$aAddedExtensions = json_decode($aHiddenInputs['added_extensions'], true);
$aRemovedExtensions = json_decode($aHiddenInputs['removed_extensions'], true);
if ("[]" === $aHiddenInputs['selected_modules']) {
//it does not come from setup
// we get extensions from 1st screen uiblocks
$this->ReadExtensionsDiff();
$aHiddenInputs['force-uninstall'] = $this->bForcedUninstallation ? 'on' : '';
$aAddedExtensions = $this->aExtensionsToCheck['to_be_installed'];
$aHiddenInputs['added_extensions'] = $this->ConvertIntoSetupFormat($aAddedExtensions);
$aRemovedExtensions = $this->aExtensionsToCheck['to_be_removed'];
$aHiddenInputs['removed_extensions'] = $this->ConvertIntoSetupFormat($aRemovedExtensions);
}
$aRemoveExtensionCodes = array_keys($aRemovedExtensions);
$aParams['aAddedExtensions'] = $aAddedExtensions;
$aParams['aRemovedExtensions'] = $aRemovedExtensions;
DataFeatureRemovalLog::Debug(__METHOD__.' Extensions given in parameter', null, [
'added_extensions' => $aAddedExtensions,
'removed_extensions' => $aRemovedExtensions]);
$aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['iColumnCount'] = $this->iColumnCount;
$aParams['aAvailableExtensions'] = $this->SplitArrayIntoColumns($this->GetExtensionsDiff($aAddedExtensions, $aRemovedExtensions), $this->iColumnCount);
$bForceCompilation = Session::Get('bForceCompilation', false);
try {
$this->Compile($aAddedExtensions, $aRemoveExtensionCodes, $bForceCompilation);
} catch (CoreException $e) {
$aParams['DataFeatureRemovalErrorMessage'] = $e->getHtmlDesc();
$this->DisplayPage($aParams, 'AnalysisResult');
return;
} catch (Exception $e) {
$aParams['DataFeatureRemovalErrorMessage'] = $e->getMessage();
$this->DisplayPage($aParams, 'AnalysisResult');
return;
}
if ("[]" === $aHiddenInputs['selected_modules']) {
//to make setup redirection work, we need to pass complex data structures to setup wizards (ie extension/module lists)
$oConfig = MetaModel::GetConfig();
$aSelectedExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetSelectedExtensions($oConfig, array_keys($aAddedExtensions), array_keys($aRemovedExtensions));
$aHiddenInputs['selected_extensions'] = $this->ConvertIntoSetupFormat($aSelectedExtensions);
$oRunTimeEnvironment = $this->GetRuntimeEnvironment($aAddedExtensions, $aRemovedExtensions);
$aSearchDirs = [$oRunTimeEnvironment->GetBuildDir()];
$aSelectedModules = $oRunTimeEnvironment->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions, $aSearchDirs);
$aHiddenInputs['selected_modules'] = $this->ConvertIntoSetupFormat($aSelectedModules);
}
$sSourceEnv = MetaModel::GetEnvironment();
$oSetupAudit = new SetupAudit($sSourceEnv);
$aGetRemovedClasses = array_keys($oSetupAudit->RunDataAudit());
DataFeatureRemovalLog::Debug(__METHOD__, null, ['aGetRemovedClasses' => $aGetRemovedClasses]);
$aParams['aClasses'] = $aGetRemovedClasses;
new ContextTag(ContextTag::TAG_SETUP);
$aParams['sLaunchSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup/wizard.php';
$aParams['aSetupParams'] = [
"_class" => "WizStepLandingBeforeAudit",
"operation" => "next",
];
foreach ($aHiddenInputs as $sInputName => $sInputValue) {
$aParams['aSetupParams']["_params[$sInputName]"] = $sInputValue;
}
[$aParams['aDeletionPlanSummary'], $aParams['iQueryCount'], $aParams['bDeletionPossible']] = $this->GetDeletionPlanSummaryTable($aGetRemovedClasses);
[$aParams['aDeletionExecutionSummary'], $aParams['bHasDeletionExecution']] = $this->GetExecutionSummaryTable();
$aParams['bDeletionNeeded'] = ($aParams['iQueryCount'] > 0);
Session::Set('aDeletionExecutionSummary', serialize($this->aDeletionExecutionSummary));
if (!$aParams['bDeletionNeeded']) {
SetupUtils::CreateSetupToken();
}
$this->DisplayPage($aParams, 'AnalysisResult');
}
private function ConvertIntoSetupFormat(array $aData): string
{
$aNewData = [];
foreach ($aData as $k => $sVal) {
$aNewData[] = sprintf('"%s":"%s"', $k, $sVal);
}
return "{".implode(',', $aNewData)."}";
}
/**
* @param array $aAddedExtensions
* @param array $aRemovedExtensions
* @param bool $bForceCompilation
* @return void
* @throws \ConfigException
* @throws \CoreException
*/
private function Compile(array $aAddedExtensions, array $aRemovedExtensions, bool $bForceCompilation = true): void
{
$sSourceEnv = MetaModel::GetEnvironment();
$sBuildDir = APPROOT."/env-$sSourceEnv-build";
if (! is_dir($sBuildDir)) {
SetupUtils::builddir($sBuildDir);
}
$bIsDirEmpty = count(scandir($sBuildDir)) === 2;
if ($bIsDirEmpty || $bForceCompilation) {
DataFeatureRemovalLog::Debug(
__METHOD__,
null,
['sSourceEnv' => $sSourceEnv, 'sBuildDir' => $sBuildDir, 'bIsDirEmpty' => $bIsDirEmpty, glob("$sBuildDir/*")]
);
$this->GetRuntimeEnvironment($aAddedExtensions, $aRemovedExtensions)->CompileFrom($sSourceEnv);
}
}
private function GetRuntimeEnvironment(array $aAddedExtensions, array $aRemovedExtensions): RunTimeEnvironment
{
if (is_null($this->oRuntimeEnvironment)) {
$sSourceEnv = MetaModel::GetEnvironment();
$this->oRuntimeEnvironment = new DryRemovalRuntimeEnvironment($sSourceEnv, $aAddedExtensions, $aRemovedExtensions);
}
return $this->oRuntimeEnvironment;
}
private function GetExecutionSummaryTable(): array
{
$sName = 'ExcutionSummary';
$aTableData = [];
if (count($this->aDeletionExecutionSummary) === 0) {
return [$aTableData, false];
}
$aColumns = ['Class', 'Total Deleted Count' , 'Total Updated Count', 'Deleted Count' , 'Updated Count'];
$aRows = [];
/** @var DataCleanupSummaryEntity $oSummary */
foreach ($this->aDeletionExecutionSummary as $sClass => $oSummary) {
$aRows[] = [
$sClass,
$oSummary->iTotalDeleteCount,
$oSummary->iTotalUpdateCount,
$oSummary->iDeleteCount,
$oSummary->iUpdateCount,
];
}
$aTableData = $this->GetTableData($sName, $aColumns, $aRows);
return [$aTableData, true];
}
private function GetDeletionPlanSummaryTable(array $aRemovedClasses): array
{
$sName = 'DeletionPlanSummary';
$oDataCleanupService = new DataCleanupService();
$aDeletionPlanSummaryEntities = $oDataCleanupService->GetCleanupSummary($aRemovedClasses);
$aColumns = ['Class', 'Delete Count' , 'Update Count', 'Issue Count'];
$aRows = [];
$iQueryCount = 0;
$bHasIssues = false;
foreach ($aDeletionPlanSummaryEntities as $oDeletionPlanSummaryEntity) {
$aRows[] = [
$oDeletionPlanSummaryEntity->sClass,
$oDeletionPlanSummaryEntity->iDeleteCount,
$oDeletionPlanSummaryEntity->iUpdateCount,
$oDeletionPlanSummaryEntity->iIssueCount,
];
$bHasIssues |= ($oDeletionPlanSummaryEntity->iIssueCount !== 0);
$iQueryCount += $oDeletionPlanSummaryEntity->iDeleteCount;
$iQueryCount += $oDeletionPlanSummaryEntity->iUpdateCount;
}
return [$this->GetTableData($sName, $aColumns, $aRows), $iQueryCount, !$bHasIssues];
}
public function OperationDoDeletion(): void
{
$this->ValidateTransactionId();
$this->aDeletionExecutionSummary = unserialize(Session::Get('aDeletionExecutionSummary'));
Session::Unset('aDeletionExecutionSummary');
$aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS);
$oDataCleanupService = new DataCleanupService();
$aDeletionExecutionSummary = $oDataCleanupService->ExecuteCleanup($aClasses);
foreach ($aDeletionExecutionSummary as $sClass => $oExecutionSummary) {
if (!array_key_exists($sClass, $this->aDeletionExecutionSummary)) {
$this->aDeletionExecutionSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
}
$oSummary = $this->aDeletionExecutionSummary[$sClass];
$oSummary->iDeleteCount = $oExecutionSummary->iDeleteCount;
$oSummary->iUpdateCount = $oExecutionSummary->iUpdateCount;
$oSummary->iTotalDeleteCount += $oExecutionSummary->iDeleteCount;
$oSummary->iTotalUpdateCount += $oExecutionSummary->iUpdateCount;
}
$this->OperationAnalysisResult();
}
private function GetAvailableExtensions(bool $bIncludePackageExtensions = false): array
{
$aExtensionsData = [];
if ($bIncludePackageExtensions) {
$aExtensionsRef = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetAllExtensionsWithPreviouslyInstalled();
} else {
$aExtensionsRef = DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions();
}
foreach ($aExtensionsRef as $oExtension) {
/** @var \iTopExtension $oExtension */
$aExtensionsData[$oExtension->sCode] = [
'version' => $oExtension->sVersion,
'label' => $oExtension->sLabel,
'code' => $oExtension->sCode,
'description' => $oExtension->sDescription,
'source' => $oExtension->GetExtensionSourceLabel(),
'installed' => $oExtension->bInstalled,
'extra_flags' => [
'uninstallable' => $oExtension->CanBeUninstalled(),
'remote' => $oExtension->IsRemote(),
'missing' => $oExtension->bRemovedFromDisk,
],
];
}
return $aExtensionsData;
}
private function GetExtensionsDiff(array $aAddedExtensions, array $aRemovedExtensions): array
{
$aExtensions = [];
foreach ($this->GetAvailableExtensions(true) as $sCode => $aExtension) {
$aExtension['extra_flags']['disabled'] = true;
if (isset($aAddedExtensions[$sCode])) {
$aExtension['extra_flags']['selected'] = true;
$aExtensions[$sCode] = $aExtension;
} elseif (isset($aRemovedExtensions[$sCode])) {
$aExtension['extra_flags']['selected'] = false;
$aExtensions[$sCode] = $aExtension;
}
}
return $aExtensions;
}
private function GetTableData(string $sTableName, array $aColumns, array $aData): array
{
if (empty($aData)) {
return [
'Type' => 'Table',
'Columns' => [['label' => '']],
'Data' => [[ Dict::S('DataFeatureRemoval:Table:Empty')]],
];
}
$aNewColumns = [];
foreach ($aColumns as $sColumn) {
$aNewColumns[] = ['label' => Dict::S("DataFeatureRemoval:Table:$sTableName:$sColumn", Dict::S("DataFeatureRemoval:Column:$sColumn", $sColumn))];
}
$aColumns = $aNewColumns;
return [
'Type' => 'Table',
'Columns' => $aColumns,
'Data' => $aData,
];
}
/**
* @return void
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
*/
private function ValidateTransactionId(): void
{
if (empty($_POST)) {
return;
}
$sTransactionId = utils::ReadPostedParam('transaction_id', null, utils::ENUM_SANITIZATION_FILTER_TRANSACTION_ID);
DataFeatureRemovalLog::Debug(__FUNCTION__.": Transaction [$sTransactionId]");
if (empty($sTransactionId) || !utils::IsTransactionValid($sTransactionId, false)) {
throw new DataFeatureRemovalException(Dict::S("iTopUpdate:Error:InvalidToken"));
}
}
/**
* Read extensions selected from posted parameters
* @return int Number of extensions to be added or removed
*/
public function ReadExtensionsDiff(): int
{
if (!is_null($this->aExtensionsToCheck)) {
return count($this->aExtensionsToCheck['to_be_installed']) + count($this->aExtensionsToCheck['to_be_removed']);
}
$aAvailableExtensions = $this->GetAvailableExtensions();
$aSelectedExtensionsFromUI = utils::ReadPostedParam('aSelectedExtensions', []);
$this->aExtensionsToCheck = [
'to_be_installed' => [],
'to_be_removed' => [],
];
foreach ($aAvailableExtensions as $sCode => &$aExtensionData) {
if (!isset($aSelectedExtensionsFromUI[$sCode])) {
continue;
}
if ($aExtensionData['installed'] && $aSelectedExtensionsFromUI[$sCode] !== 'on') {
$aExtensionData['extra_flags']['selected'] = false;
$sLabel = $aAvailableExtensions[$sCode]['label'];
$this->aExtensionsToCheck['to_be_removed'][$sCode] = $sLabel;
if (! $this->bForcedUninstallation && $aExtensionData['extra_flags']['uninstallable']) {
$this->bForcedUninstallation = true;
}
} elseif (!$aExtensionData['installed'] && $aSelectedExtensionsFromUI[$sCode] === 'on') {
$aExtensionData['extra_flags']['selected'] = true;
$sLabel = $aAvailableExtensions[$sCode]['label'];
$this->aExtensionsToCheck['to_be_installed'][$sCode] = $sLabel;
}
}
return count($this->aExtensionsToCheck['to_be_installed']) + count($this->aExtensionsToCheck['to_be_removed']);
}
/**
* Divide an array into several sub arrays, distributing elements so that every sub array has an equal amount of elements
* @param mixed[] $aInput
* @param int $iColNumber
*
* @return array[]
*/
private function SplitArrayIntoColumns(array $aInput, int $iColNumber)
{
$aOutput = array_fill(0, $iColNumber, []);
$iIndex = 0;
foreach ($aInput as $mItem) {
//Split extensions in $iColNumber columns
$aOutput[$iIndex % $this->iColumnCount][] = $mItem;
$iIndex++;
}
return $aOutput;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Combodo\iTop\DataFeatureRemoval\Entity;
class DataCleanupSummaryEntity
{
public string $sClass;
public int $iIssueCount = 0;
public int $iUpdateCount = 0;
public int $iDeleteCount = 0;
public int $iTotalUpdateCount = 0;
public int $iTotalDeleteCount = 0;
/**
* @param string $sClass
*/
public function __construct(string $sClass)
{
$this->sClass = $sClass;
}
}

View File

@@ -0,0 +1,52 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Helper;
use MetaModel;
use utils;
class DataFeatureRemovalConfig
{
private static DataFeatureRemovalConfig $oInstance;
protected function __construct()
{
}
final public static function GetInstance(): DataFeatureRemovalConfig
{
if (!isset(self::$oInstance)) {
self::$oInstance = new DataFeatureRemovalConfig();
}
return self::$oInstance;
}
public function Get(string $sParamName, $default = null)
{
return MetaModel::GetModuleSetting(DataFeatureRemovalHelper::MODULE_NAME, $sParamName, $default);
}
public function GetBoolean(string $sParamName, $default = null): bool
{
$res = $this->Get($sParamName, $default);
return boolval($res);
}
public function IsEnabled(): bool
{
return $this->GetBoolean('enable', false);
}
public function Set(string $sParamName, $value)
{
$oConfig = utils::GetConfig();
$oConfig->SetModuleSetting(DataFeatureRemovalHelper::MODULE_NAME, $sParamName, $value);
}
}

View File

@@ -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);
}
}

View File

@@ -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';
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,177 @@
<?php
namespace Combodo\iTop\DataFeatureRemoval\Service;
use CMDBObjectSet;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
use Combodo\iTop\Service\Limits\ExecutionLimits;
use DBObject;
use DBObjectSearch;
use MetaModel;
class DataCleanupService
{
private array $aVisited = [];
private iObjectService $oObjectService;
private ExecutionLimits $oExecutionLimits;
public function __construct(int $iMaxExecutionTime = 30, int $iMaxMemoryPercent = 80)
{
DataFeatureRemovalLog::Enable();
$this->oExecutionLimits = new ExecutionLimits($iMaxExecutionTime, $iMaxMemoryPercent);
}
/**
* Get a summary of the deletion plan computed for the classes.
* The result is used for display
*
* @param array|null $aClasses
*
* @return array<\Combodo\iTop\DataFeatureRemoval\Entity\DataCleanupSummaryEntity>
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
*/
public function GetCleanupSummary(?array $aClasses): array
{
return $this->ExecuteCleanup($aClasses ?? [], oObjectService: new ObjectServiceSummary());
}
private function GetNextObjectToDelete(array $aClasses): ?DBObject
{
foreach ($aClasses as $sClass) {
$oFilter = new DBObjectSearch($sClass);
$oFilter->AllowAllData();
$oSet = new \DBObjectSet($oFilter);
while ($oObject = $oSet->Fetch()) {
if (!$this->IsVisited($oObject)) {
return $oObject;
}
}
}
return null;
}
/**
* @param array $aClasses
* @param \Combodo\iTop\DataFeatureRemoval\Service\iObjectService|null $oObjectService
*
* @return array execution summary
* @throws \ArchivedObjectException
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
public function ExecuteCleanup(array $aClasses, ?iObjectService $oObjectService = null): array
{
$this->oObjectService = $oObjectService ?? new ObjectService();
$this->aVisited = [];
while ($oObject = $this->GetNextObjectToDelete($aClasses)) {
if ($this->RecursiveDeletion($oObject) === false) {
// Timeout, stop here
break;
}
}
return $this->oObjectService->GetSummary();
}
private function MarkObjectAsVisited(DBObject $oObject): void
{
$sClass = get_class($oObject);
$sId = $oObject->GetKey();
$sKey = "$sClass-$sId";
$this->aVisited[$sKey] = true;
}
private function IsVisited(DBObject $oObject): bool
{
$sClass = get_class($oObject);
$sId = $oObject->GetKey();
$sKey = "$sClass-$sId";
$bRes = $this->aVisited[$sKey] ?? false;
DataFeatureRemovalLog::Debug('Checking if object is visited', null, [$sKey, $bRes]);
return $bRes;
}
/**
*
* @param \DBObject $oObjectToClean
*
* @return bool true if deletion is complete, false in case of timeout or memory limit reached
*
* @throws \ArchivedObjectException
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
private function RecursiveDeletion(DBObject $oObjectToClean): bool
{
$this->MarkObjectAsVisited($oObjectToClean);
$sClass = get_class($oObjectToClean);
$aReferencingMe = MetaModel::EnumReferencingClasses($sClass);
foreach ($aReferencingMe as $sRemoteClass => $aExtKeys) {
/** @var \AttributeExternalKey $oExtKeyAttDef */
foreach ($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef) {
// skip if this external key is behind an external field
if (!$oExtKeyAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
continue;
}
$oSearch = new DBObjectSearch($sRemoteClass);
$oSearch->AddCondition($sExtKeyAttCode, $oObjectToClean->GetKey(), '=');
$oSearch->AllowAllData();
$oSet = new CMDBObjectSet($oSearch);
$oSet->OptimizeColumnLoad([$sRemoteClass => [$oExtKeyAttDef->GetCode()]]);
/** @var DBObject $oDependentObj */
while ($oDependentObj = $oSet->Fetch()) {
$iDeletePropagationOption = $oExtKeyAttDef->GetDeletionPropagationOption();
if ($iDeletePropagationOption == DEL_MANUAL) {
$this->oObjectService->SetIssue(get_class($oDependentObj));
continue;
}
if ($oExtKeyAttDef->IsNullAllowed()) {
// Optional external key, list to reset
if (($iDeletePropagationOption == DEL_MOVEUP) && ($oExtKeyAttDef->IsHierarchicalKey())) {
// Move the child up one level i.e. set the same parent as the current object
$iParentId = $oObjectToClean->Get($oExtKeyAttDef->GetCode());
$this->oObjectService->Update($oDependentObj, $oExtKeyAttDef->GetCode(), $iParentId);
} else {
$this->oObjectService->Update($oDependentObj, $oExtKeyAttDef->GetCode(), 0);
}
if ($this->oExecutionLimits->ShouldStopExecution()) {
return false;
}
} else {
// Propagate deletion only if not visited
if ($this->IsVisited($oDependentObj)) {
continue;
}
if (!$this->RecursiveDeletion($oDependentObj)) {
// Timeout
return false;
}
}
}
}
}
$this->oObjectService->Delete($sClass, $oObjectToClean->GetKey());
if ($this->oExecutionLimits->ShouldStopExecution()) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,90 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Service;
use iTopExtension;
use iTopExtensionsMap;
use MetaModel;
class DataFeatureRemoverExtensionService
{
private static DataFeatureRemoverExtensionService $oInstance;
private ?iTopExtensionsMap $oMap = null;
private array $aItopExtensions = [];
private array $aIncludingExtensionsByModuleName = [];
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;
}
/**
* @param string $sModuleName
*
* @return array
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
*/
public function GetIncludingExtensions(string $sModuleName): array
{
if (count($this->aIncludingExtensionsByModuleName) === 0) {
foreach ($this->ReadItopExtensions() as $oExtension) {
$aModuleNames = $oExtension->aModules;
if (is_array($aModuleNames) && count($aModuleNames) > 0) {
foreach ($aModuleNames as $sModule) {
$aExtensions = $this->aIncludingExtensionsByModuleName[$sModule] ?? [];
$aExtensions[] = $oExtension->sLabel.'/'.$oExtension->sVersion;
$this->aIncludingExtensionsByModuleName[$sModule] = $aExtensions;
}
}
}
}
return $this->aIncludingExtensionsByModuleName[$sModuleName] ?? [];
}
/**
* @return \iTopExtensionsMap
*/
public function GetExtensionMap(): iTopExtensionsMap
{
if (is_null($this->oMap)) {
$this->oMap = iTopExtensionsMap::GetExtensionsMap();
$this->oMap->LoadInstalledExtensionsFromDatabase(MetaModel::GetConfig());
}
return $this->oMap;
}
/**
* @return iTopExtension[]
*/
public function ReadItopExtensions(): array
{
if (count($this->aItopExtensions) === 0) {
$this->aItopExtensions = $this->GetExtensionMap()->GetAllExtensionsToDisplayInSetup(true);
uasort($this->aItopExtensions, function (iTopExtension $oiTopExtension1, iTopExtension $oiTopExtension2) {
return strcmp($oiTopExtension1->sLabel, $oiTopExtension2->sLabel);
});
}
return $this->aItopExtensions;
}
}

View File

@@ -0,0 +1,60 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Service;
use CMDBSource;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
use DBObject;
use DBObjectSearch;
use MetaModel;
class ObjectService extends ObjectServiceSummary
{
public function Update(DBObject $oToUpdate, string $sAttCode, $value): void
{
$oToUpdate->Set($sAttCode, $value);
$oToUpdate->DBUpdate();
parent::Update($oToUpdate, $sAttCode, $value);
}
public function Delete(string $sClass, string $sId): void
{
try {
CMDBSource::Query('START TRANSACTION');
// Delete any existing change tracking about the current object
$oFilter = new DBObjectSearch('CMDBChangeOp');
$oFilter->AddCondition('objclass', $sClass, '=');
$oFilter->AddCondition('objkey', $sId, '=');
MetaModel::PurgeData($oFilter);
// Delete the entry
$aClassesToRemove = array_merge(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL), MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_EXCLUDELEAF, false));
foreach ($aClassesToRemove as $sParentClass) {
/** @var DBObjectSearch $oFilter */
$oFilter = DBObjectSearch::FromOQL_AllData("SELECT $sParentClass WHERE id=:id");
$sQuery = $oFilter->MakeDeleteQuery(['id' => $sId]);
CMDBSource::DeleteFrom($sQuery);
}
CMDBSource::Query('COMMIT');
parent::Delete($sClass, $sId);
} catch (\Exception $e) {
DataFeatureRemovalLog::Exception(__METHOD__.': Cleanup failed', $e);
CMDBSource::Query('ROLLBACK');
throw $e;
}
}
public function SetIssue(string $sClass): void
{
throw new DataFeatureRemovalException('Deletion Plan cannot be executed due to issues');
}
}

View File

@@ -0,0 +1,71 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Service;
use Combodo\iTop\DataFeatureRemoval\Entity\DataCleanupSummaryEntity;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
use DBObject;
/**
* Manage operation summary instead of doing the actual update or delete
*
* The summary is an array [class => DeletionPlanSummaryEntity]
*/
class ObjectServiceSummary implements iObjectService
{
private array $aSummary = [];
public function Update(DBObject $oToUpdate, string $sAttCode, $value): void
{
$sClass = get_class($oToUpdate);
DataFeatureRemovalLog::Debug('Object to update', null, ['class' => $sClass, 'id' => $oToUpdate->GetKey(), 'code' => $sAttCode, 'value' => "$value"]);
if (! array_key_exists($sClass, $this->aSummary)) {
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
}
$oDeletionPlanSummaryEntity = $this->aSummary[$sClass];
$oDeletionPlanSummaryEntity->iUpdateCount++;
$oDeletionPlanSummaryEntity->iTotalUpdateCount++;
}
public function Delete(string $sClass, string $sId): void
{
DataFeatureRemovalLog::Debug('Object to delete', null, ['class' => $sClass, 'id' => $sId]);
if (!array_key_exists($sClass, $this->aSummary)) {
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
}
$oDeletionPlanSummaryEntity = $this->aSummary[$sClass];
$oDeletionPlanSummaryEntity->iDeleteCount++;
$oDeletionPlanSummaryEntity->iTotalDeleteCount++;
}
public function SetIssue(string $sClass): void
{
DataFeatureRemovalLog::Debug('Issue on object', null, ['class' => $sClass]);
if (!array_key_exists($sClass, $this->aSummary)) {
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
}
$oDeletionPlanSummaryEntity = $this->aSummary[$sClass];
$oDeletionPlanSummaryEntity->iIssueCount++;
}
public function GetSummary(): array
{
return $this->aSummary;
}
public function SetSummary(array $aSummary): void
{
foreach ($aSummary as $sClass => $oPreviousSummaryEntity) {
$oSummaryEntity = new DataCleanupSummaryEntity($sClass);
$oSummaryEntity->iTotalUpdateCount = $oPreviousSummaryEntity->iTotalUpdateCount;
$oSummaryEntity->iTotalDeleteCount = $oPreviousSummaryEntity->iTotalDeleteCount;
$this->aSummary[$sClass] = $oSummaryEntity;
}
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Service;
use DBObject;
interface iObjectService
{
public function Update(DBObject $oToUpdate, string $sAttCode, $value): void;
public function Delete(string $sClass, string $sId): void;
public function SetIssue(string $sClass): void;
public function GetSummary(): array;
}

View File

@@ -0,0 +1,97 @@
{# @copyright Copyright (C) 2010-2026 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:Analysis:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Analysis:Subtitle'|dict_s} %}
{% 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>
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Result:Title'|dict_s, sSubTitle: '' } %}
{% UIMultiColumn Standard {} %}
{% for iColumnIndex in 0..iColumnCount-1 %}
{% UIColumn Standard {} %}
{% for aExtension in aAvailableExtensions[iColumnIndex] %}
{% if aExtension['installed'] %}
{% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% else %}
{% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% endif %}
{% endfor %}
{% EndUIColumn %}
{% endfor %}
{% EndUIMultiColumn %}
{% EndUIPanel %}
{% else %}
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Result:Title'|dict_s, sSubTitle: '' } %}
{% UIMultiColumn Standard {} %}
{% for iColumnIndex in 0..iColumnCount-1 %}
{% UIColumn Standard {} %}
{% for aExtension in aAvailableExtensions[iColumnIndex] %}
{% if aExtension['installed'] %}
{% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% else %}
{% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% endif %}
{% endfor %}
{% EndUIColumn %}
{% endfor %}
{% EndUIMultiColumn %}
{% EndUIPanel %}
{% if bDeletionNeeded %}
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:DeletionPlan:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aDeletionPlanSummary', aColumns:aDeletionPlanSummary.Columns, aData:aDeletionPlanSummary.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% if bDeletionPossible %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'DoDeletion'} %}
{% for sKey, sClass in aClasses %}
{% UIInput ForHidden { sName:"classes[" ~ sKey ~ "]", sValue:sClass } %}
{% endfor %}
{% for sCode, sLabel in aAddedExtensions %}
{% UIInput ForHidden { sName:"aAddedExtensions[" ~ sCode ~ "]", sValue:sLabel } %}
{% endfor %}
{% for sCode, sLabel in aRemovedExtensions %}
{% UIInput ForHidden { sName:"aRemovedExtensions[" ~ sCode ~ "]", sValue:sLabel } %}
{% endfor %}
{% for sInputName, sValue in aHiddenInputs %}
{% UIInput ForHidden { sName:sInputName, sValue:sValue } %}
{% endfor %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% else %}
{% UIAlert ForFailure { sContent: 'DataFeatureRemoval:DeletionPlan:Error:Issues'|dict_s } %}{% EndUIAlert %}
{% endif %}
{% else %}
{% UIAlert ForSuccess { sTitle:'DataFeatureRemoval:CleanupComplete:Title'|dict_s, sContent:'DataFeatureRemoval:CompilComplete'|dict_s, sId:value } %}{% EndUIAlert %}
{% UIForm Standard {'sId':'launch-setup-form', Action:sLaunchSetupUrl, 'EncType': 'application/x-www-form-urlencoded'} %}
{% for sKey, sValue in aSetupParams %}
{% UIInput ForHidden { sName:sKey, sValue:sValue } %}
{% endfor %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:Setup'|dict_s, sName:'btn_setup', sId:'btn_setup', bIsSubmit:true} %}
{% EndUIForm %}
{% endif %}
{% if bHasDeletionExecution %}
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:Execution:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aDeletionExecutionSummary', aColumns:aDeletionExecutionSummary.Columns, aData:aDeletionExecutionSummary.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% endif %}
{% endif %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'Main'} %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:BackToMain'|dict_s, sName:'btn_back', sId:'btn_back', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% EndUIPanel %}

View File

@@ -0,0 +1,14 @@
{# @copyright Copyright (C) 2010-2026 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:DoDeletion:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:DoDeletion:SubTitle'|dict_s } %}
{% UIDataTable ForForm { sRef:'aDeletionExecutionSummary', aColumns:aDeletionExecutionSummary.Columns, aData:aDeletionExecutionSummary.Data} %}{% EndUIDataTable %}
{% EndUIPanel %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'Main'} %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:BackToMain'|dict_s, sName:'btn_back_to_main', sId:'btn_back_to_main', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}

View File

@@ -0,0 +1,29 @@
{# @copyright Copyright (C) 2010-2024 Combodo SAS #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% UIForm Standard {} %}
{% UIInput ForHidden {sName:'operation', sValue:'AnalysisResult'} %}
{% UIInput ForHidden {sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden {sName:'return_application', sValue:'itop'} %}
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Features:Title'|dict_s, sSubTitle: '' } %}
{% UIMultiColumn Standard {} %}
{% for iColumnIndex in 0..iColumnCount-1 %}
{% UIColumn Standard {} %}
{% for aExtension in aAvailableExtensions[iColumnIndex] %}
{% if aExtension['installed'] %}
{% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% else %}
{% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% endif %}
{% endfor %}
{% EndUIColumn %}
{% endfor %}
{% EndUIMultiColumn %}
{% EndUIPanel %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:Analyze'|dict_s, sName:'btn_apply', sId:'btn_apply', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}

View File

@@ -0,0 +1,17 @@
{# @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 ForInformation { sTitle:'DataFeatureRemoval:Main:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Main:SubTitle'|dict_s } %}
{% UIAlert ForInformation { sTitle:'DataFeatureRemoval:Helper:Title'|dict_s } %}
{% EndUIAlert %}
{% include 'Features.html.twig' %}
{% EndUIPanel %}

View File

@@ -0,0 +1,22 @@
<?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;
}
}
throw new RuntimeException($err);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464::getLoader();

View 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);
}
}

View File

@@ -0,0 +1,396 @@
<?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;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
* @internal
*/
private static $selfDir = null;
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
* @var bool
*/
private static $installedIsLocalDir;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
// so we have to assume it does not, and that may result in duplicate data being returned when listing
// all installed packages for example
self::$installedIsLocalDir = false;
}
/**
* @return string
*/
private static function getSelfDir()
{
if (self::$selfDir === null) {
self::$selfDir = strtr(__DIR__, '\\', '/');
}
return self::$selfDir;
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
$copiedLocalDir = false;
if (self::$canGetVendors) {
$selfDir = self::getSelfDir();
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
$vendorDir = strtr($vendorDir, '\\', '/');
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require $vendorDir.'/composer/installed.php';
self::$installedByVendor[$vendorDir] = $required;
$installed[] = $required;
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
self::$installed = $required;
self::$installedIsLocalDir = true;
}
}
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
$copiedLocalDir = true;
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require __DIR__ . '/installed.php';
self::$installed = $required;
} else {
self::$installed = array();
}
}
if (self::$installed !== array() && !$copiedLocalDir) {
$installed[] = self::$installed;
}
return $installed;
}
}

View File

@@ -0,0 +1,21 @@
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
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
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.

View File

@@ -0,0 +1,21 @@
<?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\\Entity\\DataCleanupSummaryEntity' => $baseDir . '/src/Entity/DataCleanupSummaryEntity.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalConfig' => $baseDir . '/src/Helper/DataFeatureRemovalConfig.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\\Service\\DataCleanupService' => $baseDir . '/src/Service/DataCleanupService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => $baseDir . '/src/Service/DataFeatureRemoverExtensionService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectService' => $baseDir . '/src/Service/ObjectService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectServiceSummary' => $baseDir . '/src/Service/ObjectServiceSummary.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\iObjectService' => $baseDir . '/src/Service/iObjectService.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);

View File

@@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -0,0 +1,10 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Combodo\\iTop\\DataFeatureRemoval\\' => array($baseDir . '/src'),
);

View 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;
}
}

View File

@@ -0,0 +1,47 @@
<?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 $classMap = array (
'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => __DIR__ . '/../..' . '/src/Controller/DataFeatureRemovalController.php',
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DataCleanupSummaryEntity' => __DIR__ . '/../..' . '/src/Entity/DataCleanupSummaryEntity.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalConfig' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalConfig.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\\Service\\DataCleanupService' => __DIR__ . '/../..' . '/src/Service/DataCleanupService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => __DIR__ . '/../..' . '/src/Service/DataFeatureRemoverExtensionService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectService' => __DIR__ . '/../..' . '/src/Service/ObjectService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectServiceSummary' => __DIR__ . '/../..' . '/src/Service/ObjectServiceSummary.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\iObjectService' => __DIR__ . '/../..' . '/src/Service/iObjectService.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->classMap = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$classMap;
}, null, ClassLoader::class);
}
}

View File

@@ -0,0 +1,5 @@
{
"packages": [],
"dev": true,
"dev-package-names": []
}

View File

@@ -0,0 +1,23 @@
<?php return array(
'root' => array(
'name' => 'combodo/combodo-data-feature-removal',
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'reference' => '19bbf6759bb4f6f5814d9ec1b0b5514208efc0b2',
'type' => 'itop-extension',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev' => true,
),
'versions' => array(
'combodo/combodo-data-feature-removal' => array(
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'reference' => '19bbf6759bb4f6f5814d9ec1b0b5514208efc0b2',
'type' => 'itop-extension',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev_requirement' => false,
),
),
);

View File

@@ -4,7 +4,7 @@
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @license http://opensource.org/licenses/AGPL-3.0
*
* This file is part of iTop.
*
@@ -21,14 +21,15 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
// Database inconsistencies
Dict::Add('ZH CN', 'Chinese', '简体中文', [
// Dictionary entries go here
'Menu:DBToolsMenu' => '数据库工具',
'Menu:DBToolsMenu' => '数据库完整性',
'DBTools:Class' => '类型',
'DBTools:Title' => '数据库维护工具',
'DBTools:Title' => '数据库完整性检查',
'DBTools:ErrorsFound' => '发现错误',
'DBTools:Indication' => '重要: 修复数据库错误后, 可能会出现新的不一致, 您必须重新运行一次分析.',
'DBTools:Indication' => '重要提示: 修复数据库错误后, 可能会出现新的不一致, 您必须重新运行一次分析.',
'DBTools:Disclaimer' => '免责申明: 在应用修复之前, 应先备份数据库',
'DBTools:Error' => '错误',
'DBTools:Count' => '个数',
@@ -42,17 +43,20 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'DBTools:IntegrityCheck' => '完整性检查',
'DBTools:FetchCheck' => '提取检查 (耗时长)',
'DBTools:SelectAnalysisType' => '请选择分析类型',
'DBTools:Analyze' => '分析',
'DBTools:Details' => '显示详情',
'DBTools:ShowAll' => '显示所有错误',
'DBTools:Inconsistencies' => '数据库不一致',
'DBTools:DetailedErrorTitle' => '%2$s个错误在类型%1$s: %3$s',
'DBTools:DetailedErrorLimit' => '列表限制为%1$s错误',
'DBAnalyzer-Integrity-OrphanRecord' => '孤立记录位于 `%1$s`, 其应该有副本位于表 `%2$s`',
'DBAnalyzer-Integrity-InvalidExtKey' => '无效的外键%1$s (列: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-MissingExtKey' => '外键丢失%1$s (列: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-InvalidValue' => '无效的值%1$s (列: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-UsersWithoutProfile' => '一些用户账号没有角色',
'DBAnalyzer-Integrity-UsersWithoutProfile' => '有的账号没有角色',
'DBAnalyzer-Integrity-HKInvalid' => '损坏的层级链 `%1$s`',
'DBAnalyzer-Fetch-Count-Error' => '读取计数出错于 `%1$s`, %2$d个记录已读取 / %3$d已',
'DBAnalyzer-Integrity-FinalClass' => '字段 `%2$s`.`%1$s` 必须是相同的值, 而不是 `%3$s`.`%1$s`',
@@ -70,19 +74,24 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'DBTools:LostAttachments' => '附件缺失',
'DBTools:LostAttachments:Disclaimer' => '可以在此搜索数据库中丢失或错放的附件. 这不是数据恢复工具, 其无法恢复已删除的数据.',
'DBTools:LostAttachments:Button:Analyze' => '分析',
'DBTools:LostAttachments:Button:Restore' => '还原',
'DBTools:LostAttachments:Button:Restore:Confirm' => '此操作无法回退, 请确认是否继续还原.',
'DBTools:LostAttachments:Button:Busy' => '请稍候...',
'DBTools:LostAttachments:Step:Analyze' => '首先, 通过分析数据库来搜索丢失或误挪动的附件.',
'DBTools:LostAttachments:Step:AnalyzeResults' => '分析结果:',
'DBTools:LostAttachments:Step:AnalyzeResults:None' => '非常好! 所有附件都是正常的.',
'DBTools:LostAttachments:Step:AnalyzeResults:Some' => '某些附件 (%1$d) 看起来放错了位置. 请检查下面的列表并选择要挪动的文件.',
'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => '文件名',
'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => '当前位置',
'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => '移动到...',
'DBTools:LostAttachments:Step:RestoreResults' => '还原结果:',
'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d的附件被还原.',
'DBTools:LostAttachments:StoredAsInlineImage' => '存储为内嵌图像',
'DBTools:LostAttachments:History' => '附件 "%1$s" 已使用数据库工具还原',
]);

View File

@@ -10,6 +10,7 @@ namespace Combodo\iTop\DBTools\Service;
use CMDBSource;
use DBObjectSearch;
use DBObjectSet;
use IssueLog;
class DBToolsUtils
{

View File

@@ -27,12 +27,6 @@
<module>combodo-backoffice-fullmoon-protanopia-deuteranopia-theme</module>
<module>combodo-backoffice-fullmoon-tritanopia-theme</module>
<module>itop-themes-compat</module>
<module>combodo-my-account</module>
<module>combodo-my-account-user-info</module>
<module>combodo-oauth2-client</module>
<module>itop-attribute-class-set</module>
<module>itop-attribute-encrypted-password</module>
<module>itop-ui-copypaste</module>
</modules>
<mandatory>true</mandatory>
</choice>
@@ -94,15 +88,6 @@
</options>
</sub_options>
</choice>
<choice>
<extension_code>itop-flow-map</extension_code>
<title>Data flow</title>
<description>Map data flows between applications</description>
<modules type="array">
<module>itop-flow-map</module>
</modules>
<default>false</default>
</choice>
</options>
</step>
<step>
@@ -250,7 +235,7 @@
<choice>
<extension_code>itop-problem-mgmt</extension_code>
<title>Problem Management</title>
<description>Select this option track "Problems" in iTop.</description>
<description>Select this option to track "Problems" in iTop.</description>
<modules type="array">
<module>itop-problem-mgmt</module>
</modules>

View File

@@ -1,15 +1,23 @@
<?php
/**
* Localized data
* Copyright (C) 2013-2024 Combodo SAS
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*/
/**
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Attachments:TabTitle_Count' => '附件 (%1$d)',
'Attachments:EmptyTabTitle' => '附件',
@@ -39,10 +47,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Attachment' => '附件',
'Class:Attachment+' => '',
'Class:Attachment+' => '文件: 链接到单一对象的文本或图片. 它无法被修改,只能被删除. 附件无法在编辑界面之外创建.',
'Class:Attachment/Attribute:expire' => '过期',
'Class:Attachment/Attribute:expire+' => '',
'Class:Attachment/Attribute:temp_id' => '临时编号',
'Class:Attachment/Attribute:temp_id' => '临时id',
'Class:Attachment/Attribute:temp_id+' => '',
'Class:Attachment/Attribute:item_class' => '项目类型',
'Class:Attachment/Attribute:item_class+' => '',
@@ -69,11 +77,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Attachment/Attribute:creation_date' => '创建日期',
'Class:Attachment/Attribute:creation_date+' => '~~',
'Class:Attachment/Attribute:user_id' => '用户编号',
'Class:Attachment/Attribute:user_id+' => '~~',
'Class:Attachment/Attribute:contact_id' => '联系人编号',
'Class:Attachment/Attribute:contact_id+' => '~~',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => '用户id',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => '联系人id',
'Class:Attachment/Attribute:contact_id+' => '',
]);
//
@@ -81,15 +89,15 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TriggerOnAttachmentDownload' => '触发器 (对象附件下载时)',
'Class:TriggerOnAttachmentDownload+' => '触发器于指定类型 [子类型] 对象附件下载时',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment creation)~~',
'Class:TriggerOnAttachmentCreate+' => 'Trigger on object\'s attachment creation~~',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email' => 'Add file in email~~',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment deletion)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment deletion~~',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email' => 'Add deleted file in email~~',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email+' => 'If checked, the deleted file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
'Class:TriggerOnAttachmentDownload' => '触发器 (对象附件下载时)',
'Class:TriggerOnAttachmentDownload+' => '触发器于指定类型 [子类型] 对象附件下载时',
'Class:TriggerOnAttachmentCreate' => '触发器 (对象附件被创建时)',
'Class:TriggerOnAttachmentCreate+' => '触发器 (对象附件被创建时)',
'Class:TriggerOnAttachmentDelete' => '触发器 (对象附件被删除时)',
'Class:TriggerOnAttachmentDelete+' => '触发器 (对象附件被删除时)',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email' => '在邮件里添加文件',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => '如果勾选,文件将在触发邮件操作时自动附加到邮件中',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email' => '在邮件里添加已删除的文件',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email+' => '如果勾选,已删除的文件将在触发邮件操作时自动附加到邮件中',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => '此触发器不允许用于附件. 请使用特定的触发器',
]);

View File

@@ -36,7 +36,6 @@ class TriggerOnAttachmentDelete extends TriggerOnObject
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeBoolean("file_in_email", ["sql" => 'file_in_email', "is_null_allowed" => false, "default_value" => 'true', "allowed_values" => null, "depends_on" => [], "always_load_in_tables" => false]));
// Display lists
MetaModel::Init_SetZListItems('details', ['description', 'context', 'filter', 'action_list', 'target_class','file_in_email']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['finalclass', 'target_class']); // Attributes to be displayed for a list

View File

@@ -131,7 +131,7 @@ try {
$oPage = new JsonPage();
$oPage->SetOutputDataOnly(true);
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
$sEnvironment = utils::ReadParam('environment', ITOP_DEFAULT_ENV, false, 'raw_data');
$oRestoreMutex = new iTopMutex('restore.'.$sEnvironment);
if ($oRestoreMutex->IsLocked()) {
DisplayErrorAndDie($oPage, '<p>'.Dict::S('bkp-restore-running').'</p>');
@@ -156,7 +156,7 @@ try {
require_once(APPROOT.'/setup/backup.class.inc.php');
require_once(__DIR__.'/dbrestore.class.inc.php');
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
$sEnvironment = utils::ReadParam('environment', ITOP_DEFAULT_ENV, false, 'raw_data');
try {
set_time_limit(0);

View File

@@ -97,7 +97,7 @@ class DBRestore extends DBBackup
*
* @uses \RunTimeEnvironment::CompileFrom()
*/
public function RestoreFromCompressedBackup($sFile, $sEnvironment = 'production')
public function RestoreFromCompressedBackup($sFile, $sEnvironment = ITOP_DEFAULT_ENV)
{
$oRestoreMutex = new iTopMutex('restore.'.$sEnvironment);
IssueLog::Info("Backup Restore - Acquiring the LOCK 'restore.$sEnvironment'");

View File

@@ -21,25 +21,28 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'bkp-backup-running' => '备份正在进行, 请稍候...',
'bkp-restore-running' => '还原正在进行, 请稍等...',
'Menu:BackupStatus' => '定时备份',
'bkp-status-title' => '定时备份',
'Menu:BackupStatus' => '备份',
'bkp-status-title' => '备份',
'bkp-status-checks' => '设置与检查',
'bkp-mysqldump-ok' => '已找到 mysqldump : %1$s',
'bkp-mysqldump-notfound' => 'mysqldump找不到: %1$s - 请确认它安装在正确的路径, 或者调整'.ITOP_APPLICATION_SHORT.'配置文件的参数mysql_bindir.',
'bkp-mysqldump-issue' => 'mysqldump无法运行 (retcode=%1$d): 请确认它安装在正确的路径, 或者调整'.ITOP_APPLICATION_SHORT.'配置文件的参数mysql_bindir',
'bkp-mysqldump-notfound' => 'mysqldump 找不到: %1$s - 请确认它安装在正确的路径, 或者调整'.ITOP_APPLICATION_SHORT.'配置文件的参数 mysql_bindir.',
'bkp-mysqldump-issue' => 'mysqldump 无法运行 (retcode=%1$d): 请确认它安装在正确的路径, 或者调整'.ITOP_APPLICATION_SHORT.'配置文件的参数 mysql_bindir',
'bkp-missing-dir' => '目标目录<code>%1$s</code>找不到',
'bkp-free-disk-space' => '<b>%1$s可用空间</b>位于<code>%2$s</code>',
'bkp-dir-not-writeable' => '%1$s没有写入权限',
'bkp-wrong-format-spec' => '当前文件名格式错误 (%1$s). 默认格式应该是: %2$s',
'bkp-name-sample' => '备份文件将以数据库名, 日期和时间进行命名. 例如: %1$s',
'bkp-week-days' => '在每个<b>%1$s的%2$s</b>进行备份',
'bkp-retention' => '最多<b>%1$d份备份文件</b>在目标目录.',
'bkp-retention' => '在目标目录中最多保留<b>%1$d份备份文件</b>.',
'bkp-next-to-delete' => '当下一次备份时将被删除 (参阅设置 "retention_count")',
'bkp-table-file' => '文件',
'bkp-table-file+' => '只有扩展名是.zip的文件才被认为是备份文件',
'bkp-table-file+' => '只有扩展名是.zip的文件才被认为是有效的备份文件',
'bkp-table-size' => '大小',
'bkp-table-size+' => '',
'bkp-table-actions' => '操作',
@@ -47,7 +50,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'bkp-status-backups-auto' => '定时备份',
'bkp-status-backups-manual' => '手动备份',
'bkp-status-backups-none' => '尚未开始备份',
'bkp-next-backup' => '下一次备份将发生在<b>%1$s</b> (%2$s) 的%3$s',
'bkp-next-backup' => '下一次备份将发生在<b>%1$s</b> (%2$s) 的%3$s',
'bkp-next-backup-unknown' => '下一次备份<b>尚未被计划</b>.',
'bkp-button-backup-now' => '立即备份!',
'bkp-button-restore-now' => '还原!',

View File

@@ -126,7 +126,7 @@ function ExecuteMainOperation($oP)
if (MetaModel::GetConfig()->Get('demo_mode')) {
$oP->p("Sorry, iTop is in demonstration mode: the feature is disabled");
} else {
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
$sEnvironment = utils::ReadParam('environment', ITOP_DEFAULT_ENV, false, 'raw_data');
$oRestore->RestoreFromCompressedBackup($sBackupFile, $sEnvironment);
}
}

View File

@@ -17,10 +17,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @author Benjamin Planque <benjamin.planque@combodo.com>
* @author Benjamin Planque <benjamin.planque@combodo.com>
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
//////////////////////////////////////////////////////////////////////
// Note: The classes have been grouped by categories: bizmodel
//////////////////////////////////////////////////////////////////////
@@ -31,8 +32,9 @@
//
// Class: lnkFunctionalCIToProviderContract
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkFunctionalCIToProviderContract' => '关联功能配置项/供应商合同',
'Class:lnkFunctionalCIToProviderContract' => '链接 功能配置项/供应商合同',
'Class:lnkFunctionalCIToProviderContract+' => '',
'Class:lnkFunctionalCIToProviderContract/Name' => '%1$s / %2$s',
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id' => '供应商合同',
@@ -50,9 +52,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkFunctionalCIToService' => '关联 功能配置项/服务',
'Class:lnkFunctionalCIToService+' => '',
'Class:lnkFunctionalCIToService/Name' => '%1$s / %2$s~~',
'Class:lnkFunctionalCIToService' => '链接 功能配置项/服务',
'Class:lnkFunctionalCIToService+' => 'This link models the functional CIs that are required to deliver a Service and whose malfunction would affect the quality of the Service.~~',
'Class:lnkFunctionalCIToService/Name' => '%1$s / %2$s',
'Class:lnkFunctionalCIToService/Attribute:service_id' => '服务',
'Class:lnkFunctionalCIToService/Attribute:service_id+' => '',
'Class:lnkFunctionalCIToService/Attribute:service_name' => '服务名称',
@@ -80,7 +82,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Document/Attribute:contracts_list' => '合同',
'Class:Document/Attribute:contracts_list+' => '此文档关的所有合同',
'Class:Document/Attribute:contracts_list+' => '此文档关的所有合同',
'Class:Document/Attribute:services_list' => '服务',
'Class:Document/Attribute:services_list+' => '此文档关的所有服务',
'Class:Document/Attribute:services_list+' => '此文档关的所有服务',
]);

View File

@@ -17,10 +17,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @author Benjamin Planque <benjamin.planque@combodo.com>
*/
* @author Benjamin Planque <benjamin.planque@combodo.com>
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
//////////////////////////////////////////////////////////////////////
// Note: The classes have been grouped by categories: bizmodel
//////////////////////////////////////////////////////////////////////
@@ -28,19 +29,21 @@
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
//
// Class: lnkFunctionalCIToTicket
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkFunctionalCIToTicket' => '关联 功能配置项/工单',
'Class:lnkFunctionalCIToTicket+' => '',
'Class:lnkFunctionalCIToTicket' => '链接 功能配置项/工单',
'Class:lnkFunctionalCIToTicket+' => 'This link models the functional CIs that are concerned by a Ticket (such as a User Request, an Incident, a Change, ...)~~',
'Class:lnkFunctionalCIToTicket/Name' => '%1$s / %2$s',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_id' => '工单',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_id+' => '',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_ref' => '工单编号',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_ref+' => '',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_title' => '工单标题',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_title+' => '~~',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_title+' => '',
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_id' => '配置项',
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_id+' => '',
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_name' => '配置项名称',
@@ -50,7 +53,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkFunctionalCIToTicket/Attribute:impact_code' => '影响',
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:manual' => '手动添加',
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:computed' => '自动添加',
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:not_impacted' => '不通知',
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:not_impacted' => '未被影响',
]);
//

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:ChangeManagement' => '变更管理',
'Menu:Change:Overview' => '概况',
@@ -125,7 +126,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Change/Attribute:parent_name' => '变更编号',
'Class:Change/Attribute:parent_name+' => '',
'Class:Change/Attribute:related_request_list' => '相关需求',
'Class:Change/Attribute:related_request_list+' => '此变更相关的所有用户需求',
'Class:Change/Attribute:related_request_list+' => '此变更相关的所有需求',
'Class:Change/Attribute:related_problems_list' => '相关问题',
'Class:Change/Attribute:related_problems_list+' => '此变更相关的所有问题',
'Class:Change/Attribute:related_incident_list' => '相关事件',

View File

@@ -109,7 +109,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Change/Attribute:fallback_plan' => '回滚计划',
'Class:Change/Attribute:fallback_plan+' => '',
'Class:Change/Attribute:related_request_list' => '相关需求',
'Class:Change/Attribute:related_request_list+' => '此变更相关的所有用户需求',
'Class:Change/Attribute:related_request_list+' => '此变更相关的所有需求',
'Class:Change/Attribute:related_incident_list' => '相关事件',
'Class:Change/Attribute:related_incident_list+' => '此变更相关的所有事件',
'Class:Change/Attribute:related_problems_list' => '相关问题',

View File

@@ -0,0 +1,257 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<Brand alias="Brand" id="6">
<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>
</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>
</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>
</Brand>
<Brand alias="Brand" id="10">
<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>
</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>
</Brand>
<Brand alias="Brand" id="7">
<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>
</Brand>
<Brand alias="Brand" id="1">
<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>
</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>
</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>
</Brand>
<Brand alias="Brand" id="4">
<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>
</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>
</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>
</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>
</Brand>
</Set>

View File

@@ -0,0 +1,292 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<NetworkDeviceType alias="NetworkDeviceType" id="1">
<name>Firewall</name>
<logo>
<mimetype>image/png</mimetype>
<filename>firewall.png</filename>
<data>iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABmJLR0QA/wD/AP+gvaeTAAAIdUlEQVR4nO2bXWwc1RXH/3f2a3bXiXHiJM4HCVRqBXEqHG8SlGRJtgGS2okLJjhNRHmoWvJQJKQgtahVK0VVRamqqlVppSK1AlW8IJ6gUkMlxEsAKbHBJHZQCyLB2EqMwd71bryza+/e04dknV3veHbufOzswv1J98E7c885c/537tx7ZgxIJBKJRCKRSCQSiUQikUi+LjCvAxAh3ff9hxixfwA0xoj+HI3Qy+zVV4tex2UHxesARGCcngbx1SDqJuCl61l2Pn34+B6v47JDUwlAHCkioKx1g/jb6Z5jz9Hp0011LSWaKmgGXAYISxoDo2cyg5f+lXz44du8jVCcphKAg1+uzv/NxtGr5ANvpftOtHsZoyhNJYAClseSOai8MaLtrLDwxlRioMXrWM3SVAIQaKX+8L/ViCimqvRPapIVXlMJAM7bDG6Askb96UNHn/Q6XDM0lQAEutdE9kvtd8neR7Z4HXMtmkYA6ukJETGRNX9EKeA51wJyiKYRIFMM9TCisMAdABAdSx88epfXsRvRNAIQZ0+L5R4ggsI5nfI6diOaYqUw80B/XAGdtdh9tjWQX8fOnMk7GpRDNPwdQImEX6HiX0SHfllrzcyrD3p9HcvR8AKkfa2/ALF7aiz/DVuR6JAXsZvB73UARqQO9B0gol/ZtcMY7XAiHjdo2GdA8kDvFpB/EMAau7YYkGttD7U04ruDhrwD0om+ds5xhkC2kw8ABKhzM/l2AJ87Yc9JGu4ZMN3Ts7IIeoNAd1ue9HXaAucdJR+p/UeeSCaOTM7u79tZvyvTp6EEuJJIqErW9xoIMQdzDxDAimx1mat+ENZx0MvjuwfC9bk6fRpGAEok/K08+goRJYgIjjeFeMkXJ7rn5u/figayv/byuhtCAMJpJUnRFwF8zz0frAAAqX19dwLYUHboVCrR69kqqSEESO47/zw4/cDGZqt2TaLANQDgVHx0yTEf53iePFoRer4Mnbmv91kAP3fbT8GH9X7/vIZ8cBTApqXHGfDDtrP/fsntOJbi6R0wEz/8DASTrz5wGa1/+A8ij10E/Lx2hxvk13wRnaH5wIvQST4AEPDs1VhfRCQWJ/BMgJl47wkw+q1ov+DecbBQEcHdE2h56hxYdN5Mt3Sybe5NRqzf4Jz1oSj/iWg8dvFkCkrdd6ibk3IWgPCIa/npu/BvmV38uzixEtf/dC8o58ie8ssiBb6x5p3XM04YM0Pd74DZ3YdWcVJeg4Xk6+HblEb0yUGwoCNVhnaFFZ5wwpBZ6i5A0af8FcvMw2ZgrfmqfZbvzhTCj404Eh8DPUUDAz5HjJmgrgJM7+09RsBxqxtatkqDcltO13Ygdg3BfWNObJq3TF/NPOT4xS9D3QS4kkioYPR7OzYCsWuGmQv3/7fi+WAVprAf2TZikroJsGIhcgrAZqv9mVpA6DufGp/k5wg/fkFkeaoP4eDknoNr7RkxR10EuBrrizAUf2ZnJ6v2fAylJV9z/vCtnYP64Cd2d87+oKI8Wo/c1EWAoLowADDLXy77N88iFB8DOEw19f7L8HVctxUzEQ7bMmCSugjAAMtzKgsVoD5+EaSQ+QHs4wgd+chu2PupcyBo10gtXBdgKtHbASButX/4+Ch8q+dMj/5SC2ydgu+OlJ3Qo8m2zC47BszgugC++UIcRMzKXBzaO4bAtyeFk784FX33I1vPAiq6/zLf9XfCnGMPAwn3890+i1DP/0AF6759d8xA2ZhCcbzVUn/GcLd17+ZwXQBGfLtwJ4Wg9n8IAgdsCAAAwV3j0D5bYakvJ2y15702rgtAnITX08H4GJQ1GVujv4SvcxJ4/ZtWi3Xr7UdgjPufpXBaJXI6i84jGL8CMlVlNhUA/Fs/x8LQhtqnVmNt7hLA/TugWGgTOT/Q/RmIiiAHP6VVNn8JOmdpY/tVEECsTKzcNQXu2Oi/aXNjCsQLAAm//nD9Szr3BSgUMwBCZs5VVmmgYA7FrNNRFMBWZ8Ano6IdXX8xIzwk3nrn3GGAXgCw0clACpnreHd4BBNT0xW/b1y/Dju3b0M4rArbNFz80o2j83NZXBi6gE+mkxWHN3SsXfRrZhFNwISP8ZP3x+NnRGK0sBGjv8Hh5AOAf0ULYju7qn7f0SWe/FJtTv8gLSYfAILRCDp36fjdvg2qyeQDACPaxDl7QShQWJuCLL/NMoIARMLVXwlGIuaTb2bE66Hn17TolXZvN9fpFp5/Hb0YvkGCTNvQPWjdrrFTZ+x6JoATia+wU3XAvF2hCAzsWrmSugsgE19J3QSQidfH/X1AxR8uzPNNmvgSrgrQSA9YJ5LmxuPcFQGcmm6Wd9D8iS8hvBHLZvU/jALKNkBLNjumbWuasT8Bu4absSofOn61nJANqwgLcO79i1Ui2E08AMxpGs6/V/154eDwyI0EuZB4ECGb1TA0PFrt9
4NRaNryg80phGtBPz71S7cHRVPz9z/+RiinDfEvSl9npAAeIwXwGOFl6Imj5r7Yy2ZzOD88gmuTUxW/b1ha3xd4uJryq+UwNDyCa5NfVPrtWIsdXZ1QLbxXuBUELRuLpuUw9MElYZOu3QGRiIqd3duqfl+s7wsuKU37VUPY0VXtN
2Yn+WWxLhdLOKwi1tUpbNrVjZhufT8cciXx5TYjOom28kat3KaZWPT81sJRAZxanzpVs7EXhPGIdwpHBGikxNuOpU6JL2FbgK9MlbLOiS9hWQCZeGcQFkAm3lnsPwMEH4IihTLbNgzsep34EvYEcGMF4nLibdtxGPGNGGHC7CZKt
75vVOI1WNmIJE3Ph1af+v64aAdhARjDSQATtc6b0zQMvl9dZx8aHq1O0DKCWklYVsvhPd36/iW36/vjxOmkmw4kEolEIpFIJBKJRCKRSCTNzf8B9DlMYsFrhfAAAAAASUVORK5CYII=
</data>
<downloads_count>0</downloads_count>
</logo>
</NetworkDeviceType>
<NetworkDeviceType alias="NetworkDeviceType" id="2">
<name>Load Balancer</name>
<logo>
<mimetype>image/svg+xml</mimetype>
<filename>icons8-loadbalancer-6.svg</filename>
<data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcg
eG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIg
eG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAw
IDk2IDk2IiB3aWR0aD0iOTYiIGhlaWdodD0iOTYiIHZlcnNpb249IjEuMSIgaWQ9InN2ZzE2IiBzb2RpcG9kaTpkb2NuYW1lPSJpY29uczgtbG9hZGJhbGFuY2VyLTYuc3ZnIiB4bWw6c3BhY2U9InByZXNlcnZlIiBpbmtzY2Fw
ZTp2ZXJzaW9uPSIxLjQuMyAoMGQxNWY3NTA0MiwgMjAyNS0xMi0yNSkiPjxkZWZzIGlkPSJkZWZzMTYiPjxsaW5lYXJHcmFkaWVudCBpZD0icmd0eWJSNWZEVThSNElnSUZrT1A1YiIgeDE9IjE5LjM4OCIgeDI9IjI4LjQxMyIg
eTE9Ii05Ljk0NDk5OTciIHkyPSI1Mi4wOTg5OTkiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMCwtMC40OTMxMTUxMywtMC40OTMxMTUxMywwLDQ2LjAxOTQ5NCw0My45OTUwMjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3Bh
Y2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMWVhMmU0IiBpZD0ic3RvcDctNiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzMyYmRlZiIgaWQ9InN0b3A4LTIiLz48L2xpbmVhckdyYWRpZW50
PjxsaW5lYXJHcmFkaWVudCBpZD0icmd0eWJSNWZEVThSNElnSUZrT1A1YSIgeDE9IjQ3Ny4xNzg5OSIgeDI9IjQ3Mi43NzIiIHkxPSI1MjIuMTg3MDEiIHkyPSI1MjIuMTg3MDEiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgo
LTAuMzQ4Njg1MDUsMC4zNDg2ODUwNSwwLjM0ODY4NTA1LDAuMzQ4Njg1MDUsMjMuNzgzMDkxLC0zMDYuNjYwNDQpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuMzY1IiBzdG9wLWNvbG9y
PSIjMTk5YWUwIiBpZD0ic3RvcDEiLz48c3RvcCBvZmZzZXQ9Ii42OTkiIHN0b3AtY29sb3I9IiMxODk4ZGUiIGlkPSJzdG9wMiIvPjxzdG9wIG9mZnNldD0iLjgxOSIgc3RvcC1jb2xvcj0iIzE2OTFkOCIgaWQ9InN0b3AzLTki
Lz48c3RvcCBvZmZzZXQ9Ii45MDUiIHN0b3AtY29sb3I9IiMxMTg2Y2MiIGlkPSJzdG9wNC0xIi8+PHN0b3Agb2Zmc2V0PSIuOTc0IiBzdG9wLWNvbG9yPSIjMGE3NWJjIiBpZD0ic3RvcDUtMiIvPjxzdG9wIG9mZnNldD0iMSIg
c3RvcC1jb2xvcj0iIzA3NmNiMyIgaWQ9InN0b3A2LTciLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iQXJ0RFlaMmxUNzV2a2FiUkVzVERFYiIgeDE9IjEwLjQ0MyIgeDI9IjM0Ljg5NDAwMSIgeTE9IjM1
Ljk4NTAwMSIgeTI9IjExLjUzMyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMC43MzI5NTMwMywwLDAsMC43MzI5NTMwMyw2MC40MDkwOTQsMjkuOTkxODEyKSI+PHN0
b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMzJiZGVmIiBpZD0ic3RvcDctMyIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzFlYTJlNCIgaWQ9InN0b3A4LTciLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFk
aWVudCBpZD0iQXJ0RFlaMmxUNzV2a2FiUkVzVERFYSIgeDE9IjM3IiB4Mj0iMzciIHkxPSI0MS41NTUiIHkyPSIyOC4wMzAwMDEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0
cml4KDAuNzMyOTUzMDMsMCwwLDAuNzMyOTUzMDMsNjAuNDA5MDk0LDI5Ljk5MTgxMikiPjxzdG9wIG9mZnNldD0iLjM2NSIgc3RvcC1jb2xvcj0iIzE5OWFlMCIgaWQ9InN0b3AxLTUiLz48c3RvcCBvZmZzZXQ9Ii42OTkiIHN0
b3AtY29sb3I9IiMxODk4ZGUiIGlkPSJzdG9wMi05Ii8+PHN0b3Agb2Zmc2V0PSIuODE5IiBzdG9wLWNvbG9yPSIjMTY5MWQ4IiBpZD0ic3RvcDMtMiIvPjxzdG9wIG9mZnNldD0iLjkwNSIgc3RvcC1jb2xvcj0iIzExODZjYyIg
aWQ9InN0b3A0LTIiLz48c3RvcCBvZmZzZXQ9Ii45NzQiIHN0b3AtY29sb3I9IiMwYTc1YmMiIGlkPSJzdG9wNS04Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDc2Y2IzIiBpZD0ic3RvcDYtOSIvPjwvbGluZWFy
R3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSI5MDFSSUhjTHl6NmRaUEdTdlNmMVhjIiB4MT0iMzMuNDM2MDAxIiB4Mj0iMzguMTU3MDAxIiB5MT0iMjEuNTYzOTk5IiB5Mj0iMTYuODQzIiBncmFkaWVudFRyYW5zZm9ybT0i
bWF0cml4KC0xLDAsMCwxLDEyMS43MTIxOSwxNy4zNjgxMjkpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjYWU0Y2Q1IiBpZD0ic3RvcDUtNiIvPjxzdG9wIG9m
ZnNldD0iMSIgc3RvcC1jb2xvcj0iI2FjNGFkNSIgaWQ9InN0b3A2LTEiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iOTAxUklIY0x5ejZkWlBHU3ZTZjFYYiIgeDE9IjY5NC45NzYwMSIgeDI9IjcxNy43
MTgwMiIgeTE9IjM1LjcwOSIgeTI9IjEyLjk2NyIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSgtNjA2LjI4NzgyLDE3LjM2ODEyOSkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAi
IHN0b3AtY29sb3I9IiNhZTRjZDUiIGlkPSJzdG9wMy0yOSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2FjNGFkNSIgaWQ9InN0b3A0LTMiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iOTAx
UklIY0x5ejZkWlBHU3ZTZjFYYSIgeDE9IjM2LjI1IiB4Mj0iMzYuMjUiIHkxPSIzOC4wNDI5OTkiIHkyPSIyMy4wMDYwMDEiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoLTEsMCwwLDEsMTIxLjcxMjE5LDE3LjM2ODEyOSki
IGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM5MTJmYmQiIGlkPSJzdG9wMS0xIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjOTMzMmJmIiBpZD0ic3Rv
cDItOTQiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpbmtzY2FwZTpjb2xsZWN0PSJhbHdheXMiIHhsaW5rOmhyZWY9IiNBcnREWVoybFQ3NXZrYWJSRXNUREVhIiBpZD0ibGluZWFyR3JhZGllbnQyNCIgZ3Jh
ZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMCwwLjczMjk1MzAzLC0wLjczMjk1MzAzLDAsNjUuNjM1NTkyLDYwLjE1MzUxNSkiIHgxPSIzNyIgeTE9IjQxLjU1NSIgeDI9IjM3
IiB5Mj0iMjguMDMwMDAxIi8+PGxpbmVhckdyYWRpZW50IGlua3NjYXBlOmNvbGxlY3Q9ImFsd2F5cyIgeGxpbms6aHJlZj0iI0FydERZWjJsVDc1dmthYlJFc1RERWIiIGlkPSJsaW5lYXJHcmFkaWVudDI1IiBncmFkaWVudFVu
aXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgwLDAuNzMyOTUzMDMsLTAuNzMyOTUzMDMsMCw2NS42MzU1OTIsNjAuMTUzNTE1KSIgeDE9IjEwLjQ0MyIgeTE9IjM1Ljk4NTAwMSIgeDI9IjM0
Ljg5NDAwMSIgeTI9IjExLjUzMyIvPjxsaW5lYXJHcmFkaWVudCBpbmtzY2FwZTpjb2xsZWN0PSJhbHdheXMiIHhsaW5rOmhyZWY9IiNBcnREWVoybFQ3NXZrYWJSRXNUREViIiBpZD0ibGluZWFyR3JhZGllbnQyNiIgZ3JhZGll
bnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMC41MTgyNzYwNiwwLjUxODI3NjA2LC0wLjUxODI3NjA2LDAuNTE4Mjc2MDYsNjUuMDk5NTg5LDM4LjI4MzI5NSkiIHgxPSIxMC40NDMi
IHkxPSIzNS45ODUwMDEiIHgyPSIzNC44OTQwMDEiIHkyPSIxMS41MzMiLz48bGluZWFyR3JhZGllbnQgaW5rc2NhcGU6Y29sbGVjdD0iYWx3YXlzIiB4bGluazpocmVmPSIjQXJ0RFlaMmxUNzV2a2FiUkVzVERFYSIgaWQ9Imxp
bmVhckdyYWRpZW50MjciIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDAuNTE4Mjc2MDYsMC41MTgyNzYwNiwtMC41MTgyNzYwNiwwLjUxODI3NjA2LDY1LjA5OTU4OSwz
OC4yODMyOTUpIiB4MT0iMzciIHkxPSI0MS41NTUiIHgyPSIzNyIgeTI9IjI4LjAzMDAwMSIvPjxsaW5lYXJHcmFkaWVudCBpbmtzY2FwZTpjb2xsZWN0PSJhbHdheXMiIHhsaW5rOmhyZWY9IiNBcnREWVoybFQ3NXZrYWJSRXNU
REVhIiBpZD0ibGluZWFyR3JhZGllbnQyOCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoLTAuNTE4Mjc2MDYsMC41MTgyNzYwNiwwLjUxODI3NjA2LDAuNTE4Mjc2MDYs
MzEuMDYzOTkzLDM4LjIzOTEwMSkiIHgxPSIzNyIgeTE9IjQxLjU1NSIgeDI9IjM3IiB5Mj0iMjguMDMwMDAxIi8+PGxpbmVhckdyYWRpZW50IGlua3NjYXBlOmNvbGxlY3Q9ImFsd2F5cyIgeGxpbms6aHJlZj0iI0FydERZWjJs
VDc1dmthYlJFc1RERWIiIGlkPSJsaW5lYXJHcmFkaWVudDI5IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgtMC41MTgyNzYwNiwwLjUxODI3NjA2LDAuNTE4Mjc2MDYs
MC41MTgyNzYwNiwzMS4wNjM5OTMsMzguMjM5MTAxKSIgeDE9IjEwLjQ0MyIgeTE9IjM1Ljk4NTAwMSIgeDI9IjM0Ljg5NDAwMSIgeTI9IjExLjUzMyIvPjxsaW5lYXJHcmFkaWVudCBpZD0iOTAxUklIY0x5ejZkWlBHU3ZTZjFY
Yy04IiB4MT0iMzMuNDM2MDAxIiB4Mj0iMzguMTU3MDAxIiB5MT0iMjEuNTYzOTk5IiB5Mj0iMTYuODQzIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDAsMC43ODYzOTQyMiwwLjc4NjM5NDIyLDAsMjguNzA4NjE1LC0xLjEx
MzM1MzMpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjYWU0Y2Q1IiBpZD0ic3RvcDUtODQiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNhYzRhZDUi
IGlkPSJzdG9wNi0zIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IjkwMVJJSGNMeXo2ZFpQR1N2U2YxWGItMSIgeDE9IjY5NC45NzYwMSIgeDI9IjcxNy43MTgwMiIgeTE9IjM1LjcwOSIgeTI9IjEyLjk2
NyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgwLC0wLjc4NjM5NDIyLDAuNzg2Mzk0MjIsMCwyOC43MDg2MTUsNTcxLjM4MTY1KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3Rv
cC1jb2xvcj0iI2FlNGNkNSIgaWQ9InN0b3AzLTQiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNhYzRhZDUiIGlkPSJzdG9wNC05Ii8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IjkwMVJJSGNM
eXo2ZFpQR1N2U2YxWGEtMiIgeDE9IjM2LjI1IiB4Mj0iMzYuMjUiIHkxPSIzOC4wNDI5OTkiIHkyPSIyMy4wMDYwMDEiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMCwwLjc4NjM5NDIyLDAuNzg2Mzk0MjIsMCwyOC43MDg2
MTUsLTEuMTEzMzUzMykiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM5MTJmYmQiIGlkPSJzdG9wMS0wIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIj
OTMzMmJmIiBpZD0ic3RvcDItNiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxzb2RpcG9kaTpuYW1lZHZpZXcgaWQ9Im5hbWVkdmlldzE2IiBwYWdlY29sb3I9IiNmZmZmZmYiIGJvcmRlcmNvbG9yPSIjMDAwMDAwIiBib3Jk
ZXJvcGFjaXR5PSIwLjI1IiBpbmtzY2FwZTpzaG93cGFnZXNoYWRvdz0iMiIgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIgaW5rc2NhcGU6ZGVza2NvbG9yPSIjZDFkMWQx
IiBzaG93Z3VpZGVzPSJ0cnVlIiBpbmtzY2FwZTp6b29tPSI1LjY1Njg1NDMiIGlua3NjYXBlOmN4PSI0NS4zNDMyMjIiIGlua3NjYXBlOmN5PSIzMC40MDU1OTIiIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMjU2MCIgaW5rc2Nh
cGU6d2luZG93LWhlaWdodD0iMTM2MCIgaW5rc2NhcGU6d2luZG93LXg9IjAiIGlua3NjYXBlOndpbmRvdy15PSIwIiBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIiBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmcxNiI+
PHNvZGlwb2RpOmd1aWRlIHBvc2l0aW9uPSIxOS41NTk3ODksMTQzLjczODM0IiBvcmllbnRhdGlvbj0iMSwwIiBpZD0iZ3VpZGUxNyIgaW5rc2NhcGU6bG9ja2VkPSJmYWxzZSIvPjxzb2RpcG9kaTpndWlkZSBwb3NpdGlvbj0i
MjQuMDg0NDY5LDk4LjIyNDIxMiIgb3JpZW50YXRpb249IjAsLTEiIGlkPSJndWlkZTE4IiBpbmtzY2FwZTpsb2NrZWQ9ImZhbHNlIi8+PHNvZGlwb2RpOmd1aWRlIHBvc2l0aW9uPSIxOS44NDUxNjksMTE2LjQzOTYyIiBvcmll
bnRhdGlvbj0iMCwtMSIgaWQ9Imd1aWRlMTkiIGlua3NjYXBlOmxvY2tlZD0iZmFsc2UiLz48c29kaXBvZGk6Z3VpZGUgcG9zaXRpb249IjQ4LjA0MTUwNCw4My40NjU4MiIgb3JpZW50YXRpb249IjEsMCIgaWQ9Imd1aWRlMjAi
IGlua3NjYXBlOmxvY2tlZD0iZmFsc2UiLz48c29kaXBvZGk6Z3VpZGUgcG9zaXRpb249Ijc4LjI1LDQ3Ljc1IiBvcmllbnRhdGlvbj0iMCwtMSIgaWQ9Imd1aWRlMjEiIGlua3NjYXBlOmxvY2tlZD0iZmFsc2UiLz48c29kaXBv
ZGk6Z3VpZGUgcG9zaXRpb249IjUwLjM5NDQ1Nyw2NS4zMTY0NjgiIG9yaWVudGF0aW9uPSIwLC0xIiBpZD0iZ3VpZGUyOSIgaW5rc2NhcGU6bG9ja2VkPSJmYWxzZSIvPjxzb2RpcG9kaTpndWlkZSBwb3NpdGlvbj0iNjcuNjA1
MzQ3LDIxLjA2MDgzNyIgb3JpZW50YXRpb249IjAsLTEiIGlkPSJndWlkZTMwIiBpbmtzY2FwZTpsb2NrZWQ9ImZhbHNlIi8+PC9zb2RpcG9kaTpuYW1lZHZpZXc+PGxpbmVhckdyYWRpZW50IGlkPSI2ZlNPVVBhfkNQOHRjc0l4
X1d2dWZhIiB4MT0iMjIuMDExIiB4Mj0iMjYuMjEyIiB5MT0iNzg1Ljc5MTAyIiB5Mj0iNzg5Ljk5Mjk4IiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTc4MS43OCkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9u
VXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiMzM2JlZjAiIGlkPSJzdG9wMyIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzBhODVkOSIgaWQ9InN0b3A0Ii8+PC9saW5lYXJHcmFkaWVudD48bGluZWFy
R3JhZGllbnQgaWQ9IjZmU09VUGF+Q1A4dGNzSXhfV3Z1ZmIiIHgxPSI2LjAxMTAwMDIiIHgyPSIxMC4yMTMiIHkxPSI3OTQuNzkxMDIiIHkyPSI3OTguOTkyIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTc4MS43
OCkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiMzM2JlZjAiIGlkPSJzdG9wNSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzBhODVkOSIgaWQ9InN0
b3A2Ii8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IjZmU09VUGF+Q1A4dGNzSXhfV3Z1ZmMiIHgxPSI2LjAxMTAwMDIiIHgyPSIxMC4yMTMiIHkxPSI4MTIuNzkxMDIiIHkyPSI4MTYuOTkyIiBncmFkaWVu
dFRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTc4MS43OCkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiMzM2JlZjAiIGlkPSJzdG9wNyIvPjxzdG9wIG9mZnNldD0i
MSIgc3RvcC1jb2xvcj0iIzBhODVkOSIgaWQ9InN0b3A4Ii8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IjZmU09VUGF+Q1A4dGNzSXhfV3Z1ZmQiIHgxPSIzOC4wMTEwMDIiIHgyPSI0Mi4yMTIwMDIiIHkx
PSI3OTQuNzkxMDIiIHkyPSI3OTguOTkyIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTc4MS43OCkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiMz
M2JlZjAiIGlkPSJzdG9wOSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzBhODVkOSIgaWQ9InN0b3AxMCIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSI2ZlNPVVBhfkNQOHRjc0l4X1d2dWZl
IiB4MT0iMzguMDExMDAyIiB4Mj0iNDIuMjEyMDAyIiB5MT0iODEyLjc5MTAyIiB5Mj0iODE2Ljk5MiIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSgwLC03ODEuNzgpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVz
ZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMzNiZWYwIiBpZD0ic3RvcDExIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMGE4NWQ5IiBpZD0ic3RvcDEyIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFy
R3JhZGllbnQgaWQ9IjZmU09VUGF+Q1A4dGNzSXhfV3Z1ZmYiIHgxPSIyMi4wMTEiIHgyPSIyNi4yMTIiIHkxPSI4MjEuNzkxMDIiIHkyPSI4MjUuOTkyIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTc4MS43OCki
IGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiMzM2JlZjAiIGlkPSJzdG9wMTMiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwYTg1ZDkiIGlkPSJzdG9w
MTQiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iNmZTT1VQYX5DUDh0Y3NJeF9XdnVmZyIgeDE9IjIyLjM4OTk5OSIgeDI9IjI1LjUxIiB5MT0iMjcuODQxIiB5Mj0iMjAuMTg0IiBncmFkaWVudFRyYW5z
Zm9ybT0ibWF0cml4KDIuMjc1MDY0OSwwLDAsLTIuMjc1MDY0OSwtNi40NzA0OTc2LDcxLjA3ODY1OSkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiMyYWE0ZjQi
IGlkPSJzdG9wMTUiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwMDdhZDkiIGlkPSJzdG9wMTYiLz48L2xpbmVhckdyYWRpZW50PjxjaXJjbGUgY3g9IjQ4LjEzMTA1IiBjeT0iMTYuNzI3MzU2IiBmaWxsPSJ1cmwo
IzZmU09VUGF+Q1A4dGNzSXhfV3Z1ZmcpIiBpZD0iY2lyY2xlMTYiIHN0eWxlPSJmaWxsOnVybCgjNmZTT1VQYX5DUDh0Y3NJeF9XdnVmZyk7c3Ryb2tlLXdpZHRoOjIuMjc1MDYiIHI9IjExLjM3NTMyNCIvPjxwYXRoIGZpbGw9
InVybCgjQXJ0RFlaMmxUNzV2a2FiUkVzVERFYSkiIGQ9Im0gNzYuODU2MTY0LDczLjcwNjQyNiB2IC0zLjQ3MTQxMyBjIDEwZS03LC0wLjY2ODU3NiAtMC41NDE1OTgsLTEuMjEwMTc1IC0xLjIxMDE3NSwtMS4yMTAxNzUgbCAt
MTAuMDI4MTIzLC0yLjIzNjM2MSAtNi42MzM0MTUsNi42MzM0MTYgYyAtMC41NTE5NjQsMC41NTE5NjQgLTAuMTYxMTg1LDEuNDk1MjI2IDAuNjE5MzQsMS40OTUyMjYgaCAxNi4wNDE2OCBjIDAuNjY4NTc3LDAgMS4yMTA2OTQs
LTAuNTQyMTE3IDEuMjEwNjkzLC0xLjIxMDY5MyB6IiBpZD0icGF0aDYtNyIgc3R5bGU9ImZpbGw6dXJsKCNsaW5lYXJHcmFkaWVudDI3KTtzdHJva2Utd2lkdGg6MC43MzI5NTMiLz48cGF0aCBmaWxsPSJ1cmwoI0FydERZWjJs
VDc1dmthYlJFc1RERWIpIiBkPSJtIDc2Ljg1NjE2NCw3My43MDY0MjYgdiAtMTYuMDQxNjggYyAwLC0wLjc4MDUyNSAtMC45NDMyNjIsLTEuMTcxMzA0IC0xLjQ5NTIyNiwtMC42MTkzNCBMIDY5Ljc2NDA3NCw2Mi42NDIyNjkg
NTEuNzk0MTk5LDQ1LjE3MjM5MyBjIC0wLjU4MDcxNywtMC41NjQ1NTkgLTEuODkzMDk3LDAuNjY1MTkgLTEuNzkxODU0LDEuNDY4NzUgbCAwLjcwMjg0Myw1LjU3ODQwNyBjIDAuMTAxMjQzLDAuODAzNTYgLTAuMTU5ODQyLDEu
MDg3NjMxIDAuNDA2MjUsMS42NjY4NTQgbCAyMC4yMDc0NjUsMjAuNjc2MjE0IGMgMC4yMTY3MDIsMC4yMjE3MjkgMC41MjEzODUsMC4zNTQ1MDEgMC44NTU2NzMsMC4zNTM5ODIgaCAzLjQ3MTQxMyBjIDAuNjY4MDU5LDUuMTll
LTQgMS4yMTAxNzYsLTAuNTQxNTk4IDEuMjEwMTc1LC0xLjIxMDE3NCB6IiBpZD0icGF0aDgtMyIgc3R5bGU9ImZpbGw6dXJsKCNsaW5lYXJHcmFkaWVudDI2KTtzdHJva2Utd2lkdGg6MC43MzI5NTMiIHNvZGlwb2RpOm5vZGV0
eXBlcz0iY3NzY3Nzc3NzY2NjIi8+PHBhdGggZmlsbD0idXJsKCNBcnREWVoybFQ3NXZrYWJSRXNUREVhKSIgZD0ibSAxOS4zMDc0MTgsNzMuNjYyMjMyIHYgLTMuNDcxNDEzIGMgLTEwZS03LC0wLjY2ODU3NiAwLjU0MTU5OCwt
MS4yMTAxNzUgMS4yMTAxNzUsLTEuMjEwMTc1IGwgMTAuMDI4MTIzLC0yLjIzNjM2MSA2LjYzMzQxNSw2LjYzMzQxNiBjIDAuNTUxOTY0LDAuNTUxOTY0IDAuMTYxMTg1LDEuNDk1MjI2IC0wLjYxOTM0LDEuNDk1MjI2IGggLTE2
LjA0MTY4IGMgLTAuNjY4NTc3LDAgLTEuMjEwNjk0LC0wLjU0MjExNyAtMS4yMTA2OTMsLTEuMjEwNjkzIHoiIGlkPSJwYXRoNi03LTgiIHN0eWxlPSJmaWxsOnVybCgjbGluZWFyR3JhZGllbnQyOCk7c3Ryb2tlLXdpZHRoOjAu
NzMyOTUzIiBzb2RpcG9kaTpub2RldHlwZXM9InNzY2Nzc3NzIi8+PHBhdGggZmlsbD0idXJsKCNBcnREWVoybFQ3NXZrYWJSRXNUREViKSIgZD0ibSAxOS4zMDc0MTgsNzMuNjYyMjMyIHYgLTE2LjA0MTY4IGMgMCwtMC43ODA1
MjUgMC45NDMyNjIsLTEuMTcxMzA0IDEuNDk1MjI2LC0wLjYxOTM0IGwgNS41OTY4NjQsNS41OTY4NjMgMTkuMjE5ODc1LC0xOS4wMzIzNzYgYyAwLjU3NTQ5NSwtMC41Njk4ODEgMC41MzQ1OTcsMS4yOTI0NDEgMC40MTY4NTQs
Mi4wOTM3NSBsIC0wLjk1Mjg0Myw2LjQ4NDY1NyBjIC0wLjExNzc0MywwLjgwMTMwOSAwLjUwNzA5OSwxLjQwMzU4IC0wLjA2MjUsMS45NzkzNTQgTCAyNC44NDQ2NzksNzQuNTE4NDI0IGMgLTAuMjE4MDQ1LDAuMjIwNDA5IC0w
LjUyMTM4NSwwLjM1NDUwMSAtMC44NTU2NzMsMC4zNTM5ODIgaCAtMy40NzE0MTMgYyAtMC42NjgwNTksNS4xOWUtNCAtMS4yMTAxNzYsLTAuNTQxNTk4IC0xLjIxMDE3NSwtMS4yMTAxNzQgeiIgaWQ9InBhdGg4LTMtNiIgc3R5
bGU9ImZpbGw6dXJsKCNsaW5lYXJHcmFkaWVudDI5KTtzdHJva2Utd2lkdGg6MC43MzI5NTMiIHNvZGlwb2RpOm5vZGV0eXBlcz0iY3NzY3Nzc3NzY2NjIi8+PHBhdGggZmlsbD0idXJsKCNBcnREWVoybFQ3NXZrYWJSRXNUREVh
KSIgZD0ibSA0OC45MDA4MDksOTMuNTE0NjA1IDIuNDU0NjYsLTIuNDU0NjYgYyAwLjQ3Mjc1NSwtMC40NzI3NTQgMC40NzI3NTUsLTEuMjM4NjkgMCwtMS43MTE0NDUgbCAtNS41MDk2MDgsLTguNjcyMyBoIC05LjM4MTA2NiBj
IC0wLjc4MDU5NSwwIC0xLjE3MTI1OSwwLjk0MzMxIC0wLjYxOTM0NSwxLjQ5NTIyNCBsIDExLjM0MzE4MSwxMS4zNDMxODEgYyAwLjQ3Mjc1NSwwLjQ3Mjc1NSAxLjIzOTQyNCwwLjQ3Mjc1NSAxLjcxMjE3OCwwIHoiIGlkPSJw
YXRoNi03LTQiIHN0eWxlPSJmaWxsOnVybCgjbGluZWFyR3JhZGllbnQyNCk7c3Ryb2tlLXdpZHRoOjAuNzMyOTUzIi8+PHBhdGggZmlsbD0idXJsKCNBcnREWVoybFQ3NXZrYWJSRXNUREViKSIgZD0iTSA0OC45MDA4MDksOTMu
NTE0NjA1IDYwLjI0Mzk5LDgyLjE3MTQyNCBDIDYwLjc5NTkwNCw4MS42MTk1MSA2MC40MDUyNCw4MC42NzYyIDU5LjYyNDY0NSw4MC42NzYyIGggLTcuOTE1MTYgbCAwLjAyMTE1LC01MC4xMDMwNTIgQyA1MS43MzA5NzcsMjku
NzYzMjM1IDUxLjI0MDExMiwyOS4zMDEzNjUgNTAuNDMwMiwyOS4zMDIyMyBsIC00LjM5NjgzOCwwLjAwNDcgYyAtMC44MDk5MTIsOC42NGUtNCAtMS42NDk0NDcsMC40NTI4NjkgLTEuNjQ5NSwxLjI2Mjc4MSBsIC0wLjAwMzks
NTkuNjM0ODg3IGMgLTJlLTUsMC4zMTAwMzkgMC4xMTgwMDUsMC42MTkzNDUgMC4zNTQ3NDksMC44NTUzNTYgbCAyLjQ1NDY2LDIuNDU0NjYgYyAwLjQ3MjAyMiwwLjQ3Mjc1NSAxLjIzODY5MSwwLjQ3Mjc1NSAxLjcxMTQ0NSww
IHoiIGlkPSJwYXRoOC0zLTUiIHN0eWxlPSJmaWxsOnVybCgjbGluZWFyR3JhZGllbnQyNSk7c3Ryb2tlLXdpZHRoOjAuNzMyOTUzIiBzb2RpcG9kaTpub2RldHlwZXM9InNzc2Nzc3Nzc2NjcyIvPjwvc3ZnPgo=
</data>
<downloads_count>0</downloads_count>
</logo>
</NetworkDeviceType>
<NetworkDeviceType alias="NetworkDeviceType" id="10">
<name>Router</name>
<logo>
<mimetype>image/png</mimetype>
<filename>icons8-collect-96.png</filename>
<data>iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFoklEQVR4nO1c
y27bRhQlcul8jLM0lZWCGl3FyKJB2yRrR/JLEh/9i6bpD7RetXZaoKvKjpM6ji1SEkUVyDJA06YpGjt7k6a0FKYYynEcVxJJkZyhyXuAAwgCgbn3HHKoGR1SEBAIBAKBSDlA694CtfsOtC6ZTOsIVGuBd72ZA1BhfcU/pWod8q43
cwDNImHIu97MAdAANCDXALwC0IBcA9QOCUPe9WYOgAagAbkG4BWABmQSoLYfgdIegGoSphyOuSHkHaCYh8zF/8C3Qt4hyp1PQDF77K8As0fH5t1/KiAqrSIobReUNmHDVh9q5qe8+06hCS0XlBZJls0+1AwUf6wJctMFuUmSoYHi
+18JjSLIhguyQeKljuIHno4qjSLUdBdqOomHDRSfnwkNFD+SCdUDF6oNMiX7UNvHG25kE9b2XagckJDswyqKHwvEyl4R1vZcqDwnAYnixw1xea8IK89cWN0jPuzD6i5OO4mZsPybCyu7ZAxR/KQhLj8pwtITF5afkgvsQ3kHz3xm
JpQfu7C0QzyWd/IrPqjWIxoFFL9ivLO4+OsslLe+o6SfWQ5Ne6U9g9rdFHgDVGtwmsfsgWrNCxkHqNa81+uw50EaUsvnk8l90LqZnQpExSqC1nXP95zCxFonkyaInviWm7oQ8OjIYLZMEMeIn2IDsmOCOEH8lBsQvwmzL8lVybDv
SYbzU0G3XxUMp+dRt1+dfneXHsNK/EtgQHwmSMbxFwXdeVMwHOLDvyX9+POo44la94af+OkwIFBizeyDNt2f4Hd+ISAZ9rcBhP+Yuv1QIOTKNGOKWvsGqB33UoSAg0cGpzNBmkb8U0qG/SBJ8RMxADTzFijmu7BZzED08j/BF2sS
nXamFP89rzdPbodaZHk1JtC7agZ7enN4YBIFhDNh9iW5SufzqAZIuvNPkBtzsuKf9e7/9GaiBYSYjiTDvhdV/LOrQLfvxDntRGEAA1jFA9sTTSjozs9xGSDpzuZk8U2XVd8pMmBogiA3R+5kSob9V1wG0HXCqDFmtNY170Rg2HPK
DDDpvPj9qDoKhuPGZoDhuCN7Vcx11v0GMKBNmFJpJW6ApDvOaANa66z79Tcg8XDsx0FZYdwUpNt/xncF2H+MnYJoWJdhzykyYHJK2dvbie8esME/lR3UgMSSyeFSygXdvhuXAXPN4y/5prI/0N+AqnEENYMkxqrRg2rDdyE294LM
FAzndfSz33kTaCFWbcx7tSXZe00PsBCr6QtQ1Y/iSyafY1UPJP570F3NyGe/cfKZEBBDE/ReIr3XGodQadwU4kbSQdmCbj+c+teP4XyddCBY4A2oHpAAnD6lTMiVgm5/E158+8HU29GeCftukN4E3mCVUr7ePLkd8J7wOsy0EzWV
LfAGy5Ty3AsyQzfW6N4O/W1/ulhz6Wf6Hf21Q49hmcoWeANWn5ExzERQVvRS2bvuuD551yfkIaUsTkhl865NyEtKWRyTyuZdl3CWUM5BSlm8mMpe2kmBAaXtAZS3CZS3elDazn44t7Q97/VKey5tpyCcW6pvQqn+r7i4xTSePqP9
fg3U7jol/cxybNor3K+/hVL9RyGPEL3Q1PmUcrZT2SkXv4smsBXfcrMeCE4lxIBZTTSBq/gWmsBffAtNiDWfr0ZJrE2fys49xMjiowkcz/wOmpAe8Ts4HfEXv4Mm+IvfKrJJKU9OZecSIjPx0YT/iy/jq4u5AuT2IbtXFl+g3MaX
d4Pc2gC5OWCbym7RnOYA5OYPfE+/SwSIOwSLCGtAuFcVo74xA0KGYdGAuA2ohntrLhrAJwRMUhOazRqgsk/CkHe9mQOs7ZEw5F1v5gCruyQMedebOcDKUxKGvOvNHOB8BjUAedebOUBp62iYQQ1E/6cRESENWNxagPv1IyjViQ8PoVSP/2lEBAKBQCCEePEfD3q/JRB0b7YAAAAASUVORK5CYII=
</data>
<downloads_count>0</downloads_count>
</logo>
</NetworkDeviceType>
<NetworkDeviceType alias="NetworkDeviceType" id="4">
<name>Router 4G</name>
<logo>
<mimetype>image/svg+xml</mimetype>
<filename>icons8-router-4g.svg</filename>
<data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sb
nM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIgeG1sb
nM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgOTYgOTYiIHdpZHRoPSI5NiIgaGVpZ2h0PSI5NiIgdmVyc2lvbj0iMS4xIiBpZ
D0ic3ZnMjUiIHNvZGlwb2RpOmRvY25hbWU9Imljb25zOC1yb3V0ZXItNGcuc3ZnIiBpbmtzY2FwZTp2ZXJzaW9uPSIxLjQuMyAoMGQxNWY3NTA0MiwgMjAyNS0xMi0yNSkiPjxkZWZzIGlkPSJkZWZzMjUiPjxsaW5lYXJHcmFka
WVudCBpZD0iZXd3NmZTSFhMRzNoNFllQXFnOXVfYSIgeDE9IjE3LjU5IiB4Mj0iMzIuMDciIHkxPSIyNS45MzQ5OTkiIHkyPSI0OC4yMzA5OTkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBncmFkaWVudFRyYW5zZ
m9ybT0ibWF0cml4KDEuMTYxODcxNywwLDAsMS4xNjE4NzE3LDIwLjUwNzI1NCwyLjE5MTYwNDkpIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM4NTkyOWUiIGlkPSJzdG9wMS0zIi8+PHN0b3Agb2Zmc2V0PSIxIiBzd
G9wLWNvbG9yPSIjNmQ3ODgyIiBpZD0ic3RvcDItNiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxzb2RpcG9kaTpuYW1lZHZpZXcgaWQ9Im5hbWVkdmlldzI1IiBwYWdlY29sb3I9IiNmZmZmZmYiIGJvcmRlcmNvbG9yPSIjM
DAwMDAwIiBib3JkZXJvcGFjaXR5PSIwLjI1IiBpbmtzY2FwZTpzaG93cGFnZXNoYWRvdz0iMiIgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIgaW5rc2NhcGU6ZGVza2Nvb
G9yPSIjZDFkMWQxIiBpbmtzY2FwZTp6b29tPSI4LjEwMjI2NTIiIGlua3NjYXBlOmN4PSIyMS40MTM3NjUiIGlua3NjYXBlOmN5PSIzNy4zOTY5NDkiIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMjU2MCIgaW5rc2NhcGU6d2luZ
G93LWhlaWdodD0iMTM2MCIgaW5rc2NhcGU6d2luZG93LXg9IjAiIGlua3NjYXBlOndpbmRvdy15PSIwIiBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIiBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmcyNSIgc2hvd2d1a
WRlcz0idHJ1ZSI+PHNvZGlwb2RpOmd1aWRlIHBvc2l0aW9uPSI5LjgxNzg1NjIsMzAuMTQwNzE4IiBvcmllbnRhdGlvbj0iMSwwIiBpZD0iZ3VpZGUxIiBpbmtzY2FwZTpsb2NrZWQ9ImZhbHNlIi8+PHNvZGlwb2RpOmd1aWRlI
HBvc2l0aW9uPSI4Ni40NzA4MDIsMzguMTgxOTY4IiBvcmllbnRhdGlvbj0iMSwwIiBpZD0iZ3VpZGUyIiBpbmtzY2FwZTpsb2NrZWQ9ImZhbHNlIi8+PHNvZGlwb2RpOmd1aWRlIHBvc2l0aW9uPSI0Ni4yNTg2MzYsOS40ODEwM
jMyIiBvcmllbnRhdGlvbj0iMCwtMSIgaWQ9Imd1aWRlMyIgaW5rc2NhcGU6bG9ja2VkPSJmYWxzZSIvPjxzb2RpcG9kaTpndWlkZSBwb3NpdGlvbj0iNTMuNjQxNDQyLDEwMS4yOTgiIG9yaWVudGF0aW9uPSIwLC0xIiBpZD0iZ
3VpZGU0IiBpbmtzY2FwZTpsb2NrZWQ9ImZhbHNlIi8+PC9zb2RpcG9kaTpuYW1lZHZpZXc+PGxpbmVhckdyYWRpZW50IGlkPSJzUXk3T3ZQWEgwdDJtS2ZxazdYdVhhIiB4MT0iMzQuMTE3MDAxIiB4Mj0iMzMuOTA5IiB5MT0iM
zAuNDUxIiB5Mj0iMTEuODI2IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuMDE1MTEyMSwwLDAsLTIuMDE1MTEyMSwtMC4yODI4MzI5NSw5OC4xNzI2OTQpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b
3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjNzM3YjgwIiBpZD0ic3RvcDEiLz48c3RvcCBvZmZzZXQ9Ii43MTQiIHN0b3AtY29sb3I9IiM3MzdiODAiIGlkPSJzdG9wMiIvPjxzdG9wIG9mZnNldD0iLjc1NiIgc3RvcC1jb2xvc
j0iIzczN2I4MCIgaWQ9InN0b3AzIi8+PHN0b3Agb2Zmc2V0PSIuODYzIiBzdG9wLWNvbG9yPSIjNjU2YzcxIiBpZD0ic3RvcDQiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM1NzVjNjEiIGlkPSJzdG9wNSIvPjwvb
GluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNzUXk3T3ZQWEgwdDJtS2ZxazdYdVhhKSIgZD0ibSA2Mi4xODU2NDEsODAuMjU4MzQ4IGMgLTAuMTkxNDM1LDAgLTAuMzg2OTAyLC0wLjAyODIxIC0wLjU4MDM1MiwtMC4wO
DQ2MyAtMS4wNjU5OTMsLTAuMzIwNCAtMS42NzI1NDMsLTEuNDQyODIgLTEuMzUyMTQsLTIuNTA4ODE3IEwgNzIuMzQzODIzLDM3LjM2MjY1OSBjIDAuMzIwNDA0LC0xLjA2NTk5NCAxLjQ0NDgzNCwtMS42NzI1NDMgMi41MDg4M
TUsLTEuMzUyMTQgMS4wNjU5OSwwLjMyMDQwMiAxLjY3MjUzOSwxLjQ0MjgyMSAxLjM1MjE0MSwyLjUwODgxNCBMIDY0LjExNDEwNCw3OC44MjE1NzggYyAtMC4yNTk5NSwwLjg3NDU1NSAtMS4wNTk5NSwxLjQzNjc3IC0xLjkyO
DQ2MywxLjQzNjc3IHoiIGlkPSJwYXRoNSIgc3R5bGU9ImZpbGw6dXJsKCNzUXk3T3ZQWEgwdDJtS2ZxazdYdVhhKTtzdHJva2Utd2lkdGg6Mi4wMTUxMSIvPjxsaW5lYXJHcmFkaWVudCBpZD0ic1F5N092UFhIMHQybUtmcWs3W
HVYYiIgeDE9IjE0LjEyMSIgeDI9IjEzLjkxMyIgeTE9IjMwLjcxOSIgeTI9IjEyLjA5NCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjAxNTExMjEsMCwwLC0yLjAxNTExMjEsLTAuMjgyODMyOTUsOTguMTcyNjk0KSIgZ
3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzczN2I4MCIgaWQ9InN0b3A2Ii8+PHN0b3Agb2Zmc2V0PSIuNzczIiBzdG9wLWNvbG9yPSIjNzM3YjgwIiBpZD0ic3Rvc
DciLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM1NzVjNjEiIGlkPSJzdG9wOCIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNzUXk3T3ZQWEgwdDJtS2ZxazdYdVhiKSIgZD0ibSAzMy45NzQwNzEsO
DAuMjU4MzQ4IGMgLTAuODY2NDk3LDAgLTEuNjY2NDk4LC0wLjU2NDIzMSAtMS45MzA0NzUsLTEuNDM2NzcgTCAxOS45NTI5MjIsMzguNTE5MzMzIGMgLTAuMzIwNDA0LC0xLjA2NTk5MyAwLjI4NjE0NiwtMi4xODg0MTIgMS4zN
TIxNDEsLTIuNTA4ODE0IDEuMDYzOTc5LC0wLjMxNDM1NyAyLjE4ODQxMSwwLjI4NjE0NiAyLjUwODgxNSwxLjM1MjE0IGwgMTIuMDkwNjcxLDQwLjMwMjIzOSBjIDAuMzIwNDAyLDEuMDY1OTk2IC0wLjI4NjE0NiwyLjE4ODQxN
yAtMS4zNTIxMzksMi41MDg4MTUgLTAuMTkzNDUyLDAuMDU2NDMgLTAuMzg2OTAyLDAuMDg0NjMgLTAuNTc4MzM5LDAuMDg0NjMgeiIgaWQ9InBhdGg4IiBzdHlsZT0iZmlsbDp1cmwoI3NReTdPdlBYSDB0Mm1LZnFrN1h1WGIpO
3N0cm9rZS13aWR0aDoyLjAxNTExIi8+PGxpbmVhckdyYWRpZW50IGlkPSJzUXk3T3ZQWEgwdDJtS2ZxazdYdVhjIiB4MT0iMjQiIHgyPSIyNCIgeTE9IjE0LjYxNCIgeTI9Ii0yLjA3MTAwMDEiIGdyYWRpZW50VHJhbnNmb3JtP
SJtYXRyaXgoMi4wMTUxMTIxLDAsMCwtMi4wMTUxMTIxLC0wLjI4MjgzMjk1LDk4LjE3MjY5NCkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM4OTkxOTgiIGlkP
SJzdG9wOSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzc4N2U4NSIgaWQ9InN0b3AxMCIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNzUXk3T3ZQWEgwdDJtS2ZxazdYdVhjKSIgZD0iTSA4Mi4zM
zY3NjUsODYuMzAzNjg5IEggMTMuODIyOTUxIGMgLTIuMjI2Njk4LDAgLTQuMDMwMjIzNywtMS44MDM1MzEgLTQuMDMwMjIzNywtNC4wMzAyMjcgViA2OC4xNjc2NzggYyAwLC0yLjIyNjY5OSAxLjgwMzUyNTcsLTQuMDMwMjI1I
DQuMDMwMjIzNywtNC4wMzAyMjUgaCA2OC41MTM4MTQgYyAyLjIyNjY5NiwwIDQuMDMwMjIxLDEuODAzNTI2IDQuMDMwMjIxLDQuMDMwMjI1IHYgMTQuMTA1Nzg0IGMgMCwyLjIyNjY5NiAtMS44MDM1MjUsNC4wMzAyMjcgLTQuM
DMwMjIxLDQuMDMwMjI3IHoiIGlkPSJwYXRoMTAiIHN0eWxlPSJmaWxsOnVybCgjc1F5N092UFhIMHQybUtmcWs3WHVYYyk7c3Ryb2tlLXdpZHRoOjIuMDE1MTEiLz48cmVjdCB3aWR0aD0iNjguNTEzODA5IiBoZWlnaHQ9IjE0L
jEwNTc4NSIgeD0iMTMuODIyOTUyIiB5PSI2OC4xNjc2NzEiIGZpbGw9IiM3MzdiODAiIGlkPSJyZWN0MTAiIHN0eWxlPSJzdHJva2Utd2lkdGg6Mi4wMTUxMSIvPjxyYWRpYWxHcmFkaWVudCBpZD0ic1F5N092UFhIMHQybUtmc
Ws3WHVYZCIgY3g9IjM2LjUiIGN5PSIxMS4zOSIgcj0iMi41IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuMDE1MTEyMSwwLDAsLTIuMDE1MTEyMSwtMC4yODI4MzI5NSw5OC4xNzI2OTQpIiBncmFkaWVudFVuaXRzPSJ1c
2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuNTgyIiBzdG9wLW9wYWNpdHk9Ii4yIiBpZD0ic3RvcDExIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9IjAiIGlkPSJzdG9wMTIiLz48L3JhZGlhbEdyYWRpZW50P
jxjaXJjbGUgY3g9IjczLjI2ODc1MyIgY3k9Ijc1LjIyMDU3MyIgZmlsbD0idXJsKCNzUXk3T3ZQWEgwdDJtS2ZxazdYdVhkKSIgaWQ9ImNpcmNsZTEyIiBzdHlsZT0iZmlsbDp1cmwoI3NReTdPdlBYSDB0Mm1LZnFrN1h1WGQpO
3N0cm9rZS13aWR0aDoyLjAxNTExIiByPSI1LjAzNzc4MDMiLz48cmFkaWFsR3JhZGllbnQgaWQ9InNReTdPdlBYSDB0Mm1LZnFrN1h1WGUiIGN4PSIzMC41IiBjeT0iMTEuMzkiIHI9IjIuNSIgZ3JhZGllbnRUcmFuc2Zvcm09I
m1hdHJpeCgyLjAxNTExMjEsMCwwLC0yLjAxNTExMjEsLTAuMjgyODMyOTUsOTguMTcyNjk0KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iLjU4MiIgc3RvcC1vcGFjaXR5PSIuMiIgaWQ9I
nN0b3AxMyIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1vcGFjaXR5PSIwIiBpZD0ic3RvcDE0Ii8+PC9yYWRpYWxHcmFkaWVudD48Y2lyY2xlIGN4PSI2MS4xNzgwODIiIGN5PSI3NS4yMjA1NzMiIGZpbGw9InVybCgjc1F5N092U
FhIMHQybUtmcWs3WHVYZSkiIGlkPSJjaXJjbGUxNCIgc3R5bGU9ImZpbGw6dXJsKCNzUXk3T3ZQWEgwdDJtS2ZxazdYdVhlKTtzdHJva2Utd2lkdGg6Mi4wMTUxMSIgcj0iNS4wMzc3ODAzIi8+PHJhZGlhbEdyYWRpZW50IGlkP
SJzUXk3T3ZQWEgwdDJtS2ZxazdYdVhmIiBjeD0iMjQuNSIgY3k9IjExLjM5IiByPSIyLjUiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMi4wMTUxMTIxLDAsMCwtMi4wMTUxMTIxLC0wLjI4MjgzMjk1LDk4LjE3MjY5NCkiI
GdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9Ii41ODIiIHN0b3Atb3BhY2l0eT0iLjIiIGlkPSJzdG9wMTUiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3Atb3BhY2l0eT0iMCIgaWQ9InN0b3AxNiIvP
jwvcmFkaWFsR3JhZGllbnQ+PGNpcmNsZSBjeD0iNDkuMDg3NDE0IiBjeT0iNzUuMjIwNTczIiBmaWxsPSJ1cmwoI3NReTdPdlBYSDB0Mm1LZnFrN1h1WGYpIiBpZD0iY2lyY2xlMTYiIHN0eWxlPSJmaWxsOnVybCgjc1F5N092U
FhIMHQybUtmcWs3WHVYZik7c3Ryb2tlLXdpZHRoOjIuMDE1MTEiIHI9IjUuMDM3NzgwMyIvPjxyYWRpYWxHcmFkaWVudCBpZD0ic1F5N092UFhIMHQybUtmcWs3WHVYZyIgY3g9IjExLjUiIGN5PSIxMS4zOSIgcj0iMi41IiBnc
mFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuMDE1MTEyMSwwLDAsLTIuMDE1MTEyMSwtMC4yODI4MzI5NSw5OC4xNzI2OTQpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuNTgyIiBzdG9wL
W9wYWNpdHk9Ii4yIiBpZD0ic3RvcDE3Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9IjAiIGlkPSJzdG9wMTgiLz48L3JhZGlhbEdyYWRpZW50PjxjaXJjbGUgY3g9IjIyLjg5MDk1OSIgY3k9Ijc1LjIyMDU3MyIgZ
mlsbD0idXJsKCNzUXk3T3ZQWEgwdDJtS2ZxazdYdVhnKSIgaWQ9ImNpcmNsZTE4IiBzdHlsZT0iZmlsbDp1cmwoI3NReTdPdlBYSDB0Mm1LZnFrN1h1WGcpO3N0cm9rZS13aWR0aDoyLjAxNTExIiByPSI1LjAzNzc4MDMiLz48Y
2lyY2xlIGN4PSI3My4yNjg3NTMiIGN5PSI3NS4yMjA1NzMiIGZpbGw9IiM1MGU2ZmYiIGlkPSJjaXJjbGUxOSIgc3R5bGU9InN0cm9rZS13aWR0aDoyLjAxNTExIiByPSIzLjAyMjY2ODQiLz48Y2lyY2xlIGN4PSI2MS4xNzgwO
DIiIGN5PSI3NS4yMjA1NzMiIGZpbGw9IiM1MGU2ZmYiIGlkPSJjaXJjbGUyMCIgc3R5bGU9InN0cm9rZS13aWR0aDoyLjAxNTExIiByPSIzLjAyMjY2ODQiLz48Y2lyY2xlIGN4PSI0OS4wODc0MTQiIGN5PSI3NS4yMjA1NzMiI
GZpbGw9IiM1MGU2ZmYiIGlkPSJjaXJjbGUyMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyLjAxNTExIiByPSIzLjAyMjY2ODQiLz48Y2lyY2xlIGN4PSIyMi44OTA5NTkiIGN5PSI3NS4yMjA1NzMiIGZpbGw9IiM1MGU2ZmYiIGlkP
SJjaXJjbGUyMiIgc3R5bGU9InN0cm9rZS13aWR0aDoyLjAxNTExIiByPSIzLjAyMjY2ODQiLz48cGF0aCBmaWxsPSJ1cmwoI2V3dzZmU0hYTEczaDRZZUFxZzl1X2EpIiBkPSJtIDQzLjExMTQ2NywzMy42NzAxOTcgdiAxMy4wN
zgwMjYgaCAyLjQ4ODcyOSB2IDMuNDE0NzQxIGggLTIuNDg4NzI5IHYgNC4yNTI0NTEgSCAzOC45NDQ5OTQgViA1MC4xNjI5NjQgSCAyOS45MDMzMSB2IC0zLjU3MzkxNyBjIDAuODAwNTI5LC0wLjg5NTgwNSAxLjYzMDEwNSwtM
S44Nzc1ODQgMi40ODg3MjcsLTIuOTQzMDIxIDAuODU4NjI0LC0xLjA2NTQzNiAxLjY4ODIwMSwtMi4xNjIyNDMgMi40ODg3MzEsLTMuMjkxNTgyIDAuODAwNTMsLTEuMTI5MzM5IDEuNTQ1Mjg4LC0yLjI2MzMyNiAyLjIzNTQ0L
C0zLjQwNzc3IDAuNjkwMTUyLC0xLjE0MjEyIDEuMjc1NzM2LC0yLjIzNTQ0MSAxLjc1NzkxMywtMy4yNzY0NzcgeiBtIC05LjExMzcyMiwxMy4wNzgwMjYgaCA0Ljk0NzI0OSBWIDM5LjUwMTYzIGMgLTAuMzM4MTA1LDAuNjI2M
jQ4IC0wLjcwNDA5MywxLjI2MDYzIC0xLjA5OTEzLDEuOTAxOTg0IC0wLjM5NjE5OCwwLjY0MjUxNCAtMC44MDk4MjYsMS4yNzM0MTIgLTEuMjQ0MzY0LDEuODk2MTc0IC0wLjQzMzM3NywwLjYyMTYwMiAtMC44NzI1NjYsMS4yM
jQ2MTQgLTEuMzE2NDAxLDEuODA3ODcxIC0wLjQ0MzgzNSwwLjU4MjEgLTAuODcyNTY1LDEuMTI5MzQgLTEuMjg3MzU0LDEuNjQwNTY0IHogbSAzMS43ODMwMDEsNi4yNzg3NTQgYyAtMi4wMjUxNDIsMS4xNjc2ODIgLTQuNTQyO
TE5LDEuNzUwOTQzIC03LjU1MjE2NiwxLjc1MDk0MyAtMy4zMzY4OTUsMCAtNS45NjczNzQsLTAuOTIzNjg4IC03Ljg5MTQzMywtMi43NzEwNjQgLTEuOTI0MDU5LC0xLjg0NjIxNyAtMi44ODQ5MjcsLTQuMzg5NTUzIC0yLjg4N
DkyNywtNy42MzAwMTMgMCwtMy4yNjAyMTIgMS4wNTAzMzIsLTUuOTE3NDEzIDMuMTUzMzIsLTcuOTcxNjAyIDIuMTAyOTg3LC0yLjA1NDE4OSA0Ljg5OTYxMiwtMy4wODEyODMgOC4zOTEwMzcsLTMuMDgxMjgzIDIuMTk5NDIzL
DAgNC4xMzc0MjQsMC4zMDQ0MTEgNS44MTYzMjksMC45MTIwNyB2IDQuMzgyNTggYyAtMS42MDIyMTksLTAuOTI2MDEzIC0zLjU1ODgxMiwtMS4zODg0MzkgLTUuODc0NDIyLC0xLjM4ODQzOSAtMS45MzkxNjUsMCAtMy41MTY5O
DQsMC42Mjk3MzYgLTQuNzM4MTE0LDEuODg4MDQ0IC0xLjIxOTk2NCwxLjI1ODMwNiAtMS44Mjk5NDcsMi45MzgzNzEgLTEuODI5OTQ3LDUuMDQxMzYgMCwyLjEzMjAzNiAwLjU0ODQwNCwzLjc4MDczIDEuNjQyODg3LDQuOTQ4N
DEzIDEuMDkzMzIxLDEuMTY2NTE4IDIuNTcyMzg0LDEuNzUwOTM4IDQuNDMzNzAyLDEuNzUwOTM4IDEuMTE3NzIsMCAyLjAwNTM5MiwtMC4xNjAzNDEgMi42NjE4NDgsLTAuNDc3NTI5IHYgLTQuMDUwMjgzIGggLTQuMTUzNjkyI
HYgLTMuNzMzMDk1IGggOC44MjU1NzggeiIgaWQ9InBhdGgyIiBzdHlsZT0iZmlsbDp1cmwoI2V3dzZmU0hYTEczaDRZZUFxZzl1X2EpO3N0cm9rZS13aWR0aDoxLjE2MTg3Ii8+PHBhdGggZmlsbD0iIzUwZTZmZiIgZD0ibSA1N
y4yNTcyNTUsMjYuODQ2NTIzIC03LjY0MDQ2OCw0Ljc5MDM5NiBjIC0wLjc1NTIxOSwwLjQ3NDA0MyAtMS43MTYwODYsMC40NzI4ODMgLTIuNDcxMzAyLC0wLjAwMTIgbCAtNy42MTgzOTMsLTQuNzg5MjM3IGMgMS45MDU0NywtM
y4wMjA4NjYgNS4yOTgxMzUsLTQuOTAzMDk4IDguODY1MDgxLC00LjkwMzA5OCAzLjU2Njk0NywwIDYuOTU5NjEzLDEuODgyMjMyIDguODY1MDgyLDQuOTAzMDk4IHoiIGlkPSJwYXRoMyIgc3R5bGU9InN0cm9rZS13aWR0aDoxL
jE2MTg3Ii8+PHBhdGggZmlsbD0iIzE5OWJlMiIgZD0ibSA2Ny4wOTk0NywyMC42ODI3OTIgLTYuODg5ODk3LDQuMzIxMDAyIGMgLTUuNTY2NTI4LC04LjgxNjI4NCAtMTguMjU1MzMsLTguNDg1MTQ4IC0yMy42MzQ3OTgsMCBsI
C0zLjkzNzU4MSwtMi40Njg5NzcgLTIuOTUzNDc5LC0xLjg1MjAyNSB2IC0wLjAwMTIgQyAzOC4zMTUyNiw2Ljk0MzU5MDEgNTguNDI5NTg0LDYuODk3MTE1NCA2Ny4wOTk0NywyMC42ODI3OTIgWiIgaWQ9InBhdGg0IiBzdHlsZ
T0ic3Ryb2tlLXdpZHRoOjEuMTYxODciLz48cGF0aCBmaWxsPSIjMDA3OGQ0IiBkPSJtIDcwLjIxNzkzNSwxNi45ODY4NzkgYyAwLjQ3MDU1NywwLjY2MzQzIDAuMzA2NzMzLDEuNTgyNDcgLTAuMzgyMjU2LDIuMDEzNTI1IGwgL
TMuNzA2MzcxLDIuMzIxNDE4IHYgLTAuMDAxMiBjIC04LjAzMzE4MiwtMTIuNzgxNzQ5NyAtMjcuMDYzNDc5LC0xMy4zNTMzOTA1IC0zNS40NzA3ODIsMCB2IDAuMDAxMiBMIDI2Ljk1MjE1NSwxOS4wMDA0MDQgQyAyNi4yNjMxN
jUsMTguNTY5MzQ5IDI2LjA5OTM0MywxNy42NTAzMDkgMjYuNTY4NzM5LDE2Ljk4Njg3OSAzMS41MzkyMjQsOS45NzQ5ODM1IDM5Ljc2NzYsNS42NzcyMiA0OC4zOTIxNzMsNS42NzcyMiBjIDguNjI0NTc2LDAgMTYuODUyOTUsN
C4yOTc3NjM1IDIxLjgyNTc2MiwxMS4zMDk2NTkgeiIgaWQ9InBhdGg1LTciIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4xNjE4NyIvPjxwYXRoIGZpbGw9IiMzNWMxZjEiIGQ9Im0gNjEuMTkzNjc3LDI0LjM4Njg0MSAtNC45MjE2O
DksMy4wODU5MyBjIC0zLjc1MDUyMSwtNS45MTc0MTMgLTEyLjE3NTI1NSwtNS42MjQ2MjEgLTE1Ljc1OTYyOSwwIGwgLTQuOTIxNjg3LC0zLjA4NTkzIDAuMDAyNCwtMC4wMDM0IGMgNS44MTA1MjEsLTkuMjExMzIgMTkuNTMxMDY0LC05LjU2OTE3NiAyNS41OTYwMzQsLTAuMDAzNCB6IiBpZD0icGF0aDYiIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4xNjE4NyIvPjwvc3ZnPgo=
</data>
<downloads_count>0</downloads_count>
</logo>
</NetworkDeviceType>
<NetworkDeviceType alias="NetworkDeviceType" id="11">
<name>Switch</name>
<logo>
<mimetype>image/svg+xml</mimetype>
<filename>icons8-switch.svg</filename>
<data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3
Qm94PSIwIDAgNDggNDgiIHdpZHRoPSIyNDBweCIgaGVpZ2h0PSIyNDBweCI+PGxpbmVhckdyYWRpZW50IGlkPSJGcnRMVXlMNHo1VUU5blBZQV9HelFhIiB4MT0iMTEuMjM1IiB4Mj0iNDIuNzIxIiB5MT0iNDEuMjk3IiB5Mj0i
LTEuNjM5IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAgNDcuODkpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMjFhZDY0Ii8+PHN0b3Ag
b2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDg4MjQyIi8+PC9saW5lYXJHcmFkaWVudD48cGF0aCBmaWxsPSJ1cmwoI0ZydExVeUw0ejVVRTluUFlBX0d6UWEpIiBkPSJNMzgsNDJIMTBjLTIuMiwwLTQtMS44LTQtNFYxMGMwLTIu
MiwxLjgtNCw0LTRoMjhjMi4yLDAsNCwxLjgsNCw0djI4QzQyLDQwLjIsNDAuMiw0MiwzOCw0MnoiLz48cGF0aCBkPSJNMTQuOTMsMjZjLTAuNDE5LDAtMC44MTUtMC4xNjItMS4xMTctMC40NTVMOS42MzIsMjEuNDkgQzkuMjI1
LDIxLjA5Myw5LDIwLjU2NCw5LDIwczAuMjI1LTEuMDkzLDAuNjMyLTEuNDg5bDQuMTgxLTQuMDU3QzE0LjExNSwxNC4xNjEsMTQuNTEyLDE0LDE0LjkzLDE0YzAuODg1LDAsMS42MDQsMC43MSwxLjYwNCwxLjU4MyBWMTdoNC43
MTZjMC45NjUsMCwxLjc1LDAuNzc1LDEuNzUsMS43Mjh2Mi41NDVDMjMsMjIuMjI1LDIyLjIxNSwyMywyMS4yNSwyM2gtNC43MTZ2MS40MTdjMCwwLjQ0OS0wLjE4MywwLjg2Mi0wLjUxNSwxLjE2NCBDMTUuNzIxLDI1Ljg1MSwx
NS4zMzQsMjYsMTQuOTMsMjZ6IiBvcGFjaXR5PSIuMDUiLz48cGF0aCBkPSJNMTQuOTMsMjUuNWMtMC4yODcsMC0wLjU2MS0wLjExMS0wLjc2OS0wLjMxM0w5Ljk4LDIxLjEzMSBDOS42NzEsMjAuODMsOS41LDIwLjQyOCw5LjUs
MjBzMC4xNzEtMC44MywwLjQ4LTEuMTNsNC4xODEtNC4wNTdjMC4yMDgtMC4yMDIsMC40ODEtMC4zMTMsMC43NjktMC4zMTMgYzAuNjA5LDAsMS4xMDQsMC40ODYsMS4xMDQsMS4wODNWMTcuNWg1LjIxNmMwLjY4OSwwLDEuMjUs
MC41NTEsMS4yNSwxLjIyOHYyLjU0NWMwLDAuNjc3LTAuNTYxLDEuMjI4LTEuMjUsMS4yMjhoLTUuMjE2djEuOTE3IGMwLDAuMzA3LTAuMTI1LDAuNTg5LTAuMzUxLDAuNzk0QzE1LjQ3OCwyNS4zOTcsMTUuMjEsMjUuNSwxNC45
MywyNS41TDE0LjkzLDI1LjV6IiBvcGFjaXR5PSIuMDciLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMTUuNTM0LDI0LjQxN1YyMmg1LjcxNmMwLjQxNCwwLDAuNzUtMC4zMjYsMC43NS0wLjcyOHYtMi41NDRDMjIsMTguMzI2LDIx
LjY2NCwxOCwyMS4yNSwxOGgtNS43MTYgdi0yLjQxN2MwLTAuNTE5LTAuNjQ2LTAuNzc4LTEuMDI0LTAuNDEybC00LjE4LDQuMDU2Yy0wLjQzOSwwLjQyNi0wLjQzOSwxLjExOCwwLDEuNTQ0bDQuMTgsNC4wNTYgQzE0Ljg4OCwy
NS4xOTUsMTUuNTM0LDI0LjkzNSwxNS41MzQsMjQuNDE3eiIvPjxwYXRoIGQ9Ik0xNC45MywzOWMtMC40MTksMC0wLjgxNS0wLjE2Mi0xLjExNy0wLjQ1NUw5LjYzMiwzNC40OSBDOS4yMjUsMzQuMDkzLDksMzMuNTY0LDksMzNz
MC4yMjUtMS4wOTMsMC42MzItMS40ODlsNC4xODEtNC4wNTdDMTQuMTE1LDI3LjE2MSwxNC41MTIsMjcsMTQuOTMsMjdjMC44ODUsMCwxLjYwNCwwLjcxLDEuNjA0LDEuNTgzIFYzMGg0LjcxNmMwLjk2NSwwLDEuNzUsMC43NzUs
MS43NSwxLjcyOHYyLjU0NUMyMywzNS4yMjUsMjIuMjE1LDM2LDIxLjI1LDM2aC00LjcxNnYxLjQxN2MwLDAuNDQ5LTAuMTgzLDAuODYyLTAuNTE1LDEuMTY0IEMxNS43MjEsMzguODUxLDE1LjMzNCwzOSwxNC45MywzOXoiIG9w
YWNpdHk9Ii4wNSIvPjxwYXRoIGQ9Ik0xNC45MywzOC41Yy0wLjI4NywwLTAuNTYxLTAuMTExLTAuNzY5LTAuMzEzTDkuOTgsMzQuMTMxIEM5LjY3MSwzMy44Myw5LjUsMzMuNDI4LDkuNSwzM3MwLjE3MS0wLjgzLDAuNDgtMS4x
M2w0LjE4MS00LjA1N2MwLjIwOC0wLjIwMiwwLjQ4MS0wLjMxMywwLjc2OS0wLjMxMyBjMC42MDksMCwxLjEwNCwwLjQ4NiwxLjEwNCwxLjA4M1YzMC41aDUuMjE2YzAuNjg5LDAsMS4yNSwwLjU1MSwxLjI1LDEuMjI4djIuNTQ1
YzAsMC42NzctMC41NjEsMS4yMjgtMS4yNSwxLjIyOGgtNS4yMTZ2MS45MTcgYzAsMC4zMDctMC4xMjUsMC41ODktMC4zNTEsMC43OTRDMTUuNDc4LDM4LjM5NywxNS4yMSwzOC41LDE0LjkzLDM4LjVMMTQuOTMsMzguNXoiIG9w
YWNpdHk9Ii4wNyIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0xNS41MzQsMzcuNDE3VjM1aDUuNzE2YzAuNDE0LDAsMC43NS0wLjMyNiwwLjc1LTAuNzI4di0yLjU0NEMyMiwzMS4zMjYsMjEuNjY0LDMxLDIxLjI1LDMxaC01Ljcx
NiB2LTIuNDE3YzAtMC41MTktMC42NDYtMC43NzgtMS4wMjQtMC40MTJsLTQuMTgsNC4wNTZjLTAuNDM5LDAuNDI2LTAuNDM5LDEuMTE4LDAsMS41NDRsNC4xOCw0LjA1NiBDMTQuODg4LDM4LjE5NSwxNS41MzQsMzcuOTM1LDE1
LjUzNCwzNy40MTd6Ii8+PHBhdGggZD0iTTMzLjA3LDM0Yy0wLjg4NSwwLTEuNjA0LTAuNzEtMS42MDQtMS41ODNWMzFIMjYuNzUgQzI1Ljc4NSwzMSwyNSwzMC4yMjUsMjUsMjkuMjcydi0yLjU0NUMyNSwyNS43NzUsMjUuNzg1
LDI1LDI2Ljc1LDI1aDQuNzE2di0xLjQxN2MwLTAuODczLDAuNzItMS41ODMsMS42MDQtMS41ODMgYzAuNDE5LDAsMC44MTUsMC4xNjIsMS4xMTcsMC40NTVsNC4xODEsNC4wNTVDMzguNzc1LDI2LjkwNywzOSwyNy40MzYsMzks
MjhzLTAuMjI1LDEuMDkzLTAuNjMyLDEuNDg5bC00LjE4MSw0LjA1NyBDMzMuODg1LDMzLjgzOSwzMy40ODgsMzQsMzMuMDcsMzR6IiBvcGFjaXR5PSIuMDUiLz48cGF0aCBkPSJNMzMuMDcsMzMuNWMtMC42MDksMC0xLjEwNC0w
LjQ4Ni0xLjEwNC0xLjA4M1YzMC41SDI2Ljc1IGMtMC42ODksMC0xLjI1LTAuNTUxLTEuMjUtMS4yMjh2LTIuNTQ1YzAtMC42NzcsMC41NjEtMS4yMjgsMS4yNS0xLjIyOGg1LjIxNnYtMS45MTdjMC0wLjU5OCwwLjQ5NS0xLjA4
MywxLjEwNC0xLjA4MyBjMC4yODcsMCwwLjU2MSwwLjExMSwwLjc2OSwwLjMxM2w0LjE4MSw0LjA1NmMwLjMxLDAuMzAxLDAuNDgsMC43MDMsMC40OCwxLjEzMXMtMC4xNzEsMC44My0wLjQ4LDEuMTNsLTQuMTgxLDQuMDU3IEMz
My42MzEsMzMuMzg5LDMzLjM1NywzMy41LDMzLjA3LDMzLjVMMzMuMDcsMzMuNXoiIG9wYWNpdHk9Ii4wNyIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0zMi40NjYsMjMuNTgzVjI2SDI2Ljc1QzI2LjMzNiwyNiwyNiwyNi4zMjYs
MjYsMjYuNzI4djIuNTQ0QzI2LDI5LjY3NCwyNi4zMzYsMzAsMjYuNzUsMzBoNS43MTYgdjIuNDE3YzAsMC41MTksMC42NDYsMC43NzgsMS4wMjQsMC40MTJsNC4xOC00LjA1NmMwLjQzOS0wLjQyNiwwLjQzOS0xLjExOCwwLTEu
NTQ0bC00LjE4LTQuMDU2IEMzMy4xMTIsMjIuODA1LDMyLjQ2NiwyMy4wNjUsMzIuNDY2LDIzLjU4M3oiLz48cGF0aCBkPSJNMzMuMDcsMjFjLTAuODg1LDAtMS42MDQtMC43MS0xLjYwNC0xLjU4M1YxOEgyNi43NSBDMjUuNzg1
LDE4LDI1LDE3LjIyNSwyNSwxNi4yNzJ2LTIuNTQ1QzI1LDEyLjc3NSwyNS43ODUsMTIsMjYuNzUsMTJoNC43MTZ2LTEuNDE3QzMxLjQ2Niw5LjcxLDMyLjE4Niw5LDMzLjA3LDkgYzAuNDE5LDAsMC44MTUsMC4xNjIsMS4xMTcs
MC40NTVsNC4xODEsNC4wNTVDMzguNzc1LDEzLjkwNywzOSwxNC40MzYsMzksMTVzLTAuMjI1LDEuMDkzLTAuNjMyLDEuNDg5bC00LjE4MSw0LjA1NyBDMzMuODg1LDIwLjgzOSwzMy40ODgsMjEsMzMuMDcsMjF6IiBvcGFjaXR5
PSIuMDUiLz48cGF0aCBkPSJNMzMuMDcsMjAuNWMtMC42MDksMC0xLjEwNC0wLjQ4Ni0xLjEwNC0xLjA4M1YxNy41SDI2Ljc1IGMtMC42ODksMC0xLjI1LTAuNTUxLTEuMjUtMS4yMjh2LTIuNTQ1YzAtMC42NzcsMC41NjEtMS4y
MjgsMS4yNS0xLjIyOGg1LjIxNnYtMS45MTdjMC0wLjU5OCwwLjQ5NS0xLjA4MywxLjEwNC0xLjA4MyBjMC4yODcsMCwwLjU2MSwwLjExMSwwLjc2OSwwLjMxM2w0LjE4MSw0LjA1NmMwLjMxLDAuMzAxLDAuNDgsMC43MDMsMC40
OCwxLjEzMXMtMC4xNzEsMC44My0wLjQ4LDEuMTNsLTQuMTgxLDQuMDU3IEMzMy42MzEsMjAuMzg5LDMzLjM1NywyMC41LDMzLjA3LDIwLjVMMzMuMDcsMjAuNXoiIG9wYWNpdHk9Ii4wNyIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9
Ik0zMi40NjYsMTAuNTgzVjEzSDI2Ljc1QzI2LjMzNiwxMywyNiwxMy4zMjYsMjYsMTMuNzI4djIuNTQ0QzI2LDE2LjY3NCwyNi4zMzYsMTcsMjYuNzUsMTdoNS43MTYgdjIuNDE3YzAsMC41MTksMC42NDYsMC43NzgsMS4wMjQs
MC40MTJsNC4xOC00LjA1NmMwLjQzOS0wLjQyNiwwLjQzOS0xLjExOCwwLTEuNTQ0bC00LjE4LTQuMDU2IEMzMy4xMTIsOS44MDUsMzIuNDY2LDEwLjA2NSwzMi40NjYsMTAuNTgzeiIvPjwvc3ZnPgo=
</data>
<downloads_count>0</downloads_count>
</logo>
</NetworkDeviceType>
<NetworkDeviceType alias="NetworkDeviceType" id="12">
<name>Wireless Access Point</name>
<logo>
<mimetype>image/png</mimetype>
<filename>icons8-wi-fi-router-96.png</filename>
<data>iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAIXUlEQVR
4nO1af3ATVR5/WBR1bkA5HWJrmdO7Ob3zZA4snbkRb+6PE8VqkxbK6D/3D3OcowKXhutuEmA3FGkibZOg2NCCDtzNKYwO6nj+GKu0OKMz/vinuwntAf2RJqlQ2iTciW2B+968xcBm+yO7yW7S3b7PzGemk7zse+/zee/78nkNQgQ
EBAQEBAQEBAQEBAQEslFztAghmCf/AwTKBa7jyxHd9SyieC+i+Y8QxfUgij+HaP4ionn4kRcRzQ0jmu9GNPcBorlmVMf/BTlCKxADNxDZlcDetQTR/AuI5t9DNJ8QiZwtRxHFHRNMpEM/JWZMhY3f3IjquKcRxf0LUfwlFUSfmhQ
3jijuXWTn1yHm+HxixqZ/L0AU9ydEcac0E31acn2I4rYg6xe3zD0jcF0WSgJ/Nv/CTzJiCNn5P8+dswIfjDT3ZeGF56Xl6VtEd/0OGRa45tJcA6K4KwUXm57WhCvCGA13Pji5UkRzn6st2Dx7EObZtTCC/wrRXfciQ4DiVyGaG8l
aZEcQFtR3w088p+B2by/cua8fluwfgLvaMMMCTa1hWBIYgDte6YPbvGeEtgt2dudoDjcijF3XoIJmSWCSvbJv3d0Di/f2CeKmhFZKU+sALPb3wi0v9gjPzMKIi8getCBdguafQTR/WcmEi7aFYFHTaTAJKzysKvGuWdh4GoqcIaU
m4Dk8g3QHiv9O7iRvcAZhUePpnFa7kl2xcM8poU8FZ0IE6Q4U3ytncjfv6hbqt9bCT9oRgX64ub5brgkhpDvUcY8J0X+GVb/Y15t34aXEhzY+6Gc8ByjuD0iXqAuuQTQ3Jp3U/O0huHNfX8HFTxF/s8Lnz9R3R10VSNegg0+ITbj
JdRJM+9URruTgIJQcVK8k3cicTBef5p5EhgBeRTQ3dhOLxe//n1Jxig+G4Z43huBX7wzDsg9H4KHPErCyM5nGFZ/Ghffuf+cc3PPPGBQfGFRsAh6bYMLVW9OnkJFQtJ1ba2od+I8SQX729yg88P4wlHVMFjwTy44n4dfvDcPSwxF
lJrSGR4scIZ2XnWlg2j+49q628EQmEZYejsCDH4woFn06/ub981B6KLMRptbweHHbgLFWvhSmtsHq6UwoPhCGX759NqsVn3FHdCSEZxfPZfFTWHKgv8LUFh4TC3D3axFY9vGo6sJLiXcWPrznrPhTmVB6KALL2+Oai5/ibz8ZhZL
XI3NXfLEJJa8Nji9vj0/kS/wUl7fHL5YcHJyYs+Kn8NCnIzUrOxKKDSjH/PyCwKzOhM7ED8s+HjWe+DaHq6LWwfTbnEzE5nCtkfOZss74WjkmrPr6e3j05Dg82X8FLFEAS+wqzVGAir4r8GhoHB7+6r+yxF95PPG4/PmwUWFOMud
TUAjCO1m4SiZWI/x6LTcTHvnme0HglOCZWNF7GVZNY4QgfmfiMTljwmOvdbBD1+bjYMJotgOLft0AFmqdjOz/KpV1xKvFJpSfSMLq7gnZwkv5x9C4UKquG5AYW3kiKft64W921yPiueC5odmOWgdzOG3QDtaj5PNlP5qAa/uaM5e
zFj/FNacvCUZi8cs7k4oSrs3B7kk3gD2EZjtsdmZ9ugGM4rv0so549RO9l6O5ip/i46cmBso7E6sVz8XJnkzfza4aNNuxiWEW1jrYcfHArTTzC6XPscSg2hyFCRUMGKsaAsV3O1ud9T+XlJ+JLQxzG9IDbE6mPW3lbGO3ZPMcyxC
st0ThUrbim2PwgyUKq7OawzbWmjYHB/sJ0guw4JLV057tsypjsC6bnWCOwbhlCLK+z7c5mc8kpXQz0gv+SjP3qrl9K2OwTslOwOKbI5B1yKIo9yI85lzLaEFR62SDaSbYmfW5PK9Spgm5io9hszNPpx++bBDpDfjrZ3oNZQ7n+sz
KDCZg8SsjUJn72Jl/SLKMG+kNOIBJ8sAIwzDztTLBrJL4Qvp1MufFY99qdz2M9AY8EZuDHc42FSsxQThwo2BGKsDmZH4vGfN5udcphkvFM8EcBYs5BoOWKPRWxUDWxZph06+WqTjf0GX61ToV5wu6Tr9ap+J8QNfpNx+pWGvoOv3
mKxVrBUOk33ylYi1giPSbz1SsNgyRfvOditWCYdJvIVKxGjBU+i1EKs4Vhkq/ekzFNiOlX72l4q1GTL96SsU2I6ZfPaVim57Sb2PjvlK3P/CW299yweMPAGHgmgZYE7e/5ZjH++p9GorfMkJED8y88HyBUayV6gbglU/ED8ja9W5
/y1ENDCBlxyPXAF8gqboB0k4kwWXO0yPRR30DfC0gJhGdTdNAqo/qBrh9LSDmTAZY7dthc51DoNW+QzOzrAr70bK9VB/VDWjwvgpiTj0QBp63UbBxkxU2PLdZIP4bv4bfU098RmE/Wrdn07TBLIgBeIAbNllh/ZGPoKonAVU9ceH
vDdcGr44BzyvsR+v2eTFgd/M+EHOq7YpXCR6o9Fdr+DX8nhrlyKqwH63bpyjVJ+8G4DqJtypeMdKBV/Ukhfdwm1wN2KywH63b582AF5teATGnFyY+aeDV3XENDIjL6kfr9ilK9VHfgMaXQczJpWHHtFu35s0PVSxBOxT1o3X7awZ
I9FHdgF2NL4OYU4mTfnjF83QIxxUequq3x5Tqo74Be/aCmFOLM3e/hu6S6KO6AfV79oKYmcpEfoLYDoXBSrv2Un3UN+AlP4iplag2nVKqj+oG7HzJD2IWesK2WUapPqob4HL7Luz0+IDQl1EDl8eXUN+AhuZjLrcXCL0ZNWAbvEd
UN2Cnx3sf624eJQZ4Zxbf3XyecfvvRlqgvr6xlGloPso2NCXZhmYgbBZp0JRkdzcd0Ux8AgICAgICAgICAgICAgICAgKkd/wfA+F5ouAmxqQAAAAASUVORK5CYII=
</data>
<downloads_count>0</downloads_count>
</logo>
</NetworkDeviceType>
</Set>

View File

@@ -0,0 +1,150 @@
<?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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</OSFamily>
</Set>

View File

@@ -0,0 +1,72 @@
<Set>
<OSVersion alias="OSVersion" id="1">
<name>10</name>
<osfamily_id>8</osfamily_id>
<osfamily_id_friendlyname>Windows</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="2">
<name>11</name>
<osfamily_id>8</osfamily_id>
<osfamily_id_friendlyname>Windows</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="3">
<name>11.5</name>
<osfamily_id>2</osfamily_id>
<osfamily_id_friendlyname>Debian</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="4">
<name>18.04 LTS</name>
<osfamily_id>6</osfamily_id>
<osfamily_id_friendlyname>Ubuntu server</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="5">
<name>20.04 LTS</name>
<osfamily_id>5</osfamily_id>
<osfamily_id_friendlyname>Ubuntu</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="6">
<name>20.04 LTS</name>
<osfamily_id>6</osfamily_id>
<osfamily_id_friendlyname>Ubuntu server</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="7">
<name>2019</name>
<osfamily_id>9</osfamily_id>
<osfamily_id_friendlyname>Windows server</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="8">
<name>2022</name>
<osfamily_id>9</osfamily_id>
<osfamily_id_friendlyname>Windows server</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="9">
<name>22.04 LTS</name>
<osfamily_id>5</osfamily_id>
<osfamily_id_friendlyname>Ubuntu</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="10">
<name>22.04 LTS</name>
<osfamily_id>6</osfamily_id>
<osfamily_id_friendlyname>Ubuntu server</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="11">
<name>6.7</name>
<osfamily_id>7</osfamily_id>
<osfamily_id_friendlyname>vCenter Server</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="12">
<name>9</name>
<osfamily_id>4</osfamily_id>
<osfamily_id_friendlyname>Red Hat</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="13">
<name>9.1</name>
<osfamily_id>3</osfamily_id>
<osfamily_id_friendlyname>Oracle Linux</osfamily_id_friendlyname>
</OSVersion>
<OSVersion alias="OSVersion" id="14">
<name>Roling release</name>
<osfamily_id>1</osfamily_id>
<osfamily_id_friendlyname>Arch</osfamily_id_friendlyname>
</OSVersion>
</Set>

View File

@@ -1,35 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<ApplicationSolution alias="ApplicationSolution" id="27">
<name>CRM</name>
<description></description>
<org_id>2</org_id>
<business_criticity>high</business_criticity>
<move2production></move2production>
<status>active</status>
</ApplicationSolution>
<ApplicationSolution alias="ApplicationSolution" id="28">
<name>ERP</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<status>active</status>
</ApplicationSolution>
<ApplicationSolution alias="ApplicationSolution" id="29">
<name>itop</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<status>active</status>
</ApplicationSolution>
<ApplicationSolution alias="ApplicationSolution" id="30">
<name>Sales web site</name>
<description></description>
<org_id>2</org_id>
<business_criticity>high</business_criticity>
<move2production></move2production>
<status>active</status>
</ApplicationSolution>
<ApplicationSolution alias="ApplicationSolution" id="27">
<name>CRM</name>
<description></description>
<org_id>2</org_id>
<business_criticity>high</business_criticity>
<move2production></move2production>
<status>active</status>
</ApplicationSolution>
<ApplicationSolution alias="ApplicationSolution" id="28">
<name>ERP</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<status>active</status>
</ApplicationSolution>
<ApplicationSolution alias="ApplicationSolution" id="29">
<name>itop</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<status>active</status>
</ApplicationSolution>
<ApplicationSolution alias="ApplicationSolution" id="30">
<name>Sales web site</name>
<description></description>
<org_id>2</org_id>
<business_criticity>high</business_criticity>
<move2production></move2production>
<status>active</status>
</ApplicationSolution>
</Set>

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<lnkApplicationSolutionToFunctionalCI alias="lnkApplicationSolutionToFunctionalCI" id="6">
<applicationsolution_id>28</applicationsolution_id>
<functionalci_id>20</functionalci_id>
</lnkApplicationSolutionToFunctionalCI>
<lnkApplicationSolutionToFunctionalCI alias="lnkApplicationSolutionToFunctionalCI" id="2">
<applicationsolution_id>29</applicationsolution_id>
<functionalci_id>15</functionalci_id>
</lnkApplicationSolutionToFunctionalCI>
<lnkApplicationSolutionToFunctionalCI alias="lnkApplicationSolutionToFunctionalCI" id="7">
<applicationsolution_id>30</applicationsolution_id>
<functionalci_id>27</functionalci_id>
</lnkApplicationSolutionToFunctionalCI>
<lnkApplicationSolutionToFunctionalCI alias="lnkApplicationSolutionToFunctionalCI" id="8">
<applicationsolution_id>30</applicationsolution_id>
<functionalci_id>28</functionalci_id>
</lnkApplicationSolutionToFunctionalCI>
<lnkApplicationSolutionToFunctionalCI alias="lnkApplicationSolutionToFunctionalCI" id="6">
<applicationsolution_id>28</applicationsolution_id>
<functionalci_id>20</functionalci_id>
</lnkApplicationSolutionToFunctionalCI>
<lnkApplicationSolutionToFunctionalCI alias="lnkApplicationSolutionToFunctionalCI" id="2">
<applicationsolution_id>29</applicationsolution_id>
<functionalci_id>15</functionalci_id>
</lnkApplicationSolutionToFunctionalCI>
<lnkApplicationSolutionToFunctionalCI alias="lnkApplicationSolutionToFunctionalCI" id="7">
<applicationsolution_id>30</applicationsolution_id>
<functionalci_id>27</functionalci_id>
</lnkApplicationSolutionToFunctionalCI>
<lnkApplicationSolutionToFunctionalCI alias="lnkApplicationSolutionToFunctionalCI" id="8">
<applicationsolution_id>30</applicationsolution_id>
<functionalci_id>28</functionalci_id>
</lnkApplicationSolutionToFunctionalCI>
</Set>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<lnkAuditCategoryToAuditDomain alias="lnkAuditCategoryToAuditDomain" id="1">
<category_id>1</category_id>
<domain_id>1</domain_id>
</lnkAuditCategoryToAuditDomain>
<lnkAuditCategoryToAuditDomain alias="lnkAuditCategoryToAuditDomain" id="2">
<category_id>3</category_id>
<domain_id>3</domain_id>
</lnkAuditCategoryToAuditDomain>
<lnkAuditCategoryToAuditDomain alias="lnkAuditCategoryToAuditDomain" id="3">
<category_id>4</category_id>
<domain_id>3</domain_id>
</lnkAuditCategoryToAuditDomain>
<lnkAuditCategoryToAuditDomain alias="lnkAuditCategoryToAuditDomain" id="5">
<category_id>2</category_id>
<domain_id>1</domain_id>
</lnkAuditCategoryToAuditDomain>
</Set>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<AuditCategory alias="AuditCategory" id="3">
<name>Active persons</name>
<description>Persons with status active</description>
<definition_set>SELECT Person WHERE status =&apos;active&apos;</definition_set>
<ok_error_tolerance>5</ok_error_tolerance>
<warning_error_tolerance>25</warning_error_tolerance>
</AuditCategory>
<AuditCategory alias="AuditCategory" id="4">
<name>Active teams</name>
<description>Teams with status active</description>
<definition_set>SELECT Team WHERE status=&apos;active&apos;</definition_set>
<ok_error_tolerance>5</ok_error_tolerance>
<warning_error_tolerance>25</warning_error_tolerance>
</AuditCategory>
<AuditCategory alias="AuditCategory" id="1">
<name>Physical device in production</name>
<description>All physical device (server, NAS, network device, storage system, SAN switch, PC, printer, phone...) in production</description>
<definition_set>SELECT PhysicalDevice WHERE status =&apos;Production&apos;</definition_set>
<ok_error_tolerance>0</ok_error_tolerance>
<warning_error_tolerance>20</warning_error_tolerance>
</AuditCategory>
<AuditCategory alias="AuditCategory" id="2">
<name>Physical device not in production</name>
<description>All physical device (server, NAS, network device, storage system, SAN switch, PC, printer, phone...) with status different than production</description>
<definition_set>SELECT PhysicalDevice WHERE status !=&apos;Production&apos;</definition_set>
<ok_error_tolerance>20</ok_error_tolerance>
<warning_error_tolerance>50</warning_error_tolerance>
</AuditCategory>
</Set>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<AuditRule alias="AuditRule" id="7">
<name>Active persons with no email</name>
<description>Active persons with no email</description>
<query>SELECT Person WHERE email= &apos;&apos;</query>
<valid_flag>false</valid_flag>
<category_id>3</category_id>
<contact_id>3</contact_id>
<process>&lt;p&gt;Add an email address for each person&lt;/p&gt;</process>
</AuditRule>
<AuditRule alias="AuditRule" id="8">
<name>Active teams with no members</name>
<description>Active teams with no members</description>
<query>SELECT Team AS t JOIN lnkPersonToTeam AS l ON l.team_id=t.id</query>
<valid_flag>true</valid_flag>
<category_id>4</category_id>
<contact_id>4</contact_id>
<process>&lt;p&gt;Add at least on member in each team&lt;/p&gt;</process>
</AuditRule>
<AuditRule alias="AuditRule" id="5">
<name>Physical device in production without any site</name>
<description>All physical device in production not in a site</description>
<query>SELECT PhysicalDevice WHERE location_id = 0</query>
<valid_flag>false</valid_flag>
<category_id>1</category_id>
<contact_id>26</contact_id>
<process>&lt;p&gt;&lt;span style=&quot;background-color:rgb(255,255,255);color:rgb(64,75,90)&quot;&gt;&lt;span style=&apos;float:none;font-family:Raleway, &quot;sans-serif&quot;, &quot;system-ui&quot;;font-size:14.04px;font-style:normal;text-align:start;white-space:normal&apos;&gt;Identify for each physical device the location where it is hosted.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</process>
</AuditRule>
<AuditRule alias="AuditRule" id="1">
<name>Physical device in production without provider contract</name>
<description>All physical device in production not linked to a provider contract</description>
<query>SELECT PhysicalDevice AS Ci JOIN lnkFunctionalCIToProviderContract AS lnk ON lnk.functionalci_id = Ci.id</query>
<valid_flag>true</valid_flag>
<category_id>1</category_id>
<contact_id>26</contact_id>
<process>&lt;p&gt;&lt;span style=&quot;background-color:rgb(255,255,255);color:rgb(64,75,90)&quot;&gt;&lt;span style=&apos;float:none;font-family:Raleway, &quot;sans-serif&quot;, &quot;system-ui&quot;;font-size:14.04px;font-style:normal;text-align:start;white-space:normal&apos;&gt;Identify a provider contract for each physical device&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</process>
</AuditRule>
<AuditRule alias="AuditRule" id="3">
<name>Physical device in production without serial number</name>
<description>All physical device in production without serial number</description>
<query>SELECT PhysicalDevice WHERE serialnumber=&apos;&apos;</query>
<valid_flag>false</valid_flag>
<category_id>1</category_id>
<contact_id>26</contact_id>
<process>&lt;p&gt;Add serial number for each physical device&lt;/p&gt;</process>
</AuditRule>
<AuditRule alias="AuditRule" id="6">
<name>Physical device not in production without any site</name>
<description>All physical device not in production not in a site</description>
<query>SELECT PhysicalDevice WHERE location_id = 0</query>
<valid_flag>false</valid_flag>
<category_id>2</category_id>
<contact_id>26</contact_id>
<process>&lt;p&gt;&lt;span style=&quot;background-color:rgb(255,255,255);color:rgb(64,75,90)&quot;&gt;&lt;span style=&apos;float:none;font-family:Raleway, &quot;sans-serif&quot;, &quot;system-ui&quot;;font-size:14.04px;font-style:normal;text-align:start;white-space:normal&apos;&gt;Identify for each physical device the location where it is hosted.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</process>
</AuditRule>
<AuditRule alias="AuditRule" id="2">
<name>Physical device not in production without provider contract</name>
<description>All physical device not in production not linked to a provider contract</description>
<query>SELECT PhysicalDevice AS Ci JOIN lnkFunctionalCIToProviderContract AS lnk ON lnk.functionalci_id = Ci.id</query>
<valid_flag>true</valid_flag>
<category_id>2</category_id>
<contact_id>26</contact_id>
<process>&lt;p&gt;&lt;span style=&quot;background-color:rgb(255,255,255);color:rgb(64,75,90)&quot;&gt;&lt;span style=&apos;float:none;font-family:Raleway, &quot;sans-serif&quot;, &quot;system-ui&quot;;font-size:14.04px;font-style:normal;text-align:start;white-space:normal&apos;&gt;Identify a provider contract for each physical device&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</process>
</AuditRule>
<AuditRule alias="AuditRule" id="4">
<name>Physical device not in production without serial number</name>
<description>All physical device not in production without serial number</description>
<query>SELECT PhysicalDevice WHERE serialnumber=&apos;&apos;</query>
<valid_flag>false</valid_flag>
<category_id>2</category_id>
<contact_id>26</contact_id>
<process>&lt;p&gt;Add serial number for each physical device&lt;/p&gt;</process>
</AuditRule>
</Set>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<DatabaseSchema alias="DatabaseSchema" id="20">
<name>odooprod</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<dbserver_id>17</dbserver_id>
</DatabaseSchema>
<DatabaseSchema alias="DatabaseSchema" id="20">
<name>odooprod</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<dbserver_id>17</dbserver_id>
</DatabaseSchema>
</Set>

View File

@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<DBServer alias="DBServer" id="17">
<name>Oracle</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<system_id>3</system_id>
<software_id>2</software_id>
<softwarelicence_id>0</softwarelicence_id>
<path></path>
<status></status>
</DBServer>
<DBServer alias="DBServer" id="17">
<name>Oracle</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<system_id>3</system_id>
<software_id>2</software_id>
<softwarelicence_id>0</softwarelicence_id>
<path></path>
<status></status>
</DBServer>
</Set>

View File

@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<Model alias="Model" id="11">
<name>Cisco 6500</name>
<brand_id>10</brand_id>
<type>NetworkDevice</type>
</Model>
<Model alias="Model" id="4">
<name>DL380</name>
<brand_id>1</brand_id>
<type>Server</type>
</Model>
<Model alias="Model" id="5">
<name>Procurve 2450</name>
<brand_id>1</brand_id>
<type>NetworkDevice</type>
</Model>
<Model alias="Model" id="11">
<name>Cisco 6500</name>
<brand_id>10</brand_id>
<type>NetworkDevice</type>
</Model>
<Model alias="Model" id="4">
<name>DL380</name>
<brand_id>1</brand_id>
<type>Server</type>
</Model>
<Model alias="Model" id="5">
<name>Procurve 2450</name>
<brand_id>1</brand_id>
<type>NetworkDevice</type>
</Model>
</Set>

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<NetworkDeviceType alias="NetworkDeviceType" id="10">
<name>Router</name>
</NetworkDeviceType>
<NetworkDeviceType alias="NetworkDeviceType" id="11">
<name>Switch</name>
</NetworkDeviceType>
<NetworkDeviceType alias="NetworkDeviceType" id="10">
<name>Router</name>
</NetworkDeviceType>
<NetworkDeviceType alias="NetworkDeviceType" id="11">
<name>Switch</name>
</NetworkDeviceType>
</Set>

View File

@@ -1,51 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<NetworkDevice alias="NetworkDevice" id="5">
<name>Router1</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>1</location_id>
<status>production</status>
<brand_id>10</brand_id>
<model_id>5</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<networkdevicetype_id>10</networkdevicetype_id>
<iosversion_id>0</iosversion_id>
<ram></ram>
</NetworkDevice>
<NetworkDevice alias="NetworkDevice" id="6">
<name>Switch1</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>2</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>5</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<networkdevicetype_id>11</networkdevicetype_id>
<iosversion_id>0</iosversion_id>
<ram></ram>
</NetworkDevice>
<NetworkDevice alias="NetworkDevice" id="5">
<name>Router1</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>1</location_id>
<status>production</status>
<brand_id>10</brand_id>
<model_id>5</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<networkdevicetype_id>10</networkdevicetype_id>
<iosversion_id>0</iosversion_id>
<ram></ram>
</NetworkDevice>
<NetworkDevice alias="NetworkDevice" id="6">
<name>Switch1</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>2</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>5</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<networkdevicetype_id>11</networkdevicetype_id>
<iosversion_id>0</iosversion_id>
<ram></ram>
</NetworkDevice>
</Set>

View File

@@ -1,107 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<Server alias="Server" id="2">
<name>Server1</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>1</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>4</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<osfamily_id>7</osfamily_id>
<osversion_id>8</osversion_id>
<oslicence_id>0</oslicence_id>
<cpu></cpu>
<ram></ram>
</Server>
<Server alias="Server" id="3">
<name>Server2</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>2</location_id>
<status>production</status>
<brand_id>0</brand_id>
<model_id>0</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<osfamily_id>0</osfamily_id>
<osversion_id>0</osversion_id>
<oslicence_id>0</oslicence_id>
<cpu></cpu>
<ram></ram>
</Server>
<Server alias="Server" id="4">
<name>Server3</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>0</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>4</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<osfamily_id>7</osfamily_id>
<osversion_id>8</osversion_id>
<oslicence_id>0</oslicence_id>
<cpu></cpu>
<ram></ram>
</Server>
<Server alias="Server" id="15">
<name>Server4</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber>US3215687014</serialnumber>
<location_id>0</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>4</model_id>
<asset_number></asset_number>
<purchase_date>2021-07-30</purchase_date>
<end_of_warranty>2025-07-29</end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip>10.10.24.2</managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<osfamily_id>7</osfamily_id>
<osversion_id>8</osversion_id>
<oslicence_id>0</oslicence_id>
<cpu></cpu>
<ram></ram>
</Server>
<Server alias="Server" id="2">
<name>Server1</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>1</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>4</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<osfamily_id>7</osfamily_id>
<osversion_id>8</osversion_id>
<oslicence_id>0</oslicence_id>
<cpu></cpu>
<ram></ram>
</Server>
<Server alias="Server" id="3">
<name>Server2</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>2</location_id>
<status>production</status>
<brand_id>0</brand_id>
<model_id>0</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<osfamily_id>0</osfamily_id>
<osversion_id>0</osversion_id>
<oslicence_id>0</oslicence_id>
<cpu></cpu>
<ram></ram>
</Server>
<Server alias="Server" id="4">
<name>Server3</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>0</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>4</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<osfamily_id>7</osfamily_id>
<osversion_id>8</osversion_id>
<oslicence_id>0</oslicence_id>
<cpu></cpu>
<ram></ram>
</Server>
<Server alias="Server" id="15">
<name>Server4</name>
<description></description>
<org_id>2</org_id>
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber>US3215687014</serialnumber>
<location_id>0</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>4</model_id>
<asset_number></asset_number>
<purchase_date>2021-07-30</purchase_date>
<end_of_warranty>2025-07-29</end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<managementip>10.10.24.2</managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
<osfamily_id>7</osfamily_id>
<osversion_id>8</osversion_id>
<oslicence_id>0</oslicence_id>
<cpu></cpu>
<ram></ram>
</Server>
</Set>

View File

@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<Software alias="Software" id="2">
<name>MySql</name>
<vendor>Oracle</vendor>
<version>8</version>
<type>DBServer</type>
</Software>
<Software alias="Software" id="1">
<name>Oracle DB engine</name>
<vendor>Oracle</vendor>
<version>19c</version>
<type>DBServer</type>
</Software>
<Software alias="Software" id="2">
<name>MySql</name>
<vendor>Oracle</vendor>
<version>8</version>
<type>DBServer</type>
</Software>
<Software alias="Software" id="1">
<name>Oracle DB engine</name>
<vendor>Oracle</vendor>
<version>19c</version>
<type>DBServer</type>
</Software>
</Set>

Some files were not shown because too many files have changed in this diff Show More