false, 'msg' => '이미지 URL이 제공되지 않았습니다.']); exit; } // 상대 경로인 경우 절대 경로로 변환 if (strpos($imageUrl, 'http') !== 0) { // uploads 폴더의 이미지인 경우 if (strpos($imageUrl, '/uploads/') === 0 || strpos($imageUrl, '/img/uploads/') === 0) { $imageUrl = 'http://' . $_SERVER['HTTP_HOST'] . $imageUrl; writeLog("Converted to absolute URL: $imageUrl"); } else { // 다른 상대 경로인 경우 $imageUrl = 'http://' . $_SERVER['HTTP_HOST'] . '/' . ltrim($imageUrl, '/'); writeLog("Converted to absolute URL: $imageUrl"); } } // 보안: 허용된 도메인만 처리 (더 유연하게) $allowedDomains = [ $_SERVER['HTTP_HOST'], // 현재 도메인 'localhost', '127.0.0.1', 'drive.google.com', // 구글 드라이브 'docs.google.com', // 구글 문서 'lh3.googleusercontent.com', // 구글 이미지 'lh4.googleusercontent.com', // 구글 이미지 'lh5.googleusercontent.com', // 구글 이미지 'lh6.googleusercontent.com' // 구글 이미지 ]; $parsedUrl = parse_url($imageUrl); $host = $parsedUrl['host'] ?? ''; writeLog("Parsed host: $host"); // 도메인 검증을 더 유연하게 처리 $isAllowed = false; foreach ($allowedDomains as $allowedDomain) { if ($host === $allowedDomain || strpos($host, $allowedDomain) !== false) { $isAllowed = true; writeLog("Domain allowed: $allowedDomain"); break; } } if (!$isAllowed) { writeLog("Error: Domain not allowed: $host"); echo json_encode(['success' => false, 'msg' => '허용되지 않은 도메인의 이미지입니다: ' . $host]); exit; } // 임시 디렉토리 생성 $tmpDir = $_SERVER['DOCUMENT_ROOT'] . '/tmpimg'; if (!is_dir($tmpDir)) { mkdir($tmpDir, 0755, true); writeLog("Created tmpimg directory: $tmpDir"); } // 고유한 파일명 생성 $extension = pathinfo($imageUrl, PATHINFO_EXTENSION); if (empty($extension)) { $extension = 'jpg'; // 기본 확장자 } $filename = uniqid('img_') . '.' . $extension; $tmpPath = $tmpDir . '/' . $filename; writeLog("Temporary file path: $tmpPath"); try { // 이미지 다운로드 (타임아웃 설정) $context = stream_context_create([ 'http' => [ 'timeout' => 30, // 30초 타임아웃 'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' ] ]); writeLog("Attempting to download image from: $imageUrl"); $imageContent = file_get_contents($imageUrl, false, $context); if ($imageContent === false) { writeLog("Error: Failed to download image"); throw new Exception('이미지를 다운로드할 수 없습니다: ' . $imageUrl); } writeLog("Image downloaded successfully, size: " . strlen($imageContent) . " bytes"); // 임시 파일로 저장 if (file_put_contents($tmpPath, $imageContent) === false) { writeLog("Error: Failed to save temporary file"); throw new Exception('임시 파일 저장에 실패했습니다.'); } writeLog("Temporary file saved successfully"); // 이미지 유효성 검사 $imageInfo = getimagesize($tmpPath); if ($imageInfo === false) { unlink($tmpPath); // 유효하지 않은 파일 삭제 writeLog("Error: Invalid image file"); throw new Exception('유효하지 않은 이미지 파일입니다.'); } writeLog("Image validation successful: " . $imageInfo[0] . "x" . $imageInfo[1]); // 24시간 후 자동 삭제를 위한 타임스탬프 파일 생성 $timestampFile = $tmpPath . '.timestamp'; file_put_contents($timestampFile, time()); $result = [ 'success' => true, 'imgUrl' => '/tmpimg/' . $filename ]; writeLog("Success: " . json_encode($result)); echo json_encode($result); } catch (Exception $e) { // 오류 발생 시 임시 파일 정리 if (file_exists($tmpPath)) { unlink($tmpPath); writeLog("Cleaned up temporary file after error"); } writeLog("Exception: " . $e->getMessage()); echo json_encode(['success' => false, 'msg' => $e->getMessage()]); } ?>