Files

751 lines
23 KiB
PHP

<?php
// Get parameters from URL or form submission
$protocol = $_GET['protocol'] ?? $_POST['protocol'] ?? 'ftp';
$host = $_GET['host'] ?? $_POST['host'] ?? '192.168.0.1';
$port = $_GET['port'] ?? $_POST['port'] ?? '21';
$username = $_GET['username'] ?? $_POST['username'] ?? 'anonymous';
$password = $_GET['password'] ?? $_POST['password'] ?? 'anonymous@example.com';
$anonymous = isset($_GET['anonymous']) || isset($_POST['anonymous']) ? true : false;
$output_file = __DIR__ . '/ftp_full_output.txt';
// Set default ports based on protocol
if (!isset($_GET['port']) && !isset($_POST['port'])) {
switch ($protocol) {
case 'sftp':
$port = '22';
break;
case 'webdav':
$port = '80'; // or 443 for HTTPS
break;
case 'ftp':
default:
$port = '21';
}
}
// If anonymous is checked, override username and password
if ($anonymous) {
$username = 'anonymous';
$password = 'anonymous@example.com';
}
// Check if form was submitted
$form_submitted = isset($_POST['submit']) || isset($_GET['host']);
// Protocol-specific functions
function scan_ftp($host, $port, $username, $password, $output_file) {
$conn = ftp_connect($host, intval($port));
if (!$conn) {
return ["error" => "❌ Cannot connect to $host:$port"];
}
if (!ftp_login($conn, $username, $password)) {
ftp_close($conn);
return ["error" => "❌ Login failed with username: $username"];
}
ftp_pasv($conn, true);
$output = fopen($output_file, 'w');
if (!$output) {
ftp_close($conn);
return ["error" => "❌ Cannot create output file"];
}
// Recursive FTP scanning function
function scan_ftp_recursive($conn, $path, $output_handle, $current_path = '') {
if (!@ftp_chdir($conn, $path)) {
return;
}
$items = ftp_rawlist($conn, ".");
if ($items === false) {
return;
}
$dirs = [];
$files = [];
foreach ($items as $item) {
$parts = preg_split('/\s+/', $item, 9);
if (count($parts) < 9) continue;
$permissions = $parts[0];
$name = $parts[8];
if ($name == '.' || $name == '..') continue;
if ($permissions[0] === 'd') {
$dirs[] = $name;
} else {
$files[] = $name;
}
}
sort($dirs);
sort($files);
foreach ($dirs as $name) {
$full_path = ($current_path == '' ? $name : "$current_path/$name");
fwrite($output_handle, $full_path . PHP_EOL);
echo $full_path . PHP_EOL;
$new_path = ($path == '/' ? "/$name" : "$path/$name");
scan_ftp_recursive($conn, $new_path, $output_handle, $full_path);
ftp_cdup($conn);
}
foreach ($files as $name) {
$full_path = ($current_path == '' ? $name : "$current_path/$name");
fwrite($output_handle, $full_path . PHP_EOL);
echo $full_path . PHP_EOL;
}
}
fwrite($output, "/" . PHP_EOL);
echo "/" . PHP_EOL;
scan_ftp_recursive($conn, '/', $output, '');
ftp_close($conn);
fclose($output);
return ["success" => true];
}
function scan_sftp($host, $port, $username, $password, $output_file) {
// Check if SSH2 extension is available
if (!function_exists('ssh2_connect')) {
return ["error" => "❌ SSH2 extension not available. Please install php-ssh2 extension."];
}
$conn = ssh2_connect($host, $port);
if (!$conn) {
return ["error" => "❌ Cannot connect to $host:$port via SFTP"];
}
if (!ssh2_auth_password($conn, $username, $password)) {
return ["error" => "❌ SFTP login failed with username: $username"];
}
$sftp = ssh2_sftp($conn);
if (!$sftp) {
return ["error" => "❌ Cannot initialize SFTP subsystem"];
}
$output = fopen($output_file, 'w');
if (!$output) {
return ["error" => "❌ Cannot create output file"];
}
// Recursive SFTP scanning function
function scan_sftp_recursive($sftp, $path, $output_handle, $current_path = '') {
$dir_handle = opendir("ssh2.sftp://{$sftp}{$path}");
if (!$dir_handle) return;
$items = [];
while (false !== ($entry = readdir($dir_handle))) {
if ($entry == '.' || $entry == '..') continue;
$items[] = $entry;
}
closedir($dir_handle);
// Separate directories and files
$dirs = [];
$files = [];
foreach ($items as $item) {
$full_path = $path . '/' . $item;
$stat = ssh2_sftp_stat($sftp, $full_path);
if ($stat && ($stat['mode'] & 040000)) { // Check if directory
$dirs[] = $item;
} else {
$files[] = $item;
}
}
sort($dirs);
sort($files);
foreach ($dirs as $name) {
$full_path = ($current_path == '' ? $name : "$current_path/$name");
fwrite($output_handle, $full_path . PHP_EOL);
echo $full_path . PHP_EOL;
$new_path = ($path == '/' ? "/$name" : "$path/$name");
scan_sftp_recursive($sftp, $new_path, $output_handle, $full_path);
}
foreach ($files as $name) {
$full_path = ($current_path == '' ? $name : "$current_path/$name");
fwrite($output_handle, $full_path . PHP_EOL);
echo $full_path . PHP_EOL;
}
}
fwrite($output, "/" . PHP_EOL);
echo "/" . PHP_EOL;
scan_sftp_recursive($sftp, '/', $output, '');
fclose($output);
return ["success" => true];
}
function scan_webdav($host, $port, $username, $password, $output_file) {
// Simple WebDAV scanner using cURL
$output = fopen($output_file, 'w');
if (!$output) {
return ["error" => "❌ Cannot create output file"];
}
// Basic WebDAV PROPFIND request
$url = ($port == '443' ? 'https://' : 'http://') . $host . ':' . $port . '/';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PROPFIND');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Depth: 1',
'Content-Type: text/xml'
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code != 207 && $http_code != 200) {
curl_close($ch);
fclose($output);
return ["error" => "❌ WebDAV request failed with HTTP code: $http_code"];
}
curl_close($ch);
// Parse WebDAV response (simplified)
fwrite($output, "/" . PHP_EOL);
echo "/" . PHP_EOL;
// For demonstration, we'll just list root
// Note: Full WebDAV parsing would require XML parsing
$lines = [
"WebDAV scanning requires XML parsing",
"Root directory: /",
"Note: Enable full WebDAV support with sabre/dav library"
];
foreach ($lines as $line) {
fwrite($output, $line . PHP_EOL);
echo $line . PHP_EOL;
}
fclose($output);
return ["success" => true, "note" => "Basic WebDAV scan completed. Install sabre/dav for full support."];
}
// Display HTML form
echo '<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Server Scanner</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
}
.container {
background: white;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
padding: 30px;
width: 100%;
max-width: 600px;
margin: 20px 0;
}
h1 {
color: #333;
text-align: center;
margin-bottom: 20px;
font-size: 24px;
}
h2 {
color: #666;
text-align: center;
margin-bottom: 30px;
font-size: 16px;
font-weight: normal;
}
.protocol-selector {
margin-bottom: 25px;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
}
.protocol-selector h3 {
color: #555;
margin-bottom: 15px;
font-size: 16px;
}
.protocol-options {
display: flex;
gap: 15px;
flex-wrap: wrap;
}
.protocol-option {
display: flex;
align-items: center;
padding: 10px 15px;
background: white;
border: 2px solid #ddd;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s;
}
.protocol-option:hover {
border-color: #667eea;
background: #f0f4ff;
}
.protocol-option input[type="radio"] {
margin-right: 8px;
transform: scale(1.2);
}
.protocol-option label {
font-weight: bold;
color: #555;
cursor: pointer;
}
.protocol-option.ftp label::before {
content: "📁 ";
}
.protocol-option.sftp label::before {
content: "🔒 ";
}
.protocol-option.webdav label::before {
content: "🌐 ";
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: bold;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 12px;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 14px;
transition: border-color 0.3s;
}
input[type="text"]:focus,
input[type="password"]:focus {
border-color: #667eea;
outline: none;
}
.checkbox-group {
display: flex;
align-items: center;
margin: 15px 0;
}
.checkbox-group input[type="checkbox"] {
margin-right: 10px;
transform: scale(1.2);
}
.checkbox-group label {
margin-bottom: 0;
color: #555;
}
.btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 20px;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
width: 100%;
transition: transform 0.2s, box-shadow 0.2s;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.url-example {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 5px;
padding: 15px;
margin-top: 20px;
font-family: monospace;
font-size: 12px;
word-break: break-all;
}
.url-example h3 {
color: #333;
margin-bottom: 10px;
font-size: 14px;
}
.url-example a {
color: #667eea;
text-decoration: none;
}
.url-example a:hover {
text-decoration: underline;
}
.scan-output {
background: #1a1a1a;
color: #00ff00;
border-radius: 5px;
padding: 20px;
margin-top: 20px;
font-family: monospace;
font-size: 12px;
max-height: 400px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-all;
}
.stats {
background: #e9f7fe;
border: 1px solid #b3e0f2;
border-radius: 5px;
padding: 15px;
margin-top: 20px;
}
.stats h3 {
color: #036;
margin-bottom: 10px;
}
.stats p {
margin: 5px 0;
color: #333;
}
.current-settings {
background: #fff3cd;
border: 1px solid #ffeaa7;
border-radius: 5px;
padding: 15px;
margin-top: 20px;
}
.current-settings h3 {
color: #856404;
margin-bottom: 10px;
}
.current-settings p {
margin: 5px 0;
color: #333;
}
.protocol-info {
background: #e8f5e9;
border: 1px solid #c8e6c9;
border-radius: 5px;
padding: 12px;
margin-top: 10px;
font-size: 13px;
color: #2e7d32;
}
.warning {
background: #fff3cd;
border: 1px solid #ffeaa7;
border-radius: 5px;
padding: 12px;
margin-top: 10px;
font-size: 13px;
color: #856404;
}
</style>
</head>
<body>';
echo '<div class="container">';
echo '<h1>📁 File Server Scanner</h1>';
echo '<h2>Scan and list all directories and files from FTP/SFTP/WebDAV server</h2>';
// Display current settings
echo '<div class="current-settings">';
echo '<h3>Current Settings:</h3>';
echo '<p><strong>Protocol:</strong> ' . strtoupper($protocol) . '</p>';
echo '<p><strong>Host/IP:</strong> ' . htmlspecialchars($host) . '</p>';
echo '<p><strong>Port:</strong> ' . htmlspecialchars($port) . '</p>';
echo '<p><strong>Username:</strong> ' . htmlspecialchars($username) . '</p>';
echo '<p><strong>Password:</strong> ' . str_repeat('*', strlen($password)) . '</p>';
echo '<p><strong>Anonymous:</strong> ' . ($anonymous ? 'Yes' : 'No') . '</p>';
echo '</div>';
// Protocol selector
echo '<div class="protocol-selector">';
echo '<h3>Select Protocol:</h3>';
echo '<div class="protocol-options">';
$protocols = [
'ftp' => 'FTP (File Transfer Protocol)',
'sftp' => 'SFTP (SSH File Transfer Protocol)',
'webdav' => 'WebDAV (Web Distributed Authoring)'
];
foreach ($protocols as $key => $label) {
$checked = $protocol == $key ? 'checked' : '';
$class = $key;
echo '<div class="protocol-option ' . $class . '">';
echo '<input type="radio" id="protocol_' . $key . '" name="protocol" value="' . $key . '" ' . $checked . ' onchange="updatePort(this.value)">';
echo '<label for="protocol_' . $key . '">' . $label . '</label>';
echo '</div>';
}
echo '</div>';
// Protocol information
echo '<div class="protocol-info" id="protocol_info">';
switch ($protocol) {
case 'ftp':
echo '📌 FTP uses port 21 by default. Supports anonymous login.';
break;
case 'sftp':
echo '🔒 SFTP uses port 22 by default. Requires SSH2 extension (php-ssh2).';
break;
case 'webdav':
echo '🌐 WebDAV uses port 80 (HTTP) or 443 (HTTPS). Basic authentication supported.';
break;
}
echo '</div>';
// Check for missing extensions
if ($protocol == 'sftp' && !function_exists('ssh2_connect')) {
echo '<div class="warning">⚠️ SSH2 extension not available. Install php-ssh2 for SFTP support.</div>';
}
echo '</div>';
// Display form
echo '<form method="POST" action="">';
echo '<input type="hidden" name="protocol" id="protocol_hidden" value="' . htmlspecialchars($protocol) . '">';
echo '<div class="form-group">';
echo '<label for="host">Server (Host/IP):</label>';
echo '<input type="text" id="host" name="host" value="' . htmlspecialchars($host) . '" required>';
echo '</div>';
echo '<div class="form-group">';
echo '<label for="port">Port:</label>';
echo '<input type="text" id="port" name="port" value="' . htmlspecialchars($port) . '" required>';
echo '</div>';
echo '<div class="form-group">';
echo '<label for="username">Username:</label>';
echo '<input type="text" id="username" name="username" value="' . htmlspecialchars($username) . '" ' . ($anonymous ? 'readonly' : '') . '>';
echo '</div>';
echo '<div class="form-group">';
echo '<label for="password">Password:</label>';
echo '<input type="password" id="password" name="password" value="' . htmlspecialchars($password) . '" ' . ($anonymous ? 'readonly' : '') . '>';
echo '</div>';
echo '<div class="checkbox-group">';
echo '<input type="checkbox" id="anonymous" name="anonymous" value="1" ' . ($anonymous ? 'checked' : '') . ' onchange="toggleCredentials()">';
echo '<label for="anonymous">Use anonymous login (FTP only)</label>';
echo '</div>';
echo '<button type="submit" name="submit" class="btn">🚀 Start Server Scan</button>';
echo '</form>';
// URL example
$current_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$base_url = strtok($current_url, '?');
$example_url = $base_url . '?protocol=ftp&host=192.168.0.1&port=21&username=anonymous&anonymous=1';
echo '<div class="url-example">';
echo '<h3>📋 Example URL with Parameters:</h3>';
echo '<a href="' . htmlspecialchars($example_url) . '" target="_blank">' . htmlspecialchars($example_url) . '</a>';
echo '<p style="margin-top: 10px;">You can bookmark this URL with your preferred settings.</p>';
echo '</div>';
echo '</div>'; // Close container
// JavaScript
echo '<script>
function updatePort(protocol) {
var portField = document.getElementById("port");
var protocolHidden = document.getElementById("protocol_hidden");
var protocolInfo = document.getElementById("protocol_info");
var anonymousCheckbox = document.getElementById("anonymous");
// Update hidden field
protocolHidden.value = protocol;
// Update port based on protocol
switch(protocol) {
case "ftp":
portField.value = "21";
protocolInfo.innerHTML = "📌 FTP uses port 21 by default. Supports anonymous login.";
anonymousCheckbox.disabled = false;
break;
case "sftp":
portField.value = "22";
protocolInfo.innerHTML = "🔒 SFTP uses port 22 by default. Requires SSH2 extension (php-ssh2).";
anonymousCheckbox.disabled = true;
anonymousCheckbox.checked = false;
toggleCredentials();
break;
case "webdav":
portField.value = "80";
protocolInfo.innerHTML = "🌐 WebDAV uses port 80 (HTTP) or 443 (HTTPS). Basic authentication supported.";
anonymousCheckbox.disabled = true;
anonymousCheckbox.checked = false;
toggleCredentials();
break;
}
}
function toggleCredentials() {
var anonymous = document.getElementById("anonymous");
var username = document.getElementById("username");
var password = document.getElementById("password");
if (anonymous.checked && !anonymous.disabled) {
username.value = "anonymous";
password.value = "anonymous@example.com";
username.readOnly = true;
password.readOnly = true;
username.style.backgroundColor = "#f0f0f0";
password.style.backgroundColor = "#f0f0f0";
} else {
username.readOnly = false;
password.readOnly = false;
username.style.backgroundColor = "";
password.style.backgroundColor = "";
}
}
// Initialize on page load
document.addEventListener("DOMContentLoaded", function() {
toggleCredentials();
});
</script>';
// Process scan if form was submitted
if ($form_submitted) {
echo '<div class="container">';
echo '<div class="scan-output">';
echo '<h3 style="color: #fff; margin-bottom: 10px;">Scanning Server...</h3>';
echo '<p style="color: #fff;">Protocol: ' . strtoupper($protocol) . '</p>';
echo '<p style="color: #fff;">Server: ' . htmlspecialchars($host) . ':' . htmlspecialchars($port) . '</p>';
echo str_repeat('-', 50) . PHP_EOL;
// Clear previous output
file_put_contents($output_file, "");
// Start scanning based on protocol
$result = [];
switch ($protocol) {
case 'ftp':
$result = scan_ftp($host, $port, $username, $password, $output_file);
break;
case 'sftp':
$result = scan_sftp($host, $port, $username, $password, $output_file);
break;
case 'webdav':
$result = scan_webdav($host, $port, $username, $password, $output_file);
break;
default:
$result = ["error" => "❌ Unknown protocol: $protocol"];
}
// Display result
if (isset($result['error'])) {
echo '<p style="color: #ff6b6b;">' . $result['error'] . '</p>';
} else {
echo '<p style="color: #4ecdc4;">✅ Scan completed successfully!</p>';
if (isset($result['note'])) {
echo '<p style="color: #ffd166;">' . $result['note'] . '</p>';
}
}
echo '</div>'; // Close scan-output
// Display statistics if file was created
if (file_exists($output_file) && filesize($output_file) > 0) {
echo '<div class="stats">';
echo '<h3>📊 Scan Statistics:</h3>';
echo '<p><strong>Protocol:</strong> ' . strtoupper($protocol) . '</p>';
echo '<p><strong>Server:</strong> ' . htmlspecialchars($host) . ':' . htmlspecialchars($port) . '</p>';
echo '<p><strong>Output File:</strong> ' . htmlspecialchars(basename($output_file)) . '</p>';
echo '<p><strong>Size:</strong> ' . filesize($output_file) . ' bytes</p>';
$lines = count(file($output_file));
echo '<p><strong>Total Items:</strong> ' . $lines . '</p>';
// Count lines (simplified)
$content = file_get_contents($output_file);
$lines_array = explode(PHP_EOL, trim($content));
$valid_lines = array_filter($lines_array, function($line) {
return !empty($line) && $line !== '/' && !str_contains($line, 'Note:') && !str_contains($line, 'WebDAV');
});
echo '<p><strong>Valid Items:</strong> ' . count($valid_lines) . '</p>';
// Provide download link
echo '<p style="margin-top: 10px;"><a href="' . basename($output_file) . '" download class="btn" style="text-decoration: none; display: inline-block; text-align: center; padding: 10px;">📥 Download Output File</a></p>';
echo '</div>';
}
echo '</div>'; // Close container
}
echo '</body></html>';
?>