Skip to content

Commit c4bea03

Browse files
authored
Remove fallback URL resolver. (#8454)
1 parent 9f6100a commit c4bea03

File tree

7 files changed

+30
-314
lines changed

7 files changed

+30
-314
lines changed

app/lib/package/models.dart

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import 'package:json_annotation/json_annotation.dart';
1111
import 'package:pana/models.dart';
1212
import 'package:pub_dev/service/download_counts/backend.dart';
1313
import 'package:pub_dev/service/download_counts/download_counts.dart';
14-
import 'package:pub_dev/shared/markdown.dart';
1514
import 'package:pub_semver/pub_semver.dart';
1615

1716
import '../package/model_properties.dart';
@@ -1071,11 +1070,7 @@ class PackageLinks {
10711070
/// The link to `CONTRIBUTING.md` in the git repository (when the repository is verified).
10721071
final String? contributingUrl;
10731072

1074-
/// The inferred base URL that can be used to link files from.
1075-
final String? _baseUrl;
1076-
1077-
PackageLinks._(
1078-
this._baseUrl, {
1073+
PackageLinks._({
10791074
this.homepageUrl,
10801075
String? documentationUrl,
10811076
this.repositoryUrl,
@@ -1093,12 +1088,7 @@ class PackageLinks {
10931088
}) {
10941089
repositoryUrl ??= urls.inferRepositoryUrl(homepageUrl);
10951090
issueTrackerUrl ??= urls.inferIssueTrackerUrl(repositoryUrl);
1096-
final baseUrl = urls.inferBaseUrl(
1097-
homepageUrl: homepageUrl,
1098-
repositoryUrl: repositoryUrl,
1099-
);
11001091
return PackageLinks._(
1101-
baseUrl,
11021092
homepageUrl: homepageUrl,
11031093
documentationUrl: documentationUrl,
11041094
repositoryUrl: repositoryUrl,
@@ -1156,12 +1146,7 @@ class PackagePageData {
11561146
return inferred;
11571147
}
11581148

1159-
final baseUrl = urls.inferBaseUrl(
1160-
homepageUrl: result.homepageUrl ?? inferred.homepageUrl,
1161-
repositoryUrl: result.repositoryUrl ?? inferred.repositoryUrl,
1162-
);
11631149
return PackageLinks._(
1164-
baseUrl,
11651150
homepageUrl: result.homepageUrl ?? inferred.homepageUrl,
11661151
repositoryUrl: result.repositoryUrl ?? inferred.repositoryUrl,
11671152
issueTrackerUrl: result.issueTrackerUrl ?? inferred.issueTrackerUrl,
@@ -1170,10 +1155,16 @@ class PackagePageData {
11701155
);
11711156
}();
11721157

1173-
/// The verified repository (or homepage).
1174-
late final urlResolverFn =
1175-
scoreCard.panaReport?.result?.repository?.resolveUrl ??
1176-
fallbackUrlResolverFn(packageLinks._baseUrl);
1158+
/// The URL resolver using a verified repository
1159+
/// (unless the verification explicitly failed).
1160+
late final urlResolverFn = () {
1161+
final result = scoreCard.panaReport?.result;
1162+
final status = result?.repositoryStatus;
1163+
if (status == RepositoryStatus.failed) {
1164+
return null;
1165+
}
1166+
return result?.repository?.resolveUrl;
1167+
}();
11771168

11781169
PackageView toPackageView() {
11791170
return _view ??= PackageView.fromModel(

app/lib/shared/markdown.dart

Lines changed: 1 addition & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44

55
import 'package:logging/logging.dart';
66
import 'package:markdown/markdown.dart' as m;
7-
import 'package:path/path.dart' as p;
87
import 'package:pub_semver/pub_semver.dart';
98
import 'package:sanitize_html/sanitize_html.dart';
109

11-
import 'urls.dart' show getRepositoryUrl, UriExt;
10+
import 'urls.dart' show UriExt;
1211

1312
/// Resolves [reference] relative to a repository URL.
1413
typedef UrlResolverFn = String Function(
@@ -313,67 +312,6 @@ class _TaskListRewriteNodeVisitor implements m.NodeVisitor {
313312
void visitText(m.Text text) {}
314313
}
315314

316-
bool _isAbsolute(String url) => url.contains(':');
317-
318-
String _rewriteAbsoluteUrl(String url) {
319-
final uri = Uri.parse(url);
320-
if (uri.host == 'github.com') {
321-
final segments = uri.pathSegments;
322-
if (segments.length > 3 && segments[2] == 'blob') {
323-
final newSegments = List.of(segments);
324-
newSegments[2] = 'raw';
325-
return uri.replace(pathSegments: newSegments).toString();
326-
}
327-
}
328-
return url;
329-
}
330-
331-
String _rewriteRelativeUrl({
332-
required String baseUrl,
333-
required String url,
334-
required String? baseDir,
335-
}) {
336-
final uri = Uri.parse(url);
337-
final linkPath = uri.path;
338-
final linkFragment = uri.fragment;
339-
if (linkPath.isEmpty) {
340-
return url;
341-
}
342-
String newUrl;
343-
if (linkPath.startsWith('/')) {
344-
newUrl = Uri.parse(baseUrl).replace(path: linkPath).toString();
345-
} else {
346-
final adjustedLinkPath = p.normalize(p.join(baseDir ?? '.', linkPath));
347-
final repoUrl = getRepositoryUrl(baseUrl, adjustedLinkPath);
348-
if (repoUrl == null) {
349-
return url;
350-
}
351-
newUrl = repoUrl;
352-
}
353-
if (linkFragment.isNotEmpty) {
354-
newUrl = '$newUrl#$linkFragment';
355-
}
356-
return newUrl;
357-
}
358-
359-
/// Returns null if the [url] looks invalid.
360-
String? _pruneBaseUrl(String? url) {
361-
if (url == null) return null;
362-
try {
363-
final Uri uri = Uri.parse(url);
364-
if (uri.scheme != 'http' && uri.scheme != 'https') {
365-
return null;
366-
}
367-
if (uri.host.isEmpty || !uri.host.contains('.')) {
368-
return null;
369-
}
370-
return uri.toString();
371-
} catch (e) {
372-
// url is user-provided, may be malicious, ignoring errors.
373-
}
374-
return null;
375-
}
376-
377315
/// Group corresponding changelog nodes together, if it matches the following
378316
/// pattern:
379317
/// - version identifiers are the only content in a single line
@@ -447,29 +385,3 @@ Version? _extractVersion(String? text) {
447385
return null;
448386
}
449387
}
450-
451-
// TODO: remove after repository verification is launched
452-
UrlResolverFn? fallbackUrlResolverFn(String? providedBaseUrl) {
453-
final baseUrl = _pruneBaseUrl(providedBaseUrl);
454-
if (baseUrl == null) {
455-
return null;
456-
}
457-
return (
458-
String url, {
459-
bool? isEmbeddedObject,
460-
String? relativeFrom,
461-
}) {
462-
String newUrl = url;
463-
if (!_isAbsolute(newUrl)) {
464-
newUrl = _rewriteRelativeUrl(
465-
url: newUrl,
466-
baseUrl: baseUrl,
467-
baseDir: relativeFrom == null ? null : p.dirname(relativeFrom),
468-
);
469-
}
470-
if ((isEmbeddedObject ?? false) && _isAbsolute(newUrl)) {
471-
newUrl = _rewriteAbsoluteUrl(newUrl);
472-
}
473-
return newUrl;
474-
};
475-
}

app/lib/shared/urls.dart

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,6 @@ const httpsApiDartDev = 'https://api.dart.dev/';
1717
/// rejected and the URL mustn't be displayed.
1818
const trustedUrlSchemes = <String>['http', 'https', 'mailto'];
1919

20-
/// Extensions that are considered to be images.
21-
final _imageExtensions = <String>{
22-
'.apng',
23-
'.avif',
24-
'.gif',
25-
'.jpg',
26-
'.jpeg',
27-
'.png',
28-
'.svg',
29-
'.webp',
30-
};
31-
32-
/// Common repository URL replacement patterns.
33-
const _repositoryReplacePrefixes = {
34-
'http://github.com': 'https://github.com',
35-
'https://www.github.com': 'https://github.com',
36-
'https://www.gitlab.com': 'https://gitlab.com',
37-
};
38-
3920
/// Hostnames that are trusted in user-generated content (and don't get rel="ugc").
4021
const trustedTargetHost = [
4122
'api.dart.dev',
@@ -294,42 +275,6 @@ String? inferIssueTrackerUrl(String? baseUrl) {
294275
return null;
295276
}
296277

297-
/// Infer base URL that can be used to link files from.
298-
String? inferBaseUrl({String? homepageUrl, String? repositoryUrl}) {
299-
var baseUrl = repositoryUrl ?? homepageUrl;
300-
if (baseUrl == null) return null;
301-
302-
// In a few cases people specify only a deep repository URL for their
303-
// package (e.g. a monorepo for multiple packages). While we default the
304-
// base URL to be the repository URL, this check allows us to use the deep
305-
// URL for linking.
306-
if (homepageUrl != null && homepageUrl.startsWith(baseUrl)) {
307-
baseUrl = homepageUrl;
308-
}
309-
310-
// URL cleanup
311-
final prefixReplacements = const <String, String>{
312-
'http://github.com/': 'https://github.com/',
313-
'http://www.github.com/': 'https://github.com/',
314-
'https://www.github.com/': 'https://github.com/',
315-
'http://gitlab.com/': 'https://gitlab.com/',
316-
'http://www.gitlab.com/': 'https://gitlab.com/',
317-
'https://www.gitlab.com/': 'https://gitlab.com/',
318-
};
319-
for (final prefix in prefixReplacements.keys) {
320-
if (baseUrl!.startsWith(prefix)) {
321-
baseUrl = baseUrl.replaceFirst(prefix, prefixReplacements[prefix]!);
322-
}
323-
}
324-
if ((baseUrl!.startsWith('https://github.com/') ||
325-
baseUrl.startsWith('https://gitlab.com/')) &&
326-
baseUrl.endsWith('.git')) {
327-
baseUrl = baseUrl.substring(0, baseUrl.length - 4);
328-
}
329-
330-
return baseUrl;
331-
}
332-
333278
/// Infer the hosting/service provider for a given URL.
334279
String? inferServiceProviderName(String? url) {
335280
if (url == null) {
@@ -383,57 +328,6 @@ String myPublishersUrl() => '/my-publishers';
383328
String myActivityLogUrl() => '/my-activity-log';
384329
String createPublisherUrl() => '/create-publisher';
385330

386-
/// Returns an URL that is likely the downloadable URL of the given path.
387-
String? getRepositoryUrl(
388-
String? repository,
389-
String relativePath, {
390-
String branch = 'master',
391-
}) {
392-
if (repository == null || repository.isEmpty) return null;
393-
for (final key in _repositoryReplacePrefixes.keys) {
394-
if (repository!.startsWith(key)) {
395-
repository =
396-
repository.replaceFirst(key, _repositoryReplacePrefixes[key]!);
397-
}
398-
}
399-
try {
400-
final uri = Uri.parse(repository!);
401-
final segments = List.of(uri.pathSegments);
402-
while (segments.isNotEmpty && segments.last.isEmpty) {
403-
segments.removeLast();
404-
}
405-
406-
if (repository.startsWith('https://github.com/') ||
407-
repository.startsWith('https://gitlab.com/')) {
408-
if (segments.length >= 2 &&
409-
segments[1].endsWith('.git') &&
410-
segments[1].length > 4) {
411-
segments[1] = segments[1].substring(0, segments[1].length - 4);
412-
}
413-
414-
final extension = p.extension(relativePath).toLowerCase();
415-
final isRaw = _imageExtensions.contains(extension);
416-
final typeSegment = isRaw ? 'raw' : 'blob';
417-
418-
if (segments.length < 2) {
419-
return null;
420-
} else if (segments.length == 2) {
421-
final newUrl = uri.replace(pathSegments: segments).toString();
422-
return p.url.join(newUrl, typeSegment, branch, relativePath);
423-
} else if (segments[2] == 'tree' || segments[2] == 'blob') {
424-
segments[2] = typeSegment;
425-
final newUrl = uri.replace(pathSegments: segments).toString();
426-
return p.url.join(newUrl, relativePath);
427-
} else {
428-
return null;
429-
}
430-
}
431-
} catch (_) {
432-
return null;
433-
}
434-
return null;
435-
}
436-
437331
/// Parses [url] and returns the [Uri] object only if the result Uri is valid
438332
/// (e.g. is relative or has recognized scheme).
439333
Uri? parseValidUrl(String? url) {

0 commit comments

Comments
 (0)