<?phpnamespace Plugin\ExtensionRestriction40\EventListener;use Eccube\Common\EccubeConfig;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpKernel\Event\FilterControllerEvent;use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;use Symfony\Component\HttpKernel\KernelEvents;use Symfony\Component\Routing\Generator\UrlGeneratorInterface;class FileUploadListener implements EventSubscriberInterface{ /** @var EccubeConfig */ private $eccubeConfig; /** @var UrlGeneratorInterface */ private $router; /** @var array */ private $errorFlg; public function __construct(EccubeConfig $eccubeConfig, UrlGeneratorInterface $router) { $this->eccubeConfig = $eccubeConfig; $this->router = $router; $this->errorFlg = false; } /** * イベントとコールバックメソッドの対応を定義 */ public static function getSubscribedEvents(): array { return [ KernelEvents::CONTROLLER => 'onExtensionRestriction', ]; } /** * アップロードされたファイルの拡張子をチェックする * * @param FilterControllerEvent $event * @return void * @throws \Exception */ public function onExtensionRestriction(FilterControllerEvent $event) { // リクエストの取得 $request = $event->getRequest(); // コンテンツ管理>ファイル管理のルートの場合 if ($request->attributes->get('_route') === 'admin_content_file' && $request->isMethod('POST')) { // ファイルリストの取得 $uploadedFiles = $request->files->get('form')['file'] ?? null; if (!is_array($uploadedFiles) || count($uploadedFiles) === 0) { // ファイルがない場合 return; } // セッションを取得しておく $session = $request->getSession(); // 制限された拡張子なのかチェックしていく foreach ($uploadedFiles as $uploadedFile) { try { // ファイル名を取得 $filename = $uploadedFile->getClientOriginalName(); // ファイルの拡張子を取得 $extension = pathinfo($filename, PATHINFO_EXTENSION); // 制限されているファイルの拡張子か if ($this->checkExtension($extension)) { // ホワイトリストに登録されている場合 log_info("ホワイトリスト登録の拡張子です。"); } else { // 登録されていない場合 log_error("制限された拡張子です。"); // 例外 throw new UnsupportedMediaTypeHttpException(trans('admin.content.file.extension_error')); } } catch (UnsupportedMediaTypeHttpException $e) { // エラーを追加 $this->errorFlg = true; $session->getFlashBag()->add('eccube.admin.error', $e->getMessage()); continue; } } // エラーがある場合、コントローラには行かず、リダイレクトで終了 if ($this->errorFlg) { $response = new RedirectResponse($this->router->generate('admin_content_file')); $event->setController(function () use ($response) { return $response; }); } } } /** * アップロード可能な拡張子のリストに記載されているのか判定 * @param $extension * @return bool */ public function checkExtension($extension): bool { // アップロードを許可する拡張子を取得 $whitelist = $this->eccubeConfig['eccube_file_uploadable_extensions']; // ホワイトリストに登録されているのか if (in_array($extension, $whitelist)) { return true; } return false; }}