diff options
Diffstat (limited to 'roles/wiki/templates')
| -rw-r--r-- | roles/wiki/templates/Scrubber.pm | 749 | ||||
| -rw-r--r-- | roles/wiki/templates/copyright.pm | 60 | ||||
| -rw-r--r-- | roles/wiki/templates/emacsconf.setup | 440 | ||||
| -rwxr-xr-x | roles/wiki/templates/htmlscrubber.pm | 132 | ||||
| -rw-r--r-- | roles/wiki/templates/license.pm | 59 | 
5 files changed, 1440 insertions, 0 deletions
diff --git a/roles/wiki/templates/Scrubber.pm b/roles/wiki/templates/Scrubber.pm new file mode 100644 index 0000000..2efaa10 --- /dev/null +++ b/roles/wiki/templates/Scrubber.pm @@ -0,0 +1,749 @@ +package HTML::Scrubber; + +# ABSTRACT: Perl extension for scrubbing/sanitizing html + + +use 5.008;    # enforce minimum perl version of 5.8 +use strict; +use warnings; +use HTML::Parser 3.47 (); +use HTML::Entities; +use Scalar::Util ('weaken'); + +our ( @_scrub, @_scrub_fh ); + +our $VERSION = '0.15'; # VERSION +our $AUTHORITY = 'cpan:NIGELM'; # AUTHORITY + +# my my my my, these here to prevent foolishness like +# http://perlmonks.org/index.pl?node_id=251127#Stealing+Lexicals +(@_scrub)    = ( \&_scrub,    "self, event, tagname, attr, attrseq, text" ); +(@_scrub_fh) = ( \&_scrub_fh, "self, event, tagname, attr, attrseq, text" ); + +sub new { +    my $package = shift; +    my $p       = HTML::Parser->new( +        api_version             => 3, +        default_h               => \@_scrub, +        marked_sections         => 0, +        strict_comment          => 0, +        unbroken_text           => 1, +        case_sensitive          => 0, +        boolean_attribute_value => undef, +        empty_element_tags      => 1, +    ); + +    my $self = { +        _p        => $p, +        _rules    => { '*' => 0, }, +        _comment  => 0, +        _process  => 0, +        _r        => "", +        _optimize => 1, +        _script   => 0, +        _style    => 0, +    }; + +    $p->{"\0_s"} = bless $self, $package; +    weaken( $p->{"\0_s"} ); + +    return $self unless @_; + +    my (%args) = @_; + +    for my $f (qw[ default allow deny rules process comment ]) { +        next unless exists $args{$f}; +        if ( ref $args{$f} ) { +            $self->$f( @{ $args{$f} } ); +        } +        else { +            $self->$f( $args{$f} ); +        } +    } + +    return $self; +} + + +sub comment { +    return $_[0]->{_comment} +        if @_ == 1; +    $_[0]->{_comment} = $_[1]; +    return; +} + + +sub process { +    return $_[0]->{_process} +        if @_ == 1; +    $_[0]->{_process} = $_[1]; +    return; +} + + +sub script { +    return $_[0]->{_script} +        if @_ == 1; +    $_[0]->{_script} = $_[1]; +    return; +} + + +sub style { +    return $_[0]->{_style} +        if @_ == 1; +    $_[0]->{_style} = $_[1]; +    return; +} + + +sub allow { +    my $self = shift; +    for my $k (@_) { +        $self->{_rules}{ lc $k } = 1; +    } +    $self->{_optimize} = 1;    # each time a rule changes, reoptimize when parse + +    return; +} + + +sub deny { +    my $self = shift; + +    for my $k (@_) { +        $self->{_rules}{ lc $k } = 0; +    } + +    $self->{_optimize} = 1;    # each time a rule changes, reoptimize when parse + +    return; +} + + +sub rules { +    my $self = shift; +    my (%rules) = @_; +    for my $k ( keys %rules ) { +        $self->{_rules}{ lc $k } = $rules{$k}; +    } + +    $self->{_optimize} = 1;    # each time a rule changes, reoptimize when parse + +    return; +} + + +sub default { +    return $_[0]->{_rules}{'*'} +        if @_ == 1; + +    $_[0]->{_rules}{'*'} = $_[1] if defined $_[1]; +    $_[0]->{_rules}{'_'} = $_[2] if defined $_[2] and ref $_[2]; +    $_[0]->{_optimize} = 1;    # each time a rule changes, reoptimize when parse + +    return; +} + + +sub scrub_file { +    if ( @_ > 2 ) { +        return unless defined $_[0]->_out( $_[2] ); +    } +    else { +        $_[0]->{_p}->handler( default => @_scrub ); +    } + +    $_[0]->_optimize();    #if $_[0]->{_optimize}; + +    $_[0]->{_p}->parse_file( $_[1] ); + +    return delete $_[0]->{_r} unless exists $_[0]->{_out}; +    print { $_[0]->{_out} } $_[0]->{_r} if length $_[0]->{_r}; +    delete $_[0]->{_out}; +    return 1; +} + + +sub scrub { +    if ( @_ > 2 ) { +        return unless defined $_[0]->_out( $_[2] ); +    } +    else { +        $_[0]->{_p}->handler( default => @_scrub ); +    } + +    $_[0]->_optimize();    # if $_[0]->{_optimize}; + +    $_[0]->{_p}->parse( $_[1] ) if defined( $_[1] ); +    $_[0]->{_p}->eof(); + +    return delete $_[0]->{_r} unless exists $_[0]->{_out}; +    delete $_[0]->{_out}; +    return 1; +} + + +sub _out { +    my ( $self, $o ) = @_; + +    unless ( ref $o and ref \$o ne 'GLOB' ) { +        open my $F, '>', $o or return; +        binmode $F; +        $self->{_out} = $F; +    } +    else { +        $self->{_out} = $o; +    } + +    $self->{_p}->handler( default => @_scrub_fh ); + +    return 1; +} + + +sub _validate { +    my ( $s, $t, $r, $a, $as ) = @_; +    return "<$t>" unless %$a; + +    $r = $s->{_rules}->{$r}; +    my %f; + +    for my $k ( keys %$a ) { +        my $check = exists $r->{$k} ? $r->{$k} : exists $r->{'*'} ? $r->{'*'} : next; + +        if ( ref $check eq 'CODE' ) { +            my @v = $check->( $s, $t, $k, $a->{$k}, $a, \%f ); +            next unless @v; +            $f{$k} = shift @v; +        } +        elsif ( ref $check || length($check) > 1 ) { +            $f{$k} = $a->{$k} if $a->{$k} =~ m{$check}; +        } +        elsif ($check) { +            $f{$k} = $a->{$k}; +        } +    } + +    if (%f) { +        my %seen; +        return "<$t $r>" +            if $r = join ' ', map { +            defined $f{$_} +                ? qq[$_="] . encode_entities( $f{$_} ) . q["] +                : $_;    # boolean attribute (TODO?) +            } grep { exists $f{$_} and !$seen{$_}++; } @$as; +    } + +    return "<$t>"; +} + + +sub _scrub_str { +    my ( $p, $e, $t, $a, $as, $text ) = @_; + +    my $s      = $p->{"\0_s"}; +    my $outstr = ''; + +    if ( $e eq 'start' ) { +        if ( exists $s->{_rules}->{$t} )    # is there a specific rule +        { +            if ( ref $s->{_rules}->{$t} )    # is it complicated?(not simple;) +            { +                $outstr .= $s->_validate( $t, $t, $a, $as ); +            } +            elsif ( $s->{_rules}->{$t} )     # validate using default attribute rule +            { +                $outstr .= $s->_validate( $t, '_', $a, $as ); +            } +        } +        elsif ( $s->{_rules}->{'*'} )        # default allow tags +        { +            $outstr .= $s->_validate( $t, '_', $a, $as ); +        } +    } +    elsif ( $e eq 'end' ) { +        my $place = 0; +        if ( exists $s->{_rules}->{$t} ) { +            $place = 1 if $s->{_rules}->{$t}; +        } +        elsif ( $s->{_rules}->{'*'} ) { +            $place = 1; +        } +        if ($place) { +            if ( length $text ) { +                $outstr .= "</$t>"; +            } +            else { +                substr $s->{_r}, -1, 0, ' /'; +            } +        } +    } +    elsif ( $e eq 'comment' ) { +        if ( $s->{_comment} ) { + +            # only copy comments through if they are well formed... +            $outstr .= $text if ( $text =~ m|^<!--.*-->$|ms ); +        } +    } +    elsif ( $e eq 'process' ) { +        $outstr .= $text if $s->{_process}; +    } +    elsif ( $e eq 'text' or $e eq 'default' ) { +        $text =~ s/</</g;    #https://rt.cpan.org/Ticket/Attachment/8716/10332/scrubber.patch +        $text =~ s/>/>/g; + +        $outstr .= $text; +    } +    elsif ( $e eq 'start_document' ) { +        $outstr = ""; +    } + +    return $outstr; +} + + +sub _scrub_fh { +    my $self = $_[0]->{"\0_s"}; +    print { $self->{_out} } $self->{'_r'} if length $self->{_r}; +    $self->{'_r'} = _scrub_str(@_); +} + + +sub _scrub { + +    $_[0]->{"\0_s"}->{_r} .= _scrub_str(@_); +} + +sub _optimize { +    my ($self) = @_; + +    my (@ignore_elements) = grep { not $self->{"_$_"} } qw(script style); +    $self->{_p}->ignore_elements(@ignore_elements);    # if @ is empty, we reset ;) + +    return unless $self->{_optimize}; + +    #sub allow +    #    return unless $self->{_optimize}; # till I figure it out (huh) + +    if ( $self->{_rules}{'*'} ) {    # default allow +        $self->{_p}->report_tags();    # so clear it +    } +    else { + +        my (@reports) = +            grep {                     # report only tags we want +            $self->{_rules}{$_} +            } keys %{ $self->{_rules} }; + +        $self->{_p}->report_tags(      # default deny, so optimize +            @reports +        ) if @reports; +    } + +    # sub deny +    #    return unless $self->{_optimize}; # till I figure it out (huh) +    my (@ignores) = +        grep { not $self->{_rules}{$_} } grep { $_ ne '*' } keys %{ $self->{_rules} }; + +    $self->{_p}->ignore_tags(    # always ignore stuff we don't want +        @ignores +    ) if @ignores; + +    $self->{_optimize} = 0; +    return; +} + +1; + +#print sprintf q[ '%-12s => %s,], "$_'", $h{$_} for sort keys %h;# perl! +#perl -ne"chomp;print $_;print qq'\t\t# test ', ++$a if /ok\(/;print $/" test.pl >test2.pl +#perl -ne"chomp;print $_;if( /ok\(/ ){s/\#test \d+$//;print qq'\t\t# test ', ++$a }print $/" test.pl >test2.pl +#perl -ne"chomp;if(/ok\(/){s/# test .*$//;print$_,qq'\t\t# test ',++$a}else{print$_}print$/" test.pl >test2.pl + +__END__ + +=pod + +=for stopwords html cpan callback homepage Perlbrew perltidy respository + +=head1 NAME + +HTML::Scrubber - Perl extension for scrubbing/sanitizing html + +=head1 VERSION + +version 0.15 + +=head1 SYNOPSIS + +    use HTML::Scrubber; + +    my $scrubber = HTML::Scrubber->new( allow => [ qw[ p b i u hr br ] ] ); +    print $scrubber->scrub('<p><b>bold</b> <em>missing</em></p>'); +    # output is: <p><b>bold</b> </p> + +    # more complex input +    my $html = q[ +    <style type="text/css"> BAD { background: #666; color: #666;} </style> +    <script language="javascript"> alert("Hello, I am EVIL!");    </script> +    <HR> +        a   => <a href=1>link </a> +        br  => <br> +        b   => <B> bold </B> +        u   => <U> UNDERLINE </U> +    ]; + +    print $scrubber->scrub($html); + +    $scrubber->deny( qw[ p b i u hr br ] ); + +    print $scrubber->scrub($html); + +=head1 DESCRIPTION + +If you want to "scrub" or "sanitize" html input in a reliable and flexible +fashion, then this module is for you. + +I wasn't satisfied with HTML::Sanitizer because it is based on +HTML::TreeBuilder, so I thought I'd write something similar that works directly +with HTML::Parser. + +=head1 METHODS + +First a note on documentation: just study the L<EXAMPLE|"EXAMPLE"> below. It's +all the documentation you could need + +Also, be sure to read all the comments as well as L<How does it work?|"How does +it work?">. + +If you're new to perl, good luck to you. + +=head2 comment + +    warn "comments are  ", $p->comment ? 'allowed' : 'not allowed'; +    $p->comment(0);  # off by default + +=head2 process + +    warn "process instructions are  ", $p->process ? 'allowed' : 'not allowed'; +    $p->process(0);  # off by default + +=head2 script + +    warn "script tags (and everything in between) are supressed" +        if $p->script;      # off by default +    $p->script( 0 || 1 ); + +B<**> Please note that this is implemented using HTML::Parser's ignore_elements +function, so if C<script> is set to true, all script tags encountered will be +validated like all other tags. + +=head2 style + +    warn "style tags (and everything in between) are supressed" +        if $p->style;       # off by default +    $p->style( 0 || 1 ); + +B<**> Please note that this is implemented using HTML::Parser's ignore_elements +function, so if C<style> is set to true, all style tags encountered will be +validated like all other tags. + +=head2 allow + +    $p->allow(qw[ t a g s ]); + +=head2 deny + +    $p->deny(qw[ t a g s ]); + +=head2 rules + +    $p->rules( +        img => { +            src => qr{^(?!http://)}i, # only relative image links allowed +            alt => 1,                 # alt attribute allowed +            '*' => 0,                 # deny all other attributes +        }, +        a => { +            href => sub { ... },      # check or adjust with a callback +        }, +        b => 1, +        ... +    ); + +Updates set of attribute rules. Each rule can be 1/0, regular expression or a +callback. Values longer than 1 char are treated as regexps. Callback is called +with the following arguments: this object, tag name, attribute name and +attribute value, should return empty list to drop attribute, C<undef> to keep +it without value or a new scalar value. + +=head2 default + +    print "default is ", $p->default(); +    $p->default(1);      # allow tags by default +    $p->default( +        undef,           # don't change +        {                # default attribute rules +            '*' => 1,    # allow attributes by default +        } +    ); + +=head2 scrub_file + +    $html = $scrubber->scrub_file('foo.html');   ## returns giant string +    die "Eeek $!" unless defined $html;  ## opening foo.html may have failed +    $scrubber->scrub_file('foo.html', 'new.html') or die "Eeek $!"; +    $scrubber->scrub_file('foo.html', *STDOUT) +        or die "Eeek $!" +            if fileno STDOUT; + +=head2 scrub + +    print $scrubber->scrub($html);  ## returns giant string +    $scrubber->scrub($html, 'new.html') or die "Eeek $!"; +    $scrubber->scrub($html', *STDOUT) +        or die "Eeek $!" +            if fileno STDOUT; + +=for comment _out +    $scrubber->_out(*STDOUT) if fileno STDOUT; +    $scrubber->_out('foo.html') or die "eeek $!"; + +=for comment _validate +Uses $self->{_rules} to do attribute validation. +Takes tag, rule('_' || $tag), attrref. + +=for comment _scrub_str + +I<default> handler, used by both _scrub and _scrub_fh Moved all the common code +(basically all of it) into a single routine for ease of maintenance + +=for comment _scrub_fh + +I<default> handler, does the scrubbing if we're scrubbing out to a file. Now +calls _scrub_str and pushes that out to a file. + +=for comment _scrub + +I<default> handler, does the scrubbing if we're returning a giant string. Now +calls _scrub_str and appends that to the output string. + +=head1 How does it work? + +When a tag is encountered, HTML::Scrubber allows/denies the tag using the +explicit rule if one exists. + +If no explicit rule exists, Scrubber applies the default rule. + +If an explicit rule exists, but it's a simple rule(1), the default attribute +rule is applied. + +=head2 EXAMPLE + +=for example begin + +    #!/usr/bin/perl -w +    use HTML::Scrubber; +    use strict; + +    my @allow = qw[ br hr b a ]; + +    my @rules = ( +        script => 0, +        img    => { +            src => qr{^(?!http://)}i,    # only relative image links allowed +            alt => 1,                    # alt attribute allowed +            '*' => 0,                    # deny all other attributes +        }, +    ); + +    my @default = ( +        0 =>                             # default rule, deny all tags +            { +            '*'    => 1,                             # default rule, allow all attributes +            'href' => qr{^(?:http|https|ftp)://}i, +            'src'  => qr{^(?:http|https|ftp)://}i, + +            #   If your perl doesn't have qr +            #   just use a string with length greater than 1 +            'cite'        => '(?i-xsm:^(?:http|https|ftp):)', +            'language'    => 0, +            'name'        => 1,                                 # could be sneaky, but hey ;) +            'onblur'      => 0, +            'onchange'    => 0, +            'onclick'     => 0, +            'ondblclick'  => 0, +            'onerror'     => 0, +            'onfocus'     => 0, +            'onkeydown'   => 0, +            'onkeypress'  => 0, +            'onkeyup'     => 0, +            'onload'      => 0, +            'onmousedown' => 0, +            'onmousemove' => 0, +            'onmouseout'  => 0, +            'onmouseover' => 0, +            'onmouseup'   => 0, +            'onreset'     => 0, +            'onselect'    => 0, +            'onsubmit'    => 0, +            'onunload'    => 0, +            'src'         => 0, +            'type'        => 0, +            } +    ); + +    my $scrubber = HTML::Scrubber->new(); +    $scrubber->allow(@allow); +    $scrubber->rules(@rules);    # key/value pairs +    $scrubber->default(@default); +    $scrubber->comment(1);       # 1 allow, 0 deny + +    ## preferred way to create the same object +    $scrubber = HTML::Scrubber->new( +        allow   => \@allow, +        rules   => \@rules, +        default => \@default, +        comment => 1, +        process => 0, +    ); + +    require Data::Dumper, die Data::Dumper::Dumper($scrubber) if @ARGV; + +    my $it = q[ +        <?php   echo(" EVIL EVIL EVIL "); ?>    <!-- asdf --> +        <hr> +        <I FAKE="attribute" > IN ITALICS WITH FAKE="attribute" </I><br> +        <B> IN BOLD </B><br> +        <A NAME="evil"> +            <A HREF="javascript:alert('die die die');">HREF=JAVA <!></A> +            <br> +            <A HREF="image/bigone.jpg" ONMOUSEOVER="alert('die die die');"> +                <IMG SRC="image/smallone.jpg" ALT="ONMOUSEOVER JAVASCRIPT"> +            </A> +        </A> <br> +    ]; + +    print "#original text", $/, $it, $/; +    print +        "#scrubbed text (default ", $scrubber->default(),    # no arguments returns the current value +        " comment ", $scrubber->comment(), " process ", $scrubber->process(), " )", $/, $scrubber->scrub($it), $/; + +    $scrubber->default(1);                                   # allow all tags by default +    $scrubber->comment(0);                                   # deny comments + +    print +        "#scrubbed text (default ", +        $scrubber->default(), +        " comment ", +        $scrubber->comment(), +        " process ", +        $scrubber->process(), +        " )", $/, +        $scrubber->scrub($it), +        $/; + +    $scrubber->process(1);    # allow process instructions (dangerous) +    $default[0] = 1;          # allow all tags by default +    $default[1]->{'*'} = 0;   # deny all attributes by default +    $scrubber->default(@default);    # set the default again + +    print +        "#scrubbed text (default ", +        $scrubber->default(), +        " comment ", +        $scrubber->comment(), +        " process ", +        $scrubber->process(), +        " )", $/, +        $scrubber->scrub($it), +        $/; + +=for example end + +=head2 FUN + +If you have Test::Inline (and you've installed HTML::Scrubber), try + +    pod2test Scrubber.pm >scrubber.t +    perl scrubber.t + +=head1 SEE ALSO + +L<HTML::Parser>, L<Test::Inline>. + +The C<HTML::Sanitizer> module is no longer available on CPAN. + +=head1 VERSION REQUIREMENTS + +As of version 0.14 I have added a perl minimum version requirement of 5.8. This +is basically due to failures on the smokers perl 5.6 installations - which +appears to be down to installation mechanisms and requirements. + +Since I don't want to spend the time supporting a version that is so old (and +may not work for reasons on UTF support etc), I have added a C<use 5.008;> to +the main module. + +If this is problematic I am very willing to accept patches to fix this up, +although I do not personally see a good reason to support a release that has +been obsolete for 13 years. + +=head1 CONTRIBUTING + +If you want to contribute to the development of this module, the code is on +L<GitHub|http://github.com/nigelm/html-scrubber>. You'll need a perl +environment with L<Dist::Zilla>, and if you're just getting started, there's +some documentation on using Vagrant and Perlbrew +L<here|http://mrcaron.github.io/2015/03/06/Perl-CPAN-Pull-Request.html>. + +There is now a C<.perltidyrc> and a <.tidyallrc> file within the respository +for the standard perltidy settings used - I will apply these before new +releases.  Please do not let formatting prevent you from sending in patches etc +- this can be sorted out as part of the release process.  Info on C<tidyall> +can be found at +L<https://metacpan.org/pod/distribution/Code-TidyAll/bin/tidyall>. + +=head1 INSTALLATION + +See perlmodinstall for information and options on installing Perl modules. + +=head1 BUGS AND LIMITATIONS + +You can make new bug reports, and view existing ones, through the +web interface at L<http://rt.cpan.org/Public/Dist/Display.html?Name=HTML-Scrubber>. + +=head1 AVAILABILITY + +The project homepage is L<https://metacpan.org/release/HTML-Scrubber>. + +The latest version of this module is available from the Comprehensive Perl +Archive Network (CPAN). Visit L<http://www.perl.com/CPAN/> to find a CPAN +site near you, or see L<https://metacpan.org/module/HTML::Scrubber/>. + +=head1 AUTHORS + +=over 4 + +=item * + +Ruslan Zakirov <Ruslan.Zakirov@gmail.com> + +=item * + +Nigel Metheringham <nigelm@cpan.org> + +=item * + +D. H. <podmaster@cpan.org> + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2015 by Ruslan Zakirov, Nigel Metheringham, 2003-2004 D. H.. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut diff --git a/roles/wiki/templates/copyright.pm b/roles/wiki/templates/copyright.pm new file mode 100644 index 0000000..16acacc --- /dev/null +++ b/roles/wiki/templates/copyright.pm @@ -0,0 +1,60 @@ +# A plugin for ikiwiki to implement adding a footer with copyright information +# based on a default value taken out of a file. + +# Copyright © 2007, 2008 Thomas Schwinge <tschwinge@gnu.org> +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +#  +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License +# for more details. +#  +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Unless overridden with the `meta' plugin, a footer with copyright information +# will be added to every page using a source file `copyright' (e.g., +# `copyright.mdwn') (using the same ``locating rules'' as for the sidebar +# plugin). +# +# The state which page's copyright text was gathered from which source is not +# tracked, so you'll need a full wiki-rebuild if the `copyright' file is +# changed. + +package IkiWiki::Plugin::copyright; + +use warnings; +use strict; +use IkiWiki 2.00; + +my %copyright; + +sub import +{ +    hook (type => "scan", id => "copyright", call => \&scan); +} + +sub scan (@) +{ +    my %params = @_; +    my $page = $params{page}; + +    return if defined $pagestate{$page}{meta}{copyright}; + +    my $content; +    my $copyright_page = bestlink ($page, "copyright") || return; +    my $copyright_file = $pagesources{$copyright_page} || return; + +    # Only an optimization to avoid reading the same file again and again. +    $copyright{$copyright_file} = readfile (srcfile ($copyright_file)) +	unless defined $copyright{$copyright_file}; + +    $pagestate{$page}{meta}{copyright} = $copyright{$copyright_file}; +} + +1 diff --git a/roles/wiki/templates/emacsconf.setup b/roles/wiki/templates/emacsconf.setup new file mode 100644 index 0000000..7ab3916 --- /dev/null +++ b/roles/wiki/templates/emacsconf.setup @@ -0,0 +1,440 @@ +# This file is managed by the wiki role in git@git.emacsconf.org:pub/emacsconf-ansible +# Please make sure your changes are also reflected there. +# +# IkiWiki::Setup::Yaml - YAML formatted setup file +# +# Setup file for ikiwiki. +#  +# Passing this to ikiwiki --setup will make ikiwiki generate +# wrappers and build the wiki. +#  +# Remember to re-run ikiwiki --setup any time you edit this file. +# +# name of the wiki +wikiname: EmacsConf +# contact email for wiki +adminemail: {{ikiwiki_admin}} +# users who are wiki admins +adminuser: +- bandali +# users who are banned from the wiki +banned_users: [] +# where the source of the wiki is located +srcdir: {{ ikiwiki_src_dir }} +# where to build the wiki +destdir: {{ ikiwiki_dest }} +# base url to the wiki +url: {{ ikiwiki_url }} +# url to the ikiwiki.cgi +#cgiurl: https://emacsconf.org/ikiwiki.cgi +# do not adjust cgiurl if CGI is accessed via different URL +reverse_proxy: 0 +# filename of cgi wrapper to generate +#cgi_wrapper: /home/ikiwiki/public_html/emacsconf/ikiwiki.cgi +cgi_wrapper: {{ ikiwiki_path }}/ikiwiki.cgi +# mode for cgi_wrapper (can safely be made suid) +cgi_wrappermode: 06755 +# number of seconds to delay CGI requests when overloaded +cgi_overload_delay: '' +# message to display when overloaded (may contain html) +cgi_overload_message: '' +# enable optimization of only refreshing committed changes? +only_committed_changes: 0 +# rcs backend to use +rcs: git +# plugins to add to the default configuration +add_plugins: +{% for plugin in ikiwiki_plugins %} +- {{ plugin }} +{% endfor %} +# plugins to disable +disable_plugins: [] +#disable_plugins: +#- editpage +# additional directory to search for template files +#templatedir: /usr/share/ikiwiki/templates +#templatedir: /home/ikiwiki/.ikiwiki/templates +# base wiki source location +underlaydir: {{ ikiwiki_underlay }} +# display verbose messages? +#verbose: 1 +# log to syslog? +syslog: 1 +# create output files named page/index.html? +usedirs: 1 +# use '!'-prefixed preprocessor directives? +prefix_directives: 1 +# use page/index.mdwn source files +indexpages: 0 +# enable Discussion pages? +discussion: 1 +# name of Discussion pages +discussionpage: discussion +# use elements new in HTML5 like <section>? +html5: 0 +# only send cookies over SSL connections? +sslcookie: 0 +# extension to use for new pages +default_pageext: md +# extension to use for html files +htmlext: html +# strftime format string to display date +#timeformat: '%c' +#timeformat: '%a %d %b %Y %r %Z' +timeformat: '%A %e %B %Y at %k:%M (%Z)' +# UTF-8 locale to use +#locale: en_US.UTF-8 +#locale: en_CA.UTF-8 +# put user pages below specified page +userdir: '' +# how many backlinks to show before hiding excess (0 to show all) +numbacklinks: 10 +# attempt to hardlink source files? (optimisation for large files) +hardlink: 0 +# force ikiwiki to use a particular umask (keywords public, group or private, or a number) +#umask: public +# group for wrappers to run in +#wrappergroup: ikiwiki +# extra library and plugin directories +libdirs: [] +# extra library and plugin directory (searched after libdirs) +libdir: {{ ikiwiki_plugin_path }} +# environment variables +ENV: {} +# time zone name +timezone: :/etc/localtime +# regexp of normally excluded files to include +#include: ^\.htaccess$ +# regexp of files that should be skipped +#exclude: ^(*\.private|Makefile)$ +# specifies the characters that are allowed in source filenames +wiki_file_chars: -[:alnum:]+/.:_ +# allow symlinks in the path leading to the srcdir (potentially insecure) +allow_symlinks_before_srcdir: 0 +# cookie control +cookiejar: +  file: {{ ikiwiki_cookie_jar }} +# set custom user agent string for outbound HTTP requests e.g. when fetching aggregated RSS feeds +useragent: ikiwiki/3.20190228-1 +# theme has a responsive layout? (mobile-optimized) +responsive_layout: 1 +# try harder to produce deterministic output +deterministic: 0 + +###################################################################### +# core plugins +#   (editpage, git, htmlscrubber, inline, link, meta, parentlinks, +#    templatebody) +###################################################################### + +# git plugin +# git hook to generate +#git_wrapper: /home/ikiwiki/emacsconf.git/hooks/post-update +git_wrapper: {{ ikiwiki_git_wrapper }} +# shell command for git_wrapper to run, in the background +#git_wrapper_background_command: git push github +# mode for git_wrapper (can safely be made suid) +#git_wrappermode: 06755 +# git pre-receive hook to generate +#git_test_receive_wrapper: /git/wiki.git/hooks/pre-receive +git_test_receive_wrapper: {{ ikiwiki_git_test_receive_wrapper }} +# unix users whose commits should be checked by the pre-receive hook +#untrusted_committers: [] +untrusted_committers: +- anon +# gitweb url to show file history ([[file]] substituted) +#historyurl: http://git.example.com/gitweb.cgi?p=wiki.git;a=history;f=[[file]];hb=HEAD +historyurl: {{ ikiwiki_git_base_url }}/log/[[file]] +# gitweb url to show a diff ([[file]], [[sha1_to]], [[sha1_from]], [[sha1_commit]], and [[sha1_parent]] substituted) +#diffurl: http://git.example.com/gitweb.cgi?p=wiki.git;a=blobdiff;f=[[file]];h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_commit]];hpb=[[sha1_parent]] +diffurl: {{ ikiwiki_git_base_url }}/diff/[[file]]?id=[[sha1_commit]]&id2=[[sha1_parent]] +# where to pull and push changes (set to empty string to disable) +#gitorigin_branch: origin +# branch that the wiki is stored in +#gitmaster_branch: {{ ikiwiki_git_branch }} + +# htmlscrubber plugin +# PageSpec specifying pages not to scrub +#htmlscrubber_skip: '!*/Discussion' + +# inline plugin +# enable rss feeds by default? +rss: 1 +# enable atom feeds by default? +atom: 1 +# allow rss feeds to be used? +#allowrss: 0 +# allow atom feeds to be used? +#allowatom: 0 +# urls to ping (using XML-RPC) on feed update +#pingurl: http://rpc.technorati.com/rpc/ping + +###################################################################### +# auth plugins +#   (anonok, blogspam, emailauth, httpauth, lockedit, moderatedcomments, +#    opendiscussion, openid, passwordauth, signinedit) +###################################################################### + +# anonok plugin +# PageSpec to limit which pages anonymous users can edit +#anonok_pagespec: '*/discussion' + +# blogspam plugin +# PageSpec of pages to check for spam +#blogspam_pagespec: postcomment(*) +# options to send to blogspam server +#blogspam_options: blacklist=1.2.3.4,blacklist=8.7.6.5,max-links=10 +# blogspam server JSON url +#blogspam_server: '' + +# emailauth plugin +# email address to send emailauth mails as (default: adminemail) +#emailauth_sender: '' + +# httpauth plugin +# url to redirect to when authentication is needed +#cgiauthurl: http://example.com/wiki/auth/ikiwiki.cgi +# PageSpec of pages where only httpauth will be used for authentication +#httpauth_pagespec: '!*/Discussion' + +# lockedit plugin +# PageSpec controlling which pages are locked +#locked_pages: '!*/Discussion' +#locked_pages: 'index or edit' +locked_pages: 'edit' + +# moderatedcomments plugin +# PageSpec matching users or comment locations to moderate +#moderate_pagespec: '*' + +# openid plugin +# url pattern of openid realm (default is cgiurl) +#openid_realm: '' +# url to ikiwiki cgi to use for openid authentication (default is cgiurl) +#openid_cgiurl: '' + +# passwordauth plugin +# a password that must be entered when signing up for an account +#account_creation_password: s3cr1t +# cost of generating a password using Authen::Passphrase::BlowfishCrypt +#password_cost: 8 + +###################################################################### +# format plugins +#   (creole, highlight, hnb, html, mdwn, otl, rawhtml, rst, textile, txt) +###################################################################### + +# highlight plugin +# types of source files to syntax highlight +#tohighlight: .c .h .cpp .pl .py Makefile:make +# location of highlight's filetypes.conf +#filetypes_conf: /etc/highlight/filetypes.conf +# location of highlight's langDefs directory +#langdefdir: /usr/share/highlight/langDefs + +# mdwn plugin +# enable multimarkdown features? +#multimarkdown: 0 +# disable use of markdown discount? +#nodiscount: 0 +# enable footnotes in Markdown (where supported)? +#mdwn_footnotes: 1 +# interpret line like 'A. First item' as ordered list when using Discount? +#mdwn_alpha_lists: 0 + +###################################################################### +# special-purpose plugins +#   (osm, underlay) +###################################################################### + +# osm plugin +# the default zoom when you click on the map link +#osm_default_zoom: 15 +# the icon shown on links and on the main map +#osm_default_icon: ikiwiki/images/osm.png +# the alt tag of links, defaults to empty +#osm_alt: '' +# the output format for waypoints, can be KML, GeoJSON or CSV (one or many, comma-separated) +#osm_format: KML +# the icon attached to a tag, displayed on the map for tagged pages +#osm_tag_default_icon: icon.png +# Url for the OpenLayers.js file +#osm_openlayers_url: http://www.openlayers.org/api/OpenLayers.js +# Layers to use in the map. Can be either the 'OSM' string or a type option for Google maps (GoogleNormal, GoogleSatellite, GoogleHybrid or GooglePhysical). It can also be an arbitrary URL in a syntax acceptable for OpenLayers.Layer.OSM.url parameter. +#osm_layers: +#  OSM: GoogleSatellite +# Google maps API key, Google layer not used if missing, see https://code.google.com/apis/console/ to get an API key +#osm_google_apikey: '' + +# underlay plugin +# extra underlay directories to add +#add_underlays: +#- /home/ikiwiki/wiki.underlay + +###################################################################### +# web plugins +#   (404, attachment, comments, editdiff, edittemplate, getsource, google, +#    goto, mirrorlist, remove, rename, repolist, search, theme, userlist, +#    websetup, wmd) +###################################################################### + +# attachment plugin +# enhanced PageSpec specifying what attachments are allowed +#allowed_attachments: virusfree() and mimetype(image/*) and maxsize(50kb) +allowed_attachments: (mimetype(text/*) or *.m3u or *.svg) and maxsize(300kb) +# virus checker program (reads STDIN, returns nonzero if virus found) +#virus_checker: clamdscan - + +# comments plugin +# PageSpec of pages where comments are allowed +#comments_pagespec: blog/* and !*/Discussion +# PageSpec of pages where posting new comments is not allowed +#comments_closed_pagespec: blog/controversial or blog/flamewar +# Base name for comments, e.g. "comment_" for pages like "sandbox/comment_12" +#comments_pagename: '' +# Interpret directives in comments? +#comments_allowdirectives: 0 +# Allow anonymous commenters to set an author name? +#comments_allowauthor: 0 +# commit comments to the VCS +#comments_commit: 1 +# Restrict formats for comments to (no restriction if empty) +#comments_allowformats: mdwn txt + +# getsource plugin +# Mime type for returned source. +#getsource_mimetype: text/plain; charset=utf-8 + +# mirrorlist plugin +# list of mirrors +#mirrorlist: {} +# generate links that point to the mirrors' ikiwiki CGI +#mirrorlist_use_cgi: 1 + +# repolist plugin +# URIs of repositories containing the wiki's source +#repositories: +#- svn://svn.example.org/wiki/trunk +repositories: +- https://git.emacsconf.org/emacsconf-wiki +- git://git.emacsconf.org/emacsconf-wiki +- ssh://anon@git.emacsconf.org:emacsconf-wiki + +# search plugin +# path to the omega cgi program +#omega_cgi: /usr/lib/cgi-bin/omega/omega +# use google site search rather than internal xapian index? +#google_search: 1 + +# theme plugin +# name of theme to enable +#theme: actiontabs +theme: actiontabs + +# websetup plugin +# list of plugins that cannot be enabled/disabled via the web interface +#websetup_force_plugins: [] +# list of additional setup field keys to treat as unsafe +#websetup_unsafe: [] +# show unsafe settings, read-only, in web interface? +#websetup_show_unsafe: 1 + +###################################################################### +# widget plugins +#   (calendar, color, conditional, cutpaste, date, format, fortune, +#    graphviz, haiku, headinganchors, img, linkmap, listdirectives, map, +#    more, orphans, pagecount, pagestats, poll, polygen, postsparkline, +#    progress, shortcut, sparkline, table, template, teximg, toc, toggle, +#    version) +###################################################################### + +# calendar plugin +# base of the archives hierarchy +#archivebase: archives +# PageSpec of pages to include in the archives, if option `calendar_autocreate` is true. +#archive_pagespec: page(posts/*) and !*/Discussion +# autocreate new calendar pages? +#calendar_autocreate: 1 +# if set, when building calendar pages, also build pages of year and month when no pages were published (building empty calendars). +#calendar_fill_gaps: 1 + +# img plugin +# Image formats to process (jpeg, png, gif, svg, pdf or 'everything' to accept all) +#img_allowed_formats: '' + +# listdirectives plugin +# directory in srcdir that contains directive descriptions +#directive_description_dir: ikiwiki/directive + +# teximg plugin +# Should teximg use dvipng to render, or dvips and convert? +#teximg_dvipng: '' +# LaTeX prefix for teximg plugin +#teximg_prefix: | +#  \documentclass{article} +#  \usepackage[utf8]{inputenc} +#  \usepackage{amsmath} +#  \usepackage{amsfonts} +#  \usepackage{amssymb} +#  \pagestyle{empty} +#  \begin{document} +# LaTeX postfix for teximg plugin +#teximg_postfix: \end{document} + +###################################################################### +# other plugins +#   (aggregate, autoindex, brokenlinks, camelcase, ddate, embed, favicon, +#    filecheck, flattr, goodstuff, htmlbalance, localstyle, loginselector, +#    notifyemail, pagetemplate, pingee, pinger, prettydate, recentchanges, +#    recentchangesdiff, relativedate, rsync, sidebar, smiley, +#    sortnaturally, tag, testpagespec, trail, transient) +###################################################################### + +# aggregate plugin +# enable aggregation to internal pages? +#aggregateinternal: 1 +# allow aggregation to be triggered via the web? +#aggregate_webtrigger: 0 + +# autoindex plugin +# commit autocreated index pages +#autoindex_commit: 1 + +# camelcase plugin +# list of words to not turn into links +#camelcase_ignore: [] + +# flattr plugin +# userid or user name to use by default for Flattr buttons +#flattr_userid: joeyh + +# pinger plugin +# how many seconds to try pinging before timing out +#pinger_timeout: 15 + +# prettydate plugin +# format to use to display date +#prettydateformat: '%X, %B %o, %Y' + +# recentchanges plugin +# name of the recentchanges page +#recentchangespage: recentchanges +recentchangespage: recent-changes +# number of changes to track +#recentchangesnum: 100 + +# rsync plugin +# command to run to sync updated pages +#rsync_command: rsync -qa --delete . user@host:/path/to/docroot/ + +# sidebar plugin +# show sidebar page on all pages? +#global_sidebars: 1 + +# tag plugin +# parent page tags are located under +#tagbase: tag +# autocreate new tag pages? +tag_autocreate: 1 +# commit autocreated tag pages +#tag_autocreate_commit: 1 diff --git a/roles/wiki/templates/htmlscrubber.pm b/roles/wiki/templates/htmlscrubber.pm new file mode 100755 index 0000000..904a2dc --- /dev/null +++ b/roles/wiki/templates/htmlscrubber.pm @@ -0,0 +1,132 @@ +#!/usr/bin/perl +package IkiWiki::Plugin::htmlscrubber; + +use warnings; +use strict; +use IkiWiki 3.00; + +# This regexp matches urls that are in a known safe scheme. +# Feel free to use it from other plugins. +our $safe_url_regexp; + +sub import { +	hook(type => "getsetup", id => "htmlscrubber", call => \&getsetup); +	hook(type => "sanitize", id => "htmlscrubber", call => \&sanitize); + +	# Only known uri schemes are allowed to avoid all the ways of +	# embedding javascrpt. +	# List at http://en.wikipedia.org/wiki/URI_scheme +	my $uri_schemes=join("|", map quotemeta, +		# IANA registered schemes +		"http", "https", "ftp", "mailto", "file", "telnet", "gopher", +		"aaa", "aaas", "acap", 	"cap", "cid", "crid",  +		"dav", "dict", "dns", "fax", "go", "h323", "im", "imap", +		"ldap", "mid", "news", "nfs", "nntp", "pop", "pres", +		"sip", "sips", "snmp", "tel", "urn", "wais", "xmpp", +		"z39.50r", "z39.50s", +		# Selected unofficial schemes +		"aim", "callto", "cvs", "ed2k", "feed", "fish", "gg", +		"irc", "ircs", "lastfm", "ldaps", "magnet", "mms", +		"msnim", "notes", "rsync", "secondlife", "skype", "ssh", +		"sftp", "smb", "sms", "snews", "webcal", "ymsgr", +		"bitcoin", "git", "svn", "bzr", "darcs", "hg" +	); +	# data is a special case. Allow a few data:image/ types, +	# but disallow data:text/javascript and everything else. +	$safe_url_regexp=qr/^(?:(?:$uri_schemes):|data:image\/(?:png|jpeg|gif)|[^:]+(?:$|[\/\?#]))|^#/i; +} + +sub getsetup () { +	return +		plugin => { +			safe => 1, +			rebuild => undef, +			section => "core", +		}, +		htmlscrubber_skip => { +			type => "pagespec", +			example => "!*/Discussion", +			description => "PageSpec specifying pages not to scrub", +			link => "ikiwiki/PageSpec", +			safe => 1, +			rebuild => undef, +		}, +} + +sub sanitize (@) { +	my %params=@_; + +	if (exists $config{htmlscrubber_skip} && +	    length $config{htmlscrubber_skip} && +	    exists $params{page} && +	    pagespec_match($params{page}, $config{htmlscrubber_skip})) { +		return $params{content}; +	} + +	return scrubber()->scrub($params{content}); +} + +my $_scrubber; +sub scrubber { +	return $_scrubber if defined $_scrubber; + +	eval q{use HTML::Scrubber}; +	error($@) if $@; +	# Lists based on http://feedparser.org/docs/html-sanitization.html +	# With html5 tags added. +	$_scrubber = HTML::Scrubber->new( +      allow => [qw{ +          svg rect text g title +			a abbr acronym address area b big blockquote br br/ +			button caption center cite code col colgroup dd del +			dfn dir div dl dt em fieldset font form h1 h2 h3 h4 +			h5 h6 hr hr/ i img input ins kbd label legend li map +			track +			menu ol optgroup option p p/ pre q s samp select small +			span strike strong sub sup table tbody td textarea +			tfoot th thead tr tt u ul var +			video audio source section nav article aside hgroup +			header footer figure figcaption time mark canvas +			datalist progress meter ruby rt rp details summary +		}], +		default => [undef, { ( +                             map { $_ => 1 } qw{ +                                 version xmlns x y fill font-size stroke stroke-dasharray transform  +          data-start data-end data-video data-target data-tracks +              kind label srclang default +				abbr accept accept-charset accesskey +				align alt axis border cellpadding cellspacing +				char charoff charset checked class +				clear cols colspan color compact coords +				datetime dir disabled enctype for frame +				headers height hreflang hspace id ismap +				kind srclang src default +				label lang maxlength media method +				multiple name nohref noshade nowrap prompt +				readonly rel rev rows rowspan rules scope +				selected shape size span start summary +				tabindex target title type valign +				value vspace width +				autofocus autoplay preload loopstart +				loopend end playcount controls pubdate +				loop muted +				placeholder min max step low high optimum +				form required autocomplete novalidate pattern +				list formenctype formmethod formnovalidate +				formtarget reversed spellcheck open hidden +			} ), +			"/" => 1, # emit proper <hr /> XHTML +			href => $safe_url_regexp, +			src => $safe_url_regexp, +			action => $safe_url_regexp, +			formaction => $safe_url_regexp, +			cite => $safe_url_regexp, +			longdesc => $safe_url_regexp, +			poster => $safe_url_regexp, +			usemap => $safe_url_regexp +		}], +	); +	return $_scrubber; +} + +1 diff --git a/roles/wiki/templates/license.pm b/roles/wiki/templates/license.pm new file mode 100644 index 0000000..651c039 --- /dev/null +++ b/roles/wiki/templates/license.pm @@ -0,0 +1,59 @@ +# A plugin for ikiwiki to implement adding a footer with licensing information +# based on a default value taken out of a file. + +# Copyright © 2007, 2008 Thomas Schwinge <tschwinge@gnu.org> +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +#  +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License +# for more details. +#  +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Unless overridden with the `meta' plugin, a footer with licensing information +# will be added to every page using a source file `license' (e.g., +# `license.mdwn') (using the same ``locating rules'' as for the sidebar +# plugin). +# +# The state which page's license text was gathered from which source is not +# tracked, so you'll need a full wiki-rebuild if the `license' file is changed. + +package IkiWiki::Plugin::license; + +use warnings; +use strict; +use IkiWiki 2.00; + +my %license; + +sub import +{ +    hook (type => "scan", id => "license", call => \&scan); +} + +sub scan (@) +{ +    my %params = @_; +    my $page = $params{page}; + +    return if defined $pagestate{$page}{meta}{license}; + +    my $content; +    my $license_page = bestlink ($page, "license") || return; +    my $license_file = $pagesources{$license_page} || return; + +    # Only an optimization to avoid reading the same file again and again. +    $license{$license_file} = readfile (srcfile ($license_file)) +	unless defined $license{$license_file}; + +    $pagestate{$page}{meta}{license} = $license{$license_file}; +} + +1  | 
