diff options
author | Yorhel <git@yorhel.nl> | 2017-02-26 08:52:23 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2017-02-26 08:52:23 +0100 |
commit | 8e5fa1e1652a007a49805ba7e35d5aba935bfc1e (patch) | |
tree | ab50217b4818d8174562965d64c11abf0b87be2f | |
parent | 81e2c99503a35cb73346a625097f17eb457992eb (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.pm | 8 | ||||
-rwxr-xr-x | www/index.pl | 60 |
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, ''); } |