feat: initial project setup with Laravel 12 and Filament v4

This commit is contained in:
SajjadMahmoody
2026-04-03 17:25:17 +03:30
parent eca5d74b36
commit 09ee1cb743
324 changed files with 78304 additions and 23 deletions
+20
View File
@@ -0,0 +1,20 @@
@echo off
setlocal
set "SCRIPTS_DIR=%~dp0"
set "SCRIPTS_DIR=%SCRIPTS_DIR:~0,-1%"
for %%F in ("%SCRIPTS_DIR%\..") do set "PROJECT_DIR=%%~fF"
set "PHP=%SCRIPTS_DIR%\php\php.exe"
echo ===================================
echo Storage Fix - Matab Panel
echo ===================================
echo.
echo [1/2] Fixing storage link (no admin needed)...
echo [2/2] Scanning for orphan files...
echo.
"%PHP%" "%SCRIPTS_DIR%\fix_storage.php" --delete
echo.
pause
+36
View File
@@ -0,0 +1,36 @@
$vbsPath = 'D:\git\matab-panel\scripts\start-server.vbs'
$taskName = 'MatabPanel'
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
$action = New-ScheduledTaskAction -Execute 'wscript.exe' -Argument "`"$vbsPath`""
$trigger = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME
$trigger.Delay = 'PT20S'
$settings = New-ScheduledTaskSettingsSet `
-ExecutionTimeLimit (New-TimeSpan -Hours 0) `
-MultipleInstances IgnoreNew `
-StartWhenAvailable
$principal = New-ScheduledTaskPrincipal `
-UserId $env:USERNAME `
-LogonType Interactive `
-RunLevel Limited
Register-ScheduledTask `
-TaskName $taskName `
-Action $action `
-Trigger $trigger `
-Settings $settings `
-Principal $principal `
-Force
Write-Host ""
Write-Host "Task created. Verifying..."
$info = Get-ScheduledTaskInfo -TaskName $taskName
Write-Host " State : $((Get-ScheduledTask -TaskName $taskName).State)"
Write-Host " Last Run : $($info.LastRunTime)"
Write-Host " Next Run : $($info.NextRunTime)"
Write-Host ""
Write-Host "DONE. Task will run 20s after next login."
+117
View File
@@ -0,0 +1,117 @@
<?php
define('LARAVEL_START', microtime(true));
$projectRoot = dirname(__DIR__);
require $projectRoot . '/vendor/autoload.php';
$app = require_once $projectRoot . '/bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap();
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
$dryRun = !in_array('--delete', $argv ?? []);
echo "\n=== ۱. Storage Link Fix ===\n\n";
$link = $projectRoot . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'storage';
$target = $projectRoot . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'public';
echo "Link : {$link}\n";
echo "Target : {$target}\n\n";
if (!is_dir($target)) {
echo "ERROR: Target directory not found!\n";
} else {
if (is_link($link) || (PHP_OS_FAMILY === 'Windows' && is_dir($link))) {
if (PHP_OS_FAMILY === 'Windows') {
exec('rmdir "' . $link . '"', $out, $code);
} else {
unlink($link);
}
echo "Old link removed.\n";
}
if (!file_exists($link) && !is_dir($link)) {
if (PHP_OS_FAMILY === 'Windows') {
exec('mklink /J "' . $link . '" "' . $target . '"', $out, $code);
if ($code === 0) {
echo "Junction created successfully! (no admin needed)\n";
} else {
echo "ERROR: " . implode("\n", $out) . "\n";
}
} else {
if (symlink($target, $link)) {
echo "Symlink created successfully!\n";
} else {
echo "ERROR: Could not create symlink.\n";
}
}
} else {
echo "OK: Link already exists and points to correct target.\n";
}
}
echo "\n=== ۲. Orphan Files Cleanup ===\n";
echo $dryRun ? "Mode: DRY RUN (add --delete to actually delete)\n\n" : "Mode: DELETE\n\n";
$referencedFiles = [];
$patients = DB::table('patients')->select('photos_before', 'photos_after', 'videos', 'audio_files')->get();
foreach ($patients as $p) {
foreach (['photos_before', 'photos_after', 'videos', 'audio_files'] as $field) {
foreach (json_decode($p->$field ?? '[]', true) ?? [] as $file) {
$referencedFiles[] = $file;
}
}
}
$initials = DB::table('osurg_initials')->select('attachment')->whereNotNull('attachment')->get();
foreach ($initials as $i) {
if ($i->attachment) {
$referencedFiles[] = $i->attachment;
}
}
$referencedFiles = array_filter($referencedFiles);
echo "Files referenced in DB: " . count($referencedFiles) . "\n\n";
$dirs = ['patients/photos-before', 'patients/photos-after', 'patients/videos', 'patients/audio', 'initials'];
$totalOrphans = 0;
$totalSize = 0;
foreach ($dirs as $dir) {
$diskFiles = Storage::disk('public')->files($dir);
if (empty($diskFiles)) {
echo "[{$dir}] No files.\n";
continue;
}
$orphans = array_values(array_filter($diskFiles, fn($f) => !in_array($f, $referencedFiles)));
echo "[{$dir}] total=" . count($diskFiles) . " orphans=" . count($orphans) . "\n";
foreach ($orphans as $orphan) {
$size = Storage::disk('public')->size($orphan);
$totalSize += $size;
$totalOrphans++;
echo " - {$orphan} (" . number_format($size / 1024, 1) . " KB)";
if (!$dryRun) {
Storage::disk('public')->delete($orphan);
echo " [DELETED]";
}
echo "\n";
}
}
echo "\n─────────────────────────────────\n";
echo "Orphan files : {$totalOrphans}\n";
echo "Wasted space : " . number_format($totalSize / 1024 / 1024, 2) . " MB\n";
if ($dryRun && $totalOrphans > 0) {
echo "\nبرای حذف اجرا کن:\n php scripts/fix_storage.php --delete\n";
}
echo "\nDone!\n";
+278
View File
@@ -0,0 +1,278 @@
<?php
set_time_limit(0);
error_reporting(E_ERROR);
$FTP_HOST = '0.0.0.0';
$FTP_PORT = 2121;
$FTP_USER = 'root';
$FTP_PASS = 'Mjoshanitcm7717';
$FTP_ROOT = realpath(__DIR__ . '/../storage/app/public');
$envFile = __DIR__ . '/../.env';
if (file_exists($envFile)) {
foreach (file($envFile) as $line) {
$line = trim($line);
if (strpos($line, '=') === false || strpos($line, '#') === 0) continue;
[$key, $val] = explode('=', $line, 2);
$key = trim($key); $val = trim($val, "\" \t\n\r");
if ($key === 'FTP_PORT') $FTP_PORT = (int)$val;
if ($key === 'FTP_USER') $FTP_USER = $val;
if ($key === 'FTP_PASS') $FTP_PASS = $val;
if ($key === 'FTP_ROOT') $FTP_ROOT = $val;
}
}
if (!$FTP_ROOT || !is_dir($FTP_ROOT)) {
die("ERROR: Root dir not found: {$FTP_ROOT}\n");
}
$server = @stream_socket_server("tcp://{$FTP_HOST}:{$FTP_PORT}", $errno, $errstr);
if (!$server) {
die("ERROR: Cannot start FTP server on port {$FTP_PORT}: {$errstr}\n"
. "Hint: Run as Administrator or change FTP_PORT in .env\n");
}
echo "=========================================\n";
echo " matab-panel FTP Server\n";
echo "=========================================\n";
echo "Port : {$FTP_PORT}\n";
echo "User : {$FTP_USER}\n";
echo "Root : {$FTP_ROOT}\n";
echo "Press Ctrl+C to stop\n\n";
while ($ctrl = stream_socket_accept($server, -1)) {
$peer = stream_socket_get_name($ctrl, true);
echo "[" . date('H:i:s') . "] Connected: {$peer}\n";
try {
ftpSession($ctrl, $FTP_USER, $FTP_PASS, $FTP_ROOT);
} catch (\Throwable $e) {
echo "Error: " . $e->getMessage() . "\n";
}
fclose($ctrl);
echo "[" . date('H:i:s') . "] Disconnected: {$peer}\n";
}
fclose($server);
function ftpSend($ctrl, string $msg): void
{
fwrite($ctrl, $msg . "\r\n");
}
function ftpRead($ctrl): string
{
$line = fgets($ctrl, 8192);
return $line ? rtrim($line, "\r\n") : '';
}
function ftpOpenData(&$pasvSock): mixed
{
if (!$pasvSock) return null;
stream_set_timeout($pasvSock, 15);
$data = stream_socket_accept($pasvSock, 15);
fclose($pasvSock);
$pasvSock = null;
return $data ?: null;
}
function ftpResolvePath(string $cwd, string $arg, string $root): ?string
{
if ($arg === '') {
$path = $cwd;
} elseif ($arg[0] === '/') {
$path = $arg;
} else {
$path = rtrim($cwd, '/') . '/' . $arg;
}
// Normalize
$parts = explode('/', $path);
$out = [];
foreach ($parts as $p) {
if ($p === '' || $p === '.') continue;
if ($p === '..') { array_pop($out); } else { $out[] = $p; }
}
$path = '/' . implode('/', $out);
$real = realpath($root . $path);
if ($real !== false && strpos($real, realpath($root)) !== 0) return null;
return $path;
}
function ftpSession($ctrl, string $user, string $pass, string $root): void
{
$cwd = '/';
$authed = false;
$pendUser = '';
$pasvSock = null;
ftpSend($ctrl, '220 matab-panel FTP Server');
while (!feof($ctrl)) {
$line = ftpRead($ctrl);
if ($line === '') continue;
$parts = explode(' ', $line, 2);
$cmd = strtoupper($parts[0]);
$arg = isset($parts[1]) ? trim($parts[1]) : '';
switch ($cmd) {
case 'USER':
$pendUser = $arg;
ftpSend($ctrl, '331 Password required');
break;
case 'PASS':
if ($pendUser === $user && $arg === $pass) {
$authed = true;
ftpSend($ctrl, '230 Login successful');
echo " Auth OK\n";
} else {
ftpSend($ctrl, '530 Login incorrect');
}
break;
case 'SYST':
ftpSend($ctrl, '215 UNIX Type: L8');
break;
case 'FEAT':
ftpSend($ctrl, "211-Features:\r\n PASV\r\n211 End");
break;
case 'TYPE':
ftpSend($ctrl, '200 Type set to ' . ($arg ?: 'I'));
break;
case 'PWD': case 'XPWD':
if (!$authed) { ftpSend($ctrl, '530 Not logged in'); break; }
ftpSend($ctrl, '257 "' . $cwd . '"');
break;
case 'CWD': case 'XCWD':
if (!$authed) { ftpSend($ctrl, '530 Not logged in'); break; }
$p = ftpResolvePath($cwd, $arg, $root);
if ($p !== null && is_dir($root . $p)) {
$cwd = $p;
ftpSend($ctrl, '250 OK');
} else {
ftpSend($ctrl, '550 No such directory');
}
break;
case 'CDUP':
if (!$authed) { ftpSend($ctrl, '530 Not logged in'); break; }
$cwd = dirname($cwd) ?: '/';
ftpSend($ctrl, '200 OK');
break;
case 'MKD': case 'XMKD':
if (!$authed) { ftpSend($ctrl, '530 Not logged in'); break; }
$p = ftpResolvePath($cwd, $arg, $root);
if ($p !== null) {
$full = $root . $p;
if (!is_dir($full)) mkdir($full, 0755, true);
ftpSend($ctrl, '257 "' . $p . '" created');
} else {
ftpSend($ctrl, '550 Failed');
}
break;
case 'PASV':
if (!$authed) { ftpSend($ctrl, '530 Not logged in'); break; }
if ($pasvSock) fclose($pasvSock);
$pasvPort = rand(49152, 65534);
$pasvSock = @stream_socket_server("tcp://0.0.0.0:{$pasvPort}", $e1, $e2);
if (!$pasvSock) { ftpSend($ctrl, '425 Cannot open passive connection'); break; }
$localAddr = stream_socket_get_name($ctrl, false);
$localIp = explode(':', $localAddr)[0];
$p1 = intdiv($pasvPort, 256);
$p2 = $pasvPort % 256;
ftpSend($ctrl, '227 Entering Passive Mode (' . str_replace('.', ',', $localIp) . ",{$p1},{$p2})");
break;
case 'LIST': case 'NLST':
if (!$authed) { ftpSend($ctrl, '530 Not logged in'); break; }
$data = ftpOpenData($pasvSock);
if (!$data) { ftpSend($ctrl, '425 No data connection'); break; }
ftpSend($ctrl, '150 Opening data connection');
$dirPath = $root . $cwd;
$list = '';
if (is_dir($dirPath)) {
foreach (scandir($dirPath) as $f) {
if ($f === '.' || $f === '..') continue;
$fp = $dirPath . '/' . $f;
$size = is_file($fp) ? filesize($fp) : 0;
$type = is_dir($fp) ? 'd' : '-';
$list .= "{$type}rw-r--r-- 1 root root {$size} Jan 1 00:00 {$f}\r\n";
}
}
fwrite($data, $list);
fclose($data);
ftpSend($ctrl, '226 Transfer complete');
break;
case 'STOR':
if (!$authed) { ftpSend($ctrl, '530 Not logged in'); break; }
$p = ftpResolvePath($cwd, $arg, $root);
if ($p === null) { ftpSend($ctrl, '550 Invalid path'); break; }
$full = $root . $p;
$dir = dirname($full);
if (!is_dir($dir)) mkdir($dir, 0755, true);
$data = ftpOpenData($pasvSock);
if (!$data) { ftpSend($ctrl, '425 No data connection'); break; }
ftpSend($ctrl, '150 Ready to receive');
$fp = fopen($full, 'wb');
if (!$fp) { fclose($data); ftpSend($ctrl, '550 Cannot write file'); break; }
while (!feof($data)) {
$buf = fread($data, 65536);
if ($buf !== false && $buf !== '') fwrite($fp, $buf);
}
fclose($fp);
fclose($data);
echo " STOR: {$p} (" . number_format(filesize($full)) . " bytes)\n";
ftpSend($ctrl, '226 Transfer complete');
break;
case 'RETR':
if (!$authed) { ftpSend($ctrl, '530 Not logged in'); break; }
$p = ftpResolvePath($cwd, $arg, $root);
if ($p === null || !file_exists($root . $p)) { ftpSend($ctrl, '550 File not found'); break; }
$data = ftpOpenData($pasvSock);
if (!$data) { ftpSend($ctrl, '425 No data connection'); break; }
ftpSend($ctrl, '150 Opening data connection');
$fp = fopen($root . $p, 'rb');
while (!feof($fp)) {
$buf = fread($fp, 65536);
if ($buf !== false && $buf !== '') fwrite($data, $buf);
}
fclose($fp);
fclose($data);
echo " RETR: {$p}\n";
ftpSend($ctrl, '226 Transfer complete');
break;
case 'SIZE':
if (!$authed) { ftpSend($ctrl, '530 Not logged in'); break; }
$p = ftpResolvePath($cwd, $arg, $root);
if ($p !== null && file_exists($root . $p)) {
ftpSend($ctrl, '213 ' . filesize($root . $p));
} else {
ftpSend($ctrl, '550 File not found');
}
break;
case 'NOOP':
ftpSend($ctrl, '200 OK');
break;
case 'QUIT':
ftpSend($ctrl, '221 Goodbye');
return;
default:
ftpSend($ctrl, '502 Not implemented: ' . $cmd);
}
}
}
+75
View File
@@ -0,0 +1,75 @@
@echo off
setlocal
set "SCRIPTS_DIR=%~dp0"
set "SCRIPTS_DIR=%SCRIPTS_DIR:~0,-1%"
for %%F in ("%SCRIPTS_DIR%\..") do set "PROJECT_DIR=%%~fF"
echo =============================================
echo MatabPanel - First Time Install
echo =============================================
echo.
echo Project folder: %PROJECT_DIR%
echo.
REM --- Find PHP (bundled first, then system fallbacks) ---
set "PHP_EXE="
if exist "%SCRIPTS_DIR%\php\php.exe" (
set "PHP_EXE=%SCRIPTS_DIR%\php\php.exe"
)
if not defined PHP_EXE (
for %%P in (
"C:\xampp\php\php.exe"
"C:\php\php.exe"
) do (
if exist %%P set "PHP_EXE=%%~P"
)
)
if not defined PHP_EXE (
powershell -NoProfile -Command ^
"if(Test-Path 'C:\wamp64\bin\php'){$v=Get-ChildItem 'C:\wamp64\bin\php' -Directory | Sort-Object Name | Select-Object -Last 1; if($v){Write-Host ($v.FullName+'\php.exe')}}" > "%TEMP%\phppath.txt" 2>nul
set /p PHP_EXE=<"%TEMP%\phppath.txt"
del "%TEMP%\phppath.txt" >nul 2>&1
)
if not exist "%PHP_EXE%" (
echo [ERROR] PHP not found!
echo Bundled PHP not found in scripts\php\, and no system PHP detected.
pause
exit /b 1
)
echo [OK] PHP found: %PHP_EXE%
echo.
REM --- [1/3] storage:link ---
echo [1/3] Creating storage link...
cd /d "%PROJECT_DIR%"
"%PHP_EXE%" artisan storage:link >nul 2>&1
if exist "%PROJECT_DIR%\public\storage" (
echo [OK] Storage link ready.
) else (
echo [WARN] Storage link may need admin rights. Run as Administrator if images don't show.
)
echo.
REM --- [2/3] Optimize Laravel ---
echo [2/3] Optimizing Laravel cache...
"%PHP_EXE%" artisan optimize >nul 2>&1
echo [OK] Done.
echo.
REM --- [3/3] Firewall rules for FTP ---
echo [3/3] Adding firewall rules for FTP...
netsh advfirewall firewall delete rule name="MatabPanel FTP" >nul 2>&1
netsh advfirewall firewall add rule name="MatabPanel FTP" protocol=TCP dir=in localport=2121 action=allow >nul 2>&1
netsh advfirewall firewall delete rule name="MatabPanel FTP Data" >nul 2>&1
netsh advfirewall firewall add rule name="MatabPanel FTP Data" protocol=TCP dir=in localport=49152-65534 action=allow >nul 2>&1
echo [OK] Firewall rules added.
echo.
REM --- [4/4] Autostart + Start server ---
echo [4/4] Setting up autostart and starting server...
call "%SCRIPTS_DIR%\setup-autostart.bat"
+97
View File
@@ -0,0 +1,97 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Sockets;
using System.Reflection;
using System.Drawing;
using System.Windows.Forms;
class TrayApp : ApplicationContext
{
private NotifyIcon tray;
private int port = 8000;
private string phpExe = @"C:\wamp64\bin\php\php8.3.28\php.exe";
private string projectDir;
public TrayApp(string dir)
{
projectDir = dir;
StartServer();
BuildTray();
}
void StartServer()
{
bool inUse = false;
try {
TcpClient tcp = new TcpClient();
tcp.Connect("127.0.0.1", port);
tcp.Close();
inUse = true;
} catch {}
if (!inUse) {
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = phpExe;
psi.Arguments = "artisan serve --host=0.0.0.0 --port=" + port;
psi.WorkingDirectory = projectDir;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
Process.Start(psi);
}
}
void BuildTray()
{
Icon icon = SystemIcons.Application;
string ico = Path.Combine(projectDir, "public", "favicon.ico");
if (File.Exists(ico)) { try { icon = new Icon(ico); } catch {} }
tray = new NotifyIcon();
tray.Icon = icon;
tray.Text = "Matab Panel";
tray.Visible = true;
ContextMenuStrip menu = new ContextMenuStrip();
ToolStripMenuItem openItem = new ToolStripMenuItem("Open Matab Panel");
openItem.Font = new Font(openItem.Font, FontStyle.Bold);
openItem.Click += delegate { OpenBrowser(); };
menu.Items.Add(openItem);
menu.Items.Add(new ToolStripSeparator());
ToolStripMenuItem stopItem = new ToolStripMenuItem("Stop Server");
stopItem.Click += delegate {
foreach (Process p in Process.GetProcessesByName("php"))
try { p.Kill(); } catch {}
tray.Visible = false;
ExitThread();
};
menu.Items.Add(stopItem);
tray.ContextMenuStrip = menu;
tray.DoubleClick += delegate { OpenBrowser(); };
tray.BalloonTipTitle = "Matab Panel";
tray.BalloonTipText = "Server running - http://localhost:" + port;
tray.BalloonTipIcon = ToolTipIcon.Info;
tray.ShowBalloonTip(4000);
}
void OpenBrowser()
{
ProcessStartInfo psi = new ProcessStartInfo("http://localhost:" + port);
psi.UseShellExecute = true;
Process.Start(psi);
}
[STAThread]
static void Main()
{
string exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string projectDir = Path.GetFullPath(Path.Combine(exeDir, ".."));
Application.Run(new TrayApp(projectDir));
}
}
+30
View File
@@ -0,0 +1,30 @@
@echo off
setlocal
set "SCRIPTS_DIR=%~dp0"
set "SCRIPTS_DIR=%SCRIPTS_DIR:~0,-1%"
for %%F in ("%SCRIPTS_DIR%\..") do set "PROJECT_DIR=%%~fF"
echo === MatabPanel Autostart Setup ===
echo.
echo [1/3] Registering web server autostart...
set "VBS_PATH=%SCRIPTS_DIR%\start-server.vbs"
powershell -NoProfile -Command "$vbs='%VBS_PATH%'; $startup=[Environment]::GetFolderPath('Startup'); $s=(New-Object -COM WScript.Shell).CreateShortcut($startup+'\MatabPanel.lnk'); $s.TargetPath='wscript.exe'; $s.Arguments=[char]34+$vbs+[char]34; $s.WindowStyle=7; $s.Save(); Write-Host ('Registered: '+$startup+'\MatabPanel.lnk')"
echo.
echo [2/3] Registering FTP server autostart...
set "FTP_VBS=%SCRIPTS_DIR%\start-ftp-server.vbs"
powershell -NoProfile -Command "$vbs='%FTP_VBS%'; $startup=[Environment]::GetFolderPath('Startup'); $s=(New-Object -COM WScript.Shell).CreateShortcut($startup+'\MatabPanelFTP.lnk'); $s.TargetPath='wscript.exe'; $s.Arguments=[char]34+$vbs+[char]34; $s.WindowStyle=7; $s.Save(); Write-Host ('Registered: '+$startup+'\MatabPanelFTP.lnk')"
echo.
echo [3/3] Starting servers now...
wscript.exe "%SCRIPTS_DIR%\start-ftp-server.vbs"
wscript.exe "%SCRIPTS_DIR%\start-server.vbs"
echo Waiting for server to be ready...
powershell -NoProfile -Command "$max=30; $i=0; while($i -lt $max){ try{ $t=New-Object Net.Sockets.TcpClient; $t.Connect('127.0.0.1',8000); $t.Close(); Write-Host '[OK] Server is ready.'; $i=$max+1 }catch{ $i++; Start-Sleep -Milliseconds 500 } }; if($i -eq $max){ Write-Host '[WARN] Server did not respond in 15s. Check scripts\server.log' }"
if not errorlevel 1 start "" "http://localhost:8000"
echo.
echo Done! Servers will auto-start on every login.
echo Web : http://localhost:8000
echo FTP : port 2121
pause
+65
View File
@@ -0,0 +1,65 @@
Dim shell, fso, scriptsDir, phpExe, logFile
Set shell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
scriptsDir = fso.GetParentFolderName(WScript.ScriptFullName)
logFile = scriptsDir & "\ftp-server.log"
' --- Find PHP ---
phpExe = ""
Dim candidates(4)
candidates(0) = scriptsDir & "\php\php.exe"
candidates(1) = "C:\xampp\php\php.exe"
candidates(2) = "C:\php\php.exe"
candidates(3) = "C:\wamp64\bin\php\php.exe"
candidates(4) = "C:\wamp\bin\php\php.exe"
Dim i
For i = 0 To 4
If fso.FileExists(candidates(i)) Then
phpExe = candidates(i)
Exit For
End If
Next
' --- Try WAMP versioned folders ---
If phpExe = "" Then
Dim wampBase(1)
wampBase(0) = "C:\wamp64\bin\php"
wampBase(1) = "C:\wamp\bin\php"
Dim w
For w = 0 To 1
If fso.FolderExists(wampBase(w)) Then
Dim subF
For Each subF In fso.GetFolder(wampBase(w)).SubFolders
phpExe = subF.Path & "\php.exe"
Next
If fso.FileExists(phpExe) Then Exit For
phpExe = ""
End If
Next
End If
If phpExe = "" Then
On Error Resume Next
Dim ts
Set ts = fso.OpenTextFile(logFile, 8, True)
ts.WriteLine Now & " - ERROR: php.exe not found in any known location"
ts.Close
WScript.Quit 1
End If
' --- Skip if already running on port 2121 ---
Dim portInUse
portInUse = shell.Run("cmd /c netstat -ano | find "":2121 "" >nul 2>&1", 0, True)
If portInUse = 0 Then WScript.Quit 0
' --- Log start ---
On Error Resume Next
Dim ts2
Set ts2 = fso.OpenTextFile(logFile, 8, True)
ts2.WriteLine Now & " - Starting FTP server with: " & phpExe
ts2.Close
On Error GoTo 0
' --- Start FTP server silently in background ---
shell.Run "cmd /c """ & phpExe & """ -d display_errors=0 """ & scriptsDir & "\ftp-server.php"" >> """ & logFile & """ 2>&1", 0, False
+33
View File
@@ -0,0 +1,33 @@
@echo off
setlocal
set "SCRIPTS_DIR=%~dp0"
set "SCRIPTS_DIR=%SCRIPTS_DIR:~0,-1%"
REM --- Find PHP ---
set "PHP_EXE="
if exist "%SCRIPTS_DIR%\php\php.exe" set "PHP_EXE=%SCRIPTS_DIR%\php\php.exe"
if not defined PHP_EXE (
for %%P in ("C:\xampp\php\php.exe" "C:\php\php.exe") do (
if exist %%P set "PHP_EXE=%%~P"
)
)
if not defined PHP_EXE (
powershell -NoProfile -Command ^
"if(Test-Path 'C:\wamp64\bin\php'){$v=Get-ChildItem 'C:\wamp64\bin\php' -Directory|Sort-Object Name|Select-Object -Last 1;if($v){Write-Host ($v.FullName+'\php.exe')}}" > "%TEMP%\phppath.txt" 2>nul
set /p PHP_EXE=<"%TEMP%\phppath.txt"
del "%TEMP%\phppath.txt" >nul 2>&1
)
if not exist "%PHP_EXE%" (
echo [ERROR] PHP not found!
pause
exit /b 1
)
echo [FTP] Starting FTP server with: %PHP_EXE%
echo [FTP] Port 21 - Run as Administrator if access denied
echo.
"%PHP_EXE%" -d display_errors=0 "%SCRIPTS_DIR%\ftp-server.php"
pause
+18
View File
@@ -0,0 +1,18 @@
@echo off
setlocal
set "SCRIPTS_DIR=%~dp0"
set "SCRIPTS_DIR=%SCRIPTS_DIR:~0,-1%"
for %%F in ("%SCRIPTS_DIR%\..") do set "PROJECT_DIR=%%~fF"
echo Checking port 8000...
powershell -NoProfile -Command ^
"if((Test-NetConnection -ComputerName localhost -Port 8000 -WarningAction SilentlyContinue).TcpTestSucceeded){Write-Host 'Already running on http://localhost:8000';exit 0}else{Write-Host 'Not running. Starting...';exit 1}"
if %errorLevel% equ 0 (
start "" "http://localhost:8000"
exit /b 0
)
wscript.exe "%SCRIPTS_DIR%\start-server.vbs"
echo Waiting for server to be ready...
powershell -NoProfile -Command "$max=30; $i=0; $ok=$false; while($i -lt $max){ try{ $t=New-Object Net.Sockets.TcpClient; $t.Connect('127.0.0.1',8000); $t.Close(); Write-Host '[OK] Server ready: http://localhost:8000'; Start-Process 'http://localhost:8000'; $ok=$true; break }catch{ $i++; Start-Sleep -Milliseconds 500 } }; if(-not $ok){ Write-Host '[FAIL] Server did not start. Check: %SCRIPTS_DIR%\server.log' }"
pause
+89
View File
@@ -0,0 +1,89 @@
Dim shell, fso, scriptsDir, projectDir, phpExe, logFile
Set shell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
scriptsDir = fso.GetParentFolderName(WScript.ScriptFullName)
projectDir = fso.GetParentFolderName(scriptsDir)
logFile = scriptsDir & "\server.log"
phpExe = ""
' --- Method 0: Bundled PHP inside scripts\php\ ---
If fso.FileExists(scriptsDir & "\php\php.exe") Then
phpExe = scriptsDir & "\php\php.exe"
End If
' --- Method 1: Scan WAMP's php folder for any version ---
If phpExe = "" Then
On Error Resume Next
If fso.FolderExists("C:\wamp64\bin\php") Then
Dim phpFolder, subFolder, latestPhp
latestPhp = ""
Set phpFolder = fso.GetFolder("C:\wamp64\bin\php")
For Each subFolder In phpFolder.SubFolders
If fso.FileExists(subFolder.Path & "\php.exe") Then
latestPhp = subFolder.Path & "\php.exe"
End If
Next
If latestPhp <> "" Then phpExe = latestPhp
End If
On Error GoTo 0
End If
' --- Method 2: where php (reads stdout directly, no temp file) ---
If phpExe = "" Then
On Error Resume Next
Dim oExec, firstLine
Set oExec = shell.Exec("cmd /c where php")
If Err.Number = 0 Then
Do While Not oExec.StdOut.AtEndOfStream
firstLine = Trim(oExec.StdOut.ReadLine())
If firstLine <> "" Then
If fso.FileExists(firstLine) Then
phpExe = firstLine
Exit Do
End If
End If
Loop
End If
On Error GoTo 0
End If
' --- Method 3: known fixed paths ---
If phpExe = "" Then
Dim candidates(2)
candidates(0) = "C:\xampp\php\php.exe"
candidates(1) = "C:\php\php.exe"
candidates(2) = shell.ExpandEnvironmentStrings("%PHPRC%\php.exe")
Dim i
For i = 0 To UBound(candidates)
On Error Resume Next
If fso.FileExists(candidates(i)) Then phpExe = candidates(i)
On Error GoTo 0
If phpExe <> "" Then Exit For
Next
End If
' --- PHP not found ---
If phpExe = "" Then
On Error Resume Next
Dim tsErr
Set tsErr = fso.OpenTextFile(logFile, 8, True)
tsErr.WriteLine Now & " - ERROR: php.exe not found. Install WAMP or add PHP to PATH."
tsErr.Close
On Error GoTo 0
WScript.Quit 1
End If
' --- Port check: exit only if actively LISTENING on 8000 ---
Dim portInUse
portInUse = shell.Run("cmd /c netstat -ano | find ""0.0.0.0:8000"" >nul 2>&1", 0, True)
If portInUse = 0 Then WScript.Quit 0
' --- Log and start server ---
On Error Resume Next
Dim ts
Set ts = fso.OpenTextFile(logFile, 8, True)
ts.WriteLine Now & " - Starting MatabPanel server with: " & phpExe
ts.Close
On Error GoTo 0
shell.Run "cmd /c cd /d """ & projectDir & """ && """ & phpExe & """ artisan serve --host=0.0.0.0 --port=8000 >> """ & logFile & """ 2>&1", 0, False
+5
View File
@@ -0,0 +1,5 @@
@echo off
echo Stopping Matab Panel server...
taskkill /f /im php.exe >nul 2>&1
echo Done.
pause
+110
View File
@@ -0,0 +1,110 @@
<?php
$ip = $argv[1] ?? null;
$port = (int)($argv[2] ?? 2121);
$user = $argv[3] ?? 'root';
$pass = $argv[4] ?? 'Mjoshanitcm7717';
if (!$ip) {
$envFile = __DIR__ . '/../.env';
if (file_exists($envFile)) {
foreach (file($envFile) as $line) {
$line = trim($line);
if (strpos($line, 'SYNC_PEER_IP=') === 0) {
$ip = trim(substr($line, 13), '"\'');
}
}
}
}
if (!$ip) {
$pdo = null;
$dbEnv = [];
foreach (file(__DIR__ . '/../.env') as $line) {
$line = trim($line);
if (strpos($line, '=') === false || $line[0] === '#') continue;
[$k, $v] = explode('=', $line, 2);
$dbEnv[trim($k)] = trim($v, '"\'');
}
try {
$dsn = "mysql:host=" . ($dbEnv['DB_HOST'] ?? '127.0.0.1')
. ";port=" . ($dbEnv['DB_PORT'] ?? '3306')
. ";dbname=" . ($dbEnv['DB_DATABASE'] ?? '');
$pdo = new PDO($dsn, $dbEnv['DB_USERNAME'] ?? 'root', $dbEnv['DB_PASSWORD'] ?? '');
$ip = $pdo->query("SELECT init_value FROM osurg_initials WHERE init_parameter='sync_peer_ip'")->fetchColumn() ?: $ip;
$port = (int)($pdo->query("SELECT init_value FROM osurg_initials WHERE init_parameter='ftp_port'")->fetchColumn() ?: $port);
$user = $pdo->query("SELECT init_value FROM osurg_initials WHERE init_parameter='ftp_user'")->fetchColumn() ?: $user;
$pass = $pdo->query("SELECT init_value FROM osurg_initials WHERE init_parameter='ftp_pass'")->fetchColumn() ?: $pass;
} catch (\Throwable $e) {}
}
if (!$ip) {
echo "ERROR: IP سیستم مطب مشخص نیست.\n";
echo "Usage: php test-ftp.php 192.168.1.X\n";
exit(1);
}
echo "==========================================\n";
echo " تست FTP سیستم مطب\n";
echo "==========================================\n";
echo "IP : {$ip}\n";
echo "Port : {$port}\n";
echo "User : {$user}\n\n";
echo "[1] بررسی پورت {$port}... ";
$sock = @fsockopen($ip, $port, $errno, $errstr, 5);
if ($sock) {
fclose($sock);
echo "باز است ✓\n";
} else {
echo "بسته است ✗ ({$errstr})\n";
echo "\n=> FTP server روی سیستم مطب اجرا نیست.\n";
echo " scripts\\start-ftp-server.vbs یا install.bat را اجرا کن.\n";
exit(1);
}
echo "[2] اتصال FTP... ";
$ftp = @ftp_connect($ip, $port, 10);
if (!$ftp) {
echo "ناموفق ✗\n";
exit(1);
}
echo "موفق ✓\n";
// ---- تست 3: لاگین ----
echo "[3] ورود با {$user}... ";
if (!@ftp_login($ftp, $user, $pass)) {
echo "ناموفق ✗ (کاربر یا رمز اشتباه)\n";
ftp_close($ftp);
exit(1);
}
echo "موفق ✓\n";
echo "[4] Passive mode... ";
ftp_pasv($ftp, true);
echo "OK ✓\n";
echo "[5] لیست پوشه اصلی... ";
$list = @ftp_nlist($ftp, '/');
if ($list !== false) {
echo "موفق ✓ (" . count($list) . " آیتم)\n";
} else {
echo "خالی یا خطا\n";
}
echo "[6] ارسال فایل تست... ";
$tmpLocal = tempnam(sys_get_temp_dir(), 'ftp_test_');
file_put_contents($tmpLocal, 'FTP test from ' . gethostname() . ' at ' . date('Y-m-d H:i:s'));
if (@ftp_put($ftp, '/ftp_test.txt', $tmpLocal, FTP_BINARY)) {
echo "موفق ✓\n";
@ftp_delete($ftp, '/ftp_test.txt');
echo "[6] پاکسازی فایل تست... OK ✓\n";
} else {
echo "ناموفق ✗ (مشکل دسترسی به پوشه)\n";
}
unlink($tmpLocal);
ftp_close($ftp);
echo "\n==========================================\n";
echo " همه تست‌ها موفق بودن! FTP آماده است.\n";
echo "==========================================\n";