fox/app/Tools/FileManagerTool.php

77 lines
2.3 KiB
PHP

<?php
namespace App\Tools;
use Illuminate\Support\Facades\Storage;
use Prism\Prism\Tool;
/**
* Lese- und Schreibzugriff in storage/app/public/files. Sandboxed - keine
* Path-Traversal über '..' möglich.
*/
class FileManagerTool
{
protected string $base = 'files';
public function asPrismTool(): Tool
{
return (new Tool)
->as('file_manager')
->for('Liest oder schreibt Dateien im Fox-Sandbox-Verzeichnis. action ist "read", "write" oder "list".')
->withStringParameter('action', 'Eine der Aktionen: read, write, list')
->withStringParameter('path', 'Relativer Pfad innerhalb der Sandbox (für list leer)')
->withStringParameter('content', 'Inhalt zum Schreiben (nur bei action=write)')
->using(fn (string $action, string $path = '', string $content = '') => $this->execute($action, $path, $content));
}
public function execute(string $action, string $path = '', string $content = ''): string
{
$safe = $this->safePath($path);
return match ($action) {
'read' => $this->read($safe),
'write' => $this->write($safe, $content),
'list' => $this->list($safe),
default => "Unbekannte Aktion: {$action}",
};
}
protected function read(string $path): string
{
$disk = Storage::disk('public');
if (! $disk->exists($path)) {
return "Datei nicht gefunden: {$path}";
}
return (string) $disk->get($path);
}
protected function write(string $path, string $content): string
{
Storage::disk('public')->put($path, $content);
return "Geschrieben: {$path} (".strlen($content).' Bytes)';
}
protected function list(string $path): string
{
$disk = Storage::disk('public');
$files = $disk->files($path ?: $this->base);
$dirs = $disk->directories($path ?: $this->base);
$lines = array_merge(
array_map(fn ($d) => "[dir] {$d}", $dirs),
array_map(fn ($f) => "[file] {$f}", $files),
);
return $lines ? implode("\n", $lines) : '(leer)';
}
protected function safePath(string $path): string
{
$path = ltrim(str_replace(['..', '\\'], '', $path), '/');
return str_starts_with($path, $this->base) ? $path : $this->base.'/'.$path;
}
}