Add directory listing feature

This commit is contained in:
Jansen Price 2020-08-27 02:46:11 -05:00
parent 4083638ab0
commit a305a5a92a
3 changed files with 61 additions and 5 deletions

View file

@ -17,4 +17,6 @@ class Config
public $verbose = false; public $verbose = false;
public $root_dir = "."; public $root_dir = ".";
public $index_file = "index.gmi";
public $enable_directory_index = true;
} }

View file

@ -49,8 +49,12 @@ class Response
if (false === $fp) { if (false === $fp) {
throw new \Exception("Error reading file '{$this->filepath}'"); throw new \Exception("Error reading file '{$this->filepath}'");
} }
while (!feof($fp)) {
fwrite($client, fread($fp, 8192)); $result = 1;
while (!feof($fp) && $result) {
// If the client cancels, bail out before trying large files
// So, result will be 0 if the client cancels (broken socket)
$result = fwrite($client, fread($fp, 8192));
} }
return $size; return $size;
} else { } else {

View file

@ -131,14 +131,33 @@ class Server
} }
// Check if index file exists // Check if index file exists
if (file_exists($resource_path . DIRECTORY_SEPARATOR . "index.gmi")) { if (file_exists($resource_path . DIRECTORY_SEPARATOR . $this->config->index_file)) {
$resource_path = $resource_path . "/index.gmi"; $resource_path = $resource_path . DIRECTORY_SEPARATOR . $this->config->index_file;
} else {
if (!$this->config->enable_directory_index) {
$response->setStatus(Response::STATUS_BAD_REQUEST);
$response->setMeta('Path not available');
return $response;
} else {
$response->setStatus(Response::STATUS_SUCCESS);
$response->setMeta('text/gemini');
$response->setBody($this->makeDirectoryIndex($resource_path, $dir));
return $response;
}
} }
} }
if (file_exists($resource_path)) { // File exists and is world readable
if (file_exists($resource_path) && (fileperms($resource_path) & 0x0004)) {
$response->setStatus(Response::STATUS_SUCCESS); $response->setStatus(Response::STATUS_SUCCESS);
$pathinfo = pathinfo($resource_path); $pathinfo = pathinfo($resource_path);
if (!isset($pathinfo['extension'])) {
$response->setStatus(Response::STATUS_TEMPORARY_FAILURE);
$response->setMeta('Error reading resource');
return $response;
}
if ($pathinfo['extension'] == 'gmi' || $pathinfo['extension'] == 'gemini') { if ($pathinfo['extension'] == 'gmi' || $pathinfo['extension'] == 'gemini') {
$response->setMeta('text/gemini'); $response->setMeta('text/gemini');
} elseif ($pathinfo['extension'] == 'md' || $pathinfo['extension'] == 'markdown') { } elseif ($pathinfo['extension'] == 'md' || $pathinfo['extension'] == 'markdown') {
@ -179,6 +198,37 @@ class Server
return sprintf('tls://%s:%s', $this->config->host, $this->config->port); return sprintf('tls://%s:%s', $this->config->host, $this->config->port);
} }
public function makeDirectoryIndex($path, $root)
{
$files = glob($path . "*");
$body = "# Directory listing " . str_replace($root, '', $path) . "\n\n";
$body .= "=> " . str_replace($root, '', dirname($path)) . " ..\n";
foreach ($files as $file) {
$relative_path = str_replace($path, '', $file);
$is_dir = false;
if (is_dir($file)) {
$is_dir = true;
$size = '';
} else {
$size = filesize($file);
}
$body .= sprintf(
"=> %s%s %s%s%s\n",
urlencode($relative_path),
($is_dir ? '/' : ''),
$relative_path,
($is_dir ? '/' : ''),
($size ? " ($size)" : '')
);
}
return $body;
}
private function generateCert() private function generateCert()
{ {
// Certificate data // Certificate data