source: trunk/wiki.cgi @ 1462

Last change on this file since 1462 was 1462, checked in by bob, 9 years ago

merge in stuff from 0.71 release branch

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 15.8 KB
Line 
1#!/usr/local/bin/perl
2
3use strict;
4use warnings;
5use sigtrap die => 'normal-signals';
6use vars qw( $VERSION );
7$VERSION = '0.71';
8
9use CGI qw/:standard/;
10use CGI::Carp qw(croak);
11use Wiki::Toolkit;
12use OpenGuides;
13use OpenGuides::CGI;
14use OpenGuides::Config;
15use OpenGuides::RDF;
16use OpenGuides::JSON;
17use OpenGuides::Utils;
18use OpenGuides::Template;
19use Time::Piece;
20use URI::Escape;
21
22my $config_file = $ENV{OPENGUIDES_CONFIG_FILE} || "wiki.conf";
23my $config = OpenGuides::Config->new( file => $config_file );
24
25my $script_name = $config->script_name;
26my $script_url  = $config->script_url;
27
28my ($guide, $wiki, $formatter, $q);
29eval {
30    $guide = OpenGuides->new( config => $config );
31    $wiki = $guide->wiki;
32    $formatter = $wiki->formatter;
33    $q = CGI->new;
34
35    # See if we need to redirect due to spaces in URL.  Don't do this for
36    # POST requests though - it leads to all the data being stuffed into the
37    # URL, which breaks things if there's a lot of data.
38    my $request_method = $q->request_method() || "";
39    unless ( $request_method eq "POST" ) {
40      my $redirect = OpenGuides::CGI->check_spaces_redirect(
41                                         cgi_obj => $q, wiki => $wiki );
42
43      if ( $redirect ) {
44          print $q->redirect( -uri => $redirect, -status => 303 );
45          exit 0;
46      }
47    }
48
49    # No redirect - carry on.
50    my $node = OpenGuides::CGI->extract_node_name(
51                                         cgi_obj => $q, wiki => $wiki );
52
53    # If we did a post, then CGI->param probably hasn't fully de-escaped,
54    #  in the same way as a get would've done
55    if($request_method eq 'POST') {
56        $node = uri_unescape($node);
57    }
58
59    # Grab our common parameters
60    my $action       = $q->param('action')  || 'display';
61    my $commit       = $q->param('Save')    || 0;
62    my $preview      = $q->param('preview') || 0;
63    my $search_terms = $q->param('terms')   || $q->param('search') || '';
64    my $format       = $q->param('format')  || '';
65    my $oldid        = $q->param('oldid')   || '';
66
67    # Alternative method of calling search, supported by usemod.
68    $action = 'search' if $q->param("search");
69
70    if ($commit) {
71        $guide->commit_node(
72                             id      => $node,
73                             cgi_obj => $q,
74                           );
75    } elsif ($preview) {
76        $guide->preview_edit(
77                              id      => $node,
78                              cgi_obj => $q,
79                            );
80    } elsif ($action eq 'edit') {
81        $guide->display_edit_form( id => $node );
82    } elsif ($action eq 'search') {
83        do_search($search_terms);
84    } elsif ($action eq 'show_backlinks') {
85        $guide->show_backlinks( id => $node );
86    } elsif ($action eq 'show_wanted_pages') {
87        show_wanted_pages();
88    } elsif ($action eq 'show_needing_moderation') {
89        show_needing_moderation();
90    } elsif ($action eq 'index') {
91        $guide->show_index(
92                            cat    => $q->param( "cat" ) || "",
93                            loc    => $q->param( "loc" ) || "",
94                            format => $format,
95                            # Next two for backwards compatibility (deprecated)
96                            type   => $q->param("index_type") || "Full",
97                            value  => $q->param("index_value") || "",
98                          );
99    } elsif ($action eq 'random') {
100        print $guide->display_random_page(
101                            category => $q->param( "category" ) || "",
102                            locale   => $q->param( "locale" ) || "",
103                                         );
104    } elsif ($action eq 'find_within_distance') {
105        $guide->find_within_distance(
106                                      id => $node,
107                                      metres => $q->param("distance_in_metres")
108                                    );
109    } elsif ( $action eq 'admin' ) {
110        $guide->display_admin_interface(
111                             moderation_completed => $q->param("moderation"),
112        );
113    } elsif ( $action eq 'revert_user' ) {
114        $guide->revert_user_interface(
115                        username => $q->param("username") || "",
116                        host     => $q->param("host") || "",
117                        password => $q->param("password") || "",
118        );
119    } elsif ( $action eq 'show_missing_metadata' ) {
120        $guide->show_missing_metadata(
121                   metadata_type  => $q->param("metadata_type") || "",
122                   metadata_value => $q->param("metadata_value") || "",
123                   exclude_locales => $q->param("exclude_locales") || "",
124                   exclude_categories => $q->param("exclude_categories") || "",
125                   format => $q->param( "format" ) || "",
126        );
127    } elsif ( $action eq 'set_moderation' ) {
128        $guide->set_node_moderation(
129                             id       => $node,
130                             password => $q->param("password") || "",
131                             moderation_flag => $q->param("moderation_flag") || "",
132                           );
133    } elsif ( $action eq 'moderate' ) {
134        $guide->moderate_node(
135                             id       => $node,
136                             version  => $q->param("version") || "",
137                             password => $q->param("password") || "",
138                           );
139    } elsif ( $action eq 'delete'
140              and ( lc($config->enable_page_deletion) eq "y"
141                    or $config->enable_page_deletion eq "1" )
142            ) {
143        $guide->delete_node(
144                             id       => $node,
145                             version  => $q->param("version") || "",
146                             password => $q->param("password") || "",
147                           );
148    } elsif ($action eq 'userstats') {
149        show_userstats(
150                        username => $q->param("username") || "",
151                        host     => $q->param("host") || "",
152                      );
153    } elsif ($action eq 'list_all_versions') {
154        if($format && ($format eq "rss" || $format eq "atom")) {
155            my %args = (
156                            feed_type    => $format,
157                            feed_listing => 'node_all_versions',
158                            name         => $node
159            );
160            $guide->display_feed( %args );
161        } else {
162            $guide->list_all_versions( id => $node );
163        }
164    } elsif ($action eq 'rc') {
165        if ($format && $format eq 'rss') {
166            my $feed = $q->param("feed");
167            if ( !defined $feed or $feed eq "recent_changes" ) {
168                my %args = map { $_ => ( $q->param($_) || "" ) }
169                           qw( feed items days ignore_minor_edits username
170                               category locale );
171                $args{feed_type} = 'rss';
172                $args{feed_listing} = 'recent_changes';
173                $guide->display_feed( %args );
174            } elsif ( $feed eq "chef_dan" ) {
175                display_node_rdf( node => $node );
176            } else {
177                croak "Unknown RSS feed type '$feed'";
178            }
179        } elsif ($format && $format eq 'atom') {
180            my %args = map { $_ => ( $q->param($_) || "" ) }
181                       qw( feed items days ignore_minor_edits username
182                           category locale );
183            $args{feed_type} = 'atom';
184            $args{feed_listing} = 'recent_changes';
185            $guide->display_feed( %args );
186        } else {
187            $guide->display_node( id => 'RecentChanges' );
188        }
189    } elsif ($action eq 'rss') {
190        my $redir_target = $script_url . $script_name . '?action=rc;format=rss';
191        my %args = map { $_ => ( $q->param($_) || "" ) }
192            qw( feed items days ignore_minor_edits username
193                category locale );
194        foreach my $arg (sort keys %args) {
195            if ($args{$arg} ne "") {
196                $redir_target .= ";$arg=$args{$arg}";
197            }
198        }
199        print $q->redirect( $redir_target );
200    } elsif ($action eq 'about') {
201        $guide->display_about(format => $format);
202    } elsif ($action eq 'metadata') {
203        $guide->show_metadata(
204                            type   => $q->param("type") || "",
205                            format => $format,
206                          );
207    } elsif ($action eq 'display') { 
208        if ( $format and $format eq "rdf" ) {
209            display_node_rdf( node => $node );
210        } elsif ( $format and $format eq "json" ) {
211            display_node_json( node => $node );
212        } elsif ( $format and $format eq 'raw' ) {
213            $guide->display_node(
214                                  id       => $node,
215                                  format   => 'raw',
216                                );
217        } else {
218            my $version = $q->param("version");
219            my $other_ver = $q->param("diffversion");
220            if ( $other_ver ) {
221                $guide->display_diffs(
222                                       id            => $node,
223                                       version       => $version,
224                                       other_version => $other_ver,
225                                     );
226            } else {
227                my $redirect;
228               
229                if ((defined $q->param("redirect")) && ($q->param("redirect") == 0)) {
230                  $redirect = 0;
231                } else {
232                  $redirect = 1;               
233                }
234               
235                $guide->display_node(
236                                      id       => $node,
237                                      version  => $version,
238                                      oldid    => $oldid,
239                                      redirect => $redirect,
240                                    );
241            }
242        }
243    } else { 
244        # Fallback: redirect to the display page, preserving all vars
245        # except for the action, which we override.
246        # Note: $q->Vars needs munging if we need to support any
247        # multi-valued params
248        my $params = $q->Vars;
249        $params->{'action'} = 'display';
250        my $redir_target = $script_url . $script_name . '?';
251        my @args = map { "$_=" . $params->{$_} } keys %{$params};
252        $redir_target .= join ';', @args;
253       
254        print $q->redirect(
255            -uri => $redir_target,
256            -status => 303
257        );
258    }
259
260};
261
262if ($@) {
263    my $error = $@;
264    warn $error;
265    print $q->header;
266    my $contact_email = $config->contact_email;
267    print qq(<html><head><title>ERROR</title></head><body>
268             <p>Sorry!  Something went wrong.  Please contact the
269             Wiki administrator at
270             <a href="mailto:$contact_email">$contact_email</a> and quote
271             the following error message:</p><blockquote>)
272      . $q->escapeHTML($error)
273      . qq(</blockquote><p><a href="$script_name">Return to the Wiki home page</a>
274           </body></html>);
275}
276
277############################ subroutines ###################################
278
279sub show_userstats {
280    my %args = @_;
281    my ($username, $host) = @args{ qw( username host ) };
282    croak "No username or host supplied to show_userstats"
283        unless $username or $host;
284    my %criteria = ( last_n_changes => 5 );
285    $criteria{metadata_was} = $username ? { username => $username }
286                                        : { host     => $host };
287    my @nodes = $wiki->list_recent_changes( %criteria );
288    @nodes = map { {name          => $q->escapeHTML($_->{name}),
289            last_modified => $q->escapeHTML($_->{last_modified}),
290            comment       => OpenGuides::Utils::parse_change_comment(
291                $q->escapeHTML($_->{metadata}{comment}[0]),
292                $script_url . '?',
293            ),
294            url           => "$script_name?"
295          . $q->escape($formatter->node_name_to_node_param($_->{name})) }
296                       } @nodes;
297    my %tt_vars = ( last_five_nodes => \@nodes,
298            username        => $username,
299            username_param  => $wiki->formatter->node_name_to_node_param($username),
300                    host            => $host,
301                  );
302    process_template("userstats.tt", "", \%tt_vars);
303}
304
305sub get_cookie {
306    my $pref_name = shift or return "";
307    my %cookie_data = OpenGuides::CGI->get_prefs_from_cookie(config=>$config);
308    return $cookie_data{$pref_name};
309}
310
311sub display_node_rdf {
312    my %args = @_;
313    my $rdf_writer = OpenGuides::RDF->new( wiki => $wiki,
314                                           config => $config );
315    print "Content-type: application/rdf+xml\n\n";
316    print $rdf_writer->emit_rdfxml( node => $args{node} );
317}
318
319sub display_node_json { 
320    my %args = @_; 
321    my $json_writer = OpenGuides::JSON->new( wiki => $wiki, 
322                                             config => $config ); 
323    print "Content-type: text/javascript\n\n"; 
324    print $json_writer->emit_json( node => $args{node} ); 
325} 
326
327sub process_template {
328    my ($template, $node, $vars, $conf, $omit_header) = @_;
329
330    my %output_conf = ( wiki     => $wiki,
331            config   => $config,
332                        node     => $node,
333            template => $template,
334            vars     => $vars
335    );
336    $output_conf{noheaders} = 1 if $omit_header; # defaults otherwise
337    print OpenGuides::Template->output( %output_conf );
338}
339
340
341sub do_search {
342    my $terms = shift;
343    my %finds = $wiki->search_nodes($terms);
344#    my @sorted = sort { $finds{$a} cmp $finds{$b} } keys %finds;
345    my @sorted = sort keys %finds;
346    my @results = map {
347        { url   => $q->escape($formatter->node_name_to_node_param($_)),
348      title => $q->escapeHTML($_)
349        }             } @sorted;
350    my %tt_vars = ( results      => \@results,
351                    num_results  => scalar @results,
352                    not_editable => 1,
353                    search_terms => $q->escapeHTML($terms) );
354    process_template("search_results.tt", "", \%tt_vars);
355}
356
357sub show_wanted_pages {
358    my @dangling = $wiki->list_dangling_links;
359    my @wanted;
360    my %backlinks_count;
361    foreach my $node_name (@dangling) {
362        $backlinks_count{$node_name} = scalar($wiki->list_backlinks( node => $node_name ));
363    }
364    foreach my $node_name (sort { $backlinks_count{$b} <=> $backlinks_count{$a} } @dangling) {
365        my $node_param =
366         uri_escape($formatter->node_name_to_node_param($node_name));
367        push @wanted, {
368            name          => $q->escapeHTML($node_name),
369            edit_link     => $script_url . uri_escape($script_name)
370                           . "?action=edit;id=$node_param",
371            backlink_link => $script_url . uri_escape($script_name)
372                    . "?action=show_backlinks;id=$node_param",
373            backlinks_count => $backlinks_count{$node_name}
374        };
375    }
376    process_template( "wanted_pages.tt",
377                      "",
378                      { not_editable  => 1,
379                        not_deletable => 1,
380                        deter_robots  => 1,
381                        wanted        => \@wanted } );
382}
383
384sub show_needing_moderation {
385    my @nodes = $wiki->list_unmoderated_nodes;
386
387    # Build the moderate links
388    foreach my $node (@nodes) {
389        my $node_param =
390            uri_escape($formatter->node_name_to_node_param($node->{'name'}));
391        $node->{'moderate_url'} = $script_name . "?action=moderate;id=".$node_param.";version=".$node->{'version'};
392        $node->{'view_url'} = $script_name . "?id=".$node_param.";version=".$node->{'version'};
393        $node->{'diff_url'} = $script_name . "?id=".$node_param.";version=".$node->{'moderated_version'}.";diffversion=".$node->{'version'};
394        $node->{'delete_url'} = $script_name . "?action=delete;version=".$node->{'version'}.";id=".$node_param;
395    }
396
397    process_template( "needing_moderation.tt",
398                      "",
399                      { not_editable  => 1,
400                        not_deletable => 1,
401                        deter_robots  => 1,
402                        nodes        => \@nodes } );
403}
Note: See TracBrowser for help on using the repository browser.