├── locales ├── cs_CZ.mo ├── en_GB.mo ├── en_US.mo ├── es_AR.mo ├── es_EC.mo ├── es_ES.mo ├── fr_FR.mo ├── hr_HR.mo ├── it_IT.mo ├── pt_BR.mo └── ru_RU.mo ├── pics ├── budget.png ├── process.png ├── billingmodel.png ├── countertype.png ├── recordmodel.png ├── large-loading.gif ├── planification.png └── snmpauthentication.png ├── printercounters.png ├── scripts ├── .htaccess ├── run.bat ├── glpienv.php ├── clean_records.php ├── printercounters_fullsync.sh ├── printercounters_fullsync.php └── run.php ├── install ├── sql │ ├── update-1.0.2.sql │ ├── update-2.0.2.sql │ ├── update-1.0.6.sql │ ├── update-1.0.1.sql │ ├── update-1.0.7.sql │ ├── update-1.0.3.sql │ ├── update-1.0.5.sql │ ├── update-1.0.4.sql │ └── update-part 2.sql ├── index.php ├── update_101_102.php ├── update_105_106.php ├── update_100_101.php ├── update_106_107.php ├── update_102_103.php ├── update_103_104.php └── update_104_105.php ├── tools ├── extract_template.sh ├── update_mo.pl └── update_po.pl ├── ISSUE_TEMPLATE.md ├── .github └── workflows │ ├── updatepot.yml │ ├── generatemo.yml │ └── release.yml ├── README.md ├── printercounters_load_scripts.js.php ├── index.php ├── ajax ├── index.php ├── additional_data.php ├── viewsubitem.php ├── infocom.php ├── process.php ├── loadscripts.php ├── search.php ├── searchoption.php ├── record.php └── searchoptionvalue.php ├── front ├── index.php ├── budget.form.php ├── countertype.php ├── recordmodel.php ├── billingmodel.php ├── countertype.form.php ├── billingmodel.form.php ├── snmpauthentication.php ├── recordmodel.form.php ├── snmpauthentication.form.php ├── search.form.php ├── budget.php ├── menu.php ├── config.php ├── record.form.php ├── item_billingmodel.form.php ├── pagecost.form.php ├── sysdescr.form.php ├── countertype_recordmodel.form.php ├── item_recordmodel.form.php ├── snmpset.form.php └── config.form.php ├── inc ├── index.php ├── counter.class.php ├── countertype_recordmodelinjection.class.php ├── recordmodelinjection.class.php ├── countertypeinjection.class.php ├── exception.class.php ├── item_recordmodelinjection.class.php ├── toolbox.class.php ├── ajax.class.php └── countertype.class.php ├── report ├── index.php ├── printercountersreport │ ├── index.php │ ├── printercountersreport.en_GB.php │ ├── printercountersreport.fr_FR.php │ └── printercountersreport.pt_BR.php ├── printercountersreport2 │ ├── index.php │ ├── printercountersreport2.en_GB.php │ ├── printercountersreport2.pt_BR.php │ └── printercountersreport2.fr_FR.php ├── printercountersreport3 │ ├── index.php │ ├── printercountersreport3.en_GB.php │ ├── printercountersreport3.fr_FR.php │ └── printercountersreport3.pt_BR.php ├── printercountersreport4 │ ├── index.php │ ├── printercountersreport4.en_GB.php │ ├── printercountersreport4.fr_FR.php │ └── printercountersreport4.pt_BR.php └── printercountersreport5 │ ├── index.php │ ├── printercountersreport5.en_GB.php │ ├── printercountersreport5.fr_FR.php │ └── printercountersreport5.pt_BR.php ├── printercounters.js.php ├── printercounters.css ├── printercounters.xml └── setup.php /locales/cs_CZ.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/cs_CZ.mo -------------------------------------------------------------------------------- /locales/en_GB.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/en_GB.mo -------------------------------------------------------------------------------- /locales/en_US.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/en_US.mo -------------------------------------------------------------------------------- /locales/es_AR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/es_AR.mo -------------------------------------------------------------------------------- /locales/es_EC.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/es_EC.mo -------------------------------------------------------------------------------- /locales/es_ES.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/es_ES.mo -------------------------------------------------------------------------------- /locales/fr_FR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/fr_FR.mo -------------------------------------------------------------------------------- /locales/hr_HR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/hr_HR.mo -------------------------------------------------------------------------------- /locales/it_IT.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/it_IT.mo -------------------------------------------------------------------------------- /locales/pt_BR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/pt_BR.mo -------------------------------------------------------------------------------- /locales/ru_RU.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/locales/ru_RU.mo -------------------------------------------------------------------------------- /pics/budget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/pics/budget.png -------------------------------------------------------------------------------- /pics/process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/pics/process.png -------------------------------------------------------------------------------- /printercounters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/printercounters.png -------------------------------------------------------------------------------- /pics/billingmodel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/pics/billingmodel.png -------------------------------------------------------------------------------- /pics/countertype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/pics/countertype.png -------------------------------------------------------------------------------- /pics/recordmodel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/pics/recordmodel.png -------------------------------------------------------------------------------- /pics/large-loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/pics/large-loading.gif -------------------------------------------------------------------------------- /pics/planification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/pics/planification.png -------------------------------------------------------------------------------- /pics/snmpauthentication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/pics/snmpauthentication.png -------------------------------------------------------------------------------- /scripts/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | deny from all 3 | 4 | = 2.4> 5 | Require all denied 6 | -------------------------------------------------------------------------------- /install/sql/update-1.0.2.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `glpi_plugin_printercounters_configs` ADD `set_first_record` tinyint(1) NOT NULL DEFAULT '0'; 2 | -------------------------------------------------------------------------------- /install/sql/update-2.0.2.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `glpi_plugin_printercounters_configs` 2 | ADD `can_kill_processes` tinyint NOT NULL DEFAULT '0'; 3 | -------------------------------------------------------------------------------- /install/sql/update-1.0.6.sql: -------------------------------------------------------------------------------- 1 | -- Default authentication 2 | ALTER TABLE `glpi_plugin_printercounters_snmpauthentications` ADD `is_default` tinyint(1) NOT NULL DEFAULT '0'; 3 | -------------------------------------------------------------------------------- /install/sql/update-1.0.1.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `glpi_plugin_printercounters_billingmodels` DROP `plugin_printercounters_budgets_id`; 2 | ALTER TABLE `glpi_plugin_printercounters_billingmodels` ADD `budgets_id` int(11) NOT NULL DEFAULT '0'; 3 | -------------------------------------------------------------------------------- /scripts/run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo Chemins php et du script a lancer 3 | 4 | SET path_php="D:\wamp\bin\php\php5.4.16" 5 | SET plugin_glpi="D:\wamp\www\glpi84\plugins\printercounters\scripts" 6 | 7 | echo Definition du path 8 | 9 | PATH = %PATH%;%path_php% 10 | 11 | 12 | IF EXIST %plugin_glpi%\run.php GOTO RUN 13 | 14 | IF NOT EXIST %plugin_glpi%\run.php GOTO EXIT 15 | 16 | :RUN 17 | echo Lancement du script 18 | php %plugin_glpi%\run.php 19 | GOTO FIN 20 | 21 | :EXIT 22 | echo Le chemin vers run.php est incorrect 23 | pause 24 | 25 | :FIN -------------------------------------------------------------------------------- /tools/extract_template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | soft='GLPI - Printercounters plugin' 4 | version='1.3.0' 5 | email='glpi-translation@gna.org' 6 | copyright='INDEPNET Development Team' 7 | 8 | xgettext *.php */*.php --copyright-holder='Printercounters Development Team' --package-name='GLPI - Printercounters plugin' -o locales/glpi.pot -L PHP --add-comments=TRANS --from-code=UTF-8 --force-po \ 9 | --keyword=_n:1,2,4t --keyword=__s:1,2t --keyword=__:1,2t --keyword=_e:1,2t --keyword=_x:1c,2,3t \ 10 | --keyword=_ex:1c,2,3t --keyword=_nx:1c,2,3,5t --keyword=_sx:1c,2,3t -------------------------------------------------------------------------------- /install/sql/update-1.0.7.sql: -------------------------------------------------------------------------------- 1 | -- Add item_recordmodel fields for items in error 2 | ALTER TABLE `glpi_plugin_printercounters_items_recordmodels` ADD `status` int(11) NOT NULL DEFAULT '0'; 3 | ALTER TABLE `glpi_plugin_printercounters_items_recordmodels` ADD `error_counter` int(11) NOT NULL DEFAULT '0'; 4 | 5 | -- Maximum number of interrogation for records in error 6 | ALTER TABLE `glpi_plugin_printercounters_configs` ADD `max_error_counter` int(11) NOT NULL DEFAULT '3'; 7 | ALTER TABLE `glpi_plugin_printercounters_configs` ADD `enable_error_handler` int(11) NOT NULL DEFAULT '0'; -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Dear GLPi user. 2 | 3 | BEFORE SUBMITTING YOUR ISSUE, please make sure to read and follow these steps : 4 | 5 | * Verify that your question has not already been asked 6 | * Please use the below template. 7 | * Delete this text before submiting your issue. 8 | 9 | The Plugin team. 10 | 11 | ------------ 12 | * Version of the plugin : 13 | 14 | 15 | * Version of your GLPI : 16 | 17 | 18 | * Steps to reproduce (which actions have you made) : 19 | 20 | 21 | * Expected result : 22 | 23 | 24 | * Actual result : 25 | 26 | 27 | * URL of the page : 28 | 29 | 30 | * Screenshot of the problem (if pertinent) : 31 | 32 | -------------------------------------------------------------------------------- /tools/update_mo.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/bin/perl -w 3 | 4 | if (@ARGV!=0){ 5 | print "USAGE update_mo.pl\n\n"; 6 | 7 | exit(); 8 | } 9 | 10 | 11 | opendir(DIRHANDLE,'locales')||die "ERROR: can not read current directory\n"; 12 | foreach (readdir(DIRHANDLE)){ 13 | if ($_ ne '..' && $_ ne '.'){ 14 | 15 | if(!(-l "$dir/$_")){ 16 | if (index($_,".po",0)==length($_)-3) { 17 | $lang=$_; 18 | $lang=~s/\.po//; 19 | 20 | `msgfmt locales/$_ -o locales/$lang.mo`; 21 | } 22 | } 23 | 24 | } 25 | } 26 | closedir DIRHANDLE; 27 | 28 | # 29 | # 30 | -------------------------------------------------------------------------------- /.github/workflows/updatepot.yml: -------------------------------------------------------------------------------- 1 | name: Update POT 2 | on: 3 | push: 4 | branches: [ master ] 5 | paths-ignore: 6 | - 'locales/**' 7 | 8 | env: 9 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 10 | jobs: 11 | run: 12 | 13 | name: Update POT 14 | 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout repo 18 | uses: actions/checkout@v4 19 | 20 | - name: install xgettext 21 | 22 | run: sudo apt-get install gettext; 23 | - name: Update POT 24 | run: sh tools/extract_template.sh; 25 | 26 | 27 | - name: Commit changes 28 | uses: EndBug/add-and-commit@v9 29 | with: 30 | message: "Update POT" 31 | - name: Push changes 32 | 33 | uses: actions-go/push@master 34 | 35 | -------------------------------------------------------------------------------- /tools/update_po.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/bin/perl -w 3 | 4 | if (@ARGV!=2){ 5 | print "USAGE update_po.pl transifex_login transifex_password\n\n"; 6 | 7 | exit(); 8 | } 9 | $user = $ARGV[0]; 10 | $password = $ARGV[1]; 11 | 12 | opendir(DIRHANDLE,'locales')||die "ERROR: can not read current directory\n"; 13 | foreach (readdir(DIRHANDLE)){ 14 | if ($_ ne '..' && $_ ne '.'){ 15 | 16 | if(!(-l "$dir/$_")){ 17 | if (index($_,".po",0)==length($_)-3) { 18 | $lang=$_; 19 | $lang=~s/\.po//; 20 | 21 | `wget --user=$user --password=$password --output-document=locales/$_ http://www.transifex.com/api/2/project/GLPI_printercounters/resource/glpipot/translation/$lang/?file=$_`; 22 | } 23 | } 24 | 25 | } 26 | } 27 | closedir DIRHANDLE; 28 | 29 | # 30 | # 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # printercounters 2 | Plugin Printercounters pour GLPI 3 | 4 | Ce plugin est sur Transifex - Aidez-nous à le traduire : https://www.transifex.com/infotelGLPI/GLPI_printercounters/ 5 | 6 | This plugin is on Transifex - Help us to translate : https://www.transifex.com/infotelGLPI/GLPI_printercounters/ 7 | 8 | Mise en place d'un plugin de gestion des compteurs des imprimantes basé sur le protocole SNMP. 9 | Le plugin se base sur l'inventaire déja existant de GLPI, pour récupérer les adresses IP des imprimantes de chaque entité. 10 | Le plugin permet : 11 | 12 | * d'effectuer le relevé des compteurs des imprimantes sur le réseau 13 | * de configurer et de gérer l'interrogation des compteurs pour chaque imprimante 14 | * d'afficher et de gérer les coûts par entités 15 | 16 | Contraintes : 17 | 18 | * Utilisable à partir de la version 5.4 de PHP. 19 | * Le plugin doit pouvoir interroger 3000 à 4500 imprimantes potentielles. 20 | 21 | https://github.com/InfotelGLPI/printercounters/wiki/Notice-d%E2%80%99utilisation 22 | -------------------------------------------------------------------------------- /.github/workflows/generatemo.yml: -------------------------------------------------------------------------------- 1 | name: Generate MO 2 | on: 3 | push: 4 | branches: [ master ] 5 | paths: 6 | - '**.po' 7 | env: 8 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 9 | jobs: 10 | run: 11 | 12 | name: Generate mo 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repo 16 | uses: actions/checkout@v4 17 | 18 | - name: Setup Perl environment 19 | # You may pin to the exact commit or the version. 20 | # uses: shogo82148/actions-setup-perl@8d2e3d59a9516b785ed32169d48a4888eaa9b514 21 | uses: shogo82148/actions-setup-perl@v1 22 | - name: msgfmt 23 | # You may pin to the exact commit or the version. 24 | # uses: whtsky/msgfmt-action@6b2181f051b002182d01a1e1f1aff216230c5a4d 25 | uses: whtsky/msgfmt-action@20190305 26 | - name: Generate mo 27 | run: perl tools/update_mo.pl; 28 | 29 | - name: Commit changes 30 | uses: EndBug/add-and-commit@v9 31 | with: 32 | 33 | message: "Generate mo" 34 | - name: Push changes 35 | 36 | uses: actions-go/push@master 37 | 38 | -------------------------------------------------------------------------------- /printercounters_load_scripts.js.php: -------------------------------------------------------------------------------- 1 | 7 | 8 | var root_printercounters_doc = ""; 9 | (function ($) { 10 | $.fn.printercounters_load_scripts = function () { 11 | 12 | init(); 13 | 14 | // Start the plugin 15 | function init() { 16 | // $(document).ready(function () { 17 | // Send data 18 | $.ajax({ 19 | url: root_printercounters_doc + '/ajax/loadscripts.php', 20 | type: "POST", 21 | dataType: "html", 22 | data: 'action=load', 23 | success: function (response, opts) { 24 | var scripts, scriptsFinder = /]*>([\s\S]+?)<\/script>/gi; 25 | while (scripts = scriptsFinder.exec(response)) { 26 | eval(scripts[1]); 27 | } 28 | } 29 | }); 30 | // }); 31 | } 32 | 33 | return this; 34 | }; 35 | }(jQuery)); 36 | 37 | $(document).printercounters_load_scripts(); 38 | -------------------------------------------------------------------------------- /install/sql/update-1.0.3.sql: -------------------------------------------------------------------------------- 1 | -- Coutertypes recordmodel 2 | ALTER TABLE `glpi_plugin_printercounters_countertypes_recordmodels` ADD INDEX `oid_type` (`oid_type`); 3 | ALTER TABLE `glpi_plugin_printercounters_countertypes_recordmodels` ADD INDEX `plugin_printercounters_recordmodels_id` (`plugin_printercounters_recordmodels_id`); 4 | 5 | -- Record 6 | ALTER TABLE `glpi_plugin_printercounters_records` ADD INDEX `date` (`date`); 7 | ALTER TABLE `glpi_plugin_printercounters_records` ADD INDEX `result` (`result`); 8 | ALTER TABLE `glpi_plugin_printercounters_records` ADD INDEX `state` (`state`); 9 | ALTER TABLE `glpi_plugin_printercounters_records` ADD INDEX `record_type` (`record_type`); 10 | ALTER TABLE `glpi_plugin_printercounters_records` ADD INDEX `last_recordmodels_id` (`last_recordmodels_id`); 11 | ALTER TABLE `glpi_plugin_printercounters_records` ADD INDEX `locations_id` (`locations_id`); 12 | ALTER TABLE `glpi_plugin_printercounters_records` ADD INDEX `entities_id` (`entities_id`); 13 | 14 | -- Billingmodel 15 | ALTER TABLE `glpi_plugin_printercounters_billingmodels` ADD INDEX `budgets_id` (`budgets_id`); 16 | ALTER TABLE `glpi_plugin_printercounters_billingmodels` ADD INDEX `entities_id` (`entities_id`); 17 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /ajax/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /front/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /inc/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /report/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /install/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /report/printercountersreport/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /report/printercountersreport2/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /report/printercountersreport3/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /report/printercountersreport4/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /report/printercountersreport5/index.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | -------------------------------------------------------------------------------- /report/printercountersreport5/printercountersreport5.en_GB.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport5'] = "Repport of printer's counters"; 30 | -------------------------------------------------------------------------------- /install/sql/update-1.0.5.sql: -------------------------------------------------------------------------------- 1 | -- Toner level 2 | ALTER TABLE `glpi_plugin_printercounters_recordmodels` ADD `enable_toner_level` tinyint(1) NOT NULL DEFAULT '0'; 3 | ALTER TABLE `glpi_plugin_printercounters_recordmodels` ADD `enable_printer_info` tinyint(1) NOT NULL DEFAULT '0'; 4 | ALTER TABLE `glpi_plugin_printercounters_configs` ADD `enable_toner_alert` tinyint(1) NOT NULL DEFAULT '0'; 5 | ALTER TABLE `glpi_plugin_printercounters_configs` ADD `toner_alert_repeat` int(11) NOT NULL DEFAULT '0'; 6 | ALTER TABLE `glpi_plugin_printercounters_configs` ADD `toner_treshold` int(11) NOT NULL DEFAULT '0'; 7 | 8 | -- -------------------------------------------------------- 9 | -- Structure de la table 'glpi_plugin_printercounters_additionals_datas' 10 | -- -------------------------------------------------------- 11 | CREATE TABLE IF NOT EXISTS `glpi_plugin_printercounters_additionals_datas` ( 12 | `id` int(11) NOT NULL auto_increment, 13 | `name` varchar(255) default NULL, 14 | `type` varchar(255) default NULL, 15 | `sub_type` varchar(255) default NULL, 16 | `value` varchar(255) default NULL, 17 | `plugin_printercounters_items_recordmodels_id` int(11) NOT NULL default '0', 18 | PRIMARY KEY (`id`), 19 | UNIQUE KEY `unicity` (`plugin_printercounters_items_recordmodels_id`, `sub_type`), 20 | KEY `type` (`type`) 21 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 22 | -------------------------------------------------------------------------------- /report/printercountersreport5/printercountersreport5.fr_FR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport5'] = "Rapport des compteurs des imprimantes"; 30 | -------------------------------------------------------------------------------- /report/printercountersreport5/printercountersreport5.pt_BR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport5'] = "Relatório de contadores de impressora"; 30 | -------------------------------------------------------------------------------- /install/sql/update-1.0.4.sql: -------------------------------------------------------------------------------- 1 | -- Snmp authentications 2 | ALTER TABLE `glpi_plugin_printercounters_snmpauthentications` ADD INDEX `entities_id` (`entities_id`); 3 | ALTER TABLE `glpi_plugin_printercounters_snmpauthentications` ADD `community_write` varchar(255) NULL default 'private'; 4 | 5 | -- Profiles 6 | ALTER TABLE `glpi_plugin_printercounters_profiles` ADD `snmpset` tinyint(1) NOT NULL default '0'; 7 | ALTER TABLE `glpi_plugin_printercounters_profiles` 8 | MODIFY COLUMN `add_lower_records` tinyint(1) NOT NULL default '0', 9 | MODIFY COLUMN `update_records` tinyint(1) NOT NULL default '0'; 10 | 11 | -- -------------------------------------------------------- 12 | -- Structure de la table 'glpi_plugin_printercounters_snmpsets' 13 | -- -------------------------------------------------------- 14 | CREATE TABLE IF NOT EXISTS `glpi_plugin_printercounters_snmpsets` ( 15 | `id` int(11) NOT NULL auto_increment, 16 | `entities_id` int(11) NOT NULL default '0', 17 | `is_recursive` tinyint(1) NOT NULL default '0', 18 | `set_location` tinyint(1) NOT NULL default '1', 19 | `set_contact` tinyint(1) NOT NULL default '1', 20 | `set_name` tinyint(1) NOT NULL default '1', 21 | `contact` text COLLATE utf8_unicode_ci, 22 | PRIMARY KEY (`id`), 23 | UNIQUE KEY `unicity` (`entities_id`), 24 | KEY `entities_id` (`entities_id`) 25 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 26 | 27 | -------------------------------------------------------------------------------- /front/budget.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $dropdown = new PluginPrintercountersBudget(); 33 | include (GLPI_ROOT . "/front/dropdown.common.form.php"); 34 | -------------------------------------------------------------------------------- /front/countertype.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $dropdown = new PluginPrintercountersCountertype(); 33 | include (GLPI_ROOT . "/front/dropdown.common.php"); 34 | -------------------------------------------------------------------------------- /front/recordmodel.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $dropdown = new PluginPrintercountersRecordmodel(); 33 | include (GLPI_ROOT . "/front/dropdown.common.php"); 34 | -------------------------------------------------------------------------------- /front/billingmodel.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $dropdown = new PluginPrintercountersBillingmodel(); 33 | include (GLPI_ROOT . "/front/dropdown.common.php"); 34 | -------------------------------------------------------------------------------- /front/countertype.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $dropdown = new PluginPrintercountersCountertype(); 33 | include (GLPI_ROOT . "/front/dropdown.common.form.php"); 34 | -------------------------------------------------------------------------------- /scripts/glpienv.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | define ("GLPI_ROOT", "../../.."); 30 | include GLPI_ROOT."/config/based_config.php"; 31 | echo "GLPI_LOG_DIR=".GLPI_LOG_DIR."\n"; 32 | echo "GLPI_LOCK_DIR=".GLPI_LOCK_DIR."\n"; 33 | -------------------------------------------------------------------------------- /front/billingmodel.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $dropdown = new PluginPrintercountersBillingmodel(); 33 | include (GLPI_ROOT . "/front/dropdown.common.form.php"); 34 | -------------------------------------------------------------------------------- /front/snmpauthentication.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $dropdown = new PluginPrintercountersSnmpauthentication(); 33 | include (GLPI_ROOT . "/front/dropdown.common.php"); 34 | -------------------------------------------------------------------------------- /front/recordmodel.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $dropdown = new PluginPrintercountersRecordmodel(); 33 | include (GLPI_ROOT . "/front/dropdown.common.form.php"); 34 | 35 | -------------------------------------------------------------------------------- /front/snmpauthentication.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $dropdown = new PluginPrintercountersSnmpauthentication(); 33 | include (GLPI_ROOT . "/front/dropdown.common.form.php"); 34 | 35 | -------------------------------------------------------------------------------- /report/printercountersreport2/printercountersreport2.en_GB.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport2'] = "List of printers with no statement for more than 3 months"; 30 | $LANG['plugin_printercounters']['printercountersreport2_date'] = "Last successful record date"; 31 | 32 | -------------------------------------------------------------------------------- /report/printercountersreport2/printercountersreport2.pt_BR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport2'] = "Lista de impressoras sem registro há mais de 3 meses"; 30 | $LANG['plugin_printercounters']['printercountersreport2_date'] = "Data do último registro bem-sucedido"; 31 | -------------------------------------------------------------------------------- /report/printercountersreport2/printercountersreport2.fr_FR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport2'] = "Liste des imprimantes avec absence de relevé depuis plus de 3 mois"; 30 | $LANG['plugin_printercounters']['printercountersreport2_date'] = "Last successful record date"; 31 | -------------------------------------------------------------------------------- /front/search.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ("../../../inc/includes.php"); 31 | 32 | if (isset($_POST['item'])) { 33 | $item = unserialize(base64_decode($_POST['item'])); 34 | 35 | $search = new PluginPrintercountersSearch(); 36 | $search->manageHistoryGetValues($item, $_POST); 37 | $search->showHistory($item); 38 | } 39 | -------------------------------------------------------------------------------- /report/printercountersreport4/printercountersreport4.en_GB.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport4'] = "Counter records by printer"; 30 | $LANG['plugin_printercounters']['printercountersreport4_date'] = "Page number at %s"; 31 | $LANG['plugin_printercounters']['printercountersreport4_date2'] = "Page number from %s to %s"; 32 | -------------------------------------------------------------------------------- /report/printercountersreport4/printercountersreport4.fr_FR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport4'] = "Relevé de compteurs par imprimante"; 30 | $LANG['plugin_printercounters']['printercountersreport4_date'] = "Nombre de pages au %s"; 31 | $LANG['plugin_printercounters']['printercountersreport4_date2'] = "Nombre de pages du %s au %s"; 32 | -------------------------------------------------------------------------------- /report/printercountersreport4/printercountersreport4.pt_BR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport4'] = "Registros de contador por impressora"; 30 | $LANG['plugin_printercounters']['printercountersreport4_date'] = "Número de página(s) em %s"; 31 | $LANG['plugin_printercounters']['printercountersreport4_date2'] = "Número de página(s) de %s a %s"; 32 | -------------------------------------------------------------------------------- /install/update_101_102.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | /** 31 | * Update from 1.0.1 to 1.0.2 32 | * 33 | * @return bool for success (will die for most error) 34 | * */ 35 | function update101to102() { 36 | global $DB; 37 | 38 | $migration = new Migration(102); 39 | 40 | $migration->addField('glpi_plugin_printercounters_configs', 'set_first_record', 'bool'); 41 | 42 | $migration->executeMigration(); 43 | 44 | return true; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /front/budget.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $budget = new PluginPrintercountersBudget(); 33 | 34 | Html::header($budget->getTypeName(2), '', "tools", "pluginprintercountersmenu", "budget"); 35 | $search = new PluginPrintercountersSearch(); 36 | echo ''; 37 | $search->showSearch($budget, ['fixedDisplay' => false, 'massiveaction' => true]); 38 | Html::footer(); 39 | -------------------------------------------------------------------------------- /install/update_105_106.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | /** 30 | * Update from 1.0.5 to 1.0.6 31 | * 32 | * @return bool for success (will die for most error) 33 | * */ 34 | function update105to106() { 35 | 36 | $migration = new Migration(106); 37 | 38 | // Default authentication 39 | $migration->addField('glpi_plugin_printercounters_snmpauthentications', 'is_default', 'bool', ['value' => '0']); 40 | 41 | $migration->executeMigration(); 42 | 43 | return true; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /report/printercountersreport3/printercountersreport3.en_GB.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport3'] = "Complementary report"; 30 | $LANG['plugin_printercounters']['printercountersreport3_confidencerate'] = "Confidence rate"; 31 | $LANG['plugin_printercounters']['printercountersreport3_consumptionrate'] = "Consumption rate"; 32 | $LANG['plugin_printercounters']['printercountersreport3_extrapolation'] = "Extrapolation (over 12 months) based on the month recorded"; 33 | -------------------------------------------------------------------------------- /report/printercountersreport3/printercountersreport3.fr_FR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport3'] = "Rapport complémentaire"; 30 | $LANG['plugin_printercounters']['printercountersreport3_confidencerate'] = "Confidence rate"; 31 | $LANG['plugin_printercounters']['printercountersreport3_consumptionrate'] = "Consumption rate"; 32 | $LANG['plugin_printercounters']['printercountersreport3_extrapolation'] = "Extrapolation (over 12 months) based on the month recorded"; 33 | -------------------------------------------------------------------------------- /report/printercountersreport3/printercountersreport3.pt_BR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport3'] = "Relatório complementar"; 30 | $LANG['plugin_printercounters']['printercountersreport3_confidencerate'] = "Taxa de confiabilidade"; 31 | $LANG['plugin_printercounters']['printercountersreport3_consumptionrate'] = "Taxa de consumo"; 32 | $LANG['plugin_printercounters']['printercountersreport3_extrapolation'] = "Extrapolação (nos últimos meses 12 meses) com base no mês registrado"; 33 | -------------------------------------------------------------------------------- /front/menu.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | if (Session::getCurrentInterface() == 'central') { 33 | Html::header(PluginPrintercountersMenu::getTypeName(2), '', "tools", "pluginprintercountersmenu", "menu"); 34 | } else { 35 | Html::helpHeader(PluginPrintercountersMenu::getTypeName(2)); 36 | } 37 | 38 | $menu = new PluginPrintercountersMenu(); 39 | $menu->showMenu(); 40 | 41 | if (Session::getCurrentInterface() == 'central') { 42 | Html::footer(); 43 | } else { 44 | Html::helpFooter(); 45 | } 46 | -------------------------------------------------------------------------------- /install/update_100_101.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | /** 31 | * Update from 1.0.0 to 1.0.1 32 | * 33 | * @return bool for success (will die for most error) 34 | * */ 35 | function update100to101() { 36 | global $DB; 37 | 38 | $migration = new Migration(101); 39 | 40 | $migration->dropField('glpi_plugin_printercounters_billingmodels', 'plugin_printercounters_budgets_id'); 41 | $migration->addField('glpi_plugin_printercounters_billingmodels', 'budgets_id', 'integer'); 42 | 43 | $migration->executeMigration(); 44 | 45 | return true; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /report/printercountersreport/printercountersreport.en_GB.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport'] = "Contradiction with the holders of markets"; 30 | $LANG['plugin_printercounters']['printercountersreport_budget'] = "Acquisition budget"; 31 | $LANG['plugin_printercounters']['printercountersreport_monochrome1'] = "Monochrome start date ~ 3 month"; 32 | $LANG['plugin_printercounters']['printercountersreport_color1'] = "Color start date ~ 3 month"; 33 | $LANG['plugin_printercounters']['printercountersreport_monochrome2'] = "Monochrome end date ~ start"; 34 | $LANG['plugin_printercounters']['printercountersreport_color2'] = "Color end date ~ start"; 35 | 36 | -------------------------------------------------------------------------------- /report/printercountersreport/printercountersreport.fr_FR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport'] = "Contradiction avec les titulaires des marchés"; 30 | $LANG['plugin_printercounters']['printercountersreport_budget'] = "Acquisition budget"; 31 | $LANG['plugin_printercounters']['printercountersreport_monochrome1'] = "Monochrome start date ~ 3 month"; 32 | $LANG['plugin_printercounters']['printercountersreport_color1'] = "Color start date ~ 3 month"; 33 | $LANG['plugin_printercounters']['printercountersreport_monochrome2'] = "Monochrome end date ~ start"; 34 | $LANG['plugin_printercounters']['printercountersreport_color2'] = "Color end date ~ start"; 35 | 36 | -------------------------------------------------------------------------------- /report/printercountersreport/printercountersreport.pt_BR.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | $LANG['plugin_printercounters']['printercountersreport'] = "Divergência entre monocromático e cor"; 30 | $LANG['plugin_printercounters']['printercountersreport_budget'] = "Orçamento de aquisição"; 31 | $LANG['plugin_printercounters']['printercountersreport_monochrome1'] = "Data de início monocromático ~ 3 meses"; 32 | $LANG['plugin_printercounters']['printercountersreport_color1'] = "Data de início cor ~ 3 meses"; 33 | $LANG['plugin_printercounters']['printercountersreport_monochrome2'] = "Data fim ~ início monocromático"; 34 | $LANG['plugin_printercounters']['printercountersreport_color2'] = "Data fim ~ início cor"; 35 | 36 | -------------------------------------------------------------------------------- /inc/counter.class.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | if (!defined('GLPI_ROOT')) { 31 | die("Sorry. You can't access directly to this file"); 32 | } 33 | 34 | /** 35 | * Class PluginPrintercountersCounter 36 | * 37 | * This class allows to manage the counters added in the records 38 | * 39 | * @package Printercounters 40 | * @author Ludovic Dupont 41 | */ 42 | class PluginPrintercountersCounter extends CommonDBTM { 43 | 44 | static $rightname = 'plugin_printercounters'; 45 | 46 | /** 47 | * functions mandatory 48 | * getTypeName(), canCreate(), canView() 49 | * */ 50 | static function getTypeName($nb = 0) { 51 | return __('Counter', 'Counters', $nb, 'printercounters'); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /ajax/additional_data.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ("../../../inc/includes.php"); 31 | 32 | Session::checkLoginUser(); 33 | //Html::header_nocache(); 34 | 35 | $_POST['itemtype'] = isset($_POST['itemtype']) ? $_POST['itemtype'] : 'printer'; 36 | $_POST['items_id'] = isset($_POST['items_id']) ? $_POST['items_id'] : 0; 37 | $additional_data = new PluginPrintercountersAdditional_data($_POST['itemtype'], $_POST['items_id']); 38 | 39 | if (!isset($_POST['action'])) { 40 | $_POST['action'] = $_GET['action']; 41 | } 42 | 43 | switch ($_POST['action']) { 44 | case 'showAdditionalData': 45 | header("Content-Type: text/html; charset=UTF-8"); 46 | $additional_data->showAdditionalData(); 47 | break; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /front/config.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | Session::checkRight("config", UPDATE); 33 | 34 | if (Plugin::isPluginActive("printercounters")) { 35 | $config = new PluginPrintercountersConfig(); 36 | Html::header(PluginPrintercountersConfig::getTypeName(), '', "tools", "pluginprintercountersmenu", "config"); 37 | $data = $config->getInstance(); 38 | $config->display(['id' => $data['configs_id']]); 39 | Html::footer(); 40 | } else { 41 | Html::header(PluginPrintercountersConfig::getTypeName(), '', "tools", "pluginprintercountersmenu", "config"); 42 | echo "
"; 43 | echo "".__('Please activate the plugin', 'printercounters')."
"; 44 | Html::footer(); 45 | } 46 | 47 | Html::footer(); 48 | -------------------------------------------------------------------------------- /ajax/viewsubitem.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ("../../../inc/includes.php"); 31 | 32 | header("Content-Type: text/html; charset=UTF-8"); 33 | 34 | Html::header_nocache(); 35 | 36 | Session::checkLoginUser(); 37 | 38 | if (!isset($_POST['type'])) { 39 | exit(); 40 | } 41 | if (!isset($_POST['parenttype'])) { 42 | exit(); 43 | } 44 | 45 | $dbu = new DbUtils(); 46 | if (($item = $dbu->getItemForItemtype($_POST['type'])) 47 | && ($parent = $dbu->getItemForItemtype($_POST['parenttype']))) { 48 | 49 | if (isset($_POST[$parent->getForeignKeyField()]) 50 | && isset($_POST["id"]) 51 | && $parent->getFromDB($_POST[$parent->getForeignKeyField()])) { 52 | $item->showForm($_POST["id"], ['parent' => $parent]); 53 | 54 | } else { 55 | echo __('Access denied'); 56 | } 57 | } 58 | 59 | Html::ajaxFooter(); 60 | -------------------------------------------------------------------------------- /ajax/infocom.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ("../../../inc/includes.php"); 31 | 32 | Session::checkLoginUser(); 33 | //Html::header_nocache(); 34 | 35 | switch ($_POST['action']) { 36 | case 'getTco': 37 | header('Content-Type: application/json; charset=UTF-8"'); 38 | $result = 0; 39 | if (isset($_POST['items_id']) && isset($_POST['itemtype'])) { 40 | $item_recordmodel = new PluginPrintercountersItem_Recordmodel(); 41 | if ($item_recordmodel->getFromDBByCrit(['itemtype' => "LOWER(" . $_POST['itemtype'] . ")", 42 | 'items_id' => $_POST['items_id']])) { 43 | $result = $item_recordmodel->fields['global_tco']; 44 | } 45 | } 46 | echo json_encode(['global_tco' => Html::formatNumber($result)]); 47 | break; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /printercounters.js.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | define('GLPI_ROOT', '../..'); 31 | include (GLPI_ROOT."/inc/includes.php"); 32 | 33 | //change mimetype 34 | header("Content-type: application/javascript"); 35 | 36 | //not executed in self-service interface & right verification 37 | if (Session::getCurrentInterface() == "central") { 38 | // Get item type 39 | $itemtype = PluginPrintercountersItem_Recordmodel::$types; 40 | 41 | if (!empty($itemtype)) { 42 | $params = ['root_doc' => PLUGIN_PRINTERCOUNTERS_WEBDIR, 43 | 'itemtype' => $itemtype[0], 44 | 'itemToShow' => 'Infocom', 45 | 'glpi_tab' => 'Infocom$1', 46 | 'lang' => ['global_tco' => __('Global TCO', 'printercounters')]]; 47 | 48 | echo "printercounters_addelements(".json_encode($params).");"; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /install/update_106_107.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | /** 30 | * Update from 1.0.6 to 1.0.7 31 | * 32 | * @return bool for success (will die for most error) 33 | * */ 34 | function update106to107() { 35 | 36 | $migration = new Migration(107); 37 | 38 | // Add item_recordmodel fields for items in error 39 | $migration->addField('glpi_plugin_printercounters_items_recordmodels', 'status', 'int', ['value' => '0']); 40 | $migration->addField('glpi_plugin_printercounters_items_recordmodels', 'error_counter', 'int', ['value' => '0']); 41 | 42 | // Maximum number of interrogation for records in error 43 | $migration->addField('glpi_plugin_printercounters_configs', 'max_error_counter', 'int', ['value' => '3']); 44 | $migration->addField('glpi_plugin_printercounters_configs', 'enable_error_handler', 'int', ['value' => '0']); 45 | 46 | $migration->executeMigration(); 47 | 48 | return true; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /front/record.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | $record = new PluginPrintercountersRecord(); 33 | 34 | if (isset($_POST["immediate_record"])) { 35 | $record->check(-1, UPDATE, $_POST); 36 | $record->immediateRecord($_POST); 37 | Html::back(); 38 | 39 | } else if (isset($_POST["manual_record"])) { 40 | $record->check($_POST['id'], UPDATE, $_POST); 41 | $record->manualRecord($_POST); 42 | Html::back(); 43 | 44 | } else if (isset($_POST["update_counter_position"])) { 45 | $record->check($_POST['id'], UPDATE, $_POST); 46 | $record->updateCounterPosition($_POST); 47 | Html::back(); 48 | 49 | } else if (isset($_GET["initAjaxMassiveAction"])) { 50 | Html::header(__('Printer'), '', "tools", "pluginprintercountersmenu"); 51 | $item_recordmodel = new PluginPrintercountersItem_Recordmodel(); 52 | $item_recordmodel->initMassiveActionsProcess(); 53 | Html::footer(); 54 | } 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /ajax/process.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ("../../../inc/includes.php"); 31 | 32 | Session::checkLoginUser(); 33 | if (Session::haveRight(PluginPrintercountersProcess::$rightname, UPDATE)) { 34 | //Html::header_nocache(); 35 | 36 | $process = new PluginPrintercountersProcess(); 37 | 38 | switch ($_POST['action']) { 39 | case 'killProcess': 40 | $config = PluginPrintercountersConfig::getInstance(); 41 | if ($config['can_kill_processes']) { 42 | header('Content-Type: application/json; charset=UTF-8"'); 43 | list($messages, $error) = $process->killProcesses($_POST['items_id'], PluginPrintercountersProcess::SIGKILL); 44 | echo json_encode(['message' => $messages, 45 | 'error' => $error]); 46 | break; 47 | } 48 | case 'getProcesses': 49 | header("Content-Type: text/html; charset=UTF-8"); 50 | $process->getProcesses(); 51 | break; 52 | } 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /front/item_billingmodel.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | if (empty($_GET["id"])) { 33 | $_GET["id"] = ""; 34 | } 35 | 36 | $item_billingmodel = new PluginPrintercountersItem_Billingmodel(); 37 | 38 | if (isset($_POST["add"])) { 39 | // Check update rights for fields 40 | $item_billingmodel->check(-1, CREATE, $_POST); 41 | $newID = $item_billingmodel->add($_POST); 42 | 43 | Html::back(); 44 | 45 | } else if (isset($_POST["update"]) || isset($_POST["update_config"])) { 46 | // Check update rights for fields 47 | $item_billingmodel->check($_POST['id'], UPDATE, $_POST); 48 | if ($item_billingmodel->update($_POST) && isset($_POST["update_config"])) { 49 | $item_billingmodel->addLog(); 50 | } 51 | Html::back(); 52 | 53 | } else if (isset($_POST["delete"])) { 54 | // Check update rights for fields 55 | $item_billingmodel->check($_POST['id'], DELETE, $_POST); 56 | $item_billingmodel->delete($_POST, 1); 57 | $item_billingmodel->redirectToList(); 58 | } 59 | 60 | -------------------------------------------------------------------------------- /front/pagecost.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | if (empty($_GET["id"])) { 33 | $_GET["id"] = ""; 34 | } 35 | 36 | $pagecost = new PluginPrintercountersPagecost(); 37 | 38 | if (isset($_POST["add"])) { 39 | // Check update rights for fields 40 | $pagecost->check(-1, CREATE, $_POST); 41 | $newID = $pagecost->add($_POST); 42 | 43 | Html::back(); 44 | 45 | } else if (isset($_POST["update"])) { 46 | // Check update rights for fields 47 | $pagecost->check($_POST['id'], UPDATE, $_POST); 48 | $pagecost->update($_POST); 49 | 50 | Html::back(); 51 | 52 | } else if (isset($_POST["delete"])) { 53 | // Check update rights for fields 54 | $pagecost->check($_POST['id'], DELETE, $_POST); 55 | $pagecost->delete($_POST, 1); 56 | $pagecost->redirectToList(); 57 | 58 | } else { 59 | $pagecost->checkGlobal(READ); 60 | Html::header(PluginPrintercountersPagecost::getTypeName(1), '', "tools", "pluginprintercountersmenu"); 61 | $pagecost->display($_GET); 62 | Html::footer(); 63 | } 64 | -------------------------------------------------------------------------------- /front/sysdescr.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | if (empty($_GET["id"])) { 33 | $_GET["id"] = ""; 34 | } 35 | 36 | $sysdescr = new PluginPrintercountersSysdescr(); 37 | 38 | if (isset($_POST["add"])) { 39 | // Check add rights for fields 40 | $sysdescr->check(-1, CREATE, $_POST); 41 | $newID = $sysdescr->add($_POST); 42 | 43 | Html::back(); 44 | 45 | } else if (isset($_POST["update"])) { 46 | // Check update rights for fields 47 | $sysdescr->check($_POST['id'], UPDATE, $_POST); 48 | $newID = $sysdescr->update($_POST); 49 | 50 | Html::back(); 51 | 52 | } else if (isset($_POST["delete"])) { 53 | // Check delete rights for fields 54 | $sysdescr->check($_POST['id'], DELETE, $_POST); 55 | $sysdescr->delete($_POST, 1); 56 | $sysdescr->redirectToList(); 57 | 58 | } else { 59 | $sysdescr->checkGlobal(READ); 60 | Html::header(PluginPrintercountersItem_Recordmodel::getTypeName(1), '', "tools", "pluginprintercountersmenu", "sysdescr"); 61 | $sysdescr->display($_GET); 62 | Html::footer(); 63 | } 64 | -------------------------------------------------------------------------------- /ajax/loadscripts.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | Html::header_nocache(); 33 | Session::checkLoginUser(); 34 | header("Content-Type: text/html; charset=UTF-8"); 35 | 36 | switch ($_POST['action']) { 37 | case "load" : 38 | foreach (PluginPrintercountersItem_Recordmodel::$types as $item) { 39 | if (isset($_SERVER['HTTP_REFERER']) 40 | && strpos($_SERVER['HTTP_REFERER'], strtolower($item)) !== false 41 | && Session::getCurrentInterface() == "central") { 42 | 43 | $params = ['root_doc' => $CFG_GLPI['root_doc'], 44 | 'itemtype' => $item, 45 | 'itemToShow' => 'Infocom', 46 | 'glpi_tab' => 'Infocom$1', 47 | 'lang' => ['global_tco' => __('Global TCO', 'printercounters')]]; 48 | 49 | echo ""; 52 | } 53 | } 54 | break; 55 | } 56 | -------------------------------------------------------------------------------- /front/countertype_recordmodel.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | if (empty($_GET["id"])) { 33 | $_GET["id"] = ""; 34 | } 35 | 36 | $countertype_recordmodel = new PluginPrintercountersCountertype_Recordmodel(); 37 | 38 | if (isset($_POST["add"])) { 39 | // Check update rights for fields 40 | $countertype_recordmodel->check(-1, CREATE, $_POST); 41 | $newID = $countertype_recordmodel->add($_POST); 42 | 43 | Html::back(); 44 | 45 | } else if (isset($_POST["update"])) { 46 | // Check update rights for fields 47 | $countertype_recordmodel->check($_POST['id'], UPDATE, $_POST); 48 | $countertype_recordmodel->update($_POST); 49 | 50 | Html::back(); 51 | 52 | } else if (isset($_POST["purge"])) { 53 | // Check update rights for fields 54 | $countertype_recordmodel->check($_POST['id'], DELETE, $_POST); 55 | $countertype_recordmodel->delete($_POST, 1); 56 | Html::back(); 57 | 58 | } else { 59 | $countertype_recordmodel->checkGlobal(READ); 60 | Html::header(PluginPrintercountersCountertype::getTypeName(1), '', "tools", "pluginprintercountersmenu", "countertype"); 61 | $countertype_recordmodel->display(['id' => $_GET["id"]]); 62 | Html::footer(); 63 | } 64 | -------------------------------------------------------------------------------- /scripts/clean_records.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | ini_set("memory_limit", "-1"); 31 | ini_set("max_execution_time", "0"); 32 | 33 | // Can't run on MySQL replicate 34 | $USEDBREPLICATE = 0; 35 | $DBCONNECTION_REQUIRED = 1; 36 | 37 | 38 | include ('../../../inc/includes.php'); 39 | 40 | // Check PHP Version - sometime (debian) cli version != module version 41 | if (version_compare(phpversion(), '5.4', 'lt')) { 42 | die("PHP version:".phpversion()." - "."You must install at least PHP 5.4\n\n"); 43 | } 44 | // Chech Memory_limit - sometine cli limit (php-cli.ini) != module limit (php.ini) 45 | $mem = Toolbox::getMemoryLimit(); 46 | if (($mem > 0) && ($mem < (64 * 1024 * 1024))) { 47 | die("PHP memory_limit = ".$mem." - "."A minimum of 64Mio is commonly required for GLPI.'\n\n"); 48 | } 49 | 50 | if (Plugin::isPluginActive("printercounters")) { 51 | 52 | // Clean record 53 | $record = new PluginPrintercountersRecord(); 54 | if ($record->cleanRecords()) { 55 | echo __('Records cleaned', 'printercounters'); 56 | } else { 57 | echo __('No records to clean', 'printercounters'); 58 | } 59 | 60 | } else { 61 | echo __('Plugin disabled or automatic record disabled', 'printercounters'); 62 | exit(1); 63 | } 64 | 65 | -------------------------------------------------------------------------------- /front/item_recordmodel.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | if (empty($_GET["id"])) { 33 | $_GET["id"] = ""; 34 | } 35 | 36 | $item_recordmodel = new PluginPrintercountersItem_Recordmodel(); 37 | 38 | if (isset($_POST["add"])) { 39 | // Check update rights for fields 40 | $item_recordmodel->check(-1, CREATE, $_POST); 41 | $newID = $item_recordmodel->add($_POST); 42 | 43 | Html::back(); 44 | 45 | } else if (isset($_POST["update"]) || isset($_POST["update_config"])) { 46 | // Check update rights for fields 47 | $item_recordmodel->check($_POST['id'], UPDATE, $_POST); 48 | if ($item_recordmodel->update($_POST) && isset($_POST["update_config"])) { 49 | $item_recordmodel->addLog(); 50 | } 51 | Html::back(); 52 | 53 | } else if (isset($_POST["delete"])) { 54 | // Check update rights for fields 55 | $item_recordmodel->check($_POST['id'], DELETE, $_POST); 56 | $item_recordmodel->delete($_POST, 1); 57 | $item_recordmodel->redirectToList(); 58 | 59 | } else { 60 | Html::header(__('Record planning', 'printercounters'), '', "tools", "pluginprintercountersmenu", "record"); 61 | echo ''; 62 | $item_recordmodel->showRecordPlanning(); 63 | Html::footer(); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /front/snmpset.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | if (empty($_GET["id"])) { 33 | $_GET["id"] = ""; 34 | } 35 | 36 | $snmpset = new PluginPrintercountersSnmpset(); 37 | 38 | $_POST['set_location'] = isset($_POST['set_location']) ? $_POST['set_location'] : 0; 39 | $_POST['set_name'] = isset($_POST['set_name']) ? $_POST['set_name'] : 0; 40 | $_POST['set_contact'] = isset($_POST['set_contact']) ? $_POST['set_contact'] : 0; 41 | 42 | if (isset($_POST["add"])) { 43 | // Check add rights for fields 44 | $snmpset->check(-1, CREATE, $_POST); 45 | $newID = $snmpset->add($_POST); 46 | 47 | Html::back(); 48 | 49 | } else if (isset($_POST["update"])) { 50 | // Check update rights for fields 51 | $snmpset->check($_POST['id'], UPDATE, $_POST); 52 | $snmpset->update($_POST); 53 | 54 | Html::back(); 55 | 56 | } else if (isset($_POST["delete"])) { 57 | // Check delete rights for fields 58 | $snmpset->check($_POST['id'], DELETE, $_POST); 59 | $snmpset->delete($_POST, 1); 60 | 61 | $snmpset->redirectToList(); 62 | 63 | } else { 64 | $snmpset->checkGlobal(READ); 65 | Html::header(PluginPrintercountersItem_Recordmodel::getTypeName(1), '', "tools", "pluginprintercountersmenu", "snmpset"); 66 | $snmpset->display(['id' => $_GET["id"]]); 67 | Html::footer(); 68 | } 69 | -------------------------------------------------------------------------------- /install/update_102_103.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | /** 31 | * Update from 1.0.2 to 1.0.3 32 | * 33 | * @return bool for success (will die for most error) 34 | * */ 35 | function update102to103() { 36 | global $DB; 37 | 38 | $migration = new Migration(103); 39 | 40 | // Coutertypes recordmodel 41 | $migration->addKey('glpi_plugin_printercounters_countertypes_recordmodels', 'oid_type', 'oid_type'); 42 | $migration->addKey('glpi_plugin_printercounters_countertypes_recordmodels', 'plugin_printercounters_recordmodels_id', 'plugin_printercounters_recordmodels_id'); 43 | 44 | // Record 45 | $migration->addKey('glpi_plugin_printercounters_records', 'date', 'date'); 46 | $migration->addKey('glpi_plugin_printercounters_records', 'result', 'result'); 47 | $migration->addKey('glpi_plugin_printercounters_records', 'state', 'state'); 48 | $migration->addKey('glpi_plugin_printercounters_records', 'record_type', 'record_type'); 49 | $migration->addKey('glpi_plugin_printercounters_records', 'last_recordmodels_id', 'last_recordmodels_id'); 50 | $migration->addKey('glpi_plugin_printercounters_records', 'locations_id', 'locations_id'); 51 | $migration->addKey('glpi_plugin_printercounters_records', 'entities_id', 'entities_id'); 52 | 53 | // Billingmodel 54 | $migration->addKey('glpi_plugin_printercounters_billingmodels', 'budgets_id', 'budgets_id'); 55 | $migration->addKey('glpi_plugin_printercounters_billingmodels', 'entities_id', 'entities_id'); 56 | 57 | $migration->executeMigration(); 58 | 59 | return true; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /ajax/search.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include("../../../inc/includes.php"); 31 | 32 | Session::checkLoginUser(); 33 | header("Content-Type: text/html; charset=UTF-8"); 34 | //Html::header_nocache(); 35 | 36 | $search = new PluginPrintercountersSearch(); 37 | 38 | switch ($_POST['action']) { 39 | case 'addSearchField': 40 | if (!isset($_POST['item'])) { 41 | exit; 42 | } 43 | if (!isset($_SESSION['plugin_printercounters_item_' . $_POST['item']])) { 44 | exit; 45 | } 46 | $search->addSearchField($_POST['search_count'], unserialize($_SESSION['plugin_printercounters_item_' . $_POST['item']])); 47 | 48 | break; 49 | 50 | case 'resetSearchField': 51 | if (!isset($_POST['item'])) { 52 | exit; 53 | } 54 | if (!isset($_SESSION['plugin_printercounters_item_' . $_POST['item']])) { 55 | exit; 56 | } 57 | $item = unserialize($_SESSION['plugin_printercounters_item_' . $_POST['item']]); 58 | if (!get_class($item) == PluginPrintercountersRecord::class) { 59 | return; 60 | } 61 | $search->showHistoryGenericSearch($item); 62 | break; 63 | 64 | case 'initSearch': 65 | if (!isset($_POST['item'])) { 66 | exit; 67 | } 68 | $item = unserialize($_SESSION['plugin_printercounters_item_' . $_POST['item']]); 69 | if (!get_class($item) == PluginPrintercountersRecord::class) { 70 | return; 71 | } 72 | $search->manageHistoryGetValues($item, $_POST); 73 | $search->showHistory($item); 74 | break; 75 | 76 | case 'reloadCsrf': 77 | Session::cleanCSRFTokens(); 78 | echo Session::getNewCSRFToken(); 79 | break; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /printercounters.css: -------------------------------------------------------------------------------- 1 | /* 2 | * @version $Id: HEADER 15930 2011-10-30 15:47:55Z tsmr $ 3 | ------------------------------------------------------------------------- 4 | printercounters plugin for GLPI 5 | Copyright (C) 2014-2022 by the printercounters Development Team. 6 | 7 | https://github.com/InfotelGLPI/printercounters 8 | ------------------------------------------------------------------------- 9 | 10 | LICENSE 11 | 12 | This file is part of printercounters. 13 | 14 | printercounters is free software; you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation; either version 2 of the License, or 17 | (at your option) any later version. 18 | 19 | printercounters is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with printercounters. If not, see . 26 | -------------------------------------------------------------------------- 27 | */ 28 | 29 | .printercounters_action_button{ 30 | margin: 10px 80px 0px 80px; 31 | display: block; 32 | width : 70%; 33 | } 34 | 35 | .printercounters_action_group{ 36 | display: inline-block; 37 | width:50%; 38 | } 39 | 40 | .printercounters_menu_item{ 41 | border:solid 1px #CCCCCC; 42 | -moz-border-radius: 3px; 43 | -webkit-border-radius: 3px; 44 | border-radius: 3px; 45 | } 46 | 47 | td.printercounters_menu_item:hover{ 48 | border:solid 1px #535b5c; 49 | opacity : .7; 50 | } 51 | 52 | .printercounters_menu_img{} 53 | 54 | .printercounters_menu_a{ 55 | display:block; 56 | width:150px; 57 | height:100px; 58 | margin-top:30px; 59 | } 60 | 61 | .printercounters_tree{ 62 | border-bottom:1px dotted #888888; 63 | border-left:1px dotted #888888; 64 | float:left; 65 | height:10px; 66 | width:10px; 67 | margin-right:5px; 68 | } 69 | 70 | .printercounters_tree_bold{ 71 | border-bottom:2px dotted #FFF; 72 | border-left:2px dotted #FFF; 73 | float:left; 74 | height:10px; 75 | width:10px; 76 | margin-right:5px; 77 | } 78 | 79 | .printercounters_toner_level{ 80 | height:15px; 81 | width:300px; 82 | border:solid 1px #CCCCCC; 83 | 84 | -moz-border-radius: 5px; 85 | -webkit-border-radius: 5px; 86 | border-radius: 5px; 87 | } 88 | 89 | .printercounters_toner_level_cyan{ 90 | border:0px; 91 | background-color:cyan; 92 | } 93 | 94 | .printercounters_toner_level_yellow{ 95 | border:0px; 96 | background-color:yellow; 97 | } 98 | 99 | .printercounters_toner_level_black{ 100 | border:0px; 101 | background-color:black; 102 | } 103 | 104 | .printercounters_toner_level_magenta{ 105 | border:0px; 106 | background-color:magenta; 107 | } 108 | 109 | .printercounters_toner_level_other{ 110 | border:0px; 111 | background-color: #0464BB; 112 | } 113 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | 2 | on: 3 | push: 4 | # Sequence of patterns matched against refs/tags 5 | tags: 6 | - '*.*.*' # Push events to matching ex:20.15.10 7 | 8 | name: Create release with tag 9 | env: 10 | TAG_VALUE: ${GITHUB_REF/refs\/tags\//} 11 | jobs: 12 | build: 13 | name: Upload Release Asset 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v4 18 | - name: Setup PHP 19 | uses: shivammathur/setup-php@v2 20 | with: 21 | php-version: 7.4 22 | - name: Build project # This would actually build your project, using zip for an example artifact 23 | id: build_ 24 | env: 25 | GITHUB_NAME: ${{ github.event.repository.name }} 26 | 27 | 28 | run: php -v ;sudo apt-get install libxml-xpath-perl; sudo apt-get install composer;echo $(xpath -e '/root/versions/version[num="'${GITHUB_REF/refs\/tags\//}'"]/compatibility/text()' $GITHUB_NAME.xml);echo ::set-output name=version_glpi::$(xpath -e '/root/versions/version[num="'${GITHUB_REF/refs\/tags\//}'"]/compatibility/text()' $GITHUB_NAME.xml); [[ -f composer.json ]] && composer install --no-dev; rm -rf $GITHUB_NAME.xml tools wiki screenshots test .git .github ISSUE_TEMPLATE.md TODO.txt $GITHUB_NAME.png;cd ..; tar -jcvf glpi-$GITHUB_NAME-${GITHUB_REF/refs\/tags\//}.tar.bz2 $GITHUB_NAME;ls -al;echo ::set-output name=tag::${GITHUB_REF/refs\/tags\//};echo ${{ steps.getxml.outputs.info }}; 29 | # run: rm -rf $GITHUB_NAME.xml tools wiki screenshots test ISSUE_TEMPLATE.md TODO.txt $GITHUB_NAME.png; tar -zcvf glpi-$GITHUB_NAME-$GITHUB_TAG.tar.bz2 $GITHUB_NAME 30 | - name: Create Release 31 | id: create_release 32 | uses: actions/create-release@v1 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | with: 36 | tag_name: ${{ github.ref }} 37 | release_name: | 38 | GLPI ${{ steps.build_.outputs.version_glpi }} : Version ${{ github.ref }} disponible / available 39 | body : Version ${{ steps.build_.outputs.tag }} released for GLPI ${{ steps.build_.outputs.version_glpi }} 40 | draft: false 41 | prerelease: true 42 | - name: Upload Release Asset 43 | id: upload-release-asset 44 | uses: actions/upload-release-asset@v1 45 | env: 46 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 47 | GITHUB_NAME: ${{ github.event.repository.name }} 48 | with: 49 | upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 50 | asset_path: /home/runner/work/${{ github.event.repository.name }}/glpi-${{ github.event.repository.name }}-${{ steps.build_.outputs.tag }}.tar.bz2 51 | asset_name: glpi-${{ github.event.repository.name }}-${{ steps.build_.outputs.tag }}.tar.bz2 52 | asset_content_type: application/zip 53 | 54 | -------------------------------------------------------------------------------- /scripts/printercounters_fullsync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd $(dirname $0) 3 | 4 | eval $(php -f ./glpienv.php) 5 | 6 | PROCESS_ID=$(date +%j%H%M%S) 7 | 8 | pid_dir="/tmp" 9 | pidfile="$pid_dir/printercounters_fullsync.pid" 10 | runningpid="" 11 | scriptname="printercounters_fullsync.sh" 12 | logfilename="printercounters_fullsync.log" 13 | 14 | 15 | # Predefined settings 16 | sonprocess_nbr=2 17 | itemtype=Printer 18 | 19 | trap cleanup 1 2 3 6 20 | 21 | usage() 22 | { 23 | echo "Usage:" 24 | echo " $0 [--arg]" 25 | echo 26 | echo "Arguments:" 27 | echo " --sonprocess_nbr=num: number of sonprocesss to launch" 28 | echo " --itemtype=string: Type of item" 29 | } 30 | 31 | exit_if_soft_lock() 32 | { 33 | if [ -f $GLPI_LOCK_DIR/printercounters.lock ] 34 | then 35 | echo "Software lock : script can't run !" 36 | exit 1 37 | fi 38 | } 39 | 40 | read_argv() 41 | { 42 | for i in $@; do 43 | valname=`echo $i| sed 's/--\(.*\)=.*/\1/'` 44 | valcontent=`echo $i| sed 's/--.*=\(.*\)/\1/'` 45 | 46 | [ -z $valname ] && usage 47 | case "$valname" in 48 | sonprocess_nbr) 49 | sonprocess_nbr=$valcontent 50 | ;; 51 | itemtype) 52 | itemtype=$valcontent 53 | ;; 54 | --nolog) 55 | logfilename= 56 | ;; 57 | *) 58 | usage 59 | exit 1 60 | ;; 61 | esac 62 | done 63 | } 64 | 65 | cleanup() 66 | { 67 | echo "cleaning up." 68 | # echo "kill pids: $runningpid" 69 | for pid in $runningpid; do 70 | kill $pid 2>/dev/null; 71 | done 72 | rm -f $pidfile 73 | rm -f "$GLPI_LOCK_DIR/lock_entity*" 74 | 75 | echo $(date) ended 76 | exit 0 77 | } 78 | 79 | exit_if_already_running() 80 | { 81 | # No pidfile, probably no daemon present 82 | # 83 | if [ ! -f $pidfile ] 84 | then 85 | return 1 86 | fi 87 | 88 | pid=`cat $pidfile` 89 | 90 | # No pid, probably no daemon present 91 | # 92 | if [ -z "$pid" ] 93 | then 94 | return 1 95 | fi 96 | 97 | if [ ! -d /proc/$pid ] 98 | then 99 | return 1 100 | fi 101 | 102 | cmd=`cat /proc/$pid/cmdline | grep $scriptname` 103 | 104 | if [ "$cmd" != "" ] 105 | then 106 | exit 1 107 | fi 108 | } 109 | 110 | if [ ! -w $GLPI_LOCK_DIR ] 111 | then 112 | echo -e "\tERROR : $GLPI_LOCK_DIR not writable" 113 | echo -e "\trun script as 'apache' user" 114 | exit 1 115 | fi 116 | 117 | read_argv "$@" 118 | if [ -n "$logfilename" ]; then 119 | exec >>$GLPI_LOG_DIR/$logfilename 2>&1 120 | fi 121 | 122 | exit_if_soft_lock 123 | exit_if_already_running 124 | 125 | echo $$ > $pidfile 126 | 127 | rm -f "$GLPI_LOCK_DIR/lock_entity*" 128 | cpt=0 129 | 130 | echo $(date) $0 started 131 | 132 | while [ $cpt -lt $sonprocess_nbr ]; do 133 | cpt=$(($cpt+1)) 134 | cmd="php printercounters_fullsync.php --itemtype=$itemtype --sonprocess_nbr=$sonprocess_nbr --sonprocess_id=$cpt --process_id=$PROCESS_ID" 135 | sh -c "$cmd"& 136 | runningpid="$runningpid $!" 137 | sleep 1 138 | done 139 | 140 | wait 141 | 142 | cleanup 143 | -------------------------------------------------------------------------------- /install/update_103_104.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | /** 31 | * Update from 1.0.3 to 1.0.4 32 | * 33 | * @return bool for success (will die for most error) 34 | * */ 35 | function update103to104() { 36 | global $DB; 37 | 38 | $migration = new Migration(104); 39 | 40 | // Snmp authentications 41 | $migration->addKey('glpi_plugin_printercounters_snmpauthentications', 'entities_id', 'entities_id'); 42 | $migration->addField('glpi_plugin_printercounters_snmpauthentications', 'community_write', 'string', ['value' => 'private']); 43 | 44 | // Profile 45 | $migration->addField('glpi_plugin_printercounters_profiles', 'snmpset', 'bool', ['value' => 0]); 46 | $query_profile = "ALTER TABLE `glpi_plugin_printercounters_profiles` 47 | MODIFY COLUMN `add_lower_records` tinyint(1) NOT NULL default '0', 48 | MODIFY COLUMN `update_records` tinyint(1) NOT NULL default '0';"; 49 | 50 | $DB->queryOrDie($query_profile, "Change profile column types"); 51 | 52 | // Create snmpset table 53 | $query_snmpset = "CREATE TABLE IF NOT EXISTS `glpi_plugin_printercounters_snmpsets` ( 54 | `id` int(11) NOT NULL auto_increment, 55 | `entities_id` int(11) NOT NULL default '0', 56 | `is_recursive` tinyint(1) NOT NULL default '0', 57 | `set_location` tinyint(1) NOT NULL default '1', 58 | `set_contact` tinyint(1) NOT NULL default '1', 59 | `set_name` tinyint(1) NOT NULL default '1', 60 | `contact` text COLLATE utf8_unicode_ci, 61 | PRIMARY KEY (`id`), 62 | UNIQUE KEY `unicity` (`entities_id`), 63 | KEY `entities_id` (`entities_id`) 64 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;"; 65 | 66 | $DB->queryOrDie($query_snmpset, "Create snmpset table"); 67 | 68 | $migration->executeMigration(); 69 | 70 | return true; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /inc/countertype_recordmodelinjection.class.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | if (!defined('GLPI_ROOT')) { 31 | die("Sorry. You can't access directly to this file"); 32 | } 33 | 34 | /** 35 | * Class PluginPrintercountersCountertype_RecordmodelInjection 36 | * 37 | * This class allows to inject OIDs on the record models with the plugin Datainjection 38 | * 39 | * @package Printercounters 40 | * @author Ludovic Dupont 41 | */ 42 | class PluginPrintercountersCountertype_RecordmodelInjection extends PluginPrintercountersCountertype_Recordmodel 43 | implements PluginDatainjectionInjectionInterface { 44 | 45 | static function getTable($classname = null) { 46 | $parenttype = get_parent_class(); 47 | return $parenttype::getTable(); 48 | } 49 | 50 | 51 | function isPrimaryType() { 52 | return true; 53 | } 54 | 55 | 56 | function connectedTo() { 57 | return []; 58 | } 59 | 60 | 61 | 62 | function getOptions($primary_type = '') { 63 | 64 | $tab = Search::getOptions(get_parent_class($this)); 65 | 66 | //Remove some options because some fields cannot be imported 67 | $blacklist = PluginDatainjectionCommonInjectionLib::getBlacklistedOptions(get_parent_class($this)); 68 | $notimportable = [2]; 69 | 70 | $options['displaytype'] = ["dropdown" => [72, 75]]; 71 | 72 | $options['ignore_fields'] = array_merge($blacklist, $notimportable); 73 | 74 | return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options, $this); 75 | } 76 | /** 77 | * Standard method to add an object into glpi 78 | 79 | * 80 | * @param values fields to add into glpi 81 | * @param options options used during creation 82 | * 83 | * @return an array of IDs of newly created objects : for example array(Computer=>1, Networkport=>10) 84 | **/ 85 | function addOrUpdateObject($values = [], $options = []) { 86 | 87 | $lib = new PluginDatainjectionCommonInjectionLib($this, $values, $options); 88 | $lib->processAddOrUpdate(); 89 | return $lib->getInjectionResults(); 90 | } 91 | 92 | 93 | } 94 | 95 | -------------------------------------------------------------------------------- /install/update_104_105.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | /** 31 | * Update from 1.0.4 to 1.0.5 32 | * 33 | * @return bool for success (will die for most error) 34 | * */ 35 | function update104to105() { 36 | global $DB; 37 | 38 | $migration = new Migration(105); 39 | 40 | // Toner level 41 | $migration->addField('glpi_plugin_printercounters_recordmodels', 'enable_toner_level', 'bool', ['value' => '0']); 42 | $migration->addField('glpi_plugin_printercounters_recordmodels', 'enable_printer_info', 'bool', ['value' => '0']); 43 | $migration->addField('glpi_plugin_printercounters_configs', 'enable_toner_alert', 'bool', ['value' => '0']); 44 | $migration->addField('glpi_plugin_printercounters_configs', 'toner_alert_repeat', 'integer', ['value' => '0']); 45 | $migration->addField('glpi_plugin_printercounters_configs', 'toner_treshold', 'integer', ['value' => '0']); 46 | 47 | // Create additional_datas table 48 | $query_snmpset = "CREATE TABLE IF NOT EXISTS `glpi_plugin_printercounters_additionals_datas` ( 49 | `id` int(11) NOT NULL auto_increment, 50 | `name` varchar(255) default NULL, 51 | `type` varchar(255) default NULL, 52 | `sub_type` varchar(255) default NULL, 53 | `value` varchar(255) default NULL, 54 | `plugin_printercounters_items_recordmodels_id` int(11) NOT NULL default '0', 55 | PRIMARY KEY (`id`), 56 | UNIQUE KEY `unicity` (`plugin_printercounters_items_recordmodels_id`, `sub_type`), 57 | KEY `type` (`type`) 58 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;"; 59 | 60 | $DB->queryOrDie($query_snmpset, "Create additional datas table"); 61 | 62 | // Add record notification 63 | include_once(PLUGIN_PRINTERCOUNTERS_DIR ."/inc/notificationtargetadditional_data.class.php"); 64 | call_user_func(["PluginPrintercountersNotificationTargetAdditional_Data",'install']); 65 | $migration->displayMessage("Add record notifications"); 66 | 67 | $migration->executeMigration(); 68 | 69 | return true; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /inc/recordmodelinjection.class.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | if (!defined('GLPI_ROOT')) { 31 | die("Sorry. You can't access directly to this file"); 32 | } 33 | 34 | /** 35 | * Class PluginPrintercountersRecordmodelInjection 36 | * 37 | * This class allows to inject record models with the plugin Datainjection 38 | * 39 | * @package Printercounters 40 | * @author Ludovic Dupont 41 | */ 42 | class PluginPrintercountersRecordmodelInjection extends PluginPrintercountersRecordmodel 43 | implements PluginDatainjectionInjectionInterface { 44 | 45 | static function getTable($classname = null) { 46 | $parenttype = get_parent_class(); 47 | return $parenttype::getTable(); 48 | } 49 | 50 | 51 | function isPrimaryType() { 52 | return true; 53 | } 54 | 55 | 56 | function connectedTo() { 57 | return []; 58 | } 59 | 60 | 61 | 62 | function getOptions($primary_type = '') { 63 | 64 | $tab = Search::getOptions(get_parent_class($this)); 65 | 66 | //Remove some options because some fields cannot be imported 67 | $blacklist = PluginDatainjectionCommonInjectionLib::getBlacklistedOptions(get_parent_class($this)); 68 | $notimportable = [2]; 69 | 70 | $options['ignore_fields'] = array_merge($blacklist, $notimportable); 71 | 72 | return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options, $this); 73 | } 74 | /** 75 | * Standard method to add an object into glpi 76 | 77 | * 78 | * @param values fields to add into glpi 79 | * @param options options used during creation 80 | * 81 | * @return an array of IDs of newly created objects : for example array(Computer=>1, Networkport=>10) 82 | **/ 83 | function addOrUpdateObject($values = [], $options = []) { 84 | 85 | $lib = new PluginDatainjectionCommonInjectionLib($this, $values, $options); 86 | $lib->processAddOrUpdate(); 87 | return $lib->getInjectionResults(); 88 | } 89 | 90 | 91 | //function addSpecificNeededFields($primary_type, $values) { 92 | 93 | // $fields['groups_id'] = $values['Group']['id']; 94 | // return $fields; 95 | //} 96 | 97 | } 98 | 99 | -------------------------------------------------------------------------------- /inc/countertypeinjection.class.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | if (!defined('GLPI_ROOT')) { 31 | die("Sorry. You can't access directly to this file"); 32 | } 33 | 34 | /** 35 | * Class PluginPrintercountersCountertypeInjection 36 | * 37 | * This class allows to inject OIDs on the record models with the plugin Datainjection 38 | * 39 | * @package Printercounters 40 | * @author Ludovic Dupont 41 | */ 42 | class PluginPrintercountersCountertypeInjection extends PluginPrintercountersCountertype 43 | implements PluginDatainjectionInjectionInterface { 44 | 45 | static function getTable($classname = null) { 46 | $parenttype = get_parent_class(); 47 | return $parenttype::getTable(); 48 | } 49 | 50 | 51 | function isPrimaryType() { 52 | return true; 53 | } 54 | 55 | 56 | function connectedTo() { 57 | return []; 58 | } 59 | 60 | 61 | 62 | function getOptions($primary_type = '') { 63 | 64 | $tab = Search::getOptions(get_parent_class($this)); 65 | 66 | //Remove some options because some fields cannot be imported 67 | $blacklist = PluginDatainjectionCommonInjectionLib::getBlacklistedOptions(get_parent_class($this)); 68 | $notimportable = [2]; 69 | 70 | $options['ignore_fields'] = array_merge($blacklist, $notimportable); 71 | 72 | return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options, $this); 73 | } 74 | /** 75 | * Standard method to add an object into glpi 76 | 77 | * 78 | * @param values fields to add into glpi 79 | * @param options options used during creation 80 | * 81 | * @return an array of IDs of newly created objects : for example array(Computer=>1, Networkport=>10) 82 | **/ 83 | function addOrUpdateObject($values = [], $options = []) { 84 | 85 | $lib = new PluginDatainjectionCommonInjectionLib($this, $values, $options); 86 | $lib->processAddOrUpdate(); 87 | return $lib->getInjectionResults(); 88 | } 89 | 90 | 91 | //function addSpecificNeededFields($primary_type, $values) { 92 | 93 | // $fields['groups_id'] = $values['Group']['id']; 94 | // return $fields; 95 | //} 96 | 97 | } 98 | 99 | -------------------------------------------------------------------------------- /scripts/printercounters_fullsync.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | ini_set("memory_limit", "-1"); 31 | ini_set("max_execution_time", "0"); 32 | 33 | // Converts cli parameter to web parameter for compatibility 34 | if (isset($_SERVER["argv"]) && !isset($argv)) { 35 | $argv = $_SERVER["argv"]; 36 | } 37 | if ($argv) { 38 | for ($i = 1; $i < count($argv); $i++) { 39 | $it = explode("=", $argv[$i], 2); 40 | $it[0] = preg_replace('/^--/', '', $it[0]); 41 | $_GET[$it[0]] = $it[1]; 42 | } 43 | } 44 | 45 | // Can't run on MySQL replicate 46 | $USEDBREPLICATE = 0; 47 | $DBCONNECTION_REQUIRED = 1; 48 | 49 | 50 | include ('../../../inc/includes.php'); 51 | 52 | $_SESSION["glpicronuserrunning"] = $_SESSION["glpiname"] = 'printercounters'; 53 | // Check PHP Version - sometime (debian) cli version != module version 54 | if (version_compare(phpversion(), '5.4', 'lt')) { 55 | die("PHP version:".phpversion()." - "."You must install at least PHP 5.4\n\n"); 56 | } 57 | // Chech Memory_limit - sometine cli limit (php-cli.ini) != module limit (php.ini) 58 | $mem = Toolbox::getMemoryLimit(); 59 | if (($mem > 0) && ($mem < (64 * 1024 * 1024))) { 60 | die("PHP memory_limit = ".$mem." - "."A minimum of 64Mio is commonly required for GLPI.'\n\n"); 61 | } 62 | 63 | $config = PluginPrintercountersConfig::getInstance(); 64 | 65 | if (Plugin::isPluginActive("printercounters") && !$config['disable_autosearch']) { 66 | $sonprocess_nbr = $_GET['sonprocess_nbr']; 67 | $sonprocess_id = $_GET['sonprocess_id']; 68 | $itemtype = $_GET['itemtype']; 69 | $record_type = $_GET['record_type']; 70 | 71 | switch ($record_type) { 72 | case 'error': 73 | // Init error record 74 | $record = new PluginPrintercountersErrorItem($itemtype, 0); 75 | list($messages, $error) = $record->initRecord($sonprocess_id, $sonprocess_nbr); 76 | break; 77 | case 'normal': 78 | // Init record 79 | $record = new PluginPrintercountersRecord($itemtype); 80 | list($messages, $error) = $record->initRecord($itemtype, 0, $sonprocess_id, $sonprocess_nbr); 81 | break; 82 | } 83 | 84 | echo implode("\n", $messages); 85 | 86 | } else { 87 | echo __('Plugin disabled or automatic record disabled', 'printercounters'); 88 | exit(1); 89 | } 90 | 91 | -------------------------------------------------------------------------------- /inc/exception.class.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | if (!defined('GLPI_ROOT')) { 31 | die("Sorry. You can't access directly to this file"); 32 | } 33 | 34 | /** 35 | * Class PluginPrintercountersException 36 | * 37 | * This class adds custom exception management for the plugin 38 | * 39 | * @package Printercounters 40 | * @author Ludovic Dupont 41 | */ 42 | class PluginPrintercountersException extends Exception { 43 | 44 | protected $itemptype; 45 | protected $items_id; 46 | 47 | /** 48 | * Constructor 49 | * 50 | * @param string $message 51 | * @param int $code 52 | * @param Exception $previous 53 | * @param int $items_id 54 | * @param string $itemtype 55 | */ 56 | public function __construct($message, $code, $previous, $items_id, $itemtype) { 57 | $this->setItemtype($itemtype); 58 | $this->setItems_id($items_id); 59 | 60 | parent::__construct($message, $code, $previous); 61 | } 62 | 63 | /** 64 | * Function sets items_id 65 | * 66 | * @param string 67 | */ 68 | public function setItems_id($items_id) { 69 | $this->items_id = $items_id; 70 | } 71 | 72 | /** 73 | * Function sets itemtype 74 | * 75 | * @param string 76 | */ 77 | public function setItemtype($itemtype) { 78 | $this->itemptype = $itemtype; 79 | } 80 | 81 | 82 | /** 83 | * Function sets plugin error message 84 | * @return string 85 | */ 86 | function getPrintercountersMessage() { 87 | 88 | // Debug mode 89 | $user = new User(); 90 | $user->getFromDB(Session::getLoginUserID()); 91 | if (isset($user->fields['use_mode']) && $user->fields['use_mode'] == Session::DEBUG_MODE) { 92 | $trace = $this->getTraceAsString(); 93 | $trace = preg_replace('/#(\d)/', '
#$1', $trace); 94 | return __('SNMP Error: ', 'printercounters').$this->getMessage().' '.$trace.' (itemtype : '.$this->itemptype.', items_id : '.$this->items_id.')
'; 95 | 96 | // Normal mode 97 | } else { 98 | return __('SNMP Error: ', 'printercounters').$this->getMessage().' (itemtype : '.$this->itemptype.', items_id : '.$this->items_id.')'; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /inc/item_recordmodelinjection.class.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | if (!defined('GLPI_ROOT')) { 31 | die("Sorry. You can't access directly to this file"); 32 | } 33 | 34 | /** 35 | * Class PluginPrintercountersItem_Recordmodel 36 | * 37 | * This class allows to inject record models on the items with the plugin Datainjection 38 | * 39 | * @package Printercounters 40 | * @author Ludovic Dupont 41 | */ 42 | class PluginPrintercountersItem_RecordmodelInjection extends PluginPrintercountersItem_Recordmodel 43 | implements PluginDatainjectionInjectionInterface { 44 | 45 | static function getTable($classname = null) { 46 | $parenttype = get_parent_class(); 47 | return $parenttype::getTable(); 48 | } 49 | 50 | 51 | function isPrimaryType() { 52 | return true; 53 | } 54 | 55 | 56 | function connectedTo() { 57 | return []; 58 | } 59 | 60 | 61 | 62 | function getOptions($primary_type = '') { 63 | 64 | $tab = Search::getOptions(get_parent_class($this)); 65 | 66 | //Remove some options because some fields cannot be imported 67 | $blacklist = PluginDatainjectionCommonInjectionLib::getBlacklistedOptions(get_parent_class($this)); 68 | $notimportable = [2, 90, 81, 91, 92, 93, 87, 84, 86, 83, 82, 80, 79, 85]; 69 | 70 | $options['displaytype'] = ["dropdown" => [95]]; 71 | 72 | $options['ignore_fields'] = array_merge($blacklist, $notimportable); 73 | 74 | return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options, $this); 75 | } 76 | /** 77 | * Standard method to add an object into glpi 78 | 79 | * 80 | * @param values fields to add into glpi 81 | * @param options options used during creation 82 | * 83 | * @return an array of IDs of newly created objects : for example array(Computer=>1, Networkport=>10) 84 | **/ 85 | function addOrUpdateObject($values = [], $options = []) { 86 | 87 | $lib = new PluginDatainjectionCommonInjectionLib($this, $values, $options); 88 | $lib->processAddOrUpdate(); 89 | return $lib->getInjectionResults(); 90 | } 91 | 92 | 93 | // function addSpecificNeededFields($primary_type, $values) { 94 | // Toolbox::logDebug($primary_type);Toolbox::logDebug($values); 95 | // $fields['groups_id'] = $values['Group']['id']; 96 | // return $fields; 97 | // } 98 | 99 | } 100 | 101 | -------------------------------------------------------------------------------- /inc/toolbox.class.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | if (!defined('GLPI_ROOT')) { 31 | die("Sorry. You can't access directly to this file"); 32 | } 33 | 34 | /** 35 | * Class PluginPrintercountersToolbox 36 | * 37 | * This class adds usefull functions 38 | * 39 | * @package Printercounters 40 | * @author Ludovic Dupont 41 | */ 42 | class PluginPrintercountersToolbox { 43 | 44 | /** 45 | * Check if mac address is valid and return it in the format 00:00:00:00:00:00:00:00 46 | * 47 | * @param type $mac 48 | * @return boolean 49 | */ 50 | static function getValidMacAddress($mac) { 51 | 52 | if (preg_match("/^([0-9a-f]{1,2}[\.:\-\s]){5}([0-9a-f]{1,2})$/i", $mac)) { 53 | $mac = str_replace(['.', '-', ' '], ':', $mac); 54 | 55 | $hexa = explode(':', $mac); 56 | foreach ($hexa as &$value) { 57 | $value = strtolower(str_pad($value, 2, '0', STR_PAD_LEFT)); 58 | } 59 | 60 | return implode(':', $hexa); 61 | } 62 | 63 | return false; 64 | } 65 | 66 | /** 67 | * Get number of same item name 68 | * 69 | * @global type $DB 70 | * @param type $name 71 | * @param type $table 72 | * @return int 73 | */ 74 | static function getCopyNumber($name, $table) { 75 | global $DB; 76 | 77 | $query = "SELECT count(*) as count 78 | FROM ".$table." 79 | WHERE `name` LIKE '%".$name."%';"; 80 | 81 | $result = $DB->query($query); 82 | if ($DB->numrows($result)) { 83 | while ($data = $DB->fetchAssoc($result)) { 84 | return $data['count']; 85 | } 86 | } 87 | 88 | return 0; 89 | } 90 | 91 | static function replaceAccents($string) { 92 | $unwanted_array = [ 'Š'=>'S', 'š'=>'s', 'Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E', 93 | 'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 94 | 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 95 | 'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o', 96 | 'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y' ]; 97 | return strtr($string, $unwanted_array); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /front/config.form.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ('../../../inc/includes.php'); 31 | 32 | if (Plugin::isPluginActive("printercounters")) { 33 | $config = new PluginPrintercountersConfig(); 34 | if (!$config->canCreate()) { 35 | Html::displayRightError(); 36 | } 37 | 38 | if (isset($_POST['items_status']) && !empty($_POST['items_status'])) { 39 | $_POST['items_status'] = json_encode($_POST['items_status']); 40 | } else { 41 | $_POST['items_status'] = ""; 42 | } 43 | 44 | if (isset($_POST["update_config"])) { 45 | $dbu = new DbUtils(); 46 | if (!$dbu->countElementsInTable("glpi_plugin_printercounters_configs", ["id" => 1])) { 47 | $config->add($_POST); 48 | } else { 49 | $_POST['id'] = 1; 50 | $config->update($_POST); 51 | } 52 | Html::back(); 53 | 54 | } else if (isset($_POST["clean_error_records"])) { 55 | $record = new PluginPrintercountersRecord(); 56 | if ($records_id = $record->getRecordsToClean(PluginPrintercountersRecord::$CLEAN_ERROR_RECORDS, ['date' => $_POST['date']])) { 57 | Html::header(PluginPrintercountersConfig::getTypeName(), '', "tools", "pluginprintercountersmenu", "config"); 58 | $record->initCleanRecords(__('Clean records in error', 'printercounters'), $records_id); 59 | Html::footer(); 60 | Session::addMessageAfterRedirect(__('Records cleaned', 'printercounters')); 61 | 62 | } else { 63 | Session::addMessageAfterRedirect(__('No records to clean', 'printercounters')); 64 | Html::back(); 65 | } 66 | 67 | } else if (isset($_POST["clean_empty_records"])) { 68 | $record = new PluginPrintercountersRecord(); 69 | if ($records_id = $record->getRecordsToClean(PluginPrintercountersRecord::$CLEAN_EMTPY_RECORDS, ['date' => $_POST['date']])) { 70 | Html::header(PluginPrintercountersConfig::getTypeName(), '', "tools", "pluginprintercountersmenu", "config"); 71 | $record->initCleanRecords(__('Clean empty records', 'printercounters'), $records_id); 72 | Html::footer(); 73 | Session::addMessageAfterRedirect(__('Records cleaned', 'printercounters')); 74 | 75 | } else { 76 | Session::addMessageAfterRedirect(__('No records to clean', 'printercounters')); 77 | Html::back(); 78 | } 79 | 80 | } else { 81 | Html::header(PluginPrintercountersConfig::getTypeName(), '', "tools", "pluginprintercountersmenu", "config"); 82 | $data = $config->getInstance(); 83 | $config->display(['id' => $data['configs_id']]); 84 | Html::footer(); 85 | } 86 | 87 | } else { 88 | Html::header(PluginPrintercountersConfig::getTypeName(), '', "tools", "pluginprintercountersmenu", "config"); 89 | echo "
"; 90 | echo "".__('Please activate the plugin', 'printercounters')."
"; 91 | Html::footer(); 92 | } 93 | 94 | -------------------------------------------------------------------------------- /ajax/searchoption.php: -------------------------------------------------------------------------------- 1 | . 30 | * --------------------------------------------------------------------- 31 | */ 32 | 33 | // Direct access to file 34 | if (strpos($_SERVER['PHP_SELF'], "searchoption.php")) { 35 | include ('../../../inc/includes.php'); 36 | header("Content-Type: text/html; charset=UTF-8"); 37 | Html::header_nocache(); 38 | } else if (!defined('GLPI_ROOT')) { 39 | die("Sorry. You can't access this file directly"); 40 | } 41 | 42 | Session::checkLoginUser(); 43 | 44 | // Non define case 45 | if (isset($_POST["itemtype"]) 46 | && isset($_POST["field"]) 47 | && isset($_POST["num"]) ) { 48 | 49 | if (!is_subclass_of($_POST['itemtype'], 'CommonDBTM')) { 50 | throw new \RuntimeException('Invalid itemtype provided!'); 51 | } 52 | 53 | $_POST['num'] = intval($_POST['num']); 54 | 55 | if (isset($_POST['meta']) && $_POST['meta']) { 56 | $fieldname = 'metacriteria'; 57 | } else { 58 | $fieldname = 'criteria'; 59 | $_POST['meta'] = 0; 60 | } 61 | 62 | $actions = Search::getActionsFor($_POST["itemtype"], $_POST["field"]); 63 | 64 | // is it a valid action for type ? 65 | if (count($actions) 66 | && (empty($_POST['searchtype']) || !isset($actions[$_POST['searchtype']]))) { 67 | $tmp = $actions; 68 | unset($tmp['searchopt']); 69 | $_POST['searchtype'] = key($tmp); 70 | unset($tmp); 71 | } 72 | 73 | $randsearch = -1; 74 | $dropdownname = "searchtype$fieldname".$_POST["itemtype"].$_POST["num"]; 75 | $searchopt = []; 76 | 77 | echo "
"; 78 | if (count($actions)>0) { 79 | 80 | // get already get search options 81 | if (isset($actions['searchopt'])) { 82 | $searchopt = $actions['searchopt']; 83 | // No name for clean array with quotes 84 | unset($searchopt['name']); 85 | unset($actions['searchopt']); 86 | } 87 | $randsearch = Dropdown::showFromArray($fieldname."[".$_POST["num"]."][searchtype]", 88 | $actions, 89 | ['value' => $_POST["searchtype"]]); 90 | $fieldsearch_id = Html::cleanId("dropdown_".$fieldname."[".$_POST["num"]."][searchtype]$randsearch"); 91 | } 92 | echo ""; 93 | echo "\n"; 94 | 95 | $_POST['value'] = stripslashes($_POST['value']); 96 | $_POST['searchopt'] = $searchopt; 97 | 98 | include(PLUGIN_PRINTERCOUNTERS_DIR."/ajax/searchoptionvalue.php"); 99 | echo "\n"; 100 | echo "
"; 101 | 102 | $paramsaction = ['searchtype' => '__VALUE__', 103 | 'field' => $_POST["field"], 104 | 'itemtype' => $_POST["itemtype"], 105 | 'num' => $_POST["num"], 106 | 'value' => rawurlencode($_POST['value']), 107 | 'searchopt' => $searchopt, 108 | 'meta' => $_POST['meta']]; 109 | 110 | Ajax::updateItemOnSelectEvent($fieldsearch_id, 111 | "span$dropdownname", 112 | PLUGIN_PRINTERCOUNTERS_WEBDIR."//ajax/searchoptionvalue.php", 113 | $paramsaction); 114 | } 115 | -------------------------------------------------------------------------------- /ajax/record.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | include ("../../../inc/includes.php"); 31 | 32 | Session::checkLoginUser(); 33 | //Html::header_nocache(); 34 | 35 | $_POST['itemtype'] = isset($_POST['itemtype']) ? $_POST['itemtype'] : 'printer'; 36 | $_POST['items_id'] = isset($_POST['items_id']) ? $_POST['items_id'] : 0; 37 | $record = new PluginPrintercountersRecord($_POST['itemtype'], $_POST['items_id']); 38 | 39 | if (!isset($_POST['action']) && isset($_GET['action'])) { 40 | $_POST['action'] = $_GET['action']; 41 | } 42 | 43 | if (isset($_POST['action'])) { 44 | switch ($_POST['action']) { 45 | case 'immediateRecord': 46 | header('Content-Type: application/json; charset=UTF-8"'); 47 | list($messages, $error) = $record->immediateRecord($_POST['items_id'], $_POST['itemtype']); 48 | echo json_encode(['message' => implode('
', $messages), 49 | 'error' => $error]); 50 | break; 51 | 52 | case 'showManualRecord': 53 | header("Content-Type: text/html; charset=UTF-8"); 54 | $record->showManualRecord($_POST['items_id'], $_POST['itemtype'], $_POST['records_id'], $_POST['rand'], $_POST['addLowerRecord']); 55 | break; 56 | 57 | case 'setManualRecord': 58 | header('Content-Type: application/json; charset=UTF-8"'); 59 | list($messages, $error) = $record->setManualRecord($_POST['items_id'], $_POST['itemtype'], $_POST['counters'], $_POST['records_id'], $_POST['addLowerRecord']); 60 | echo json_encode(['message' => implode('
', $messages), 61 | 'error' => $error]); 62 | break; 63 | 64 | case 'SNMPSet': 65 | header('Content-Type: application/json; charset=UTF-8"'); 66 | $snmpset = new PluginPrintercountersSnmpset(); 67 | list($messages, $error) = $snmpset->snmpSet($_POST['items_id'], $_POST['itemtype']); 68 | echo json_encode(['message' => implode('
', $messages), 69 | 'error' => $error]); 70 | break; 71 | 72 | case 'updateGlobalTco': 73 | header('Content-Type: application/json; charset=UTF-8"'); 74 | list($messages, $result, $error) = $record->updateGlobalTco($_POST['items_id'], $_POST['itemtype']); 75 | echo json_encode(['result' => $result, 76 | 'message' => $messages, 77 | 'error' => $error]); 78 | break; 79 | 80 | case 'updatePrinterData': 81 | header('Content-Type: application/json; charset=UTF-8"'); 82 | list($messages, $error) = $record->updatePrinterData($_POST['items_id'], $_POST['itemtype']); 83 | echo json_encode(['message' => implode('
', $messages), 84 | 'error' => $error]); 85 | break; 86 | 87 | case 'ajaxMassiveAction': 88 | header("Content-Type: text/html; charset=UTF-8"); 89 | $item_recordmodel = new PluginPrintercountersItem_Recordmodel(); 90 | $item_recordmodel->doMassiveActionProcess(); 91 | break; 92 | 93 | case 'ajaxMassiveActionTimeOut': 94 | header("Content-Type: text/html; charset=UTF-8"); 95 | $item_recordmodel = new PluginPrintercountersItem_Recordmodel(); 96 | $item_recordmodel->massiveActionTimeOut(); 97 | break; 98 | 99 | case 'loadCleanErrorRecords': 100 | header("Content-Type: text/html; charset=UTF-8"); 101 | $record->cleanRecords(); 102 | break; 103 | 104 | case 'showErrorItem': 105 | header("Content-Type: text/html; charset=UTF-8"); 106 | // Record error 107 | $errorItem = new PluginPrintercountersErrorItem($_POST['itemtype'], $_POST['items_id']); 108 | $errorItem->showErrorItem(); 109 | break; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /inc/ajax.class.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | if (!defined('GLPI_ROOT')) { 31 | die("Sorry. You can't access directly to this file"); 32 | } 33 | 34 | /** 35 | * Class PluginPrintercountersAjax 36 | * 37 | * Ajax functions 38 | * 39 | * @package Printercounters 40 | * @author Ludovic Dupont 41 | */ 42 | class PluginPrintercountersAjax extends CommonDBTM { 43 | 44 | /** 45 | * Js edition system 46 | * 47 | * @global type $CFG_GLPI 48 | * @param type $toupdate 49 | * @param type $function_name 50 | * @param type $itemtype 51 | * @param type $items_id 52 | * @param type $parenttype 53 | * @param type $parents_id 54 | */ 55 | static function getJSEdition($toupdate, $function_name, $itemtype, $items_id, $parenttype, $parents_id) { 56 | global $CFG_GLPI; 57 | 58 | $dbu = new DbUtils(); 59 | $parent = $dbu->getItemForItemtype($parenttype); 60 | 61 | echo "\n\n"; 71 | } 72 | 73 | 74 | /** 75 | * Create fixed modal window 76 | * After display it using $name.dialog("open"); 77 | * 78 | * @since version 0.84 79 | * 80 | * @param string $name name of the js object 81 | * @param array $options Possible options: 82 | * - width (default 800) 83 | * - height (default 400) 84 | * - modal is a modal window? (default true) 85 | * - container specify a html element to render (default empty to html.body) 86 | * - title window title (default empty) 87 | * - display display or get string? (default true) 88 | * 89 | * @return void|string (see $options['display']) 90 | */ 91 | // static function createFixedModalWindow($name, $options = []) { 92 | // 93 | // $param = ['width' => 800, 94 | // 'height' => 400, 95 | // 'modal' => true, 96 | // 'container' => '', 97 | // 'title' => '', 98 | // 'display' => true]; 99 | // 100 | // if (count($options)) { 101 | // foreach ($options as $key => $val) { 102 | // if (isset($param[$key])) { 103 | // $param[$key] = $val; 104 | // } 105 | // } 106 | // } 107 | // 108 | // $out = ""; 135 | // 136 | // if ($param['display']) { 137 | // echo $out; 138 | // } else { 139 | // return $out; 140 | // } 141 | // 142 | // } 143 | } 144 | -------------------------------------------------------------------------------- /inc/countertype.class.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | if (!defined('GLPI_ROOT')) { 31 | die("Sorry. You can't access directly to this file"); 32 | } 33 | 34 | /** 35 | * Class PluginPrintercountersCountertype 36 | * 37 | * This class allows to manage the counter types (like color, monochrome ...) 38 | * 39 | * @package Printercounters 40 | * @author Ludovic Dupont 41 | */ 42 | class PluginPrintercountersCountertype extends CommonDropdown { 43 | 44 | static $rightname = 'plugin_printercounters'; 45 | 46 | static function getTypeName($nb = 0) { 47 | return _n("Counter type", "Counter types", $nb, 'printercounters'); 48 | } 49 | 50 | /** 51 | * Provides search options configuration. Do not rely directly 52 | * on this, @see CommonDBTM::searchOptions instead. 53 | * 54 | * @since 9.3 55 | * 56 | * This should be overloaded in Class 57 | * 58 | * @return array a *not indexed* array of search options 59 | * 60 | * @see https://glpi-developer-documentation.rtfd.io/en/master/devapi/search.html 61 | **/ 62 | public function rawSearchOptions() { 63 | 64 | $tab = parent::rawSearchOptions(); 65 | 66 | return $tab; 67 | } 68 | 69 | function displayHeader() { 70 | Html::header($this->getTypeName(), '', "tools", "pluginprintercountersmenu", "countertype"); 71 | } 72 | 73 | /** 74 | * Actions done at the end of the getEmpty function 75 | * 76 | * @return nothing 77 | **/ 78 | function post_getEmpty() { 79 | // Set session saved if exists 80 | $this->setSessionValues(); 81 | } 82 | 83 | /** 84 | * Set session values in object 85 | * 86 | * @return type 87 | */ 88 | function setSessionValues() { 89 | if (isset($_SESSION['plugin_printercounters']['countertype']) && !empty($_SESSION['plugin_printercounters']['countertype'])) { 90 | foreach ($_SESSION['plugin_printercounters']['countertype'] as $key => $val) { 91 | $this->fields[$key] = $val; 92 | } 93 | } 94 | unset($_SESSION['plugin_printercounters']['countertype']); 95 | } 96 | 97 | /** 98 | * Actions done before add 99 | * 100 | * @param type $input 101 | * @return type 102 | */ 103 | function prepareInputForAdd($input) { 104 | if (!$this->checkMandatoryFields($input)) { 105 | $_SESSION['plugin_printercounters']['countertype'] = $input; 106 | return false; 107 | } 108 | 109 | return $input; 110 | } 111 | 112 | /** 113 | * Actions done before update 114 | * 115 | * @param type $input 116 | * @return type 117 | */ 118 | function prepareInputForUpdate($input) { 119 | if (!$this->checkMandatoryFields($input)) { 120 | return false; 121 | } 122 | 123 | return $input; 124 | } 125 | 126 | /** 127 | * Check mandatory fields 128 | * 129 | * @param type $input 130 | * @return boolean 131 | */ 132 | function checkMandatoryFields($input) { 133 | $msg = []; 134 | $checkKo = false; 135 | 136 | $mandatory_fields = ['name' => __('Name')]; 137 | 138 | foreach ($input as $key => $value) { 139 | if (array_key_exists($key, $mandatory_fields)) { 140 | if (empty($value)) { 141 | $msg[] = $mandatory_fields[$key]; 142 | $checkKo = true; 143 | } 144 | } 145 | } 146 | 147 | if ($checkKo) { 148 | Session::addMessageAfterRedirect(sprintf(__("Mandatory fields are not filled. Please correct: %s"), implode(', ', $msg)), false, ERROR); 149 | return false; 150 | } 151 | return true; 152 | } 153 | 154 | /** 155 | * Get the standard massive actions which are forbidden 156 | * 157 | * @return an array of massive actions 158 | **/ 159 | function getForbiddenStandardMassiveAction() { 160 | 161 | $forbidden = parent::getForbiddenStandardMassiveAction(); 162 | $forbidden[] = 'merge'; 163 | 164 | return $forbidden; 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /install/sql/update-part 2.sql: -------------------------------------------------------------------------------- 1 | 2 | -- -------------------------------------------------------- 3 | -- 'glpi_plugin_printercounters_profiles' 4 | -- -------------------------------------------------------- 5 | 6 | ALTER TABLE `glpi_plugin_printercounters_profiles` ADD `add_lower_records` char(1) collate utf8_unicode_ci default NULL; 7 | 8 | -- -------------------------------------------------------- 9 | -- 'glpi_plugin_printercounters_configs' 10 | -- -------------------------------------------------------- 11 | 12 | ALTER TABLE `glpi_plugin_printercounters_configs` ADD `tickets_content` text COLLATE utf8_unicode_ci default NULL; 13 | ALTER TABLE `glpi_plugin_printercounters_configs` ADD `add_item_group` char(1) collate utf8_unicode_ci default NULL; 14 | ALTER TABLE `glpi_plugin_printercounters_configs` ADD `add_item_user` char(1) collate utf8_unicode_ci default NULL; 15 | 16 | -- ------------------------------------------------------- 17 | -- 'glpi_plugin_printercounters_records' 18 | -- -------------------------------------------------------- 19 | 20 | ALTER TABLE `glpi_plugin_printercounters_records` ADD `locations_id` int(11) NOT NULL default '0'; 21 | 22 | -- -------------------------------------------------------- 23 | -- Structure de la table 'glpi_plugin_printercounters_pagecosts' 24 | -- -------------------------------------------------------- 25 | CREATE TABLE IF NOT EXISTS `glpi_plugin_printercounters_pagecosts` ( 26 | `id` int(11) NOT NULL auto_increment, 27 | `cost` decimal(6,5) NOT NULL default '0', 28 | `plugin_printercounters_billingmodels_id` int(11) NOT NULL default '0', 29 | `plugin_printercounters_countertypes_id` int(11) NOT NULL default '0', 30 | PRIMARY KEY (`id`), 31 | UNIQUE KEY `unicity` (`plugin_printercounters_billingmodels_id`, `plugin_printercounters_countertypes_id`), 32 | FOREIGN KEY (`plugin_printercounters_billingmodels_id`) REFERENCES glpi_plugin_printercounters_billingmodels(id), 33 | FOREIGN KEY (`plugin_printercounters_countertypes_id`) REFERENCES glpi_plugin_printercounters_countertypes(id) 34 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 35 | 36 | -- -------------------------------------------------------- 37 | -- Structure de la table 'glpi_plugin_printercounters_billingmodels' 38 | -- -------------------------------------------------------- 39 | CREATE TABLE IF NOT EXISTS `glpi_plugin_printercounters_billingmodels` ( 40 | `id` int(11) NOT NULL auto_increment, 41 | `name` varchar(255) default NULL, 42 | `entities_id` int(11) NOT NULL default '0', 43 | `is_recursive` tinyint(1) NOT NULL default '0', 44 | `application_date` datetime default NULL, 45 | `plugin_printercounters_recordmodels_id` int(11) NOT NULL default '0', 46 | `contracts_id` int(11) NOT NULL default '0', 47 | `plugin_printercounters_budgets_id` int(11) NOT NULL default '0', 48 | `suppliers_id` int(11) NOT NULL default '0', 49 | `comment` text COLLATE utf8_unicode_ci, 50 | PRIMARY KEY (`id`), 51 | FOREIGN KEY (`plugin_printercounters_recordmodels_id`) REFERENCES glpi_plugin_printercounters_recordmodels(id), 52 | FOREIGN KEY (`contracts_id`) REFERENCES contracts_id(id), 53 | FOREIGN KEY (`plugin_printercounters_budgets_id`) REFERENCES glpi_plugin_printercounters_budgets(id), 54 | FOREIGN KEY (`suppliers_id`) REFERENCES glpi_suppliers(id), 55 | KEY `application_date` (`application_date`) 56 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 57 | 58 | -- -------------------------------------------------------- 59 | -- Structure de la table 'glpi_plugin_printercounters_items_billingmodels' 60 | -- -------------------------------------------------------- 61 | CREATE TABLE IF NOT EXISTS `glpi_plugin_printercounters_items_billingmodels` ( 62 | `id` int(11) NOT NULL auto_increment, 63 | `itemtype` varchar(255) default NULL, 64 | `items_id` int(11) NOT NULL default '0', 65 | `plugin_printercounters_billingmodels_id` int(11) NOT NULL default '0', 66 | PRIMARY KEY (`id`), 67 | FOREIGN KEY (`plugin_printercounters_billingmodels_id`) REFERENCES glpi_plugin_printercounters_billingmodels(id), 68 | KEY `items_id` (`items_id`), 69 | KEY `itemtype` (`itemtype`) 70 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 71 | 72 | -- -------------------------------------------------------- 73 | -- Structure de la table 'glpi_plugin_printercounters_budgets' 74 | -- -------------------------------------------------------- 75 | CREATE TABLE IF NOT EXISTS `glpi_plugin_printercounters_budgets` ( 76 | `id` int(11) NOT NULL auto_increment, 77 | `name` varchar(255) default NULL, 78 | `entities_id` int(11) default NULL, 79 | `is_recursive` tinyint(1) NOT NULL default '0', 80 | `amount` int(11) NOT NULL default '0', 81 | `begin_date` datetime default NULL, 82 | `end_date` datetime default NULL, 83 | `comment` text COLLATE utf8_unicode_ci, 84 | PRIMARY KEY (`id`), 85 | KEY `entities_id` (`entities_id`), 86 | KEY `begin_date` (`begin_date`), 87 | KEY `end_date` (`end_date`) 88 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 89 | 90 | -- -------------------------------------------------------- 91 | -- Structure de la table 'glpi_plugin_printercounters_items_tickets' 92 | -- -------------------------------------------------------- 93 | CREATE TABLE IF NOT EXISTS `glpi_plugin_printercounters_items_tickets` ( 94 | `id` int(11) NOT NULL auto_increment, 95 | `itemtype` varchar(255) default NULL, 96 | `items_id` int(11) NOT NULL default '0', 97 | `events_type` int(11) NOT NULL default '0', 98 | `date_mod` datetime default NULL, 99 | `tickets_id` int(11) NOT NULL default '0', 100 | PRIMARY KEY (`id`), 101 | FOREIGN KEY (`tickets_id`) REFERENCES glpi_tickets(id), 102 | KEY `items_id` (`items_id`), 103 | KEY `itemtype` (`itemtype`) 104 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 105 | -------------------------------------------------------------------------------- /printercounters.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PrinterCounters 4 | printercounters 5 | stable 6 | https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/printercounters.png 7 | 8 | 9 | 10 | 11 | 12 | 13 | - D'effectuer le relevé des compteurs des imprimantes sur le réseau 17 |
- De configurer et de gérer l'interrogation des compteurs pour chaque imprimante 18 |
- D'afficher et de gérer les coûts par imprimantes / entités 19 | ]]>
20 | - To perform counters reading printers on the network 24 |
- To configure and manage the counter interrogation for each printer 25 |
- To view and manage costs by printers / entities 26 | ]]>
27 |
28 |
29 | https://github.com/InfotelGLPI/printercounters 30 | https://github.com/InfotelGLPI/printercounters/releases 31 | https://github.com/InfotelGLPI/printercounters/issues 32 | https://raw.githubusercontent.com/InfotelGLPI/printercounters/master/README.md 33 | 34 | Ludovic Dupont 35 | Infotel 36 | 37 | 38 | 39 | 2.0.2 40 | ~10.0 41 | https://github.com/InfotelGLPI/printercounters/releases/download/2.0.2/glpi-printercounters-2.0.2.tar.bz2 42 | 43 | 44 | 2.0.1 45 | ~10.0 46 | https://github.com/InfotelGLPI/printercounters/releases/download/2.0.1/glpi-printercounters-2.0.1.tar.bz2 47 | 48 | 49 | 2.0.0 50 | ~10.0 51 | https://github.com/InfotelGLPI/printercounters/releases/download/2.0.0/glpi-printercounters-2.0.0.tar.bz2 52 | 53 | 54 | 2.0.0-rc2 55 | ~10.0 56 | https://github.com/InfotelGLPI/printercounters/releases/download/2.0.0-rc2/glpi-printercounters-2.0.0-rc2.tar.bz2 57 | 58 | 59 | 2.0.0-rc1 60 | ~10.0 61 | https://github.com/InfotelGLPI/printercounters/releases/download/2.0.0-rc1/glpi-printercounters-2.0.0-rc1.tar.bz2 62 | 63 | 64 | 1.7.0 65 | ~9.5 66 | 67 | 68 | 69 | 1.6.0 70 | 9.4 71 | 72 | 73 | 1.5.1 74 | 9.3 75 | 76 | 77 | 1.5.0 78 | 9.3 79 | 80 | 81 | 1.4.1 82 | 9.2 83 | 84 | 85 | 1.4.0 86 | 9.2 87 | 88 | 89 | 1.3.0 90 | 9.1 91 | 92 | 93 | 1.2.1 94 | 0.90 95 | 96 | 97 | 1.2.0 98 | 0.90 99 | 100 | 101 | 1.0.7 102 | 0.84 103 | 104 | 105 | 1.0.4 106 | 0.84 107 | 108 | 109 | 1.0.2 110 | 0.84 111 | 112 | 113 | 114 | cs_CZ 115 | en_GB 116 | en_US 117 | es_AR 118 | es_ES 119 | fr_FR 120 | hr_HR 121 | it_IT 122 | ru_RU 123 | 124 | 125 | 126 | 127 | gestion 128 | inventaire 129 | 130 | 131 | management 132 | inventory 133 | 134 | 135 | 136 | https://raw.githubusercontent.com/wiki/InfotelGLPI/printercounters/notice/image003.jpg 137 | https://raw.githubusercontent.com/wiki/InfotelGLPI/printercounters/notice/image021.jpg 138 | 139 |
140 | -------------------------------------------------------------------------------- /ajax/searchoptionvalue.php: -------------------------------------------------------------------------------- 1 | . 30 | * --------------------------------------------------------------------- 31 | */ 32 | 33 | $ajax = false; 34 | // Direct access to file 35 | if (strpos($_SERVER['PHP_SELF'], "searchoptionvalue.php")) { 36 | $ajax = true; 37 | include ('../../..inc/includes.php'); 38 | header("Content-Type: text/html; charset=UTF-8"); 39 | Html::header_nocache(); 40 | } else if (!defined('GLPI_ROOT')) { 41 | die("Sorry. You can't access this file directly"); 42 | } 43 | 44 | Session::checkLoginUser(); 45 | 46 | if (isset($_POST['searchtype'])) { 47 | $searchopt = $_POST['searchopt']; 48 | if ($ajax) { 49 | $_POST['value'] = rawurldecode($_POST['value']); 50 | } 51 | $fieldname = 'criteria'; 52 | if (isset($_POST['meta']) && $_POST['meta']) { 53 | $fieldname = 'metacriteria'; 54 | } 55 | 56 | $inputname = $fieldname.'['.$_POST['num'].'][value]'; 57 | $display = false; 58 | $item = getItemForItemtype($_POST['itemtype']); 59 | $options2 = []; 60 | $options2['value'] = $_POST['value']; 61 | $options2['width'] = '100%'; 62 | // For tree dropdpowns 63 | $options2['permit_select_parent'] = true; 64 | 65 | switch ($_POST['searchtype']) { 66 | case "equals" : 67 | case "notequals" : 68 | case "morethan" : 69 | case "lessthan" : 70 | case "under" : 71 | case "notunder" : 72 | if (!$display && isset($searchopt['field'])) { 73 | // Specific cases 74 | switch ($searchopt['table'].".".$searchopt['field']) { 75 | // Add mygroups choice to searchopt 76 | case "glpi_groups.completename" : 77 | $searchopt['toadd'] = ['mygroups' => __('My groups')]; 78 | break; 79 | 80 | case "glpi_users.name" : 81 | $searchopt['toadd'] = [ 82 | [ 83 | 'id' => 'myself', 84 | 'text' => __('Myself'), 85 | ] 86 | ]; 87 | break; 88 | 89 | case "glpi_changes.status" : 90 | case "glpi_changes.impact" : 91 | case "glpi_changes.urgency" : 92 | case "glpi_problems.status" : 93 | case "glpi_problems.impact" : 94 | case "glpi_problems.urgency" : 95 | case "glpi_tickets.status" : 96 | case "glpi_tickets.impact" : 97 | case "glpi_tickets.urgency" : 98 | $options2['showtype'] = 'search'; 99 | break; 100 | 101 | case "glpi_changes.priority" : 102 | case "glpi_problems.priority" : 103 | case "glpi_tickets.priority" : 104 | $options2['showtype'] = 'search'; 105 | $options2['withmajor'] = true; 106 | break; 107 | 108 | 109 | case "glpi_tickets.global_validation" : 110 | $options2['all'] = true; 111 | break; 112 | 113 | 114 | case "glpi_ticketvalidations.status" : 115 | $options2['all'] = true; 116 | break; 117 | 118 | 119 | case "glpi_users.name" : 120 | $options2['right'] = (isset($searchopt['right']) ? $searchopt['right'] : 'all'); 121 | $options2['inactive_deleted'] = 1; 122 | break; 123 | } 124 | 125 | // Standard datatype usage 126 | if (!$display && isset($searchopt['datatype'])) { 127 | switch ($searchopt['datatype']) { 128 | 129 | case "date" : 130 | case "date_delay" : 131 | case "datetime" : 132 | $options2['relative_dates'] = true; 133 | break; 134 | } 135 | } 136 | 137 | $out = $item->getValueToSelect($searchopt, $inputname, $_POST['value'], $options2); 138 | if (strlen($out)) { 139 | echo $out; 140 | $display = true; 141 | } 142 | 143 | //Could display be handled by a plugin ? 144 | if (!$display 145 | && $plug = isPluginItemType(getItemTypeForTable($searchopt['table']))) { 146 | $display = Plugin::doOneHook( 147 | $plug['plugin'], 148 | 'searchOptionsValues', 149 | [ 150 | 'name' => $inputname, 151 | 'searchtype' => $_POST['searchtype'], 152 | 'searchoption' => $searchopt, 153 | 'value' => $_POST['value'] 154 | ] 155 | ); 156 | } 157 | 158 | } 159 | break; 160 | } 161 | 162 | // Default case : text field 163 | if (!$display) { 164 | echo Html::input($inputname, ['value' => Html::cleanInputText($_POST['value']), 'size' => 13]); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /scripts/run.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | function usage() { 31 | 32 | echo "Usage:\n"; 33 | echo "\t" . $_SERVER["argv"][0]. " [--args]\n"; 34 | echo "\n\tArguments:\n"; 35 | echo "\t\t--sonprocess_nbr=num: number of son processes to launch\n"; 36 | echo "\t\t--itemtype=string: type of item to search\n"; 37 | echo "\t\t--record_type=string: type of record ('error' or 'normal')\n"; 38 | echo "\t\t--nolog: use standard output rather than log file\n"; 39 | } 40 | 41 | 42 | function readargs () { 43 | global $itemtype, $sonprocess_nbr, $record_type, $log; 44 | 45 | for ($i=1; $i<$_SERVER["argc"]; $i++) { 46 | $it = explode("=", $_SERVER["argv"][$i]); 47 | switch ($it[0]) { 48 | case '--itemtype' : 49 | $itemtype=$it[1]; 50 | break; 51 | 52 | case '--sonprocess_nbr' : 53 | $sonprocess_nbr=$it[1]; 54 | break; 55 | 56 | case '--record_type' : 57 | $record_type=$it[1]; 58 | break; 59 | 60 | case '--nolog' : 61 | fclose($log); 62 | $log=STDOUT; 63 | break; 64 | 65 | default : 66 | usage(); 67 | exit(1); 68 | } 69 | } 70 | } 71 | 72 | function exit_if_soft_lock() { 73 | 74 | if (file_exists(GLPI_LOCK_DIR."/printercounters.lock")) { 75 | echo "Software lock : script can't run !\n"; 76 | exit (1); 77 | } 78 | 79 | } 80 | 81 | 82 | function exit_if_already_running($pidfile) { 83 | 84 | // No pidfile, probably no daemon present 85 | if (!file_exists($pidfile)) { 86 | return 1; 87 | } 88 | $pid=intval(file_get_contents($pidfile)); 89 | 90 | // No pid, probably no daemon present 91 | if (!$pid || @pcntl_getpriority($pid)===false) { 92 | return 1; 93 | } 94 | exit (1); 95 | } 96 | 97 | 98 | function cleanup ($pidfile) { 99 | 100 | @unlink($pidfile); 101 | 102 | $dir=opendir(GLPI_LOCK_DIR); 103 | if ($dir) { 104 | while ($name=readdir($dir)) { 105 | if (strpos($name, "lock_entity")===0) { 106 | unlink(GLPI_LOCK_DIR."/".$name); 107 | } 108 | } 109 | } 110 | } 111 | 112 | 113 | if (!isset($_SERVER["argv"][0])) { 114 | header("HTTP/1.0 403 Forbidden"); 115 | die("403 Forbidden"); 116 | } 117 | ini_set("memory_limit", "-1"); 118 | ini_set("max_execution_time", "0"); 119 | 120 | chdir(dirname($_SERVER["argv"][0])); 121 | define ("GLPI_ROOT", realpath(dirname($_SERVER["argv"][0])."/../../..")); 122 | require GLPI_ROOT."/inc/based_config.php"; 123 | 124 | $processid = date("zHi"); 125 | $itemtype = "Printer"; 126 | $record_type = 'normal'; 127 | $sonprocess_nbr = 2; 128 | 129 | if (function_exists("sys_get_temp_dir")) { 130 | // PHP > 5.2.x 131 | $pidfile = sys_get_temp_dir()."/printercounters_fullsync.pid"; 132 | } else if (DIRECTORY_SEPARATOR=='/') { 133 | // Unix/Linux 134 | $pidfile = "/tmp/printercounters_fullsync.pid"; 135 | } else { 136 | // Windows 137 | $pidfile = GLPI_LOG_DIR . "/printercounters_fullsync.pid"; 138 | } 139 | $logfilename = GLPI_LOG_DIR."/printercounters_fullsync.log"; 140 | 141 | if (!is_writable(GLPI_LOCK_DIR)) { 142 | echo "\tERROR : " .GLPI_LOCK_DIR. " not writable\n"; 143 | echo "\trun script as 'apache' user\n"; 144 | exit (1); 145 | } 146 | $log=fopen($logfilename, "at"); 147 | readargs(); 148 | 149 | exit_if_soft_lock(); 150 | exit_if_already_running($pidfile); 151 | cleanup($pidfile); 152 | 153 | //Only available with PHP5 or later 154 | file_put_contents($pidfile, getmypid()); 155 | fwrite($log, date("r") . " " . $_SERVER["argv"][0] . " started\n"); 156 | 157 | if (function_exists("pcntl_fork")) { 158 | // Unix/Linux 159 | $pids=[]; 160 | for ($i=0; $i<$sonprocess_nbr;) { 161 | $i++; 162 | $pid=pcntl_fork(); 163 | if ($pid == -1) { 164 | fwrite ($log, "Could not fork\n"); 165 | 166 | } else if ($pid) { 167 | fwrite ($log, "$pid Started\n"); 168 | file_put_contents($pidfile, ";".$i.'$$$'.$pid, FILE_APPEND); 169 | $pids[$pid]=1; 170 | 171 | } else { 172 | $cmd="php -q -d -f printercounters_fullsync.php --record_type=$record_type --sonprocess_nbr=$sonprocess_nbr ". 173 | " --sonprocess_id=$i --itemtype=$itemtype --process_id=$processid"; 174 | 175 | $out=[]; 176 | exec($cmd, $out, $ret); 177 | foreach ($out as $line) { 178 | fwrite ($log, $line."\n"); 179 | } 180 | exit($ret); 181 | } 182 | } 183 | $status=0; 184 | while (count($pids)) { 185 | $pid=pcntl_wait($status); 186 | if ($pid<0) { 187 | fwrite ($log, "Cound not wait\n"); 188 | exit (1); 189 | } else { 190 | unset($pids[$pid]); 191 | fwrite ($log, "$pid ended, waiting for " . count($pids) . " running son process\n"); 192 | } 193 | } 194 | } else { 195 | // Windows - No fork, so Only one process :( 196 | $cmd="php -q -d -f printercounters_fullsync.php --record_type=$record_type --sonprocess_nbr=1" 197 | . " --sonprocess_id=1 --itemtype=$itemtype --process_id=$processid"; 198 | 199 | $out=[]; 200 | exec($cmd, $out, $ret); 201 | foreach ($out as $line) { 202 | fwrite ($log, $line."\n"); 203 | } 204 | } 205 | 206 | cleanup($pidfile); 207 | fwrite ($log, date("r") . " " . $_SERVER["argv"][0] . " ended\n\n"); 208 | 209 | -------------------------------------------------------------------------------- /setup.php: -------------------------------------------------------------------------------- 1 | . 27 | -------------------------------------------------------------------------- 28 | */ 29 | 30 | define('PLUGIN_PRINTERCOUNTERS_VERSION', '2.0.2'); 31 | 32 | if (!defined("PLUGIN_PRINTERCOUNTERS_DIR")) { 33 | define("PLUGIN_PRINTERCOUNTERS_DIR", Plugin::getPhpDir("printercounters")); 34 | define("PLUGIN_PRINTERCOUNTERS_NOTFULL_DIR", Plugin::getPhpDir("printercounters",false)); 35 | define("PLUGIN_PRINTERCOUNTERS_WEBDIR", Plugin::getWebDir("printercounters")); 36 | define("PLUGIN_PRINTERCOUNTERS_NOTFULL_WEBDIR", Plugin::getWebDir("printercounters",false)); 37 | } 38 | 39 | // Init the hooks of the plugins -Needed 40 | function plugin_init_printercounters() { 41 | global $PLUGIN_HOOKS, $CFG_GLPI; 42 | 43 | $PLUGIN_HOOKS['csrf_compliant']['printercounters'] = true; 44 | $PLUGIN_HOOKS['change_profile']['printercounters'] = ['PluginPrintercountersProfile', 'changeProfile']; 45 | 46 | if (isset($_SESSION['glpiactiveprofile']['interface']) 47 | && $_SESSION['glpiactiveprofile']['interface'] == 'central') { 48 | $PLUGIN_HOOKS['add_css']['printercounters'] = ['printercounters.css']; 49 | $PLUGIN_HOOKS['add_javascript']['printercounters'][] = 'printercounters.js'; 50 | $PLUGIN_HOOKS['javascript']['printercounters'][] = PLUGIN_PRINTERCOUNTERS_NOTFULL_DIR.'/printercounters.js'; 51 | } 52 | if (Session::getLoginUserID()) { 53 | if (class_exists('PluginPrintercountersItem_Recordmodel')) { 54 | foreach (PluginPrintercountersItem_Recordmodel::$types as $item) { 55 | if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], strtolower($item)) !== false) { 56 | $PLUGIN_HOOKS['add_javascript']['printercounters'][] = 'printercounters_load_scripts.js.php'; 57 | } 58 | } 59 | } 60 | 61 | // Add tabs 62 | Plugin::registerClass('PluginPrintercountersProfile', ['addtabon' => 'Profile']); 63 | Plugin::registerClass('PluginPrintercountersCountertype_Recordmodel', ['addtabon' => 'PluginPrintercountersRecordmodel']); 64 | Plugin::registerClass('PluginPrintercountersItem_Recordmodel', ['addtabon' => 'PluginPrintercountersRecordmodel']); 65 | Plugin::registerClass('PluginPrintercountersSysdescr', ['addtabon' => 'PluginPrintercountersRecordmodel']); 66 | Plugin::registerClass('PluginPrintercountersPagecost', ['addtabon' => 'PluginPrintercountersBillingmodel']); 67 | Plugin::registerClass('PluginPrintercountersItem_Billingmodel', ['addtabon' => 'PluginPrintercountersBillingmodel']); 68 | Plugin::registerClass('PluginPrintercountersItem_Ticket', ['addtabon' => 'PluginPrintercountersConfig']); 69 | Plugin::registerClass('PluginPrintercountersProcess', ['addtabon' => 'PluginPrintercountersConfig']); 70 | Plugin::registerClass('PluginPrintercountersAdditional_data', ['notificationtemplates_types' => true]); 71 | 72 | if (Session::haveRight("plugin_printercounters", READ) && class_exists('PluginPrintercountersProfile')) { 73 | Plugin::registerClass('PluginPrintercountersItem_Recordmodel', ['addtabon' => 'Printer']); 74 | Plugin::registerClass('PluginPrintercountersItem_Billingmodel', ['addtabon' => 'Printer']); 75 | 76 | $PLUGIN_HOOKS['use_massive_action']['printercounters'] = 1; 77 | 78 | // Injection 79 | $PLUGIN_HOOKS['plugin_datainjection_populate']['printercounters'] = 'plugin_datainjection_populate_printercounters'; 80 | 81 | $PLUGIN_HOOKS['menu_toadd']['printercounters'] = ['tools' => 'PluginPrintercountersMenu']; 82 | // $PLUGIN_HOOKS['helpdesk_menu_entry']['printercounters'] = true; 83 | if (Session::haveRight("plugin_printercounters", UPDATE)) { 84 | $PLUGIN_HOOKS['config_page']['printercounters'] = 'front/config.form.php'; 85 | } 86 | } 87 | 88 | $PLUGIN_HOOKS['post_init']['printercounters'] = 'plugin_printercounters_postinit'; 89 | 90 | // Pre item purge 91 | $PLUGIN_HOOKS['pre_item_purge']['printercounters'] = [ 92 | 'PluginPrintercountersRecordmodel' => 'plugin_pre_item_purge_printercounters', 93 | 'PluginPrintercountersBillingmodel' => 'plugin_pre_item_purge_printercounters', 94 | 'PluginPrintercountersCountertype' => 'plugin_pre_item_purge_printercounters', 95 | 'PluginPrintercountersItem_Recordmodel' => 'plugin_pre_item_purge_printercounters', 96 | 'PluginPrintercountersRecord' => 'plugin_pre_item_purge_printercounters', 97 | 'PluginPrintercountersCountertype_Recordmodel' => 'plugin_pre_item_purge_printercounters', 98 | 'Printer' => 'plugin_pre_item_purge_printercounters', 99 | 'Ticket' => 'plugin_pre_item_purge_printercounters', 100 | 'Entity' => 'plugin_pre_item_purge_printercounters']; 101 | 102 | // Post item purge 103 | $PLUGIN_HOOKS['item_purge']['printercounters'] = [ 104 | 'PluginPrintercountersCounter' => 'plugin_item_purge_printercounters']; 105 | 106 | // Pre item delete 107 | $PLUGIN_HOOKS['pre_item_delete']['printercounters'] = [ 108 | 'Printer' => 'plugin_item_delete_printercounters']; 109 | 110 | // Item transfer 111 | $PLUGIN_HOOKS['item_transfer']['printercounters'] = 'plugin_item_transfer_printercounters'; 112 | } 113 | } 114 | 115 | // Get the name and the version of the plugin - Needed 116 | function plugin_version_printercounters() { 117 | return [ 118 | 'name' => __('Printer counters', 'printercounters'), 119 | 'version' => PLUGIN_PRINTERCOUNTERS_VERSION, 120 | 'author' => "Infotel", 121 | 'license' => 'GPLv2+', 122 | 'homepage' => 'https://github.com/InfotelGLPI/printercounters', 123 | 'requirements' => [ 124 | 'glpi' => [ 125 | 'min' => '10.0', 126 | 'max' => '11.0', 127 | 'dev' => false 128 | ], 129 | 'php' => [ 130 | 'exts' => ['snmp'], 131 | ] 132 | ] 133 | ]; 134 | } 135 | 136 | --------------------------------------------------------------------------------