변경 파일 목록
총 1개
Controller (1)
PopupWebftpPsController.phpAdmin/Share/변경 파일 코드
추가삭제
변경 전PopupWebftpPsController.php
| ] | |
| ); | |
| } | |
| FileHandler::delete(iconv('UTF-8', 'CP949', $file), true); | |
| $this->json( | |
| [ | |
| if (!Request::request()->has('target')) { | |
| throw new \InvalidArgumentException(__('변경할 이름을 입력해주세요.')); | |
| } | |
| if (getenv('setting') == 'y') { | |
| FileHandler::rename(iconv('UTF-8', 'CP949', $file), iconv('UTF-8', 'CP949', Request::request()->get('target'))); | |
| } else { | |
| exit; | |
| } | |
| // 한글 파일명 업로드를 위해 인코딩 변경 처리 | |
| move_uploaded_file($tmpName[0], iconv('UTF-8', 'CP949', $file . '/' . $name[0])); | |
| break; | |
| } | |
| } | |
| } | |
| } | |
변경 후PopupWebftpPsController.php
| ] | |
| ); | |
| } | |
| // 목록에 없는 경로를 직접 보내 상점 폴더 밖을 지우는 것을 막는다 — data/../../route.php | |
| if ($this->isOutsideDataPath($file)) { | |
| $this->json( | |
| [ | |
| 'error' => 1, | |
| 'message' => __('삭제할 파일이 없습니다.'), | |
| ] | |
| ); | |
| } | |
| FileHandler::delete(iconv('UTF-8', 'CP949', $file), true); | |
| $this->json( | |
| [ | |
| if (!Request::request()->has('target')) { | |
| throw new \InvalidArgumentException(__('변경할 이름을 입력해주세요.')); | |
| } | |
| // 세팅 모드 target 은 앞단에서 USERPATH 로 치환돼 들어오므로 아래 호출부와 같은 방식으로 조립한다 | |
| $renameTarget = getenv('setting') == 'y' ? Request::request()->get('target') : USERPATH . Request::request()->get('target'); | |
| // 원본은 밖의 파일을 건드리는 것을(route.php → x.js), 대상은 밖으로 빼내는 것을(a.png → ../../evil.js) 막는다 | |
| if ($this->isOutsideDataPath($file) || $this->isOutsideDataPath($renameTarget)) { | |
| throw new \InvalidArgumentException(__('잘못된 경로로 접근하셨습니다.')); | |
| } | |
| if (getenv('setting') == 'y') { | |
| FileHandler::rename(iconv('UTF-8', 'CP949', $file), iconv('UTF-8', 'CP949', Request::request()->get('target'))); | |
| } else { | |
| exit; | |
| } | |
| // 저장 위치와 파일명이 합쳐진 최종 경로로 판정한다 — 둘 중 어느 쪽에 상위 이동이 섞여도 걸린다 | |
| if ($this->isOutsideDataPath($file . '/' . $name[0])) { | |
| throw new \InvalidArgumentException(__('잘못된 경로로 접근하셨습니다.')); | |
| } | |
| // 한글 파일명 업로드를 위해 인코딩 변경 처리 | |
| move_uploaded_file($tmpName[0], iconv('UTF-8', 'CP949', $file . '/' . $name[0])); | |
| break; | |
| } | |
| } | |
| } | |
| /** | |
| * 작업 대상이 상점 data 폴더 밖을 가리키는지 확인한다. | |
| * | |
| * @param string $path 파일 처리 함수에 넘어갈 경로 | |
| * | |
| * @return bool data 폴더 밖이면 true | |
| */ | |
| protected function isOutsideDataPath($path) | |
| { | |
| // 세팅 모드 파일 경로는 앞에 슬래시가 하나 더 붙어 들어온다 — //shop/user/data/a.png | |
| $targetPath = preg_replace('#/+#', '/', $path); | |
| // 세팅 모드는 화면이 넘긴 현재 경로가 상대형으로 온다 — data/logo.png | |
| if (strpos($targetPath, USERPATH) !== 0) { | |
| $targetPath = USERPATH . ltrim($targetPath, '/'); | |
| } | |
| // 상위 이동을 해석해 실제로 가리키는 경로를 구한다 — data/skin/../../route.php 는 상점 폴더 밖 | |
| $resolved = []; | |
| foreach (explode('/', $targetPath) as $segment) { | |
| if ($segment === '.') { | |
| continue; | |
| } | |
| if ($segment === '..') { | |
| array_pop($resolved); | |
| continue; | |
| } | |
| $resolved[] = $segment; | |
| } | |
| $resolvedPath = implode('/', $resolved); | |
| return strpos($resolvedPath, USERPATH . 'data/') !== 0; | |
| } | |
| } | |