1 # Blosxom Plugin: slashredir
2 # Author(s): Frank Hecker <hecker@hecker.org>
4 # Documentation: See the bottom of this file or type: perldoc slashredir
10 use CGI qw/:standard :netscape/;
13 # --- Configurable variables -----
15 my $debug = 1; # set to 1 to print debug messages
17 # --------------------------------
20 use vars qw!$redirecting!; # 1 if we are redirecting, 0 if not
24 warn "slashredir: start\n" if $debug > 1;
28 # Activate this plugin only when doing dynamic page generation.
29 return $blosxom::static_or_dynamic eq 'dynamic' ? 1 : 0;
34 my ($pkg, $files_ref) = @_;
36 warn "slashredir: filter\n" if $debug > 1;
38 warn "slashredir: \$path_info: '" . $blosxom::path_info . "'\n"
40 warn "slashredir: path_info(): '" . path_info() . "'\n"
43 # We need a copy of the original PATH_INFO, prior to Blosxom having
44 # parsed it, because we need to see the trailing slashes stripped by
45 # Blosxom and also want the full path including date information.
47 my $path = path_info();
49 # We check to see if the URI is for an entry page and redirect if the URI
50 # has a trailing slash. Otherwise we check to see if a trailing slash
51 # needs to be added or removed and redirect if needed.
53 # Note: We use $blosxom::path_info to check for the presence of a
54 # file extension because the extension may not have been present in the
55 # original URI but might have been added by the extensionless plugin.
56 # (That also implies that this plugin must run after extensionless runs.)
58 if ($blosxom::path_info =~ m!\.!) {
60 $path =~ s!/+$!!; # strip *all* trailing slashes
61 redirect($path, "Trailing slash(es) not needed");
63 } elsif ($path !~ m!/$!) {
64 $path .= '/'; # add one trailing slash
65 redirect($path, "Adding trailing slash");
66 } elsif ($path =~ m!//+$!) {
67 $path =~ s!//+$!/!; # remove redundant slash(es)
68 redirect($path, "Removing redundant trailing slash(es)");
75 warn "slashredir: skip\n" if $debug > 1;
77 return $redirecting; # skip story generation if redirecting
82 my ($path, $error_msg) = @_;
84 my $uri = "$blosxom::url$path";
85 $uri .= "?" . $ENV{QUERY_STRING} if $ENV{QUERY_STRING};
87 warn "slashredir: redirecting to '$uri', '$error_msg'\n"
90 my $redir_msg = qq!, redirecting to <a href="$uri">$uri</a>.\n!;
91 $blosxom::output = $error_msg . $redir_msg;
92 print "Status: 301\n";
93 print "Location: $uri\n";
103 Blosxom plugin: slashredir
107 Have Blosxom force a redirect if a URI is not in canonical form with respect
116 Frank Hecker <hecker@hecker.org>, http://www.hecker.org/
120 This plugin checks to see whether the requested URI has one or more
121 trailing slashes and if necessary does a browser redirect to the
122 canonical form of the URI. More specifically, URIs for the blog root,
123 categories, and date-based archives should have one (and only one)
124 trailing slash, while URIs for individual entry pages should not have
127 For example, if you request the URI
129 http://www.example.com/blog/foo
131 where "foo" is a category, this plugin will force a redirect to the
134 http://www.example.com/blog/foo/
136 This plugin essentially causes Blosxom to emulate the default behavior
137 of the Apache web server. The underlying idea is that URIs for Blosxom
138 pages should have trailing slashes if and only if there are (or could
139 be) other URIs for other pages "underneath" the URI in question.
141 Thus an individual entry page with a URI of the form
142 ".../entry.flavour" (or ".../entry" if using the extensionless plugin)
143 should not have a trailing slash, because URIs of the form
144 ".../entry.html/foo" (or ".../entry/foo" with extensionless) don't and
145 won't return anything meaningful. However a category page with a URI
146 of the form ".../category" could refer to additional pages with URIs
147 of the form ".../category/foo.html (or ".../category/foo/entry"), and
148 hence the canocical form of the category's URI should be
151 Similarly, date-based archive pages with URIs like ".../2004" or
152 ".../2004/10" could have subsidiary URIs for months or days
153 respectively; while days are not subdivided further, per-day archive
154 pages could be requested in non-default flavours, e.g.,
155 ".../2004/10/14/index.rss" (as could per-year and per-month pages as
156 well, of course). Hence for date-based archive pages the canonical
157 form of the URI should also include a trailing slash if the default
158 flavour is being requested.
160 Note that using this plugin makes most sense if you are also using URI
161 rewriting rules to hide use of "/cgi-bin/blosxom.cgi" and support URIs
162 similar to those traditionally used to access normal directories and
163 files. This plugin can be used in conjunction with the extensionless
164 plugin, but does not assume or require its use. (See also below.)
166 This plugin was inspired by the redirect plugin by Fletcher T. Penny
167 http://www.blosxom.com/plugins/general/redirect.htm and adapts a bit
170 =head1 INSTALLATION AND CONFIGURATION
172 Copy this plugin into your Blosxom plugin directory. You do not
173 normally need to rename the plugin; however see the discussion below.
175 You can change the value of the variable C<$debug> to 1 if you need to
176 debug the plugin's operation; the plugin will print to the web
177 server's error log the original path component of the URI and the new
178 URI if redirection is to be done.
180 This plugin supplies a filter and skip subroutine and can normally
181 coexist with other plugins with filter subroutines. However this
182 plugin needs to be run after the extensionless plugin, since it needs
183 the file extension (provided by extensionless if not already present)
184 to distinguish between individual entry pages and other pages.
186 Finally, note that this plugin is sensitive to the exact URI rewriting
187 rules you might have configured (e.g., in an Apache configuration file
188 or in a .htaccess file). In particular, when rewriting URIs to add the
189 name of the Blosxom CGI script (e.g., "/cgi-bin/blosxom.cgi") you need
190 to ensure that such rules preserve any trailing slash on the end of
191 the URI and pass it on to Blosxom.
195 Blosxom Home/Docs/Licensing: http://www.blosxom.com/
197 Blosxom Plugin Docs: http://www.blosxom.com/documentation/users/plugins.html
201 Address other bug reports and comments to the Blosxom mailing list:
202 http://www.yahoogroups.com/group/blosxom
206 slashredir Blosxom plugin Copyright 2004 Frank Hecker
208 Permission is hereby granted, free of charge, to any person obtaining a
209 copy of this software and associated documentation files (the "Software"),
210 to deal in the Software without restriction, including without limitation
211 the rights to use, copy, modify, merge, publish, distribute, sublicense,
212 and/or sell copies of the Software, and to permit persons to whom the
213 Software is furnished to do so, subject to the following conditions:
215 The above copyright notice and this permission notice shall be included
216 in all copies or substantial portions of the Software.
218 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
219 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
220 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
221 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
222 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
223 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
224 OTHER DEALINGS IN THE SOFTWARE.