1 # Blosxom Plugin: canonicaluri
2 # Author(s): Frank Hecker <hecker@hecker.org>
4 # Documentation: See the bottom of this file or type: perldoc canonicaluri
10 use CGI qw/:standard :netscape/;
13 # --- Configurable variables -----
15 my $debug = 0; # set to 1 to print debug messages
17 # --------------------------------
20 use vars qw!$redirecting!; # 1 if we are redirecting, 0 if not
24 warn "canonicaluri: 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 "canonicaluri: filter\n" if $debug > 1;
38 warn "canonicaluri: \$blosxom::path_info: '" . $blosxom::path_info . "'\n"
40 warn "canonicaluri: 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 original URI passed into
45 # Blosxom, including whether the URI had an index.* component, trailing
46 # slash, or file extension.
48 my $path = path_info();
50 # If the requested URI has an explicit "index.*" component where the
51 # the file extension corresponds to the default flavour (typically
52 # "html") then we rewrite the URI to strip the "index.*" component
53 # (and any spurious slashes after it) and leave a single trailing slash.
55 $path =~ s!/index\.$blosxom::default_flavour/*$!/!;
57 warn "canonicaluri: \$path (after index.html check): '" . $path . "'\n"
60 # If the requested URI has an explicit "index.*" component for any
61 # flavour other than the default then we rewrite the URI if necessary
62 # to remove any trailing slashes.
64 $path =~ s!/(index\.[^./]*)/*$!/$1!;
66 warn "canonicaluri: \$path (after index.foo check): '" . $path . "'\n"
69 # If the URI has a trailing slash but corresponds to an individual entry
70 # then we rewrite the URI to remove the trailing slash. On the other hand
71 # if the URI does not have a trailing slash but corresponds to a category
72 # or archive page then we rewrite the URI to add the trailing slash
73 # unless an "index.*" component is present in the URI.
75 if ($path =~ m!/$!) { # trailing slash, remove if need be
76 $blosxom::path_info =~ m!\.! and $path =~ s!/+$!!;
77 } else { # no trailing slash, add if needed
78 $blosxom::path_info !~ m!\.!
79 and $path !~ m!/index.[^./]*$!
83 warn "canonicaluri: \$path (after slash check): '" . $path . "'\n"
86 # If the URI has a flavour extension corresponding to the default flavour
87 # (typically "html") then we rewrite the URI to remove the extension.
89 $path =~ s!\.$blosxom::default_flavour!!;
91 warn "canonicaluri: \$path (after extension check): '" . $path . "'\n"
94 # If we have rewritten the URI then we force a redirect to the new URI.
96 $path ne path_info() and redirect($path);
103 warn "canonicaluri: skip\n" if $debug > 1;
105 return $redirecting; # skip story generation if redirecting
112 my $uri = "$blosxom::url$path";
113 $uri .= "?" . $ENV{QUERY_STRING} if $ENV{QUERY_STRING};
115 warn "canonicaluri: redirecting to '$uri'\n"
118 $blosxom::output = qq!Redirecting to <a href="$uri">$uri</a>.\n!;
119 print "Status: 301\n";
120 print "Location: $uri\n";
130 Blosxom plugin: canonicaluri
134 Have Blosxom force a redirect if a URI is not in canonical form with
135 respect to index.* component, trailing slash, or flavour extension.
143 Frank Hecker <hecker@hecker.org>, http://www.hecker.org/
145 This plugin is now maintained by the Blosxom Sourceforge Team,
146 <blosxom-devel@lists.sourceforge.net>.
150 This plugin checks to see whether the requested URI is in the
151 canonical form for the type of page being requested, and if necessary
152 does a browser redirect to the canonical form of the URI. The
153 canonical forms are defined as follows:
157 =item * URIs for the blog root, categories, and date-based archives
158 should not have an "index.*" component if the flavour being requested
159 is the default flavour, and if an "index.*" component is not present
160 then the URI should have one (and only one) trailing slash.
162 =item * URIs for individual entry pages should not have a trailing
163 slash and also should not have a flavour extension if the flavour
164 being requested is the default flavour (typically "html").
168 For example, if you request the URIs
170 http://www.example.com/blog/foo
174 http://www.example.com/blog/foo/index.html
176 where "foo" is a category and "html" is the default flavour, this
177 plugin will force a redirect to the canonical URI
179 http://www.example.com/blog/foo/
181 Similarly, if you request the URIs
183 http://www.example.com/blog/foo/
187 http://www.example.com/blog/foo.html
189 where "foo" is an individual entry and "html" is the default flavour,
190 this plugin will force a redirect to the canonical URI
192 http://www.example.com/blog/foo
194 Note that using this plugin makes the most sense if you are also using
195 URI rewriting rules to hide use of "/cgi-bin/blosxom.cgi" and support
196 URIs similar to those traditionally used to access normal directories
197 and files. This plugin should also be used in conjunction with the
198 extensionless plugin in order to recognize extensionless URIs for
199 individual entries. (See also below.)
201 This plugin was inspired by the redirect plugin by Fletcher T. Penny
202 http://www.blosxom.com/plugins/general/redirect.htm and adapts a bit
205 =head1 INSTALLATION AND CONFIGURATION
207 Copy this plugin into your Blosxom plugin directory. You do not
208 normally need to rename the plugin; however see the discussion below.
210 You can change the value of the variable C<$debug> to 1 if you need to
211 debug the plugin's operation; the plugin will print to the web
212 server's error log the original path component of the URI and the new
213 URI if redirection is to be done.
215 This plugin supplies a filter and skip subroutine and can normally
216 coexist with other plugins with filter subroutines. However this
217 plugin needs to be run after the extensionless plugin, since it needs
218 the flavour extension on C<$blosxom::path_info> (provided by
219 extensionless if not already present) to distinguish between
220 individual entry pages and other pages.
222 Finally, note that this plugin is sensitive to the exact URI rewriting
223 rules you might have configured (e.g., in the Apache httpd.conf
224 configuration file or in a .htaccess file). In particular, when
225 rewriting URIs to add the name of the Blosxom CGI script (e.g.,
226 "/cgi-bin/blosxom.cgi") you need to ensure that such rules preserve
227 any trailing slash on the end of the URI and pass it on to Blosxom.
231 Blosxom Home/Docs/Licensing: http://blosxom.sourceforge.net/
233 Blosxom Plugin Docs: http://blosxom.sourceforge.net/documentation/users/plugins.html
237 This plugin depends on the Apache URI rewriting rules to enforce the
238 restriction that a URI should never have more than one trailing
239 slash. The plugin as presently written can't handle this case properly
240 because it depends on the C<path_info()> function to get the URI path,
241 and the C<path_info()> value has already been stripped of any excess
242 trailing slashes that might have been present in the original URI.
244 Please send bug reports and feedback to the Blosxom development mailing
245 list <blosxom-devel@lists.sourceforge.net>.
249 canonicaluri Blosxom plugin Copyright 2004 Frank Hecker
251 Permission is hereby granted, free of charge, to any person obtaining a
252 copy of this software and associated documentation files (the "Software"),
253 to deal in the Software without restriction, including without limitation
254 the rights to use, copy, modify, merge, publish, distribute, sublicense,
255 and/or sell copies of the Software, and to permit persons to whom the
256 Software is furnished to do so, subject to the following conditions:
258 The above copyright notice and this permission notice shall be included
259 in all copies or substantial portions of the Software.
261 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
262 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
263 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
264 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
265 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
266 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
267 OTHER DEALINGS IN THE SOFTWARE.