02794e565e
A tool for authoring, sharing, and curating social protocols. Features: - Protocol library with search, tag filtering, and sort by date/relevance - Protocol authoring with structured fields (title, description, steps, outcome, practice, source, tags) - Protocol forking with provenance tracking - Collection creation with searchable protocol picker and ordering - User accounts with roles (admin, member, viewer) - YAML import/export for portability - Self-hostable on LAMP/Cloudron, works in subdirectories - Responsive design with hamburger menu on mobile - About page Security: - CSRF protection via Origin/Referer validation - Session regeneration on login/register - Secure session cookie params (HttpOnly, SameSite, Secure) - Visibility enforcement on private/unlisted items - YAML object injection hardening - Login rate limiting - Path traversal protection - Input validation and length clamping - Vote value constraining Stack: PHP 8.x + MySQL/MariaDB, vanilla JS frontend, no external dependencies. Hippocratic License (HL3-CORE).
67 lines
1.9 KiB
PHP
Executable File
67 lines
1.9 KiB
PHP
Executable File
<?php
|
|
// Root router — serve frontend or API
|
|
// Works at web root or in a subdirectory (e.g. /protocol-droid/)
|
|
|
|
// Detect the base path (for subdirectory deployments)
|
|
$scriptName = $_SERVER['SCRIPT_NAME'] ?? '/index.php';
|
|
$basePath = rtrim(str_replace('\\', '/', dirname($scriptName)), '/');
|
|
// If basePath is just / or . , clear it
|
|
if ($basePath === '/' || $basePath === '.') $basePath = '';
|
|
|
|
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
|
|
|
// Strip base path from URI for routing
|
|
if ($basePath && strpos($uri, $basePath) === 0) {
|
|
$uri = substr($uri, strlen($basePath));
|
|
}
|
|
|
|
if (preg_match('#^/api(/|$)#', $uri)) {
|
|
require __DIR__ . '/api/index.php';
|
|
exit;
|
|
}
|
|
|
|
// Everything else: serve frontend files
|
|
// Normalize the path to prevent traversal
|
|
$uri = preg_replace('#/+#', '/', $uri);
|
|
$file = __DIR__ . '/frontend' . $uri;
|
|
|
|
// Resolve real path and verify it's within the frontend directory
|
|
$real_file = realpath($file);
|
|
$frontend_dir = realpath(__DIR__ . '/frontend');
|
|
|
|
if ($real_file === false || strpos($real_file, $frontend_dir) !== 0) {
|
|
$index = __DIR__ . '/frontend/index.html';
|
|
if (file_exists($index)) {
|
|
header('Content-Type: text/html');
|
|
readfile($index);
|
|
exit;
|
|
}
|
|
http_response_code(404);
|
|
echo 'Frontend not found';
|
|
exit;
|
|
}
|
|
|
|
if (!is_file($real_file)) {
|
|
$index = __DIR__ . '/frontend/index.html';
|
|
if (file_exists($index)) {
|
|
header('Content-Type: text/html');
|
|
readfile($index);
|
|
exit;
|
|
}
|
|
http_response_code(404);
|
|
echo 'Frontend not found';
|
|
exit;
|
|
}
|
|
|
|
$ext = pathinfo($real_file, PATHINFO_EXTENSION);
|
|
$types = [
|
|
'css' => 'text/css',
|
|
'js' => 'application/javascript',
|
|
'html' => 'text/html',
|
|
'svg' => 'image/svg+xml',
|
|
'png' => 'image/png',
|
|
'jpg' => 'image/jpeg',
|
|
'json' => 'application/json',
|
|
];
|
|
if (isset($types[$ext])) header('Content-Type: ' . $types[$ext]);
|
|
readfile($real_file); |