blob: a9d7bfc670938fc171f856548bce600d676aea5d [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:shelf/shelf.dart';
String _getHeader(String sanitizedHeading) => '''<!DOCTYPE html>
<html>
<head>
<title>Directory listing for $sanitizedHeading</title>
<style>
html, body {
margin: 0;
padding: 0;
}
body {
font-family: sans-serif;
}
h1 {
background-color: #4078c0;
color: white;
font-weight: normal;
margin: 0 0 10px 0;
padding: 16px 32px;
white-space: nowrap;
}
ul {
margin: 0;
}
li {
padding: 0;
}
a {
line-height: 1.4em;
}
</style>
</head>
<body>
<h1>$sanitizedHeading</h1>
<ul>
''';
const String _trailer = ''' </ul>
</body>
</html>
''';
Response listDirectory(String fileSystemPath, String dirPath) {
final controller = StreamController<List<int>>();
const encoding = Utf8Codec();
const sanitizer = HtmlEscape();
void add(String string) {
controller.add(encoding.encode(string));
}
var heading = path.relative(dirPath, from: fileSystemPath);
if (heading == '.') {
heading = '/';
} else {
heading = '/$heading/';
}
add(_getHeader(sanitizer.convert(heading)));
// Return a sorted listing of the directory contents asynchronously.
Directory(dirPath).list().toList().then((entities) {
entities.sort((e1, e2) {
if (e1 is Directory && e2 is! Directory) {
return -1;
}
if (e1 is! Directory && e2 is Directory) {
return 1;
}
return e1.path.compareTo(e2.path);
});
for (var entity in entities) {
var name = path.relative(entity.path, from: dirPath);
if (entity is Directory) name += '/';
final sanitizedName = sanitizer.convert(name);
add(' <li><a href="$sanitizedName">$sanitizedName</a></li>\n');
}
add(_trailer);
controller.close();
});
return Response.ok(
controller.stream,
encoding: encoding,
headers: {HttpHeaders.contentTypeHeader: 'text/html'},
);
}