source: trunk/wiki.cgi @ 488

Last change on this file since 488 was 488, checked in by kake, 17 years ago

Fixed userstats.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1#!/usr/local/bin/perl
2
3use strict;
4use warnings;
5
6use vars qw( $VERSION );
7$VERSION = '0.40';
8
9use CGI qw/:standard/;
10use CGI::Carp qw(croak);
11use CGI::Wiki;
12use Config::Tiny;
13use Geography::NationalGrid;
14use Geography::NationalGrid::GB;
15use OpenGuides;
16use OpenGuides::CGI;
17use OpenGuides::RDF;
18use OpenGuides::Utils;
19use OpenGuides::Template;
20use Time::Piece;
21use URI::Escape;
22
23# config vars
24my $config = Config::Tiny->read('wiki.conf');
25
26# Read in configuration values from config file.
27my $script_name = $config->{_}->{script_name};
28my $script_url  = $config->{_}->{script_url};
29
30# Ensure that script_url ends in a '/' - this is done in Build.PL but
31# we need to allow for people editing the config file by hand later.
32$script_url .= "/" unless $script_url =~ /\/$/;
33
34my ($guide, $wiki, $formatter, $q);
35eval {
36    $guide = OpenGuides->new( config => $config );
37    $wiki = $guide->wiki;
38    $formatter = $wiki->formatter;
39
40    # Get CGI object, find out what to do.
41    $q = CGI->new;
42
43    # Note $q->param('keywords') gives you the entire param string.
44    # We need this to do URLs like foo.com/wiki.cgi?This_Page
45    my $node = $q->param('id') || $q->param('title') || $q->param('keywords') || "";
46    $node = $formatter->node_param_to_node_name( $node );
47
48    my $action = $q->param('action') || 'display';
49    my $commit = $q->param('Save') || 0;
50    my $preview = $q->param('preview') || 0;
51    my $search_terms = $q->param('terms') || $q->param('search') || '';
52    my $format = $q->param('format') || '';
53
54    # Alternative method of calling search, supported by usemod.
55    $action = 'search' if $q->param("search");
56
57    if ($commit) {
58        $guide->commit_node(
59                             id      => $node,
60                             cgi_obj => $q,
61                           );
62    } elsif ($preview) {
63        preview_node($node);
64    } elsif ($action eq 'edit') {
65        edit_node($node);
66    } elsif ($action eq 'search') {
67        do_search($search_terms);
68    } elsif ($action eq 'show_backlinks') {
69        show_backlinks($node);
70    } elsif ($action eq 'show_wanted_pages') {
71        show_wanted_pages();
72    } elsif ($action eq 'index') {
73        $guide->show_index(
74                            type   => $q->param("index_type") || "Full",
75                            value  => $q->param("index_value") || "",
76                            format => $format,
77                          );
78    } elsif ($action eq 'random') {
79        my @nodes = $wiki->list_all_nodes();
80        $node = $nodes[int(rand(scalar(@nodes) + 1)) + 1];
81        print $guide->redirect_to_node($node);
82        exit 0;
83    } elsif ($action eq 'find_within_distance') {
84        $guide->find_within_distance(
85                                      id => $node,
86                                      metres => $q->param("distance_in_metres")
87                                    );
88    } elsif ( $action eq 'delete'
89              and ( lc($config->{_}->{enable_page_deletion}) eq "y"
90                    or $config->{_}->{enable_page_deletion} eq "1" )
91            ) {
92        $guide->delete_node(
93                             id       => $node,
94                             version  => $q->param("version") || "",
95                             password => $q->param("password") || "",
96                           );
97    } elsif ($action eq 'userstats') {
98        show_userstats(
99                        username => $q->param("username") || "",
100                        host     => $q->param("host") || "",
101                      );
102    } elsif ($action eq 'list_all_versions') {
103        $guide->list_all_versions( id => $node );
104    } elsif ($action eq 'rss') {
105        my $feed = $q->param("feed");
106        if ( !defined $feed or $feed eq "recent_changes" ) {
107            my $items = $q->param("items") || "";
108            my $days  = $q->param("days")  || "";
109            my $ignore_minor_edits = $q->param("ignore_minor_edits") ? 1 : 0;
110            my $username = $q->param("username") || "";
111            my %criteria = (
112                             items              => $items,
113                             days               => $days,
114                             ignore_minor_edits => $ignore_minor_edits,
115                           );
116            if ( $username ) {
117                $criteria{filter_on_metadata} = {
118                                                  username => $username,
119                                                };
120            }
121            emit_recent_changes_rss( %criteria );
122        } elsif ( $feed eq "chef_dan" ) {
123            display_node_rdf( node => $node );
124        } else {
125            croak "Unknown RSS feed type '$feed'";
126        }
127    } else { # Default is to display a node.
128        if ( $format and $format eq "rdf" ) {
129            display_node_rdf( node => $node );
130        } else {
131            my $version = $q->param("version");
132            my $other_ver = $q->param("diffversion");
133            if ( $other_ver ) {
134                $guide->display_diffs(
135                                       id            => $node,
136                                       version       => $version,
137                                       other_version => $other_ver,
138                                     );
139            } else {
140                $guide->display_node( id => $node, version => $version );
141            }
142        }
143    }
144};
145
146if ($@) {
147    my $error = $@;
148    warn $error;
149    print $q->header;
150    my $contact_email = $config->{_}->{contact_email};
151    print qq(<html><head><title>ERROR</title></head><body>
152             <p>Sorry!  Something went wrong.  Please contact the
153             Wiki administrator at
154             <a href="mailto:$contact_email">$contact_email</a> and quote
155             the following error message:</p><blockquote>)
156      . $q->escapeHTML($error)
157      . qq(</blockquote><p><a href="$script_name">Return to the Wiki home page</a>
158           </body></html>);
159}
160exit 0;
161
162############################ subroutines ###################################
163
164sub show_userstats {
165    my %args = @_;
166    my ($username, $host) = @args{ qw( username host ) };
167    croak "No username or host supplied to show_userstats"
168        unless $username or $host;
169    my %criteria = ( last_n_changes => 5 );
170    $criteria{metadata_was} = $username ? { username => $username }
171                                        : { host     => $host };
172    my @nodes = $wiki->list_recent_changes( %criteria );
173    @nodes = map { {name          => $q->escapeHTML($_->{name}),
174                    last_modified => $q->escapeHTML($_->{last_modified}),
175                    comment       => $q->escapeHTML($_->{metadata}{comment}[0]),
176                    url           => "$script_name?"
177          . $q->escape($formatter->node_name_to_node_param($_->{name})) }
178                       } @nodes;
179    my %tt_vars = ( last_five_nodes => \@nodes,
180                    username        => $username,
181                    username_param  => $wiki->formatter->node_name_to_node_param($username),
182                    host            => $host,
183                  );
184    process_template("userstats.tt", "", \%tt_vars);
185}
186
187sub preview_node {
188    my $node = shift;
189    my $content  = $q->param('content');
190    $content     =~ s/\r\n/\n/gs;
191    my $checksum = $q->param('checksum');
192
193    my %tt_metadata_vars = OpenGuides::Template->extract_metadata_vars(
194                                                   wiki    => $wiki,
195                                                   config  => $config,
196                                                   cgi_obj => $q );
197    foreach my $var ( qw( username comment edit_type ) ) {
198        $tt_metadata_vars{$var} = $q->escapeHTML($q->param($var));
199    }
200
201    if ($wiki->verify_checksum($node, $checksum)) {
202        my %tt_vars = (
203            %tt_metadata_vars,
204            content                => $q->escapeHTML($content),
205            preview_html           => $wiki->format($content),
206            preview_above_edit_box => get_cookie( "preview_above_edit_box" ),
207            checksum               => $q->escapeHTML($checksum)
208        );
209        process_template("edit_form.tt", $node, \%tt_vars);
210    } else {
211        my %node_data = $wiki->retrieve_node($node);
212        my %tt_vars = ( checksum       => $node_data{checksum},
213                        new_content    => $content,
214                        stored_content => $node_data{content} );
215        foreach my $mdvar ( keys %tt_metadata_vars ) {
216            if ($mdvar eq "locales") {
217                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{locale};
218                $tt_vars{"new_$mdvar"}    = $tt_metadata_vars{locale};
219            } elsif ($mdvar eq "categories") {
220                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{category};
221                $tt_vars{"new_$mdvar"}    = $tt_metadata_vars{category};
222            } elsif ($mdvar eq "username" or $mdvar eq "comment"
223                      or $mdvar eq "edit_type" ) {
224                $tt_vars{$mdvar} = $tt_metadata_vars{$mdvar};
225            } else {
226                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{$mdvar}[0];
227                $tt_vars{"new_$mdvar"}    = $tt_metadata_vars{$mdvar};
228            }
229        }
230        process_template("edit_conflict.tt", $node, \%tt_vars);
231    }
232}
233
234sub edit_node {
235    my $node = shift;
236    my %node_data = $wiki->retrieve_node($node);
237    my ($content, $checksum) = @node_data{ qw( content checksum ) };
238    my $username = get_cookie( "username" );
239    my $edit_type = get_cookie( "default_edit_type" ) eq "normal" ?
240                        "Normal edit" : "Minor tidying";
241
242    my %metadata_vars = OpenGuides::Template->extract_metadata_vars(
243                             wiki     => $wiki,
244                             config   => $config,
245                             metadata => $node_data{metadata} );
246
247    my %tt_vars = ( content    => $q->escapeHTML($content),
248                    checksum   => $q->escapeHTML($checksum),
249                    %metadata_vars,
250                    username   => $username,
251                    edit_type  => $edit_type,
252    );
253
254    process_template("edit_form.tt", $node, \%tt_vars);
255}
256
257sub get_cookie {
258    my $pref_name = shift or return "";
259    my %cookie_data = OpenGuides::CGI->get_prefs_from_cookie(config=>$config);
260    return $cookie_data{$pref_name};
261}
262
263sub emit_recent_changes_rss {
264    my %args = @_;
265    my $rdf_writer = OpenGuides::RDF->new( wiki      => $wiki,
266                                           config => $config );
267    print "Content-type: text/plain\n\n";
268    print $rdf_writer->make_recentchanges_rss( %args );
269    exit 0;
270}
271
272sub display_node_rdf {
273    my %args = @_;
274    my $rdf_writer = OpenGuides::RDF->new( wiki      => $wiki,
275                                           config => $config );
276    print "Content-type: text/plain\n\n";
277    print $rdf_writer->emit_rdfxml( node => $args{node} );
278    exit 0;
279}
280
281sub process_template {
282    my ($template, $node, $vars, $conf, $omit_header) = @_;
283
284    my %output_conf = ( wiki     => $wiki,
285                        config   => $config,
286                        node     => $node,
287                        template => $template,
288                        vars     => $vars
289    );
290    $output_conf{content_type} = "" if $omit_header; # defaults otherwise
291    print OpenGuides::Template->output( %output_conf );
292}
293
294
295sub do_search {
296    my $terms = shift;
297    my %finds = $wiki->search_nodes($terms);
298#    my @sorted = sort { $finds{$a} cmp $finds{$b} } keys %finds;
299    my @sorted = sort keys %finds;
300    my @results = map {
301        { url   => $q->escape($formatter->node_name_to_node_param($_)),
302          title => $q->escapeHTML($_)
303        }             } @sorted;
304    my %tt_vars = ( results      => \@results,
305                    num_results  => scalar @results,
306                    not_editable => 1,
307                    search_terms => $q->escapeHTML($terms) );
308    process_template("search_results.tt", "", \%tt_vars);
309}
310
311sub show_backlinks {
312    my $node = shift;
313    my @backlinks = $wiki->list_backlinks( node => $node );
314    my @results = map {
315        { url   => $q->escape($formatter->node_name_to_node_param($_)),
316          title => $q->escapeHTML($_)
317        }             } sort @backlinks;
318    my %tt_vars = ( results       => \@results,
319                    num_results   => scalar @results,
320                    not_deletable => 1,
321                    not_editable  => 1 );
322    process_template("backlink_results.tt", $node, \%tt_vars);
323}
324
325sub show_wanted_pages {
326    my @dangling = $wiki->list_dangling_links;
327    @dangling = sort @dangling;
328    my @wanted;
329    foreach my $node_name (@dangling) {
330        my $node_param =
331            uri_escape($formatter->node_name_to_node_param($node_name));
332        push @wanted, {
333            name          => $q->escapeHTML($node_name),
334            edit_link     => $script_url . uri_escape($script_name)
335                           . "?action=edit;id=$node_param",
336            backlink_link => $script_url . uri_escape($script_name)
337                           . "?action=show_backlinks;id=$node_param"
338        };
339    }
340    process_template( "wanted_pages.tt",
341                      "",
342                      { not_editable  => 1,
343                        not_deletable => 1,
344                        wanted        => \@wanted } );
345}
346
Note: See TracBrowser for help on using the repository browser.