Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 15 |
CRAP | |
0.00% |
0 / 240 |
| FileController | |
0.00% |
0 / 1 |
|
0.00% |
0 / 15 |
2070 | |
0.00% |
0 / 240 |
| __construct | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
| index | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 41 |
|||
| view | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 9 |
|||
| create | |
0.00% |
0 / 1 |
72 | |
0.00% |
0 / 27 |
|||
| delete | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 11 |
|||
| download | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 26 |
|||
| upload | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 19 |
|||
| getJsArrayList | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 12 |
|||
| getTree | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 29 |
|||
| getFileList | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 2 |
|||
| anonymous function | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
| normalizePath | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| checkDir | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
| convertStrFromServer | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| convertStrToServer | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| <?php | |
| /* | |
| * This file is part of EC-CUBE | |
| * | |
| * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved. | |
| * | |
| * http://www.lockon.co.jp/ | |
| * | |
| * This program is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU General Public License | |
| * as published by the Free Software Foundation; either version 2 | |
| * of the License, or (at your option) any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| */ | |
| namespace Eccube\Controller\Admin\Content; | |
| use Eccube\Application; | |
| use Eccube\Controller\AbstractController; | |
| use Symfony\Component\HttpFoundation\Request; | |
| use Symfony\Component\Filesystem\Filesystem; | |
| use Symfony\Component\Finder\Finder; | |
| use Symfony\Component\HttpFoundation\ResponseHeaderBag; | |
| use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | |
| class FileController extends AbstractController | |
| { | |
| const SJIS = 'sjis-win'; | |
| const UTF = 'UTF-8'; | |
| private $error = null; | |
| private $encode = ''; | |
| public function __construct(){ | |
| $this->encode = self::UTF; | |
| if ('\\' === DIRECTORY_SEPARATOR) { | |
| $this->encode = self::SJIS; | |
| } | |
| } | |
| public function index(Application $app, Request $request) | |
| { | |
| $form = $app['form.factory']->createBuilder('form') | |
| ->add('file', 'file') | |
| ->add('create_file', 'text') | |
| ->getForm(); | |
| // user_data_dir | |
| $topDir = $this->normalizePath($app['config']['user_data_realdir']); | |
| // user_data_dirの親ディレクトリ | |
| $htmlDir = $this->normalizePath($topDir.'/../'); | |
| // カレントディレクトリ | |
| $nowDir = $this->checkDir($request->get('tree_select_file'), $topDir) | |
| ? $this->normalizePath($request->get('tree_select_file')) | |
| : $topDir; | |
| // パンくず表示用データ | |
| $nowDirList = json_encode(explode('/', trim(str_replace($htmlDir, '', $nowDir), '/'))); | |
| $isTopDir = ($topDir === $nowDir); | |
| $parentDir = substr($nowDir, 0, strrpos($nowDir, '/')); | |
| switch ($request->get('mode')) { | |
| case 'create': | |
| $this->create($app, $request); | |
| break; | |
| case 'upload': | |
| $this->upload($app, $request); | |
| break; | |
| default: | |
| break; | |
| } | |
| $tree = $this->getTree($topDir, $request); | |
| $arrFileList = $this->getFileList($app, $nowDir); | |
| $javascript = $this->getJsArrayList($tree); | |
| $onload = "eccube.fileManager.viewFileTree('tree', arrTree, '" . $nowDir . "', 'tree_select_file', 'tree_status', 'move');"; | |
| return $app->render('Content/file.twig', array( | |
| 'form' => $form->createView(), | |
| 'tpl_onload' => $onload, | |
| 'tpl_javascript' => $javascript, | |
| 'top_dir' => $topDir, | |
| 'tpl_is_top_dir' => $isTopDir, | |
| 'tpl_now_dir' => $nowDir, | |
| 'html_dir' => $htmlDir, | |
| 'now_dir_list' => $nowDirList, | |
| 'tpl_parent_dir' => $parentDir, | |
| 'arrFileList' => $arrFileList, | |
| 'error' => $this->error, | |
| )); | |
| } | |
| public function view(Application $app, Request $request) | |
| { | |
| $topDir = $app['config']['user_data_realdir']; | |
| if ($this->checkDir($this->convertStrToServer($request->get('file')), $topDir)) { | |
| $file = $this->convertStrToServer($request->get('file')); | |
| setlocale(LC_ALL, "ja_JP.UTF-8"); | |
| return $app->sendFile($file); | |
| } | |
| throw new NotFoundHttpException(); | |
| } | |
| public function create(Application $app, Request $request) | |
| { | |
| $form = $app['form.factory']->createBuilder('form') | |
| ->add('file', 'file') | |
| ->add('create_file', 'text') | |
| ->getForm(); | |
| $form->handleRequest($request); | |
| if ($form->isValid()) { | |
| $fs = new Filesystem(); | |
| $filename = $form->get('create_file')->getData(); | |
| $pattern = "/[^[:alnum:]_.\\-]/"; | |
| $pattern2 = "/^\.(.*)$/"; | |
| if (empty($filename)) { | |
| $this->error = array('message' => 'フォルダ作成名が入力されていません。'); | |
| } elseif (strlen($filename) > 0 && preg_match($pattern, $filename)) { | |
| $this->error = array('message' => 'フォルダ名には、英数字、記号(_ - .)のみを入力して下さい。'); | |
| } elseif (strlen($filename) > 0 && preg_match($pattern2, $filename)) { | |
| $this->error = array('message' => '.から始まるフォルダ名は作成できません。'); | |
| } else { | |
| $topDir = $app['config']['user_data_realdir']; | |
| $nowDir = $this->checkDir($request->get('now_dir'), $topDir) | |
| ? $this->normalizePath($request->get('now_dir')) | |
| : $topDir; | |
| $fs->mkdir($nowDir . '/' . $filename); | |
| } | |
| } | |
| return $app->redirect($app->url('admin_content_file')); | |
| } | |
| public function delete(Application $app, Request $request) | |
| { | |
| $this->isTokenValid($app); | |
| $topDir = $app['config']['user_data_realdir']; | |
| if ($this->checkDir($this->convertStrToServer($request->get('select_file')), $topDir)) { | |
| $fs = new Filesystem(); | |
| if ($fs->exists($this->convertStrToServer($request->get('select_file')))) { | |
| $fs->remove($this->convertStrToServer($request->get('select_file'))); | |
| } | |
| } | |
| return $app->redirect($app->url('admin_content_file')); | |
| } | |
| public function download(Application $app, Request $request) | |
| { | |
| $topDir = $app['config']['user_data_realdir']; | |
| $file = $this->convertStrToServer($request->get('select_file')); | |
| if ($this->checkDir($file, $topDir)) { | |
| if (!is_dir($file)) { | |
| $filename = $this->convertStrFromServer($file); | |
| setlocale(LC_ALL, 'ja_JP.UTF-8'); | |
| $pathParts = pathinfo($file); | |
| $patterns = array( | |
| '/[a-zA-Z0-9!"#$%&()=~^|@`:*;+{}]/', | |
| '/[- ,.<>?_[\]\/\\\\]/', | |
| "/['\r\n\t\v\f]/", | |
| ); | |
| $str = preg_replace($patterns, '', $pathParts['basename']); | |
| if (strlen($str) === 0) { | |
| return $app->sendFile($file)->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT); | |
| } else { | |
| return $app->sendFile($file, 200, array( | |
| "Content-Type" => "aplication/octet-stream;", | |
| "Content-Disposition" => "attachment; filename*=UTF-8\'\'".rawurlencode($this->convertStrFromServer($pathParts['basename'])) | |
| )); | |
| } | |
| } | |
| } | |
| throw new NotFoundHttpException(); | |
| } | |
| public function upload(Application $app, Request $request) | |
| { | |
| $form = $app['form.factory']->createBuilder('form') | |
| ->add('file', 'file') | |
| ->add('create_file', 'text') | |
| ->getForm(); | |
| $form->handleRequest($request); | |
| if ($form->isValid()) { | |
| $data = $form->getData(); | |
| if (empty($data['file'])) { | |
| $this->error = array('message' => 'ファイルが選択されていません。'); | |
| } else { | |
| $topDir = $app['config']['user_data_realdir']; | |
| if ($this->checkDir($request->get('now_dir'), $topDir)) { | |
| $filename = $this->convertStrToServer($data['file']->getClientOriginalName()); | |
| $data['file']->move($request->get('now_dir'), $filename); | |
| } | |
| } | |
| } | |
| } | |
| private function getJsArrayList($tree) | |
| { | |
| $str = "arrTree = new Array();\n"; | |
| foreach ($tree as $key => $val) { | |
| $str .= 'arrTree[' . $key . "] = new Array(" . $key . ", '" . $val['type'] . "', '" . $val['path'] . "', " . $val['rank'] . ','; | |
| if ($val['open']) { | |
| $str .= "true);\n"; | |
| } else { | |
| $str .= "false);\n"; | |
| } | |
| } | |
| return $str; | |
| } | |
| private function getTree($topDir, $request) | |
| { | |
| $finder = Finder::create()->in($topDir) | |
| ->directories() | |
| ->sortByName(); | |
| $tree = array(); | |
| $tree[] = array( | |
| 'path' => $topDir, | |
| 'type' => '_parent', | |
| 'rank' => 0, | |
| 'open' => true, | |
| ); | |
| $defaultRank = count(explode('/', $topDir)); | |
| $openDirs = array(); | |
| if ($request->get('tree_status')) { | |
| $openDirs = explode('|', $request->get('tree_status')); | |
| } | |
| foreach ($finder as $dirs) { | |
| $path = $this->normalizePath($dirs->getRealPath()); | |
| $type = (iterator_count(Finder::create()->in($path)->directories())) ? '_parent' : '_child'; | |
| $rank = count(explode('/', $path)) - $defaultRank; | |
| $tree[] = array( | |
| 'path' => $path, | |
| 'type' => $type, | |
| 'rank' => $rank, | |
| 'open' => (in_array($path, $openDirs)) ? true : false, | |
| ); | |
| } | |
| return $tree; | |
| } | |
| private function getFileList($app, $nowDir) | |
| { | |
| $topDir = $app['config']['user_data_realdir']; | |
| $filter = function (\SplFileInfo $file) use ($topDir) { | |
| $acceptPath = realpath($topDir); | |
| $targetPath = $file->getRealPath(); | |
| return (strpos($targetPath, $acceptPath) === 0); | |
| }; | |
| $dirFinder = Finder::create() | |
| ->filter($filter) | |
| ->in($nowDir) | |
| ->directories() | |
| ->sortByName() | |
| ->depth(0); | |
| $fileFinder = Finder::create() | |
| ->filter($filter) | |
| ->in($nowDir) | |
| ->files() | |
| ->sortByName() | |
| ->depth(0); | |
| $dirs = iterator_to_array($dirFinder); | |
| $files = iterator_to_array($fileFinder); | |
| $arrFileList = array(); | |
| foreach ($dirs as $dir) { | |
| $arrFileList[] = array( | |
| 'file_name' => $this->convertStrFromServer($dir->getFilename()), | |
| 'file_path' => $this->convertStrFromServer($this->normalizePath($dir->getRealPath())), | |
| 'file_size' => $dir->getSize(), | |
| 'file_time' => date("Y/m/d", $dir->getmTime()), | |
| 'is_dir' => true, | |
| ); | |
| } | |
| foreach ($files as $file) { | |
| $arrFileList[] = array( | |
| 'file_name' => $this->convertStrFromServer($file->getFilename()), | |
| 'file_path' => $this->convertStrFromServer($this->normalizePath($file->getRealPath())), | |
| 'file_size' => $file->getSize(), | |
| 'file_time' => date("Y/m/d", $file->getmTime()), | |
| 'is_dir' => false, | |
| ); | |
| } | |
| return $arrFileList; | |
| } | |
| protected function normalizePath($path) | |
| { | |
| return str_replace('\\', '/', realpath($path)); | |
| } | |
| protected function checkDir($targetDir, $topDir) | |
| { | |
| $targetDir = realpath($targetDir); | |
| $topDir = realpath($topDir); | |
| return (strpos($targetDir, $topDir) === 0); | |
| } | |
| private function convertStrFromServer($target) | |
| { | |
| if ($this->encode == self::SJIS) { | |
| return mb_convert_encoding($target, self::UTF, self::SJIS); | |
| } | |
| return $target; | |
| } | |
| private function convertStrToServer($target) | |
| { | |
| if ($this->encode == self::SJIS) { | |
| return mb_convert_encoding($target, self::SJIS, self::UTF); | |
| } | |
| return $target; | |
| } | |
| } |