source: trunk/wiki.cgi @ 446

Last change on this file since 446 was 446, checked in by kake, 18 years ago

Bumped version number.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1#!/usr/local/bin/perl
2
3use strict;
4use warnings;
5
6use vars qw( $VERSION );
7$VERSION = '0.37';
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        commit_node($node);
59    } elsif ($preview) {
60        preview_node($node);
61    } elsif ($action eq 'edit') {
62        edit_node($node);
63    } elsif ($action eq 'search') {
64        do_search($search_terms);
65    } elsif ($action eq 'show_backlinks') {
66        show_backlinks($node);
67    } elsif ($action eq 'show_wanted_pages') {
68        show_wanted_pages();
69    } elsif ($action eq 'index') {
70        $guide->show_index(
71                            type   => $q->param("index_type") || "Full",
72                            value  => $q->param("index_value") || "",
73                            format => $format,
74                          );
75    } elsif ($action eq 'random') {
76        my @nodes = $wiki->list_all_nodes();
77        $node = $nodes[int(rand(scalar(@nodes) + 1)) + 1];
78        print $guide->redirect_to_node($node);
79        exit 0;
80    } elsif ($action eq 'find_within_distance') {
81        $guide->find_within_distance(
82                                      id => $node,
83                                      metres => $q->param("distance_in_metres")
84                                    );
85    } elsif ( $action eq 'delete'
86              and ( lc($config->{_}->{enable_page_deletion}) eq "y"
87                    or $config->{_}->{enable_page_deletion} eq "1" )
88            ) {
89        $guide->delete_node(
90                             id       => $node,
91                             version  => $q->param("version") || "",
92                             password => $q->param("password") || "",
93                           );
94    } elsif ($action eq 'userstats') {
95        show_userstats(
96                        username => $q->param("username") || "",
97                        host     => $q->param("host") || "",
98                      );
99    } elsif ($action eq 'list_all_versions') {
100        $guide->list_all_versions( id => $node );
101    } elsif ($action eq 'rss') {
102        my $feed = $q->param("feed");
103        if ( !defined $feed or $feed eq "recent_changes" ) {
104            my $items = $q->param("items") || "";
105            my $days  = $q->param("days")  || "";
106            emit_recent_changes_rss( items => $items, days => $days);
107        } elsif ( $feed eq "chef_dan" ) {
108            display_node_rdf( node => $node );
109        } else {
110            croak "Unknown RSS feed type '$feed'";
111        }
112    } else { # Default is to display a node.
113        if ( $format and $format eq "rdf" ) {
114            display_node_rdf( node => $node );
115        } else {
116            my $version = $q->param("version");
117            my $other_ver = $q->param("diffversion");
118            if ( $other_ver ) {
119                $guide->display_diffs(
120                                       id            => $node,
121                                       version       => $version,
122                                       other_version => $other_ver,
123                                     );
124            } else {
125                $guide->display_node( id => $node, version => $version );
126            }
127        }
128    }
129};
130
131if ($@) {
132    my $error = $@;
133    warn $error;
134    print $q->header;
135    my $contact_email = $config->{_}->{contact_email};
136    print qq(<html><head><title>ERROR</title></head><body>
137             <p>Sorry!  Something went wrong.  Please contact the
138             Wiki administrator at
139             <a href="mailto:$contact_email">$contact_email</a> and quote
140             the following error message:</p><blockquote>)
141      . $q->escapeHTML($error)
142      . qq(</blockquote><p><a href="$script_name">Return to the Wiki home page</a>
143           </body></html>);
144}
145exit 0;
146
147############################ subroutines ###################################
148
149sub show_userstats {
150    my %args = @_;
151    my ($username, $host) = @args{ qw( username host ) };
152    croak "No username or host supplied to show_userstats"
153        unless $username or $host;
154    my %criteria = ( last_n_changes => 5 );
155    $criteria{metadata_is} = $username ? { username => $username }
156                                       : { host     => $host };
157    my @nodes = $wiki->list_recent_changes( %criteria );
158    @nodes = map { {name          => $q->escapeHTML($_->{name}),
159                    last_modified => $q->escapeHTML($_->{last_modified}),
160                    comment       => $q->escapeHTML($_->{metadata}{comment}[0]),
161                    url           => "$script_name?"
162          . $q->escape($formatter->node_name_to_node_param($_->{name})) }
163                       } @nodes;
164    my %tt_vars = ( last_five_nodes => \@nodes,
165                    username        => $username,
166                    username_param  => $wiki->formatter->node_name_to_node_param($username),
167                    host            => $host,
168                  );
169    process_template("userstats.tt", "", \%tt_vars);
170}
171
172sub preview_node {
173    my $node = shift;
174    my $content  = $q->param('content');
175    $content     =~ s/\r\n/\n/gs;
176    my $checksum = $q->param('checksum');
177
178    my %tt_metadata_vars = OpenGuides::Template->extract_metadata_vars(
179                                                   wiki    => $wiki,
180                                                   config  => $config,
181                                                   cgi_obj => $q );
182    foreach my $var ( qw( username comment edit_type ) ) {
183        $tt_metadata_vars{$var} = $q->escapeHTML($q->param($var));
184    }
185
186    if ($wiki->verify_checksum($node, $checksum)) {
187        my %tt_vars = (
188            %tt_metadata_vars,
189            content                => $q->escapeHTML($content),
190            preview_html           => $wiki->format($content),
191            preview_above_edit_box => get_cookie( "preview_above_edit_box" ),
192            checksum               => $q->escapeHTML($checksum)
193        );
194        process_template("edit_form.tt", $node, \%tt_vars);
195    } else {
196        my %node_data = $wiki->retrieve_node($node);
197        my %tt_vars = ( checksum       => $node_data{checksum},
198                        new_content    => $content,
199                        stored_content => $node_data{content} );
200        foreach my $mdvar ( keys %tt_metadata_vars ) {
201            if ($mdvar eq "locales") {
202                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{locale};
203                $tt_vars{"new_$mdvar"}    = $tt_metadata_vars{locale};
204            } elsif ($mdvar eq "categories") {
205                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{category};
206                $tt_vars{"new_$mdvar"}    = $tt_metadata_vars{category};
207            } elsif ($mdvar eq "username" or $mdvar eq "comment"
208                      or $mdvar eq "edit_type" ) {
209                $tt_vars{$mdvar} = $tt_metadata_vars{$mdvar};
210            } else {
211                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{$mdvar}[0];
212                $tt_vars{"new_$mdvar"}    = $tt_metadata_vars{$mdvar};
213            }
214        }
215        process_template("edit_conflict.tt", $node, \%tt_vars);
216    }
217}
218
219sub edit_node {
220    my $node = shift;
221    my %node_data = $wiki->retrieve_node($node);
222    my ($content, $checksum) = @node_data{ qw( content checksum ) };
223    my $username = get_cookie( "username" );
224    my $edit_type = get_cookie( "default_edit_type" ) eq "normal" ?
225                        "Normal edit" : "Minor tidying";
226
227    my %metadata_vars = OpenGuides::Template->extract_metadata_vars(
228                             wiki     => $wiki,
229                             config   => $config,
230                             metadata => $node_data{metadata} );
231
232    my %tt_vars = ( content    => $q->escapeHTML($content),
233                    checksum   => $q->escapeHTML($checksum),
234                    %metadata_vars,
235                    username   => $username,
236                    edit_type  => $edit_type,
237    );
238
239    process_template("edit_form.tt", $node, \%tt_vars);
240}
241
242sub get_cookie {
243    my $pref_name = shift or return "";
244    my %cookie_data = OpenGuides::CGI->get_prefs_from_cookie(config=>$config);
245    return $cookie_data{$pref_name};
246}
247
248sub emit_recent_changes_rss {
249    my %args = @_;
250    my $rdf_writer = OpenGuides::RDF->new( wiki      => $wiki,
251                                           config => $config );
252    print "Content-type: text/plain\n\n";
253    print $rdf_writer->make_recentchanges_rss( %args );
254    exit 0;
255}
256
257sub display_node_rdf {
258    my %args = @_;
259    my $rdf_writer = OpenGuides::RDF->new( wiki      => $wiki,
260                                           config => $config );
261    print "Content-type: text/plain\n\n";
262    print $rdf_writer->emit_rdfxml( node => $args{node} );
263    exit 0;
264}
265
266sub process_template {
267    my ($template, $node, $vars, $conf, $omit_header) = @_;
268
269    my %output_conf = ( wiki     => $wiki,
270                        config   => $config,
271                        node     => $node,
272                        template => $template,
273                        vars     => $vars
274    );
275    $output_conf{content_type} = "" if $omit_header; # defaults otherwise
276    print OpenGuides::Template->output( %output_conf );
277}
278
279
280sub commit_node {
281    my $node = shift;
282    my $content  = $q->param('content');
283    $content =~ s/\r\n/\n/gs;
284    my $checksum = $q->param('checksum');
285
286    my %metadata = OpenGuides::Template->extract_metadata_vars(
287        wiki    => $wiki,
288        config  => $config,
289        cgi_obj => $q
290    );
291
292    $metadata{opening_hours_text} = $q->param("hours_text") || "";
293
294    # Check to make sure all the indexable nodes are created
295    foreach my $type (qw(Category Locale)) {
296        my $lctype = lc($type);
297        foreach my $index (@{$metadata{$lctype}}) {
298            $index =~ s/(.*)/\u$1/;
299            my $node = $type . " " . $index;
300            # Uppercase the node name before checking for existence
301            $node =~ s/ (\S+)/ \u$1/g;
302            unless ( $wiki->node_exists($node) ) {
303                my $category = $type eq "Category" ? "Category" : "Locales";
304                $wiki->write_node( $node,
305                                   "\@INDEX_LINK [[$node]]",
306                                   undef,
307                                   { username => "Auto Create",
308                                     comment  => "Auto created $lctype stub page",
309                                     category => $category
310                                   }
311                );
312            }
313        }
314    }
315       
316    foreach my $var ( qw( username comment edit_type ) ) {
317        $metadata{$var} = $q->param($var) || "";
318    }
319    $metadata{host} = $ENV{REMOTE_ADDR};
320
321    my $written = $wiki->write_node($node, $content, $checksum, \%metadata );
322
323    if ($written) {
324        print $guide->redirect_to_node($node);
325    } else {
326        my %node_data = $wiki->retrieve_node($node);
327        my %tt_vars = ( checksum       => $node_data{checksum},
328                        new_content    => $content,
329                        stored_content => $node_data{content} );
330        foreach my $mdvar ( keys %metadata ) {
331            if ($mdvar eq "locales") {
332                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{locale};
333                $tt_vars{"new_$mdvar"}    = $metadata{locale};
334            } elsif ($mdvar eq "categories") {
335                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{category};
336                $tt_vars{"new_$mdvar"}    = $metadata{category};
337            } elsif ($mdvar eq "username" or $mdvar eq "comment"
338                      or $mdvar eq "edit_type" ) {
339                $tt_vars{$mdvar} = $metadata{$mdvar};
340            } else {
341                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{$mdvar}[0];
342                $tt_vars{"new_$mdvar"}    = $metadata{$mdvar};
343            }
344        }
345        process_template("edit_conflict.tt", $node, \%tt_vars);
346    }
347}
348
349
350sub do_search {
351    my $terms = shift;
352    my %finds = $wiki->search_nodes($terms);
353#    my @sorted = sort { $finds{$a} cmp $finds{$b} } keys %finds;
354    my @sorted = sort keys %finds;
355    my @results = map {
356        { url   => $q->escape($formatter->node_name_to_node_param($_)),
357          title => $q->escapeHTML($_)
358        }             } @sorted;
359    my %tt_vars = ( results      => \@results,
360                    num_results  => scalar @results,
361                    not_editable => 1,
362                    search_terms => $q->escapeHTML($terms) );
363    process_template("search_results.tt", "", \%tt_vars);
364}
365
366sub show_backlinks {
367    my $node = shift;
368    my @backlinks = $wiki->list_backlinks( node => $node );
369    my @results = map {
370        { url   => $q->escape($formatter->node_name_to_node_param($_)),
371          title => $q->escapeHTML($_)
372        }             } sort @backlinks;
373    my %tt_vars = ( results      => \@results,
374                    num_results  => scalar @results,
375                    not_editable => 1 );
376    process_template("backlink_results.tt", $node, \%tt_vars);
377}
378
379sub show_wanted_pages {
380    my @dangling = $wiki->list_dangling_links;
381    @dangling = sort @dangling;
382    my @wanted;
383    foreach my $node_name (@dangling) {
384        my $node_param =
385            uri_escape($formatter->node_name_to_node_param($node_name));
386        push @wanted, {
387            name          => $q->escapeHTML($node_name),
388            edit_link     => $script_url . uri_escape($script_name)
389                           . "?action=edit;id=$node_param",
390            backlink_link => $script_url . uri_escape($script_name)
391                           . "?action=show_backlinks;id=$node_param"
392        };
393    }
394    process_template( "wanted_pages.tt",
395                      "",
396                      { not_editable => 1,
397                        wanted       => \@wanted } );
398}
399
Note: See TracBrowser for help on using the repository browser.