| // 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'}, |
| ); |
| } |