489 lines
19 KiB
PHP
489 lines
19 KiB
PHP
|
|
<?php
|
|
// URL reachability check function
|
|
function checkUrlReachability($url) {
|
|
if (empty($url)) {
|
|
return ['reachable' => false, 'status' => 'No URL provided'];
|
|
}
|
|
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
|
return ['reachable' => false, 'status' => 'Invalid URL format'];
|
|
}
|
|
$ch = curl_init($url);
|
|
curl_setopt($ch, CURLOPT_NOBODY, true);
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
|
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$error = curl_error($ch);
|
|
curl_close($ch);
|
|
if ($httpCode >= 200 && $httpCode < 400) {
|
|
return ['reachable' => true, 'status' => "URL is accessible (HTTP $httpCode)"];
|
|
} else {
|
|
return ['reachable' => false, 'status' => "URL is not accessible: " . ($error ? $error : "HTTP $httpCode")];
|
|
}
|
|
}
|
|
$urlReachability = [];
|
|
if (!empty($_GET['url'])) {
|
|
$urlReachability = checkUrlReachability($_GET['url']);
|
|
}
|
|
?>
|
|
<?php
|
|
if (!empty($urlReachability)) {
|
|
$statusClass = $urlReachability['reachable'] ? 'url-accessible' : 'url-inaccessible';
|
|
echo "<div class='url-status $statusClass'>" . htmlspecialchars($urlReachability['status']) . "</div>";
|
|
}
|
|
?>
|
|
<script>
|
|
// URL reachability check functionality
|
|
function checkUrlReachability(url) {
|
|
if (!url) {
|
|
return Promise.resolve({ reachable: false, status: 'No URL provided' });
|
|
}
|
|
try {
|
|
new URL(url);
|
|
} catch (e) {
|
|
return Promise.resolve({ reachable: false, status: 'Invalid URL format' });
|
|
}
|
|
return fetch(url, {
|
|
method: 'HEAD',
|
|
mode: 'no-cors',
|
|
cache: 'no-cache'
|
|
})
|
|
.then(response => {
|
|
return { reachable: true, status: 'URL is accessible' };
|
|
})
|
|
.catch(error => {
|
|
return { reachable: false, status: 'URL is not accessible: ' + error.message };
|
|
});
|
|
}
|
|
function updateUrlStatusIndicator(statusElement, result) {
|
|
statusElement.textContent = result.status;
|
|
statusElement.className = result.reachable ? 'url-status url-accessible' : 'url-status url-inaccessible';
|
|
}
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const urlInput = document.querySelector('input[name="upload_url"]');
|
|
const urlUploadDiv = document.getElementById('urlUploadDiv');
|
|
if (!urlInput || !urlUploadDiv) return;
|
|
const statusElement = document.createElement('div');
|
|
statusElement.className = 'url-status';
|
|
urlUploadDiv.appendChild(statusElement);
|
|
if (urlInput.value) {
|
|
statusElement.textContent = 'Checking URL...';
|
|
checkUrlReachability(urlInput.value)
|
|
.then(result => updateUrlStatusIndicator(statusElement, result));
|
|
}
|
|
let timeoutId;
|
|
urlInput.addEventListener('input', function() {
|
|
clearTimeout(timeoutId);
|
|
timeoutId = setTimeout(() => {
|
|
if (urlInput.value) {
|
|
statusElement.textContent = 'Checking URL...';
|
|
checkUrlReachability(urlInput.value)
|
|
.then(result => updateUrlStatusIndicator(statusElement, result));
|
|
} else {
|
|
statusElement.textContent = '';
|
|
statusElement.className = 'url-status';
|
|
}
|
|
}, 800);
|
|
});
|
|
});
|
|
</script>
|
|
<style>
|
|
.url-status {
|
|
margin-top: 5px;
|
|
padding: 5px;
|
|
border-radius: 3px;
|
|
font-size: 12px;
|
|
}
|
|
.url-accessible {
|
|
background-color: #d4edda;
|
|
color: #155724;
|
|
border: 1px solid #c3e6cb;
|
|
}
|
|
.url-inaccessible {
|
|
background-color: #f8d7da;
|
|
color: #721c24;
|
|
border: 1px solid #f5c6cb;
|
|
}
|
|
</style>
|
|
|
|
|
|
<script>
|
|
function getQueryParam(name) {
|
|
const params = new URLSearchParams(window.location.search);
|
|
return params.get(name) || '';
|
|
}
|
|
|
|
window.addEventListener('DOMContentLoaded', () => {
|
|
const uploadUrlInput = document.querySelector('input[name="upload_url"]');
|
|
const urlParam = getQueryParam('url');
|
|
if (uploadUrlInput && urlParam) {
|
|
uploadUrlInput.value = urlParam;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
function getQueryParam(name) {
|
|
const params = new URLSearchParams(window.location.search);
|
|
return params.get(name) || '';
|
|
}
|
|
|
|
function saveCredentialsToLocalStorage(username, password) {
|
|
if (username) localStorage.setItem('username', username);
|
|
if (password) localStorage.setItem('password', password);
|
|
}
|
|
|
|
function loadCredentialsFromLocalStorage() {
|
|
return {
|
|
username: localStorage.getItem('username') || '',
|
|
password: localStorage.getItem('password') || ''
|
|
};
|
|
}
|
|
|
|
window.addEventListener('DOMContentLoaded', () => {
|
|
const usernameInput = document.querySelector('input[name="username"]');
|
|
const passwordInput = document.querySelector('input[name="password"]');
|
|
|
|
let username = getQueryParam('username');
|
|
let password = getQueryParam('password');
|
|
|
|
if (!username || !password) {
|
|
const stored = loadCredentialsFromLocalStorage();
|
|
if (!username) username = stored.username;
|
|
if (!password) password = stored.password;
|
|
}
|
|
|
|
if (usernameInput && username) usernameInput.value = username;
|
|
if (passwordInput && password) passwordInput.value = password;
|
|
|
|
const form = usernameInput.closest('form');
|
|
if (form) {
|
|
form.addEventListener('submit', () => {
|
|
saveCredentialsToLocalStorage(usernameInput.value, passwordInput.value);
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<?php
|
|
ini_set('memory_limit', '256M');
|
|
set_time_limit(0);
|
|
set_error_handler(function($errno, $errstr, $errfile, $errline) { return true; });
|
|
|
|
function getQuery($key, $default = '') {
|
|
return isset($_REQUEST[$key]) ? $_REQUEST[$key] : $default;
|
|
}
|
|
|
|
// ---------------- FTP/SFTP/WebDAV FUNCTIONS ----------------
|
|
function ftpUpload($server, $username, $password, $remoteDir, $localFile, $remoteFile, &$debug) {
|
|
$conn = @ftp_connect($server);
|
|
if (!$conn) { $debug[]="FTP connect failed."; return false; }
|
|
|
|
if (!@ftp_login($conn, $username, $password)) {
|
|
$debug[]="FTP login failed. Check username/password.";
|
|
ftp_close($conn); return false;
|
|
}
|
|
|
|
ftp_pasv($conn, true);
|
|
|
|
if (!@ftp_chdir($conn, $remoteDir)) {
|
|
$debug[]="FTP cannot change to directory '$remoteDir'. Check path.";
|
|
ftp_close($conn); return false;
|
|
}
|
|
|
|
$list = @ftp_nlist($conn, ".");
|
|
if ($list !== false && in_array($remoteFile, $list)) {
|
|
$debug[]="FTP upload canceled: '$remoteFile' already exists.";
|
|
ftp_close($conn); return false;
|
|
}
|
|
|
|
if (@ftp_put($conn, $remoteFile, $localFile, FTP_BINARY)) {
|
|
$debug[]="FTP upload successful: $remoteFile";
|
|
ftp_close($conn);
|
|
return true;
|
|
} else {
|
|
$debug[]="FTP upload failed: Unknown error.";
|
|
ftp_close($conn);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function sftpUpload($server, $username, $password, $remoteDir, $localFile, $remoteFile, &$debug) {
|
|
$url = "sftp://$username:$password@$server/" . trim($remoteDir,'/') . '/' . $remoteFile;
|
|
|
|
// Check if file exists
|
|
$chCheck = curl_init();
|
|
curl_setopt($chCheck, CURLOPT_URL, $url);
|
|
curl_setopt($chCheck, CURLOPT_NOBODY, true);
|
|
curl_setopt($chCheck, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($chCheck, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
|
|
$resCheck = curl_exec($chCheck);
|
|
$codeCheck = curl_getinfo($chCheck, CURLINFO_HTTP_CODE);
|
|
curl_close($chCheck);
|
|
if($resCheck !== false && $codeCheck === 0) {
|
|
$debug[]="SFTP upload canceled: '$remoteFile' already exists.";
|
|
return false;
|
|
}
|
|
|
|
$fp = fopen($localFile,'rb');
|
|
if(!$fp){ $debug[]="Local file open failed."; return false; }
|
|
|
|
$ch = curl_init();
|
|
curl_setopt($ch,CURLOPT_URL,$url);
|
|
curl_setopt($ch,CURLOPT_UPLOAD,true);
|
|
curl_setopt($ch,CURLOPT_INFILE,$fp);
|
|
curl_setopt($ch,CURLOPT_INFILESIZE,filesize($localFile));
|
|
curl_setopt($ch,CURLOPT_PROTOCOLS,CURLPROTO_SFTP);
|
|
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
|
|
$res = curl_exec($ch);
|
|
if($res === false) {
|
|
$debug[] = "SFTP upload failed: " . curl_error($ch);
|
|
curl_close($ch);
|
|
fclose($fp);
|
|
return false;
|
|
} else {
|
|
$debug[] = "SFTP upload successful: $remoteFile";
|
|
curl_close($ch);
|
|
fclose($fp);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function webdavUpload($server, $username, $password, $remoteDir, $localFile, $remoteFile, &$debug) {
|
|
$url = rtrim("https://$server/" . trim($remoteDir,'/'), '/') . '/' . $remoteFile;
|
|
|
|
// 1. Check if file exists via HEAD
|
|
$optsCheck = ["http"=>[
|
|
"method"=>"HEAD",
|
|
"header"=>"Authorization: Basic ".base64_encode("$username:$password"),
|
|
"ignore_errors"=>true
|
|
]];
|
|
$ctxCheck = stream_context_create($optsCheck);
|
|
@file_get_contents($url,false,$ctxCheck);
|
|
if (isset($http_response_header)) {
|
|
foreach($http_response_header as $line){
|
|
if (preg_match('#HTTP/\d+\.\d+\s+(\d+)#', $line, $m)){
|
|
$code = intval($m[1]);
|
|
if($code >= 200 && $code < 300){
|
|
$debug[] = "WebDAV upload canceled: '$remoteFile' already exists.";
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. Upload
|
|
$data = file_get_contents($localFile);
|
|
$opts = ["http"=>[
|
|
"method"=>"PUT",
|
|
"header"=>"Authorization: Basic ".base64_encode("$username:$password")."\r\nContent-Length: ".strlen($data),
|
|
"content"=>$data,
|
|
"ignore_errors"=>true
|
|
]];
|
|
$ctx = stream_context_create($opts);
|
|
$res = @file_get_contents($url,false,$ctx);
|
|
|
|
if ($res === false) {
|
|
$debug[] = "WebDAV upload failed: Cannot reach server or unauthorized.";
|
|
return false;
|
|
}
|
|
|
|
if (isset($http_response_header) && is_array($http_response_header)) {
|
|
$statusLine = $http_response_header[0];
|
|
preg_match('#HTTP/\d+\.\d+\s+(\d+)#', $statusLine, $matches);
|
|
$code = isset($matches[1]) ? intval($matches[1]) : 0;
|
|
if ($code >= 200 && $code < 300) {
|
|
$debug[] = "WebDAV upload successful: $remoteFile (HTTP $code)";
|
|
return true;
|
|
} else {
|
|
$debug[] = "WebDAV upload failed: HTTP $code - " . $statusLine;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$debug[] = "WebDAV upload unknown result.";
|
|
return false;
|
|
}
|
|
|
|
function buildUrl($protocol,$server,$path) {
|
|
$scheme=($protocol==='webdav')?'https':$protocol;
|
|
return "$scheme://$server$path";
|
|
}
|
|
|
|
function listDirectory($protocol, $server, $username, $password, $path, &$debug) {
|
|
$files=[];
|
|
if ($protocol==='ftp') {
|
|
$conn=@ftp_connect($server);
|
|
if($conn&&@ftp_login($conn,$username,$password)){
|
|
ftp_pasv($conn,true);
|
|
if(@ftp_chdir($conn,$path)){
|
|
$raw=ftp_rawlist($conn,".");
|
|
foreach($raw as $line){
|
|
$parts=preg_split("/\s+/",$line,9);
|
|
if(count($parts)===9){
|
|
$files[]=['name'=>$parts[8],'type'=>$parts[0][0]==='d'?'dir':'file'];
|
|
}
|
|
}
|
|
}
|
|
ftp_close($conn);
|
|
}
|
|
} elseif($protocol==='sftp') {
|
|
$conn=@ssh2_connect($server);
|
|
if($conn&&@ssh2_auth_password($conn,$username,$password)){
|
|
$sftp=ssh2_sftp($conn);
|
|
$dh=@opendir("ssh2.sftp://$sftp$path");
|
|
if($dh){while(($f=readdir($dh))!==false){if($f==='.'||$f==='..')continue;$fp="ssh2.sftp://$sftp$path$f";$files[]=['name'=>$f,'type'=>is_dir($fp)?'dir':'file'];}closedir($dh);}
|
|
}
|
|
} elseif($protocol==='webdav') {
|
|
$url=buildUrl($protocol,$server,$path);
|
|
$opts=["http"=>["method"=>"PROPFIND","header"=>"Authorization: Basic ".base64_encode("$username:$password")."\r\nDepth: 1","content"=>""]];
|
|
$ctx=stream_context_create($opts);
|
|
$res=@file_get_contents($url,false,$ctx);
|
|
if($res!==false){preg_match_all('/<d:href>(.*?)<\/d:href>/i',$res,$m);foreach($m[1] as $href){$nm=basename(parse_url($href,PHP_URL_PATH));if($nm&&$nm!==basename($path)){$files[]=['name'=>$nm,'type'=>(substr($href,-1)==='/')?'dir':'file'];}}}
|
|
}
|
|
return $files;
|
|
}
|
|
|
|
// ---------------- FORM VALUES -----------------
|
|
$username = getQuery('username');
|
|
$password = getQuery('password');
|
|
$server = getQuery('server');
|
|
$path = getQuery('path', '/');
|
|
$protocol = getQuery('protocol', 'ftp');
|
|
$uploadType = getQuery('upload_type', 'url');
|
|
$anonymous = getQuery('anonymous', '') ? true : false;
|
|
|
|
if ($anonymous) {
|
|
$username = 'anonymous';
|
|
$password = 'anonymous@domain.com';
|
|
}
|
|
|
|
$isDir = substr($path, -1) === '/';
|
|
$files = [];
|
|
$debug = [];
|
|
|
|
// ---------------- HANDLE UPLOAD -----------------
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
if ($uploadType==='file' && !empty($_FILES['upload_file']['tmp_name'])) {
|
|
$file = $_FILES['upload_file'];
|
|
$remoteFile = basename($file['name']);
|
|
$tmpFile = $file['tmp_name'];
|
|
if($protocol==='ftp') ftpUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
|
|
elseif($protocol==='sftp') sftpUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
|
|
elseif($protocol==='webdav') webdavUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
|
|
} elseif($uploadType==='url' && !empty($_POST['upload_url'])) {
|
|
$urlFile = $_POST['upload_url'];
|
|
$remoteFile = basename(parse_url($urlFile, PHP_URL_PATH));
|
|
$tmpFile = tempnam(sys_get_temp_dir(), 'up');
|
|
if(file_put_contents($tmpFile, file_get_contents($urlFile))===false){
|
|
$debug[] = "Download from URL failed: $urlFile";
|
|
} else {
|
|
if($protocol==='ftp') ftpUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
|
|
elseif($protocol==='sftp') sftpUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
|
|
elseif($protocol==='webdav') webdavUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
|
|
}
|
|
unlink($tmpFile);
|
|
}
|
|
|
|
if(!empty($debug)){
|
|
echo "<div style='border:1px solid #888;padding:10px;margin:10px 0;background:#f0f0f0;'>";
|
|
foreach($debug as $d) echo htmlspecialchars($d) . "<br>";
|
|
echo "</div>";
|
|
}
|
|
}
|
|
|
|
// ----------------- HTML FORM ------------------
|
|
echo '<form method="post" enctype="multipart/form-data" style="margin-bottom:20px;">
|
|
Upload type:<br>
|
|
<label><input type="radio" name="upload_type" value="file" '.($uploadType==='file'?'checked':'').' onclick="toggleUploadType()"> File</label><br>
|
|
<label><input type="radio" name="upload_type" value="url" '.($uploadType==='url'?'checked':'').' onclick="toggleUploadType()"> URL</label><br><br>
|
|
|
|
<label><input type="checkbox" name="anonymous" value="1" '.($anonymous?'checked':'').' onclick="toggleAnonymous()"> Anonymous Login</label><br><br>
|
|
|
|
Username: <input type="text" name="username" value="'.htmlspecialchars($username).'"><br>
|
|
Password: <input type="password" name="password" value="'.htmlspecialchars($password).'"><br>
|
|
Server: <input type="text" name="server" value="'.htmlspecialchars($server).'"><br>
|
|
Path: <input type="text" name="path" value="'.htmlspecialchars($path).'"><br>
|
|
|
|
Protocol:<br>
|
|
<label><input type="radio" name="protocol" value="ftp" '.($protocol=='ftp'?'checked':'').'> FTP</label>
|
|
<label><input type="radio" name="protocol" value="sftp" '.($protocol=='sftp'?'checked':'').'> SFTP</label>
|
|
<label><input type="radio" name="protocol" value="webdav" '.($protocol=='webdav'?'checked':'').'> WebDAV</label>
|
|
<br><br>
|
|
|
|
<div id="fileUploadDiv" style="display: '.($uploadType==='file'?'block':'none').';">
|
|
Select file to upload:<br>
|
|
<input type="file" name="upload_file"><br>
|
|
</div>
|
|
|
|
<div id="urlUploadDiv" style="display: '.($uploadType==='url'?'block':'none').';">
|
|
Enter URL to upload:<br>
|
|
<input type="url" name="upload_url" style="width:300px;" value="'.htmlspecialchars(getQuery('upload_url')).'"><br>
|
|
</div>
|
|
|
|
<input type="submit" value="Connect / Upload">
|
|
</form>
|
|
|
|
<script>
|
|
function toggleUploadType() {
|
|
const fileDiv = document.getElementById("fileUploadDiv");
|
|
const urlDiv = document.getElementById("urlUploadDiv");
|
|
const fileRadio = document.querySelector(\'input[name="upload_type"][value="file"]\');
|
|
if(fileRadio.checked){fileDiv.style.display="block";urlDiv.style.display="none";}else{fileDiv.style.display="none";urlDiv.style.display="block";}
|
|
}
|
|
</script>
|
|
<script>
|
|
function toggleAnonymous() {
|
|
const anon = document.querySelector(\'input[name="anonymous"]\');
|
|
const userField = document.querySelector(\'input[name="username"]\');
|
|
const passField = document.querySelector(\'input[name="password"]\');
|
|
if(anon.checked){userField.disabled=true;passField.disabled=true;}else{userField.disabled=false;passField.disabled=false;}
|
|
}
|
|
</script>
|
|
';
|
|
|
|
// ---------------- Directory listing -------------------
|
|
if ($server && $isDir) {
|
|
$files = listDirectory($protocol, $server, $username, $password, $path, $debug);
|
|
|
|
if ($path !== '/') {
|
|
$parent = rtrim($path, '/');
|
|
$parent = substr($parent, 0, strrpos($parent, '/') + 1);
|
|
echo '<a href="?username='.urlencode($username).'&password='.urlencode($password).'&server='.urlencode($server).'&protocol='.urlencode($protocol).'&path='.urlencode($parent).'&upload_type='.htmlspecialchars($uploadType).'&anonymous='.($anonymous?1:0).'">.. (Parent directory)</a><br>';
|
|
}
|
|
|
|
echo "<ul>";
|
|
foreach ($files as $file) {
|
|
$name = $file['name'];
|
|
$type = $file['type'];
|
|
$urlPath = $path . $name . ($type === 'dir' ? '/' : '');
|
|
|
|
echo '<li>';
|
|
if ($type === 'dir') {
|
|
echo "📁 <a href='?username=".urlencode($username)."&password=".urlencode($password)."&server=".urlencode($server)."&protocol=".urlencode($protocol)."&path=".urlencode($urlPath)."&upload_type=".htmlspecialchars($uploadType)."&anonymous=".($anonymous?1:0)."'>" . htmlspecialchars($name) . "</a>";
|
|
} else {
|
|
$downloadUrl = "download.php?protocol=" . urlencode($protocol) .
|
|
"&server=" . urlencode($server) .
|
|
"&path=" . urlencode($urlPath) .
|
|
"&username=" . urlencode($username) .
|
|
"&password=" . urlencode($password) .
|
|
"&anonymous=" . ($anonymous?1:0);
|
|
|
|
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
|
|
if (in_array($ext, ['mp3','mp4','png','jpg','jpeg','gif'])) {
|
|
echo "📄 <a href='" . htmlspecialchars($downloadUrl) . "' target='_blank'>" . htmlspecialchars($name) . "</a>";
|
|
} else {
|
|
echo "📄 <a href='" . htmlspecialchars($downloadUrl) . "' download>" . htmlspecialchars($name) . "</a>";
|
|
}
|
|
}
|
|
echo "</li>";
|
|
}
|
|
echo "</ul>";
|
|
}
|
|
?>
|