package Apache::WinBitHack; BEGIN { eval{ require Win32::File; Win32::File->import(qw(READONLY ARCHIVE)); }; } use Apache::Constants qw(OK DECLINED OPT_INCLUDES DECLINE_CMD); use Apache::File; use Apache::ModuleConfig; use DynaLoader; use 5.006; use strict; our $VERSION = '0.01'; our @ISA = qw(DynaLoader); __PACKAGE__->bootstrap($VERSION); sub handler { # Implement XBitHack on Win32. # Usage: PerlModule Apache::WinBitHack # PerlFixupHandler Apache::WinBitHack # XBitHack On|Off|Full my $r = shift; my $cfg = Apache::ModuleConfig->get($r, __PACKAGE__); return DECLINED unless ( $^O =~ m/Win32/ && # we're on Win32 -f $r->finfo && # the file exists $r->content_type eq 'text/html' && # and is HTML $r->allow_options & OPT_INCLUDES && # and we have Options +Includes $cfg->{_state} ne 'OFF'); # and XBitHack On or Full # Gather the file attributes. my $attr; Win32::File::GetAttributes($r->filename, $attr); # Return DECLINED if the file has the ARCHIVE attribute set, # which is the usual case. return DECLINED if $attr & ARCHIVE(); # Set the Last-Modified header unless the READONLY attribute is set. if ($cfg->{_state} eq 'FULL') { $r->set_last_modified((stat _)[9]) unless $attr & READONLY(); } # Make sure mod_include picks it up. $r->handler('server-parsed'); return OK; } sub DIR_CREATE { my $class = shift; my %self = (); # XBitHack is disabled by default. $self{_state} = "OFF"; return bless \%self, $class; } sub DIR_MERGE { my ($parent, $current) = @_; my %new = (%$parent, %$current); return bless \%new, ref($parent); } sub XBitHack ($$$) { my ($cfg, $parms, $arg) = @_; # Let mod_include do the Unix stuff - we only do Win32. return DECLINE_CMD unless $^O =~ m/Win32/; if ($arg =~ m/^(On|Off|Full)$/i) { $cfg->{_state} = uc($arg); } else { die "Invalid XBitHack $arg!"; } } 1; __END__ =head1 NAME Apache::WinBitHack - An Apache module to emulate XBitHack on Win32 =head1 SYNOPSIS In Apache's F: PerlModule Apache::WinBitHack SetHandler perl-script PerlFixupHandler Apache::WinBitHack XBitHack Full Options MultiViews Indexes Includes =head1 DESCRIPTION Apache contains a very useful directive C, whereby a file that has the user-execute bit set will be treated as a server-parsed html document. As well, the group-execute bit can be used to set the Last-modified time of the returned file to be the last modified time of the file, which is useful in determining if a document is to be cached or not. On Win32 the directive works in principle, but in an inconvenient fashion - the execute bit is set on Win32 by the file extension, which means that documents that are to take advantage of C must have an extension like C or C. This module emulates C on Win32 by, rather than using the user and group execute bits, using instead the attributes of the file to determine if the file is to be server-parsed by mod_include. Attributes of a file on Win32, which you can see by running C:\> attrib file_name include C, C, C, and C. Normal user files have just the C attribute set, which some back-up programs use to determine if the file should be included in the next incremental backup (most backup programs now instead use the last-modified-time of the file for this purpose). By setting certain attributes of the file and specifying directives as in the SYNOPSIS, particularly the C option, C can be emulated in the following ways. =head2 XBitHack Off With this directive, no server-side parsing of the file will be performed. =head2 XBitHack On This directive emulates setting the user-execute bit. With this directive, a file will parsed by mod_include if the C attribute is B, which you can do by C:\> attrib -a file_name Note that when a user's file is first created or when it is edited the C attribute will normally be set (and all others unset), so you must intentionally unset the C attribute to enable server-parsing of the file. =head2 XBitHack Full This directive emulates the action of also setting the group-execute bit. With this directive, as with C, a file will be parsed by mod_include if the C attribute is unset. As well, a Last-modified header will be sent, equal to the last-modified time of the file, I the C attribute of the file is B, which you can do by C:\> attrib +r file_name =head1 SEE ALSO L The description of the C directive in the Apache manual (http://httpd.apache.org/docs/mod/directives.html). =head1 AUTHORS Randy Kobes Geoffrey Young Paul Lindner =head1 COPYRIGHT Copyright (c) 2001, Geoffrey Young, Paul Lindner, Randy Kobes. All rights reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself. =head1 HISTORY This code is derived from the I module, available as part of "The mod_perl Developer's Cookbook". For more information, visit http://www.modperlcookbook.org/ =cut