/vendor/symfony/validator/Symfony/Component/Validator/Constraints/FileValidator.php

https://bitbucket.org/prauscher/att · PHP · 158 lines · 115 code · 27 blank · 16 comment · 21 complexity · cdaa1a4e542c46599c08b378028b85ad MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Validator\Constraints;
  11. use Symfony\Component\Validator\Constraint;
  12. use Symfony\Component\Validator\ConstraintValidator;
  13. use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
  14. use Symfony\Component\Validator\Exception\UnexpectedTypeException;
  15. use Symfony\Component\HttpFoundation\File\File as FileObject;
  16. use Symfony\Component\HttpFoundation\File\UploadedFile;
  17. /**
  18. * @author Bernhard Schussek <bschussek@gmail.com>
  19. *
  20. * @api
  21. */
  22. class FileValidator extends ConstraintValidator
  23. {
  24. /**
  25. * {@inheritDoc}
  26. */
  27. public function validate($value, Constraint $constraint)
  28. {
  29. if (null === $value || '' === $value) {
  30. return;
  31. }
  32. if ($value instanceof UploadedFile && !$value->isValid()) {
  33. switch ($value->getError()) {
  34. case UPLOAD_ERR_INI_SIZE:
  35. $maxSize = UploadedFile::getMaxFilesize();
  36. $maxSize = $constraint->maxSize ? min($maxSize, $constraint->maxSize) : $maxSize;
  37. $this->context->addViolation($constraint->uploadIniSizeErrorMessage, array(
  38. '{{ limit }}' => $maxSize,
  39. '{{ suffix }}' => 'bytes',
  40. ));
  41. return;
  42. case UPLOAD_ERR_FORM_SIZE:
  43. $this->context->addViolation($constraint->uploadFormSizeErrorMessage);
  44. return;
  45. case UPLOAD_ERR_PARTIAL:
  46. $this->context->addViolation($constraint->uploadPartialErrorMessage);
  47. return;
  48. case UPLOAD_ERR_NO_FILE:
  49. $this->context->addViolation($constraint->uploadNoFileErrorMessage);
  50. return;
  51. case UPLOAD_ERR_NO_TMP_DIR:
  52. $this->context->addViolation($constraint->uploadNoTmpDirErrorMessage);
  53. return;
  54. case UPLOAD_ERR_CANT_WRITE:
  55. $this->context->addViolation($constraint->uploadCantWriteErrorMessage);
  56. return;
  57. case UPLOAD_ERR_EXTENSION:
  58. $this->context->addViolation($constraint->uploadExtensionErrorMessage);
  59. return;
  60. default:
  61. $this->context->addViolation($constraint->uploadErrorMessage);
  62. return;
  63. }
  64. }
  65. if (!is_scalar($value) && !$value instanceof FileObject && !(is_object($value) && method_exists($value, '__toString'))) {
  66. throw new UnexpectedTypeException($value, 'string');
  67. }
  68. $path = $value instanceof FileObject ? $value->getPathname() : (string) $value;
  69. if (!is_file($path)) {
  70. $this->context->addViolation($constraint->notFoundMessage, array('{{ file }}' => $path));
  71. return;
  72. }
  73. if (!is_readable($path)) {
  74. $this->context->addViolation($constraint->notReadableMessage, array('{{ file }}' => $path));
  75. return;
  76. }
  77. if ($constraint->maxSize) {
  78. if (ctype_digit((string) $constraint->maxSize)) {
  79. $size = filesize($path);
  80. $limit = $constraint->maxSize;
  81. $suffix = 'bytes';
  82. } elseif (preg_match('/^(\d+)k$/', $constraint->maxSize, $matches)) {
  83. $size = round(filesize($path) / 1000, 2);
  84. $limit = $matches[1];
  85. $suffix = 'kB';
  86. } elseif (preg_match('/^(\d+)M$/', $constraint->maxSize, $matches)) {
  87. $size = round(filesize($path) / 1000000, 2);
  88. $limit = $matches[1];
  89. $suffix = 'MB';
  90. } else {
  91. throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize));
  92. }
  93. if ($size > $limit) {
  94. $this->context->addViolation($constraint->maxSizeMessage, array(
  95. '{{ size }}' => $size,
  96. '{{ limit }}' => $limit,
  97. '{{ suffix }}' => $suffix,
  98. '{{ file }}' => $path,
  99. ));
  100. return;
  101. }
  102. }
  103. if ($constraint->mimeTypes) {
  104. if (!$value instanceof FileObject) {
  105. $value = new FileObject($value);
  106. }
  107. $mimeTypes = (array) $constraint->mimeTypes;
  108. $mime = $value->getMimeType();
  109. $valid = false;
  110. foreach ($mimeTypes as $mimeType) {
  111. if ($mimeType === $mime) {
  112. $valid = true;
  113. break;
  114. }
  115. if ($discrete = strstr($mimeType, '/*', true)) {
  116. if (strstr($mime, '/', true) === $discrete) {
  117. $valid = true;
  118. break;
  119. }
  120. }
  121. }
  122. if (false === $valid) {
  123. $this->context->addViolation($constraint->mimeTypesMessage, array(
  124. '{{ type }}' => '"'.$mime.'"',
  125. '{{ types }}' => '"'.implode('", "', $mimeTypes) .'"',
  126. '{{ file }}' => $path,
  127. ));
  128. }
  129. }
  130. }
  131. }