|
home | manual | reference | regression | sequence | develop | apps |
Browse
PHP
browse.phpHTML
browse.padResult <?php
$title = 'Browse Application';
// Get the apps directory
$appsDir = dirname(APP) . '/';
// Get requested app, directory and file from query string
$app = $_GET['app'] ?? '';
$dir = $_GET['dir'] ?? '';
$file = $_GET['file'] ?? '';
$appPath = '';
$appDirs = [];
$appFiles = [];
$source = '';
$currentFile = '';
$parentDir = '';
// Validate app name (security: prevent directory traversal)
if ($app && preg_match('/^[a-zA-Z0-9_-]+$/', $app)) {
$appPath = $appsDir . $app . '/';
if (is_dir($appPath)) {
$title = "Browse: $app";
// Validate and set current directory
$currentDir = $appPath;
if ($dir && preg_match('/^[a-zA-Z0-9_\-\/]+$/', $dir)) {
$testPath = $appPath . $dir . '/';
if (is_dir($testPath) && strpos(realpath($testPath), realpath($appPath)) === 0) {
$currentDir = $testPath;
$title = "Browse: $app/$dir";
// Calculate parent directory
if (strpos($dir, '/') !== false) {
$parentDir = dirname($dir);
} else {
$parentDir = '';
}
}
} elseif ($dir) {
// Invalid dir, reset
$dir = '';
}
// Scan current directory for files and subdirectories
$items = scandir($currentDir);
foreach ($items as $item) {
// Skip hidden files and . / ..
if ($item[0] === '.') continue;
$itemPath = $currentDir . $item;
$relativePath = ($dir ? $dir . '/' : '') . $item;
if (is_dir($itemPath)) {
$appDirs[] = [
'name' => $item,
'path' => $relativePath
];
} else {
$ext = pathinfo($item, PATHINFO_EXTENSION);
// Only show source files
if (in_array($ext, ['php', 'pad', 'json', 'xml', 'html', 'js', 'css'])) {
$appFiles[] = [
'path' => $relativePath,
'name' => $item,
'ext' => $ext
];
}
}
}
// Sort directories and files by name
usort($appDirs, function($a, $b) {
return strcasecmp($a['name'], $b['name']);
});
usort($appFiles, function($a, $b) {
return strcasecmp($a['name'], $b['name']);
});
// If a file is requested, load its source
if ($file && preg_match('/^[a-zA-Z0-9_\-\/\.]+$/', $file)) {
$filePath = $appPath . $file;
if (file_exists($filePath) && strpos(realpath($filePath), realpath($appPath)) === 0) {
$currentFile = $file;
$source = padColorsFile($filePath);
}
}
}
}
$dirCount = count($appDirs);
$fileCount = count($appFiles);
$hasParent = ($dir !== '');
?><style>
.browse-page { text-align: left; display: inline-block; }
.browse-container { display: flex; gap: 20px; }
.file-list { min-width: 150px; }
.file-list ul { list-style: none; padding: 0; margin: 0; }
.file-list li { padding: 2px 0; }
.file-list a { text-decoration: none; }
.file-list a:hover { text-decoration: underline; }
.file-list .current { font-weight: bold; }
.file-list .dir { font-weight: bold; }
.file-list .parent a { font-size: 1.4em; font-weight: bold; }
.source-view { overflow-x: auto; }
.source-view pre { background: #f8f8f8; padding: 10px; border: 1px solid #ddd; margin: 0; }
.back-link { margin-bottom: 10px; }
.path-info { color: #666; margin-bottom: 5px; }
</style>
<div class="browse-page">
{if $app ne ''}
<div class="browse-container">
<div class="file-list">
<ul>
{if $hasParent}
<li class="parent">
{if $parentDir ne ''}
<a href="?browse&app={$app}&dir={$parentDir}">..</a>
@else@
<a href="?browse&app={$app}">..</a>
{/if}
</li>
{/if}
{appDirs}
<li class="dir"><a href="?browse&app={$app}&dir={$path}">{$name}/</a></li>
{/appDirs}
{appFiles}
{if $currentFile eq $path}
<li class="current">{$name}</li>
{/if}
{if $currentFile ne $path}
<li><a href="?browse&app={$app}&dir={$dir}&file={$path}">{$name}</a></li>
{/if}
{/appFiles}
</ul>
</div>
{if $currentFile ne ''}
<div class="source-view">
<h3>{$currentFile}</h3>
{!source}
</div>
{/if}
</div>
{/if}
{if $app eq ''}
<p>No application specified. <a href="?index">Return to applications list</a>.</p>
{/if}
</div>No application specified. Return to applications list.
|
home | manual | reference | regression | sequence | develop | apps |
(c) 2003-2025 Herbert Groot Jebbink