source: trunk/wiki.cgi @ 458

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

Update version, changes and credits ready for release. (couple more changes to come first)

  • 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.38';
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.