Skip to content

Commit f0cd62a

Browse files
SebSepttrasher
authored andcommitted
Make document filepath and sha1sum readonly
1 parent 6ae7fa3 commit f0cd62a

3 files changed

Lines changed: 94 additions & 13 deletions

File tree

src/Document.php

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,7 @@ public function prepareInputForAdd($input)
224224
{
225225
global $CFG_GLPI;
226226

227-
// security (don't accept filename from $_REQUEST)
228-
if (array_key_exists('filename', $_REQUEST)) {
229-
unset($input['filename']);
230-
}
227+
$input = $this->filterFields($input);
231228

232229
// current_filename is not necessary (item is new, current_filename should not exist
233230
// but used for display can lead to wrong file deletion in moveDocument() and moveUploadedDocument()
@@ -252,9 +249,6 @@ public function prepareInputForAdd($input)
252249
} elseif (!empty($input["upload_file"])) {
253250
// Move doc from upload dir
254251
$upload_ok = $this->moveUploadedDocument($input, $input["upload_file"]);
255-
} elseif (isset($input['filepath']) && file_exists(GLPI_DOC_DIR . '/' . $input['filepath'])) {
256-
// Document is created using an existing document file
257-
$upload_ok = true;
258252
}
259253

260254
// Tag
@@ -340,10 +334,7 @@ public function post_addItem()
340334

341335
public function prepareInputForUpdate($input)
342336
{
343-
// security (don't accept filename from $_REQUEST)
344-
if (array_key_exists('filename', $_REQUEST)) {
345-
unset($input['filename']);
346-
}
337+
$input = $this->filterFields($input);
347338

348339
if (isset($input['current_filepath'])) {
349340
// Always use the values stored in DB to prevent arbitrary file deletion
@@ -1809,4 +1800,21 @@ private function canViewFileFromForm(string $itemtype, int $items_id): bool
18091800
);
18101801
return $control_manager->canAnswerForm($form, $parameters);
18111802
}
1803+
1804+
/**
1805+
* Remove $input fields that should not be provided by user input
1806+
*
1807+
* @param array<string, mixed> $input
1808+
* @return array<string, mixed>
1809+
*/
1810+
private function filterFields(array $input): array
1811+
{
1812+
// security (don't accept filename from $_REQUEST)
1813+
if (array_key_exists('filename', $_REQUEST)) {
1814+
unset($input['filename']);
1815+
}
1816+
1817+
$blacklisted = ['filepath', 'sha1sum'];
1818+
return array_filter($input, static fn($v, $k) => !in_array($k, $blacklisted), ARRAY_FILTER_USE_BOTH);
1819+
}
18121820
}

tests/functional/DocumentTest.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,77 @@ public function testPrepareInputForAdd()
189189
$this->assertCount(7, $prepare);
190190
}
191191

192+
public function testPrepareInputForAddIgnoreBlacklistedFields(): void
193+
{
194+
$_ignored = 'should_be_ignored';
195+
$input = ['name' => 'legit name', 'filepath' => $_ignored, 'sha1sum' => $_ignored];
196+
$prepare = (new \Document())->prepareInputForAdd($input);
197+
198+
$this->assertArrayNotHasKey('filepath', $prepare);
199+
$this->assertArrayNotHasKey('sha1sum', $prepare);
200+
}
201+
202+
/**
203+
* Ensure filepath and sha1sum are not updated by prepareInputForUpdate, even if they are present in the input.
204+
*/
205+
public function testPrepareInputForUpdateIgnoreBlacklistedFields(): void
206+
{
207+
$_ignored = 'should_be_ignored';
208+
$input = ['name' => 'legit name', 'filepath' => $_ignored, 'sha1sum' => $_ignored];
209+
210+
$doc_id = (new \Document())->add(['name' => 'le document']);
211+
$prepare = (new \Document())->prepareInputForUpdate($input + ['id' => $doc_id]);
212+
213+
$this->assertArrayNotHasKey('filepath', $prepare);
214+
$this->assertArrayNotHasKey('sha1sum', $prepare);
215+
}
216+
217+
public function testPrepareInputForUpdateIgnoreBlacklistedFieldsWithUpload(): void
218+
{
219+
$this->login();
220+
221+
// Create a document with a mocked file upload
222+
$mdoc = $this->getMockBuilder(\Document::class)
223+
->onlyMethods(['moveUploadedDocument'])
224+
->getMock();
225+
$mdoc->method('moveUploadedDocument')->willReturn(true);
226+
227+
$doc_id = $mdoc->add([
228+
'name' => 'test document with upload',
229+
'upload_file' => 'filename.txt',
230+
]);
231+
$this->assertGreaterThan(0, $doc_id);
232+
233+
// Read back the stored values right after the upload-add
234+
$doc = new \Document();
235+
$this->assertTrue($doc->getFromDB($doc_id));
236+
$original_filepath = $doc->fields['filepath'];
237+
$original_sha1sum = $doc->fields['sha1sum'];
238+
239+
// Attempt to update the document with blacklisted fields
240+
$_fake = 'should_be_ignored';
241+
$doc->update([
242+
'id' => $doc_id,
243+
'name' => 'updated name',
244+
'filepath' => $_fake,
245+
'sha1sum' => $_fake,
246+
]);
247+
248+
// Re-read from DB and verify blacklisted fields were NOT overwritten
249+
$doc_after = new \Document();
250+
$this->assertTrue($doc_after->getFromDB($doc_id));
251+
252+
$this->assertNotSame($_fake, $doc_after->fields['filepath']);
253+
$this->assertNotSame($_fake, $doc_after->fields['sha1sum']);
254+
255+
// Values must be identical to what they were right after the upload
256+
$this->assertSame($original_filepath, $doc_after->fields['filepath']);
257+
$this->assertSame($original_sha1sum, $doc_after->fields['sha1sum']);
258+
259+
// Non-blacklisted field must have been updated correctly
260+
$this->assertSame('updated name', $doc_after->fields['name']);
261+
}
262+
192263
/** Cannot work without a real document uploaded.
193264
* Mock would be a solution but GLPI will try to use
194265
* a table based on mocked class name, this is wrong.

tests/imap/MailCollectorTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,23 +1565,25 @@ public function testCleanContent(
15651565

15661566
public function testBlacklistedDocumentNotImportedFromMail()
15671567
{
1568+
global $DB;
1569+
15681570
// Use existing test fixture files
15691571
$png_file = GLPI_ROOT . '/tests/fixtures/uploads/foo.png';
15701572

15711573
// Calculate SHA1 from existing files
15721574
$png_sha1 = sha1_file($png_file);
15731575

15741576
// Create blacklisted documents with matching SHA1
1575-
$this->createItem(
1577+
$doc = $this->createItem(
15761578
\Document::class,
15771579
[
15781580
'entities_id' => 0,
15791581
'name' => 'Blacklisted PNG Document',
15801582
'filename' => 'blacklisted.png',
1581-
'sha1sum' => $png_sha1,
15821583
'is_blacklisted' => 1,
15831584
]
15841585
);
1586+
$this->assertTrue($DB->update(\Document::getTable(), ['sha1sum' => $png_sha1], ['id' => $doc->getID()]));
15851587

15861588
// Test 1: Auto-import (mail collector) should be blocked
15871589
\Safe\copy($png_file, GLPI_TMP_DIR . '/foo.png');

0 commit comments

Comments
 (0)