setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { http_response_code(500); die(json_encode(array('error' => 'Database connection failed'))); } // Clean expired entries $pdo->exec("DELETE FROM pastes WHERE expires_at < " . time()); $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $method = $_SERVER['REQUEST_METHOD']; // Remove subdirectory from path if exists $scriptDir = dirname($_SERVER['SCRIPT_NAME']); if ($scriptDir !== '/' && strpos($path, $scriptDir) === 0) { $path = substr($path, strlen($scriptDir)); } if (empty($path)) $path = '/'; // API Routes if ($path === '/api/create' && $method === 'POST') { handleCreate($pdo); exit; } if (preg_match('/^\/api\/get\/(.+)$/', $path, $matches) && $method === 'GET') { handleGet($pdo, $matches[1]); exit; } // Serve static files if ($path === '/' || $path === '/index.html') { header('Content-Type: text/html; charset=utf-8'); readfile(__DIR__ . '/index.html'); exit; } if ($path === '/style.css') { header('Content-Type: text/css'); readfile(__DIR__ . '/style.css'); exit; } if ($path === '/script.js') { header('Content-Type: application/javascript'); readfile(__DIR__ . '/script.js'); exit; } if ($path === '/favicon.svg') { header('Content-Type: image/svg+xml'); echo ''; exit; } http_response_code(404); echo json_encode(array('error' => 'Not found')); function handleCreate($pdo) { $input = json_decode(file_get_contents('php://input'), true); if (!$input) { http_response_code(400); echo json_encode(array('error' => 'Invalid JSON')); return; } $id = isset($input['id']) ? $input['id'] : ''; $encryptedData = isset($input['encryptedData']) ? $input['encryptedData'] : null; $expiresIn = min(intval(isset($input['expiresIn']) ? $input['expiresIn'] : 3600), 2592000); $burnAfterRead = !empty($input['burnAfterRead']); $hasPassword = !empty($input['hasPassword']); if (!preg_match('/^[a-f0-9]{32}$/', $id)) { http_response_code(400); echo json_encode(array('error' => 'Invalid ID format')); return; } if (!$encryptedData || !isset($encryptedData['iv']) || !isset($encryptedData['data'])) { http_response_code(400); echo json_encode(array('error' => 'Invalid encrypted data format')); return; } $data = json_encode(array('iv' => $encryptedData['iv'], 'data' => $encryptedData['data'])); $expiresAt = time() + $expiresIn; try { $stmt = $pdo->prepare("INSERT INTO pastes (id, data, created_at, expires_at, burn_after_read, has_password, views) VALUES (?, ?, ?, ?, ?, ?, 0)"); $stmt->execute(array($id, $data, time() * 1000, $expiresAt, $burnAfterRead ? 1 : 0, $hasPassword ? 1 : 0)); echo json_encode(array( 'success' => true, 'id' => $id, 'expiresIn' => $expiresIn, 'hasPassword' => $hasPassword, 'url' => 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . '/../#' . $id )); } catch(PDOException $e) { http_response_code(500); echo json_encode(array('error' => 'Failed to save paste: ' . $e->getMessage())); } } function handleGet($pdo, $id) { if (!preg_match('/^[a-f0-9]{32}$/', $id)) { http_response_code(400); echo json_encode(array('error' => 'Invalid ID')); return; } try { $stmt = $pdo->prepare("SELECT * FROM pastes WHERE id = ? AND expires_at > ?"); $stmt->execute(array($id, time())); $paste = $stmt->fetch(PDO::FETCH_ASSOC); if (!$paste) { http_response_code(404); echo json_encode(array('error' => 'Paste not found or expired')); return; } $data = json_decode($paste['data'], true); if ($paste['burn_after_read']) { $delStmt = $pdo->prepare("DELETE FROM pastes WHERE id = ?"); $delStmt->execute(array($id)); } else { $updStmt = $pdo->prepare("UPDATE pastes SET views = views + 1 WHERE id = ?"); $updStmt->execute(array($id)); } echo json_encode(array( 'data' => $data, 'burnAfterRead' => (bool)$paste['burn_after_read'], 'hasPassword' => (bool)$paste['has_password'], 'created' => intval($paste['created_at']) )); } catch(PDOException $e) { http_response_code(500); echo json_encode(array('error' => 'Server error')); } }