Changeset 1315


Ignore:
Timestamp:
Mar 18, 2012, 9:48:44 AM (10 years ago)
Author:
kake
Message:

Added code to deal with node name parameters in URLs having spaces instead of underscores, to take account of people typing manually (#114).

Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Changes

    r1312 r1315  
    660.66    ?
    77        All templates now have access to the "username" TT variable.
     8        Node name parameters in URLs are now accepted with spaces instead of
     9          underscores, to take account of people typing manually - these will
     10          redirect (303) to the proper URLs with underscores (#114).
    811        Add CSS classes for each category and locale to the "content" div
    912          (and hence we now require version 2.24 of Template).
  • trunk/MANIFEST

    r1312 r1315  
    157157t/90_css_category_locale_classes.t
    158158t/91_username_in_templates.t
     159t/92_node_name_from_cgi_obj.t
     160t/93_redirect_without_spaces.t
    159161t/templates/15_test.tt
    160162wiki.cgi
  • trunk/lib/OpenGuides/CGI.pm

    r1256 r1315  
    7171
    7272=over 4
     73
     74=item B<extract_node_param>
     75
     76    my $config_file = $ENV{OPENGUIDES_CONFIG_FILE} || "wiki.conf";
     77    my $config = OpenGuides::Config->new( file => $config_file );
     78    my $guide = OpenGuides->new( config => $config );
     79    my $wiki = $guide->wiki;
     80
     81    my $q = CGI->new;
     82
     83    my $node_param = OpenGuides::CGI->extract_node_param(
     84                        wiki => $wiki, cgi_obj => $q );
     85
     86Returns the title, id, or keywords parameter from the URL.  Normally
     87this will be something like "British_Museum", i.e. with underscores
     88instead of spaces.  However if the URL does contain spaces (encoded as
     89%20 or +), the return value will be e.g. "British Museum" instead.
     90
     91Croaks unless a L<Wiki::Toolkit> object is supplied as C<wiki> and a
     92L<CGI> object is supplied as C<cgi_obj>.
     93
     94=cut
     95
     96sub extract_node_param {
     97    my ($class, %args) = @_;
     98    my $wiki = $args{wiki} or croak "No wiki supplied";
     99    croak "wiki not a Wiki::Toolkit object"
     100        unless UNIVERSAL::isa( $wiki, "Wiki::Toolkit" );
     101    my $q = $args{cgi_obj} or croak "No cgi_obj supplied";
     102    croak "cgi_obj not a CGI object"
     103        unless UNIVERSAL::isa( $q, "CGI" );
     104
     105    # Note $q->param( "keywords" ) gives you the entire param string.
     106    # We need this to do URLs like foo.com/wiki.cgi?This_Page
     107    my $param = $q->param( "id" )
     108                || $q->param( "title" )
     109                || join( " ", $q->param( "keywords" ) )
     110                || "";
     111    $param =~ s/%20/ /g;
     112    $param =~ s/\+/ /g;
     113    return $param;
     114}
     115
     116=item B<extract_node_name>
     117
     118    my $config_file = $ENV{OPENGUIDES_CONFIG_FILE} || "wiki.conf";
     119    my $config = OpenGuides::Config->new( file => $config_file );
     120    my $guide = OpenGuides->new( config => $config );
     121    my $wiki = $guide->wiki;
     122
     123    my $q = CGI->new;
     124
     125    my $node_name = OpenGuides::CGI->extract_node_name(
     126                        wiki => $wiki, cgi_obj => $q );
     127
     128Returns the name of the node the user wishes to display/manipulate, as
     129we expect it to be stored in the database.  Normally this will be
     130something like "British Museum", i.e. with spaces in.  Croaks unless a
     131L<Wiki::Toolkit> object is supplied as C<wiki> and a L<CGI> object is
     132supplied as C<cgi_obj>.
     133
     134=cut
     135
     136sub extract_node_name {
     137    my ($class, %args) = @_;
     138    # The next call will validate our args for us and croak if necessary.
     139    my $param = $class->extract_node_param( %args );
     140
     141    # Sometimes people type spaces instead of underscores.
     142    $param =~ s/ /_/g;
     143    $param =~ s/%20/_/g;
     144    $param =~ s/\+/_/g;
     145
     146    my $formatter = $args{wiki}->formatter;
     147    return $formatter->node_param_to_node_name( $param );
     148}
     149
     150=item B<check_spaces_redirect>
     151
     152    my $config_file = $ENV{OPENGUIDES_CONFIG_FILE} || "wiki.conf";
     153    my $config = OpenGuides::Config->new( file => $config_file );
     154    my $guide = OpenGuides->new( config => $config );
     155
     156    my $q = CGI->new;
     157
     158    my $url = OpenGuides::CGI->check_spaces_redirect(
     159                                 wiki => $wiki, cgi_obj => $q );
     160
     161If the user seems to have typed a URL with spaces in the node param
     162instead of underscores, this method will return the URL with the
     163underscores put in.  Otherwise, it returns false.
     164
     165=cut
     166
     167sub check_spaces_redirect {
     168    my ($class, %args) = @_;
     169    my $wiki = $args{wiki};
     170    my $q = $args{cgi_obj};
     171
     172    my $name = $class->extract_node_name( wiki => $wiki, cgi_obj => $q );
     173    my $param = $class->extract_node_param( wiki => $wiki, cgi_obj => $q );
     174
     175    # If we can't figure out the name or param, it's safest to do nothing.
     176    if ( !$name || !$param ) {
     177        return 0;
     178    }
     179
     180    # If the name has no spaces in, or the name and param differ, we're
     181    # probably OK.
     182    if ( ( $name !~ / / ) || ( $name ne $param ) ) {
     183        return 0;
     184    }
     185
     186    # Make a new CGI object to manipulate, to avoid action-at-a-distance.
     187    my $new_q = CGI->new( $q );
     188    my $formatter = $wiki->formatter;
     189    my $real_param = $formatter->node_name_to_node_param( $name );
     190
     191    if ( $q->param( "id" ) ) {
     192        $new_q->param( -name => "id", -value => $real_param );
     193    } elsif ( $q->param( "title" ) ) {
     194        $new_q->param( -name => "title", -value => $real_param );
     195    } else {
     196        # OK, we have the keywords case; the entire param string is the
     197        # node param.  So just delete all existing parameters and stick
     198        # the node param back in.
     199        $new_q->delete_all();
     200        $new_q->param( -name => "id", -value => $real_param );
     201    }
     202
     203    my $url = $new_q->self_url;
     204
     205    # Escaped commas are ugly.
     206    $url =~ s/%2C/,/g;
     207    return $url;
     208}
    73209
    74210=item B<make_prefs_cookie>
  • trunk/wiki.cgi

    r1313 r1315  
    3131    $wiki = $guide->wiki;
    3232    $formatter = $wiki->formatter;
    33 
    34     # Get CGI object, find out what to do.
    3533    $q = CGI->new;
    3634
    37     # Note $q->param('keywords') gives you the entire param string.
    38     # We need this to do URLs like foo.com/wiki.cgi?This_Page
    39     my $node = $q->param('id') || $q->param('title') || $q->param('keywords') || '';
    40     $node = $formatter->node_param_to_node_name( $node );
     35    # See if we need to redirect due to spaces in URL.
     36    my $redirect = OpenGuides::CGI->check_spaces_redirect(
     37                                         cgi_obj => $q, wiki => $wiki );
     38
     39    if ( $redirect ) {
     40        print $q->redirect( -uri => $redirect, -status => 303 );
     41        exit 0;
     42    }
     43
     44    # No redirect - carry on.
     45    my $node = OpenGuides::CGI->extract_node_name(
     46                                         cgi_obj => $q, wiki => $wiki );
    4147
    4248    # If we did a post, then CGI->param probably hasn't fully de-escaped,
Note: See TracChangeset for help on using the changeset viewer.