Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: pkg/http_server/lib/src/virtual_directory.dart

Issue 18333003: Correctly url-decode the path segment in the http_server. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Don't allow invalid characters in segment. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/http_server/test/utils.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of http_server; 5 part of http_server;
6 6
7 /** 7 /**
8 * A [VirtualDirectory] can serve files and directory-listing from a root path, 8 * A [VirtualDirectory] can serve files and directory-listing from a root path,
9 * to [HttpRequest]s. 9 * to [HttpRequest]s.
10 * 10 *
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 */ 58 */
59 void setErrorPageHandler(void callback(HttpRequest request)); 59 void setErrorPageHandler(void callback(HttpRequest request));
60 } 60 }
61 61
62 class _VirtualDirectory implements VirtualDirectory { 62 class _VirtualDirectory implements VirtualDirectory {
63 final String root; 63 final String root;
64 64
65 bool allowDirectoryListing = false; 65 bool allowDirectoryListing = false;
66 bool followLinks = true; 66 bool followLinks = true;
67 67
68 final RegExp _invalidPathRegExp = new RegExp("[\\\/\x00]");
69
68 Function _errorCallback; 70 Function _errorCallback;
69 Function _dirCallback; 71 Function _dirCallback;
70 72
71 _VirtualDirectory(this.root); 73 _VirtualDirectory(this.root);
72 74
73 void serve(Stream<HttpRequest> requests) { 75 void serve(Stream<HttpRequest> requests) {
74 requests.listen(serveRequest); 76 requests.listen(serveRequest);
75 } 77 }
76 78
77 void serveRequest(HttpRequest request) { 79 void serveRequest(HttpRequest request) {
78 var path = new Path(request.uri.path).canonicalize(); 80 _locateResource(new Path('.'), request.uri.pathSegments.iterator..moveNext() )
79
80 if (!path.isAbsolute) {
81 return _serveErrorPage(HttpStatus.NOT_FOUND, request);
82 }
83
84 _locateResource(new Path('.'), path.segments())
85 .then((entity) { 81 .then((entity) {
86 if (entity == null) { 82 if (entity == null) {
87 _serveErrorPage(HttpStatus.NOT_FOUND, request); 83 _serveErrorPage(HttpStatus.NOT_FOUND, request);
88 return; 84 return;
89 } 85 }
90 if (entity is File) { 86 if (entity is File) {
91 _serveFile(entity, request); 87 _serveFile(entity, request);
92 } else if (entity is Directory) { 88 } else if (entity is Directory) {
93 _serveDirectory(entity, request); 89 _serveDirectory(entity, request);
94 } else { 90 } else {
95 _serveErrorPage(HttpStatus.NOT_FOUND, request); 91 _serveErrorPage(HttpStatus.NOT_FOUND, request);
96 } 92 }
97 }); 93 });
98 } 94 }
99 95
100 void setDirectoryHandler(void callback(Directory dir, HttpRequest request)) { 96 void setDirectoryHandler(void callback(Directory dir, HttpRequest request)) {
101 _dirCallback = callback; 97 _dirCallback = callback;
102 } 98 }
103 99
104 void setErrorPageHandler(void callback(HttpRequest request)) { 100 void setErrorPageHandler(void callback(HttpRequest request)) {
105 _errorCallback = callback; 101 _errorCallback = callback;
106 } 102 }
107 103
108 Future<FileSystemEntity> _locateResource(Path path, 104 Future<FileSystemEntity> _locateResource(Path path,
109 Iterable<String> segments) { 105 Iterator<String> segments) {
106 path = path.canonicalize();
107 if (path.segments().first == "..") return new Future.value(null);
110 Path fullPath() => new Path(root).join(path); 108 Path fullPath() => new Path(root).join(path);
111 return FileSystemEntity.type(fullPath().toNativePath(), followLinks: false) 109 return FileSystemEntity.type(fullPath().toNativePath(), followLinks: false)
112 .then((type) { 110 .then((type) {
113 switch (type) { 111 switch (type) {
114 case FileSystemEntityType.FILE: 112 case FileSystemEntityType.FILE:
115 if (segments.isEmpty) return new File.fromPath(fullPath()); 113 if (segments.current == null) {
114 return new File.fromPath(fullPath());
115 }
116 break; 116 break;
117 117
118 case FileSystemEntityType.DIRECTORY: 118 case FileSystemEntityType.DIRECTORY:
119 if (segments.isEmpty) { 119 if (segments.current == null) {
120 if (allowDirectoryListing) { 120 if (allowDirectoryListing) {
121 return new Directory.fromPath(fullPath()); 121 return new Directory.fromPath(fullPath());
122 } 122 }
123 } else { 123 } else {
124 return _locateResource(path.append(segments.first), 124 if (_invalidPathRegExp.hasMatch(segments.current)) break;
125 segments.skip(1)); 125 return _locateResource(path.append(segments.current),
126 segments..moveNext());
126 } 127 }
127 break; 128 break;
128 129
129 case FileSystemEntityType.LINK: 130 case FileSystemEntityType.LINK:
130 if (followLinks) { 131 if (followLinks) {
131 return new Link.fromPath(fullPath()).target() 132 return new Link.fromPath(fullPath()).target()
132 .then((target) { 133 .then((target) {
133 var targetPath = new Path(target).canonicalize(); 134 var targetPath = new Path(target).canonicalize();
134 if (targetPath.isAbsolute) return null; 135 if (targetPath.isAbsolute) return null;
135 targetPath = 136 targetPath = path.directoryPath.join(targetPath);
136 path.directoryPath.join(targetPath).canonicalize(); 137 return _locateResource(targetPath, segments);
137 if (targetPath.segments().isEmpty ||
138 targetPath.segments().first == '..') return null;
139 if (segments.isEmpty) {
140 return _locateResource(targetPath, []);
141 }
142 return _locateResource(targetPath.append(segments.first),
143 segments.skip(1));
144 }); 138 });
145 } 139 }
146 break; 140 break;
147 } 141 }
148 // Return `null` on fall-through, to indicate NOT_FOUND. 142 // Return `null` on fall-through, to indicate NOT_FOUND.
149 return null; 143 return null;
150 }); 144 });
151 } 145 }
152 146
153 void _serveFile(File file, HttpRequest request) { 147 void _serveFile(File file, HttpRequest request) {
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 366
373 Future close() => new Future.value(); 367 Future close() => new Future.value();
374 368
375 void setMimeType(var bytes) { 369 void setMimeType(var bytes) {
376 var mimeType = lookupMimeType(path, headerBytes: bytes); 370 var mimeType = lookupMimeType(path, headerBytes: bytes);
377 if (mimeType != null) { 371 if (mimeType != null) {
378 response.headers.contentType = ContentType.parse(mimeType); 372 response.headers.contentType = ContentType.parse(mimeType);
379 } 373 }
380 } 374 }
381 } 375 }
OLDNEW
« no previous file with comments | « no previous file | pkg/http_server/test/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698