|
|
|
@ -18,14 +18,24 @@ class UploadedFileTest extends TestCase
|
|
|
|
if (file_exists('tmp_name')) {
|
|
|
|
if (file_exists('tmp_name')) {
|
|
|
|
unlink('tmp_name');
|
|
|
|
unlink('tmp_name');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (file_exists('existing.txt')) {
|
|
|
|
|
|
|
|
unlink('existing.txt');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (file_exists('real_file')) {
|
|
|
|
|
|
|
|
unlink('real_file');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// not found with file_exists...just delete it brute force
|
|
|
|
|
|
|
|
@unlink('tmp_symlink');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function testMoveToSuccess(): void
|
|
|
|
public function testMoveToFalseSuccess(): void
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// This test would have passed in the real world but we can't actually force a post request in unit tests
|
|
|
|
file_put_contents('tmp_name', 'test');
|
|
|
|
file_put_contents('tmp_name', 'test');
|
|
|
|
$uploadedFile = new UploadedFile('file.txt', 'text/plain', 4, 'tmp_name', UPLOAD_ERR_OK);
|
|
|
|
$uploadedFile = new UploadedFile('file.txt', 'text/plain', 4, 'tmp_name', UPLOAD_ERR_OK, true);
|
|
|
|
|
|
|
|
$this->expectExceptionMessage('Cannot move uploaded file');
|
|
|
|
$uploadedFile->moveTo('file.txt');
|
|
|
|
$uploadedFile->moveTo('file.txt');
|
|
|
|
$this->assertFileExists('file.txt');
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function getFileErrorMessageTests(): array
|
|
|
|
public function getFileErrorMessageTests(): array
|
|
|
|
@ -53,4 +63,62 @@ class UploadedFileTest extends TestCase
|
|
|
|
$this->expectExceptionMessage($message);
|
|
|
|
$this->expectExceptionMessage($message);
|
|
|
|
$uploadedFile->moveTo('file.txt');
|
|
|
|
$uploadedFile->moveTo('file.txt');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function testMoveToBadLocation(): void
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file_put_contents('tmp_name', 'test');
|
|
|
|
|
|
|
|
$uploadedFile = new UploadedFile('file.txt', 'text/plain', 4, 'tmp_name', UPLOAD_ERR_OK, true);
|
|
|
|
|
|
|
|
$this->expectExceptionMessage('Target directory is not writable');
|
|
|
|
|
|
|
|
$uploadedFile->moveTo('/root/file.txt');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function testMoveToSuccessNonPost(): void
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file_put_contents('tmp_name', 'test');
|
|
|
|
|
|
|
|
$uploadedFile = new UploadedFile('file.txt', 'text/plain', 4, 'tmp_name', UPLOAD_ERR_OK, false);
|
|
|
|
|
|
|
|
$uploadedFile->moveTo('file.txt');
|
|
|
|
|
|
|
|
$this->assertFileExists('file.txt');
|
|
|
|
|
|
|
|
$this->assertEquals('test', file_get_contents('file.txt'));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function testMoveToPathTraversal(): void
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file_put_contents('tmp_name', 'test');
|
|
|
|
|
|
|
|
$uploadedFile = new UploadedFile('file.txt', 'text/plain', 4, 'tmp_name', UPLOAD_ERR_OK, false);
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
|
|
|
$this->expectExceptionMessage('Invalid target path: contains directory traversal');
|
|
|
|
|
|
|
|
$uploadedFile->moveTo('../file.txt');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function testMoveToAbsolutePath(): void
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file_put_contents('tmp_name', 'test');
|
|
|
|
|
|
|
|
$uploadedFile = new UploadedFile('file.txt', 'text/plain', 4, 'tmp_name', UPLOAD_ERR_OK, false);
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
|
|
|
$this->expectExceptionMessage('Invalid target path: absolute paths not allowed');
|
|
|
|
|
|
|
|
$uploadedFile->moveTo('/tmp/file.txt');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function testMoveToOverwrite(): void
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file_put_contents('tmp_name', 'test');
|
|
|
|
|
|
|
|
file_put_contents('existing.txt', 'existing');
|
|
|
|
|
|
|
|
$uploadedFile = new UploadedFile('file.txt', 'text/plain', 4, 'tmp_name', UPLOAD_ERR_OK, false);
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
|
|
|
$this->expectExceptionMessage('Target file already exists');
|
|
|
|
|
|
|
|
$uploadedFile->moveTo('existing.txt');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function testMoveToSymlinkNonPost(): void
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file_put_contents('real_file', 'test');
|
|
|
|
|
|
|
|
if (file_exists('tmp_symlink')) {
|
|
|
|
|
|
|
|
unlink('tmp_symlink');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
symlink('real_file', 'tmp_symlink');
|
|
|
|
|
|
|
|
$uploadedFile = new UploadedFile('file.txt', 'text/plain', 4, 'tmp_symlink', UPLOAD_ERR_OK, false);
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
|
|
|
$this->expectExceptionMessage('Invalid temp file: symlink detected');
|
|
|
|
|
|
|
|
$uploadedFile->moveTo('file.txt');
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|