summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2017-02-26 08:52:23 +0100
committerYorhel <git@yorhel.nl>2017-02-26 08:52:23 +0100
commit8e5fa1e1652a007a49805ba7e35d5aba935bfc1e (patch)
treeab50217b4818d8174562965d64c11abf0b87be2f
parent81e2c99503a35cb73346a625097f17eb457992eb (diff)
www: Include .so mans if found in the same package
Unfortunately, this can lead to slightly confusing scenarios, because the exact package of the displayed man page is not very well defined. It's possible that, when browsing from a package listing to a man page, you may see an included file that does not come from the package you browsed from. E.g. https://manned.org/pwrite/5f2909f6 - that man page simply includes pread.2, but from the URL it's unclear from which package or system it should be included. The only way to fix this is to add the package ID to the link format.
-rw-r--r--lib/ManUtils/ManUtils.pm8
-rwxr-xr-xwww/index.pl60
2 files changed, 45 insertions, 23 deletions
diff --git a/lib/ManUtils/ManUtils.pm b/lib/ManUtils/ManUtils.pm
index 0b4dd08..ef59f5c 100644
--- a/lib/ManUtils/ManUtils.pm
+++ b/lib/ManUtils/ManUtils.pm
@@ -24,14 +24,6 @@ sub fmt {
$$output = '';
@$errors = ();
- # tix comes with[1] a custom(?) macro package. But it looks okay even without
- # loading that.
- # [1] It actually doesn't, the tcllib package appears to have that file, but
- # doesn't '.so' it.
- $input =~ s/^\.so man.macros$//mg;
- # Other .so's should be handled by html()
- $input =~ s/^\.so (.+)$/.in -10\n.sp\n\[\[\[MANNEDINCLUDE$1\]\]\]/mg;
-
$input =
# Disable hyphenation, since that screws up man page references. :-(
".hy 0\n.de hy\n..\n"
diff --git a/www/index.pl b/www/index.pl
index 8eb2c06..8769129 100755
--- a/www/index.pl
+++ b/www/index.pl
@@ -618,20 +618,49 @@ sub _normalizename {
}
+# Replace .so's in man source with the contents (if available in the same
+# package) or with a reference to the other man page.
+sub soelim {
+ my($self, $verid, $src) = @_;
+
+ # tix comes with[1] a custom(?) macro package. But it looks okay even without
+ # loading that.
+ # [1] It actually doesn't, the tcllib package appears to have that file, but
+ # doesn't '.so' it.
+ $src =~ s/^\.so man.macros$//mg;
+
+ # Other .so's should be handled by html()
+ $src =~ s{^\.so (.+)$}{
+ my $path = $1;
+ my $name = (reverse split /\//, $path)[0];
+ my($man) = $verid ? $self->dbManPrefName($name, pkgver => $verid) : ();
+ if($man) {
+ # Recursive soelim, but the second call gets $verid=0 so we don't keep checking the database
+ soelim($self, 0, $self->dbManContent($man->{hash}))
+ } else {
+ ".in -10\n.sp\n\[\[\[MANNEDINCLUDE$path\]\]\]"
+ }
+ }emg;
+ return $src;
+}
+
+
sub man {
my($self, $name, $hash) = @_;
$name = _normalizename($name);
- my $man;
- if($hash) {
- $man = $self->dbManInfo(name => $name, shorthash => $hash)->[0];
- } else {
- ($man, undef) = $self->dbManPrefName($name);
- }
+ # Unfortunately, even in the permalink format with the hash, we don't know
+ # from which package we're supposed to get the man page. This info is
+ # needed in order to do .so substitution, so we can substitute files from
+ # the same package as the requested man page. Use the dbManPref logic here
+ # to deterministically select a good package.
+ my($man, undef) = $hash
+ ? $self->dbManPref(name => $name, shorthash => $hash)
+ : $self->dbManPrefName($name);
return $self->resNotFound() if !$man;
- my $fmt = ManUtils::html(ManUtils::fmt_block $self->dbManContent($man->{hash}));
+ my $fmt = ManUtils::html(ManUtils::fmt_block soelim $self, $man->{verid}, $self->dbManContent($man->{hash}));
my @toc;
$fmt =~ s{\n<b>(.+?)<\/b>\n}{
push @toc, $1;
@@ -884,7 +913,7 @@ sub dbManInfo {
$o{sort} eq 'syspkgname' ? 'ORDER BY s.name, s.relorder DESC, p.name, v.released DESC, m.name, m.locale NULLS FIRST, m.filename' : '';
my $select = $o{countonly} ? 'COUNT(*) as count'
- : "p.system, p.category, p.name AS package, v.version, v.released, m.name, m.section, m.filename, m.locale, encode(m.hash, 'hex') AS hash";
+ : "p.system, p.category, p.name AS package, v.version, v.released, v.id AS verid, m.name, m.section, m.filename, m.locale, encode(m.hash, 'hex') AS hash";
my($r, $np) = $s->dbPage(\%o, q{
SELECT !s
@@ -919,10 +948,11 @@ sub dbSearch {
# Get the preferred man page for the given filters. Returns a row with the same fields as dbManInfo().
sub dbManPref {
- my($s, $name, $section, %o) = @_;
+ my($s, %o) = @_;
my %where = (
- 'm.name = ?' => $name,
- $section ? ('m.section LIKE ?' => escape_like($section).'%') : (),
+ $o{name} ? ('m.name = ?' => $o{name}) : (),
+ $o{shorthash} ? (q{substring(m.hash from 1 for 4) = decode(?, 'hex')} => $o{shorthash}) : (),
+ $o{section} ? ('m.section LIKE ?' => escape_like($o{section}).'%') : (),
$o{sysid} ? ('p.system = ?' => $o{sysid}) : (),
$o{package} ? ('p.id = ?' => $o{package}) : (),
$o{pkgver} ? ('v.id = ?' => $o{pkgver}) : (),
@@ -962,10 +992,10 @@ sub dbManPref {
), f_secorder AS(
SELECT * FROM f_sysrel a WHERE NOT EXISTS(SELECT 1 FROM f_sysrel b WHERE (a.man).section > (b.man).section)
)
- SELECT (pkg).system, (pkg).category, (pkg).name AS package, (ver).version, (ver).released,
+ SELECT (pkg).system, (pkg).category, (pkg).name AS package, (ver).version, (ver).released, (ver).id AS verid,
(man).name, (man).section, (man).filename, (man).locale, encode((man).hash, 'hex') AS hash
FROM f_secorder ORDER BY (man).hash LIMIT 1
- }, \%where, $section, $section)->[0];
+ }, \%where, $o{section}||'', $o{section}||'')->[0];
}
@@ -974,12 +1004,12 @@ sub dbManPref {
sub dbManPrefName {
my($s, $name, %o) = @_;
- my $man = $s->dbManPref($name, '', %o);
+ my $man = $s->dbManPref(%o, name => $name);
return ($man, '') if $man;
return (undef, '') if $name !~ s/\.([^.]+)$//;
my $section = $1;
- $man = $s->dbManPref($name, $section, %o);
+ $man = $s->dbManPref(%o, name => $name, section => $section);
return ($man, $section) if $man;
return (undef, '');
}