Skip to content

Commit 68db0ff

Browse files
committed
feat: tool to repair escaping problem in some tickets
1 parent 4c28a09 commit 68db0ff

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
<?php
2+
/**
3+
* ---------------------------------------------------------------------
4+
* Formcreator is a plugin which allows creation of custom forms of
5+
* easy access.
6+
* ---------------------------------------------------------------------
7+
* LICENSE
8+
*
9+
* This file is part of Formcreator.
10+
*
11+
* Formcreator is free software; you can redistribute it and/or modify
12+
* it under the terms of the GNU General Public License as published by
13+
* the Free Software Foundation; either version 2 of the License, or
14+
* (at your option) any later version.
15+
*
16+
* Formcreator is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU General Public License
22+
* along with Formcreator. If not, see <http://www.gnu.org/licenses/>.
23+
* ---------------------------------------------------------------------
24+
* @copyright Copyright © 2011 - 2021 Teclib'
25+
* @license http://www.gnu.org/licenses/gpl.txt GPLv3+
26+
* @link https://github.com/pluginsGLPI/formcreator/
27+
* @link https://pluginsglpi.github.io/formcreator/
28+
* @link http://plugins.glpi-project.org/#/plugin/formcreator
29+
* ---------------------------------------------------------------------
30+
*/
31+
32+
namespace GlpiPlugin\Formcreator\Command;
33+
34+
use Symfony\Component\Console\Command\Command;
35+
use Symfony\Component\Console\Input\InputInterface;
36+
use Symfony\Component\Console\Output\OutputInterface;
37+
use Ticket;
38+
use Item_Ticket;
39+
use PluginFormcreatorFormAnswer;
40+
use Glpi\Toolbox\Sanitizer;
41+
42+
class CleanTicketsCommand extends Command
43+
{
44+
protected function configure() {
45+
$this
46+
->setName('glpi:plugins:formcreator:clean_tickets')
47+
->setDescription("Clean Tickets having visible HTML tags in their content");
48+
}
49+
50+
protected function execute(InputInterface $input, OutputInterface $output) {
51+
$output->write("<info>-> Search tickets to clean...</info>");
52+
$output->writeln("");
53+
54+
$this->fixBadForm_1($input, $output);
55+
$this->fixBadForm_2($input, $output);
56+
57+
$output->writeln('<info>Done.</info>');
58+
return 0;
59+
}
60+
61+
/**
62+
* fix HTML tags double encoded
63+
* <p> => &lt;p&gt; => &#38;lt;p&#38;gt;
64+
*
65+
* @param InputInterface $input
66+
* @param OutputInterface $output
67+
* @return void
68+
*/
69+
protected function fixBadForm_1(InputInterface $input, OutputInterface $output) {
70+
global $DB;
71+
72+
// Search tickets having HTML tags in content in the following form
73+
// &#38;lt;p&#38;gt;Hello world&#38;lt;/p&#38;gt;
74+
// Hello world is between <p> and </p>, but with wrong escaping
75+
$itemTicketTable = Item_Ticket::getTable();
76+
$ticketTable = Ticket::getTable();
77+
$pattern = '&#38;lt;';
78+
// $pattern = str_replace(';', '\\;', $pattern);
79+
$tickets = $DB->request([
80+
'SELECT' => [$ticketTable => [Ticket::getIndexName(), 'content']],
81+
'FROM' => $ticketTable,
82+
'INNER JOIN' => [
83+
$itemTicketTable => [
84+
'FKEY' => [
85+
$ticketTable => Ticket::getIndexName(),
86+
$itemTicketTable => Ticket::getForeignKeyField(),
87+
],
88+
'AND' => [
89+
"$itemTicketTable.itemtype" => PluginFormcreatorFormAnswer::getType(),
90+
]
91+
],
92+
],
93+
'WHERE' => [
94+
"$ticketTable.content" => ['LIKE', '%' . $pattern . '%'], // Matches bad encoding for '<'
95+
],
96+
]);
97+
98+
$count = $tickets->count();
99+
if ($count < 1) {
100+
$output->writeln('<info>-> No ticket to fix.</info>');
101+
$output->writeln("");
102+
return 0;
103+
}
104+
105+
$output->write("<info>-> Found $count tickets to clean</info>");
106+
$output->writeln("");
107+
$output->write("<info>-> Cleaning tickets...</info>");
108+
$output->writeln("");
109+
foreach ($tickets as $row) {
110+
$pattern = [
111+
'/&#38;lt;([a-z0-9]+?)&#38;gt;/',
112+
'/&#38;lt;(\/[a-z0-9]+?)&#38;gt;/',
113+
];
114+
$replace = [
115+
'&#60;$1&#62;',
116+
'&#60;$1&#62;',
117+
];
118+
$row['content'] = preg_replace($pattern, $replace, $row['content']);
119+
// Direct write to the table to avoid alteration of other fields
120+
$DB->update(
121+
$ticketTable,
122+
[
123+
'content' => $DB->escape($row['content'])
124+
],
125+
[
126+
'id' => $row['id'],
127+
]
128+
);
129+
}
130+
}
131+
132+
/**
133+
* remove HTML tag <br />
134+
*
135+
* @param InputInterface $input
136+
* @param OutputInterface $output
137+
* @return void
138+
*/
139+
protected function fixBadForm_2(InputInterface $input, OutputInterface $output) {
140+
global $DB;
141+
142+
// Search tickets having HTML tags <br />
143+
$itemTicketTable = Item_Ticket::getTable();
144+
$ticketTable = Ticket::getTable();
145+
$pattern = 'br /';
146+
$tickets = $DB->request([
147+
'SELECT' => [$ticketTable => [Ticket::getIndexName(), 'content']],
148+
'FROM' => $ticketTable,
149+
'INNER JOIN' => [
150+
$itemTicketTable => [
151+
'FKEY' => [
152+
$ticketTable => Ticket::getIndexName(),
153+
$itemTicketTable => Ticket::getForeignKeyField(),
154+
],
155+
'AND' => [
156+
"$itemTicketTable.itemtype" => PluginFormcreatorFormAnswer::getType(),
157+
]
158+
],
159+
],
160+
'WHERE' => [
161+
"$ticketTable.content" => ['LIKE', '%' . $pattern . '%'], // Matches bad encoding for '<'
162+
],
163+
]);
164+
165+
$count = $tickets->count();
166+
if ($count < 1) {
167+
$output->writeln('<info>-> No ticket to fix.</info>');
168+
$output->writeln("");
169+
return 0;
170+
}
171+
172+
$output->write("<info>-> Found $count tickets to clean</info>");
173+
$output->writeln("");
174+
$output->write("<info>-> Cleaning tickets...</info>");
175+
$output->writeln("");
176+
foreach ($tickets as $row) {
177+
$pattern = [
178+
'<br />',
179+
];
180+
$replace = [
181+
'&lt;div&gt;&lt;/div&gt;',
182+
];
183+
$row['content'] = str_replace($pattern, $replace, $row['content']);
184+
// Direct write to the table to avoid alteration of other fields
185+
$DB->update(
186+
$ticketTable,
187+
[
188+
'content' => $DB->escape($row['content'])
189+
],
190+
[
191+
'id' => $row['id'],
192+
]
193+
);
194+
}
195+
}
196+
}

0 commit comments

Comments
 (0)