image_to_media_swapper-2.x-dev/tests/src/Kernel/ContentVerificationServiceTest.php

tests/src/Kernel/ContentVerificationServiceTest.php
<?php

namespace Drupal\Tests\image_to_media_swapper\Kernel;

use Drupal\Core\File\FileSystemInterface;
use Drupal\KernelTests\KernelTestBase;
use Drupal\file\Entity\File;

/**
 * Tests the content verification service.
 *
 * @group image_to_media_swapper
 */
class ContentVerificationServiceTest extends KernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'system',
    'user',
    'file',
    'field',
    'image_to_media_swapper',
    'media',
    'filter',
  ];

  /**
   * The content verification service.
   *
   * @var \Drupal\image_to_media_swapper\ContentVerificationService
   */
  protected $contentVerificationService;

  /**
   * The file system service.
   *
   * @var \Drupal\Core\File\FileSystemInterface
   */
  protected $fileSystem;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->installConfig(['system']);
    $this->installEntitySchema('file');
    $this->installSchema('file', ['file_usage']);

    // Get the service.
    $this->contentVerificationService = $this->container->get('image_to_media_swapper.content_verification');
    $this->fileSystem = $this->container->get('file_system');
    $directory = 'public://';
    // Ensure the files directory exists.
    $this->fileSystem->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY);
  }

  /**
   * Creates a test file with the given MIME type and content.
   *
   * @param string $filename
   *   The filename.
   * @param string $mime_type
   *   The MIME type.
   * @param string $content
   *   The file content.
   *
   * @return string
   *   The file URI.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  protected function createTestFile(string $filename, string $mime_type, string $content): string {
    $uri = 'public://' . $filename;
    file_put_contents($uri, $content);

    // Create a file entity.
    $file = File::create([
      'uri' => $uri,
      'filename' => $filename,
      'filemime' => $mime_type,
      'status' => 1,
    ]);
    $file->save();

    return $uri;
  }

  /**
   * Tests verification of valid image files.
   */
  public function testValidImageVerification(): void {
    // Create a simple PNG image with valid header.
    $png_header = hex2bin('89504e470d0a1a0a') . str_repeat('x', 100);
    $png_uri = $this->createTestFile('test.png', 'image/png', $png_header);

    // Verify the PNG file.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($png_uri), 'image/png');

    $this->assertTrue($result['verified'], 'PNG file should be verified');
    $this->assertEmpty($result['errors'], 'No errors should be reported for valid PNG');
  }

  /**
   * Tests verification of invalid image files.
   */
  public function testInvalidImageVerification(): void {
    // Create a text file with fake image extension.
    $fake_image = "This is not an image file";
    $fake_uri = $this->createTestFile('fake.jpg', 'image/jpeg', $fake_image);

    // Verify the fake image file.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($fake_uri), 'image/jpeg');

    $this->assertFalse($result['verified'], 'Fake image should not be verified');
    $this->assertNotEmpty($result['errors'], 'Errors should be reported for fake image');
  }

  /**
   * Tests verification of text files.
   */
  public function testTextFileVerification(): void {
    // Create a valid text file.
    $text_content = "This is a plain text file.\nIt contains normal text content.";
    $text_uri = $this->createTestFile('test.txt', 'text/plain', $text_content);

    // Verify the text file.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($text_uri), 'text/plain');

    $this->assertTrue($result['verified'], 'Text file should be verified');
  }

  /**
   * Tests verification of text files with binary content.
   */
  public function testBinaryAsTextVerification(): void {
    // Create a binary file with text extension.
    $binary_content = file_get_contents(__DIR__ . '/../../fixtures/binary_sample.bin');
    if (!$binary_content) {
      // If fixture file doesn't exist, create some binary content.
      $binary_content = '';
      for ($i = 0; $i < 100; $i++) {
        $binary_content .= chr(mt_rand(0, 31));
      }
    }

    $binary_uri = $this->createTestFile('binary.txt', 'text/plain', $binary_content);

    // Verify the binary file masquerading as text.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($binary_uri), 'text/plain');

    $this->assertFalse($result['verified'], 'Binary file with text extension should not be verified as text');
  }

  /**
   * Tests detection of malicious content in files.
   */
  public function testMaliciousContentDetection(): void {
    // Create an image file with embedded PHP code.
    $malicious_content = hex2bin('89504e470d0a1a0a') . "<?php system('ls -la'); ?>" . str_repeat('x', 50);
    $malicious_uri = $this->createTestFile('malicious.png', 'image/png', $malicious_content);

    // Verify the malicious file.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($malicious_uri), 'image/png');

    $this->assertFalse($result['verified'], 'Malicious file should not be verified');
    $this->assertNotEmpty($result['errors'], 'Errors should be reported for malicious file');

    // Create an SVG with embedded JavaScript (XSS vulnerability)
    $svg_with_js = '<?xml version="1.0" standalone="no"?>'
      . '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
      . '<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">'
      . '<script>alert("XSS")</script>'
      . '<circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />'
      . '</svg>';

    // Create the test file in the public directory.
    $svg_uri = $this->createTestFile('xss.svg', 'image/svg+xml', $svg_with_js);

    // Ensure the file was created successfully.
    $svg_path = $this->fileSystem->realpath($svg_uri);
    $this->assertFileExists($svg_path, 'SVG test file should exist');

    // Verify the SVG with JavaScript.
    $result = $this->contentVerificationService->verifyFileContent($svg_path, 'image/svg+xml');

    // Assertions.
    $this->assertFalse($result['verified'], 'SVG with JavaScript should not be verified');

    // Check for error message about script content.
    $error_string = implode(' ', $result['errors']);
    $this->assertStringContainsString('script', $error_string, 'Error should mention script content');
  }

  /**
   * Tests verification of mismatched MIME types.
   */
  public function testMimeMismatchDetection(): void {
    // Create a PNG with JPEG MIME type.
    $png_header = hex2bin('89504e470d0a1a0a') . str_repeat('x', 100);
    $mismatched_uri = $this->createTestFile('mismatch.jpg', 'image/jpeg', $png_header);

    // Verify the mismatched file.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($mismatched_uri), 'image/jpeg');

    // This is a subtle case - may or may not be verified depending on how
    // strict the check is. The test is checking that the actual_type is
    // detected and differs from declared type.
    $this->assertNotEmpty($result['actual_type'], 'Actual type should be detected');
    if ($result['actual_type'] !== 'image/jpeg') {
      $this->assertNotEquals('image/jpeg', $result['actual_type'], 'Actual type should differ from declared type');
    }
  }

  /**
   * Tests verification of PDF files.
   */
  public function testPdfVerification(): void {
    // Create a minimal valid PDF.
    $pdf_content = "%PDF-1.4\n1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R >>\nendobj\n4 0 obj\n<< /Length 22 >>\nstream\nBT /F1 12 Tf 100 700 Td (Test PDF) Tj ET\nendstream\nendobj\nxref\n0 5\n0000000000 65535 f\n0000000010 00000 n\n0000000060 00000 n\n0000000115 00000 n\n0000000200 00000 n\ntrailer << /Root 1 0 R /Size 5 >>\nstartxref\n270\n%%EOF";
    $pdf_uri = $this->createTestFile('test.pdf', 'application/pdf', $pdf_content);

    // Verify the PDF file.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($pdf_uri), 'application/pdf');

    $this->assertTrue($result['verified'], 'Valid PDF should be verified');
  }

  /**
   * Tests verification of XML files.
   */
  public function testXmlVerification(): void {
    // Create a valid XML file.
    $xml_content = '<?xml version="1.0" encoding="UTF-8"?><root><element attribute="value">Text content</element></root>';
    $xml_uri = $this->createTestFile('test.xml', 'application/xml', $xml_content);

    // Verify the XML file.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($xml_uri), 'application/xml');

    $this->assertTrue($result['verified'], 'Valid XML should be verified');

    // Create an XML with XXE vulnerability.
    $xxe_xml = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]><root>&xxe;</root>';
    $xxe_uri = $this->createTestFile('xxe.xml', 'application/xml', $xxe_xml);

    // Verify the XXE file.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($xxe_uri), 'application/xml');

    $this->assertFalse($result['verified'], 'XML with XXE should not be verified');
    $this->assertNotEmpty($result['errors'], 'Errors should be reported for XML with XXE');
  }

  /**
   * Tests handling of non-existent files.
   */
  public function testNonExistentFile(): void {
    $result = $this->contentVerificationService->verifyFileContent('/non/existent/file.txt', 'text/plain');

    $this->assertFalse($result['verified'], 'Non-existent file should not be verified');
    $this->assertStringContainsString('File does not exist', $result['errors'][0], 'Error should mention file does not exist');
  }

  /**
   * Tests the system handles empty files correctly.
   */
  public function testEmptyFile(): void {
    // Create an empty file.
    $empty_uri = $this->createTestFile('empty.txt', 'text/plain', ' ');

    // Verify the empty file.
    $result = $this->contentVerificationService->verifyFileContent($this->fileSystem->realpath($empty_uri), 'text/plain');

    // Empty files should still be validated as text files.
    $this->assertTrue($result['verified'], 'Empty text file should be verified as text');
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc