You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axkit-dev@xml.apache.org by na...@apache.org on 2004/07/13 20:05:46 UTC

cvs commit: xml-axkit/lib/Apache/AxKit/Provider File.pm

nachbaur    2004/07/13 11:05:46

  Modified:    .        axconfig.c axconfig.h
               lib/Apache/AxKit ConfigReader.pm
               lib/Apache/AxKit/Provider File.pm
  Added:       lib/Apache/AxKit DirHandler.pm
               lib/Apache/AxKit/DirHandler Basic.pm
  Log:
  Reviewed by:	Kip Hampton
  
  Added AxDirHandler directive to choose a custom directory handler for when AxHandleDirs is enabled
  
  Revision  Changes    Path
  1.19      +19 -2     xml-axkit/axconfig.c
  
  Index: axconfig.c
  ===================================================================
  RCS file: /home/cvs/xml-axkit/axconfig.c,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- axconfig.c	7 Jul 2003 22:29:50 -0000	1.18
  +++ axconfig.c	13 Jul 2004 18:05:45 -0000	1.19
  @@ -104,6 +104,7 @@
       new->config_reader_module = 0;
       new->contentprovider_module = 0;
       new->styleprovider_module = 0;
  +    new->dir_handler_module = 0;
       new->default_style = 0;
       new->default_media = 0;
       new->cache_module = 0;
  @@ -429,6 +430,13 @@
           new->trace_intermediate = ap_pstrdup(p, parent_dir->trace_intermediate);
       }
   
  +    if (subdir->dir_handler_module) {
  +        new->dir_handler_module = ap_pstrdup(p, subdir->dir_handler_module);
  +    }
  +    else if (parent_dir->dir_handler_module) {
  +        new->dir_handler_module = ap_pstrdup(p, parent_dir->dir_handler_module);
  +    }
  +
       new->debug_tidy =
           subdir->debug_tidy != -1 ? subdir->debug_tidy :
                                        parent_dir->debug_tidy;
  @@ -1338,7 +1346,12 @@
       { "AxHandleDirs", ap_set_flag_slot,
         (void *)XtOffsetOf(axkit_dir_config, handle_dirs),
         OR_ALL, FLAG,
  -      "On or Off [default] to make AxKit process directory requests using XML::Directory" },
  +      "On or Off [default] to make AxKit produce XML for directory requests" },
  +
  +    { "AxDirHandler", ax_set_module_slot,
  +      (void *)XtOffsetOf(axkit_dir_config, dir_handler_module),
  +      OR_ALL, TAKE1,
  +      "alternative module to use for generating directory xml" },
   
       { "AxIgnoreStylePI", ap_set_flag_slot,
         (void *)XtOffsetOf(axkit_dir_config, ignore_style_pi),
  @@ -1459,6 +1472,10 @@
       if (cfg->handle_dirs != -1) {
           hv_store(retval, "HandleDirs",
                   10, (newSViv(cfg->handle_dirs)), 0);
  +    }
  +    if (cfg->dir_handler_module) {
  +        hv_store(retval, "DirHandler",
  +                10, (newSVpv(cfg->dir_handler_module, 0)), 0);
       }
   
       if (cfg->dependency_checks != -1) {
  
  
  
  1.9       +2 -1      xml-axkit/axconfig.h
  
  Index: axconfig.h
  ===================================================================
  RCS file: /home/cvs/xml-axkit/axconfig.h,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- axconfig.h	28 Jun 2002 01:26:01 -0000	1.8
  +++ axconfig.h	13 Jul 2004 18:05:45 -0000	1.9
  @@ -43,6 +43,7 @@
       char * cache_module;
       char * output_charset;
       char * trace_intermediate;
  +    char * dir_handler_module;
       int    debug_tidy;
       int    debug_level;
       int    translate_output;
  
  
  
  1.19      +13 -1     xml-axkit/lib/Apache/AxKit/ConfigReader.pm
  
  Index: ConfigReader.pm
  ===================================================================
  RCS file: /home/cvs/xml-axkit/lib/Apache/AxKit/ConfigReader.pm,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- ConfigReader.pm	4 Aug 2003 23:05:17 -0000	1.18
  +++ ConfigReader.pm	13 Jul 2004 18:05:45 -0000	1.19
  @@ -193,6 +193,18 @@
               0;
   }
   
  +sub DirHandlerClass {
  +    my $self = shift;
  +    if (my $alternate = $self->{cfg}{DirHandler} || 
  +            $self->{apache}->dir_config('AxDirHandler')) {
  +        AxKit::load_module($alternate);
  +        return $alternate;
  +    }
  +    
  +    AxKit::load_module('Apache::AxKit::DirHandler::Basic');
  +    return 'Apache::AxKit::DirHandler::Basic';
  +}
  +
   sub IgnoreStylePI {
       my $self = shift;
       return $self->{cfg}{IgnoreStylePI} ||
  
  
  
  1.1                  xml-axkit/lib/Apache/AxKit/DirHandler.pm
  
  Index: DirHandler.pm
  ===================================================================
  # $Id: DirHandler.pm,v 1.1 2004/07/13 18:05:46 nachbaur Exp $
  
  package Apache::AxKit::DirHandler;
  use strict;
  use Apache;
  use Apache::Log;
  use Apache::URI;
  use AxKit;
  use Data::Dumper;
  use File::Basename;
  
  sub new {
      my $class = shift;
      my $provider = shift;
      my $self = bless {
          provider => $provider,
          directory => AxKit::FromUTF8($provider->{file}),
      }, $class;
  
      # init() ourselves, if a subclass wants to
      $self->init(@_);
  
      return $self;
  }
  
  sub init {
      # blank - override to provide functionality
  }
  
  #
  # return mtime information for all files in this directory
  sub mtime {
      my $self = shift;
      my $dir = $self->{directory};
      my $mtime = 0;
      if (opendir(DIR, $dir)) {
          while(my $line = readdir(DIR)) {
              # stat the current file and, if it's mtime is bigger than
              # anything we've so far seen, snag it
              my @stat = stat(File::Spec->catfile($dir,$line));
              $mtime = $stat[9] if ($stat[9] > $mtime);
          }
          AxKit::Debug(8, "Directory mtime is $mtime");
          return $mtime;
      }
      AxKit::Debug(8, "Directory mtime calculations failed");
      return undef;
  }
  
  #
  # return the filename for the current request...its just plain easier
  # to use this way IMHO.
  sub _request_filename {
      my $self = shift;
      my $provider = $self->{provider};
      my $apache = $provider->apache_request;
      return $apache->filename;
  }
  
  #
  # take a filename, and return a proper URI for that, given the
  # current apache request
  sub _request_uri {
      my $self = shift;
      my $path = shift;
      my $provider = $self->{provider};
      my $r = $provider->apache_request;
      my $uri = Apache::URI->parse($r);
  
      # Traverse through to the ".." directory
      if ($path and $path eq '..') {
          # We don't want to climb above the document_root
          return undef if ($uri->path eq '/');
  
          # trim off the last directory on the URI and return
          # the modified Apache::URI object
          my $new_path = $uri->path;
          $new_path =~ s{/[^/]+/$} {/};
          $uri->path($new_path);
      }
      
      # Process the "." directory
      elsif ($path and $path eq '.' or basename($path) eq '.') {
          # Take the path, which may be multi-leveled, and remove
          # the "." directory from the end of it; if this is not
          # multi-leveled, don't do anything.
          $uri->path(dirname($uri->path . $path));
      }
      
      # For all other files, tack the filename onto the end of the URI
      elsif ($path) {
          $uri->path($uri->path . $path);
      }
  
      return ($uri, $uri->unparse) if (wantarray);
      return $uri->unparse;
  }
  
  #
  # pretty-format a filesize in kilobytes, megabytes, etc
  sub _format_filesize {
      my $self = shift;
      my $size = shift;
      my $factor = undef;
      my $base = 1024;
      my @suffix = qw( B kB MB GB TB PB );
      for ($factor = $#suffix; $factor > 0; $factor--) {
          last if ($size / $base ** $factor >= 1);
      }
      return sprintf('%.2f', $size / $base ** $factor) . $suffix[$factor];
  }
  
  1;
  __END__
  
  =head1 NAME
  
  Apache::AxKit::DirHandler - base class for Directory handlers
  
  =head1 SYNOPSIS
  
  Override the base DirHandler class and enable it by using:
  
      AxDirHandler MyClass
  
      # alternatively use:
      # PerlSetVar AxDirHandler MyClass
  
  =head1 DESCRIPTION
  
  AxKit supports the capability to handle directory requests.  Therefore, instead of
  relying on Apache to serve a Directory Index file or generating a file listing,
  AxKit will generate XML representing the content of the indicated directory for
  processing by your stylesheet pipeline.
  
  In many cases the default XML grammar provided will be sufficient, but for those
  instances when something more specific is necessary, this default behavior can be
  overridden.
  
  This class is a base-class implementing basic behavior, but must be inherited for
  directory listings to function.  To write your own directory handler, simply override
  this class and implement the C<get_strref()> method.
  
  =head1 PUBLIC METHODS
  
  The following are the methods available from this class:
  
  =head2 get_strref
  
  This method is called to generate the XML contents of a directory.  The "directory"
  property of the object contains the path of the directory to be returned.  The return
  value is expected to be a reference to the XML string to be returned.
  
  =head2 init()
  
  This method is called shortly after object construction, and can be used to initialize
  anything necessary to the operation of a directory handler.
  
  =head2 mtime()
  
  This returns the latest last modified time of any file or directory within the requested
  directory.  This is used for caching purposes.
  
  =head1 PRIVATE METHODS
  
  Apache::AxKit::DirHandler provides a few convenience methods that can make the business
  of processing directory listings easier.
  
  =head2 _request_filename
  
  This returns the requested filename from the Apache object.
  
  =head2 _request_uri
  
  Given a filename relative to the currently processed directory, this will return a full
  URI for the file.  If called in a scalar context it will return the full URI, while in an
  array context it will return both an Apache::URI object and the "unparsed" URI string.
  
  =head2 _format_filesize
  
  This will return a fancy filesize string (XkB, etc) for a given byte-size.
  
  =cut
  
  
  
  1.1                  xml-axkit/lib/Apache/AxKit/DirHandler/Basic.pm
  
  Index: Basic.pm
  ===================================================================
  # $Id: Basic.pm,v 1.1 2004/07/13 18:05:46 nachbaur Exp $
  
  package Apache::AxKit::DirHandler::Basic;
  use strict;
  use vars qw/@ISA/;
  @ISA = ('Apache::AxKit::DirHandler');
  
  use Apache;
  use Apache::Log;
  use AxKit;
  use Apache::AxKit::DirHandler;
  use File::Spec;
  use Fcntl qw(O_RDONLY LOCK_SH);
  
  sub get_strref {
      my $self = shift;
      local (*DIR);
      my $dir = $self->{directory};
      if (opendir(DIR, $dir)) {
          my $output = '<?xml version="1.0" encoding="UTF-8"?>
  <filelist xmlns="http://axkit.org/2002/filelist">
  ';
          while(my $line = readdir(DIR)) {
              my $xmlline = AxKit::ToUTF8($line);
              $xmlline =~ s/&/&amp;/;
              $xmlline =~ s/</&lt;/;
              my @stat = stat(File::Spec->catfile($dir,$line));
              my $attr = "size=\"$stat[7]\" atime=\"$stat[8]\" mtime=\"$stat[9]\" ctime=\"$stat[10]\"";
              $attr .= ' readable="1"' if (-r _);
              $attr .= ' writable="1"' if (-w _);
              $attr .= ' executable="1"' if (-x _);
              
              if (-f _) {
                  $output .= "<file $attr>$xmlline</file>\n";
              } elsif (-d _) {
                  $output .= "<directory $attr>$xmlline</directory>\n";
              } else {
                  $output .= "<unknown $attr>$xmlline</unknown>\n";
              }
          }
          $output .= "</filelist>\n";
          return \$output;
      }
      return undef;
  }
  
  1;
  __END__
  
  =head1 NAME
  
  Apache::AxKit::DirHandler::Basic - directory handler implementing a simple XML output
  
  =head1 SYNOPSIS
  
  Override the base DirHandler class and enable it by using:
  
      AxHandleDirs on
      AxDirHandler Apache::AxKit::DirHandler::Basic
  
      # or
  
      AxHandleDirs on
      # This module is the default
  
  =head1 DESCRIPTION
  
  This module is the default Directory Handler when no handler is explicitly
  specified.  It is intended to be simple to use and easy to get started with.
  
  =head1 SAMPLE OUTPUT
  
    <?xml version="1.0" encoding="UTF-8"?>
    <filelist xmlns="http://axkit.org/2002/filelist">
      <directory size="4096" atime="1077320634" mtime="1077312841" ctime="1077312841" readable="1" executable="1">.</directory>
      <directory size="4096" atime="1077316522" mtime="1076743711" ctime="1076743711" readable="1" executable="1">..</directory>
      <file size="0" atime="1076770889" mtime="1076770889" ctime="1076770889" readable="1">index.xml</file>
      <directory size="4096" atime="1076954718" mtime="1076774280" ctime="1076774280" readable="1" executable="1">images</directory>
      <file size="0" atime="1077320634" mtime="1076770894" ctime="1076770894" readable="1">.htaccess</file>
      <file size="580626" atime="1077319951" mtime="1076774007" ctime="1076774007" readable="1">link-4.1a.tar.gz</file>
      <file size="708" atime="1077319951" mtime="1076774018" ctime="1076774018" readable="1" executable="1">Bender.pl</file>
    </filelist>
  
  =head1 SEE ALSO
  
  L<Apache::AxKit::DirHandler>
  
  =cut
  
  
  
  1.17      +14 -30    xml-axkit/lib/Apache/AxKit/Provider/File.pm
  
  Index: File.pm
  ===================================================================
  RCS file: /home/cvs/xml-axkit/lib/Apache/AxKit/Provider/File.pm,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- File.pm	27 Apr 2004 16:57:14 -0000	1.16
  +++ File.pm	13 Jul 2004 18:05:46 -0000	1.17
  @@ -119,36 +119,14 @@
   
   sub get_dir_xml {
   	my $self = shift;
  -	local (*DIR);
  -	my $dir = AxKit::FromUTF8($self->{file});
  -	if (opendir(DIR, $dir)) {
  -		my $output = '<?xml version="1.0" encoding="UTF-8"?>
  -<filelist xmlns="http://axkit.org/2002/filelist">
  -';
  -		while(my $line = readdir(DIR)) {
  -			my $xmlline = AxKit::ToUTF8($line);
  -			$xmlline =~ s/&/&amp;/;
  -			$xmlline =~ s/</&lt;/;
  -			my @stat = stat(File::Spec->catfile($dir,$line));
  -			my $attr = "size=\"$stat[7]\" atime=\"$stat[8]\" mtime=\"$stat[9]\" ctime=\"$stat[10]\"";
  -			$attr .= ' readable="1"' if (-r _);
  -			$attr .= ' writable="1"' if (-w _);
  -			$attr .= ' executable="1"' if (-x _);
  -			
  -			if (-f _) {
  -				$output .= "<file $attr>$xmlline</file>\n";
  -			} elsif (-d _) {
  -				$output .= "<directory $attr>$xmlline</directory>\n";
  -			} else {
  -				$output .= "<unknown $attr>$xmlline</unknown>\n";
  -			}
  -		}
  -		$output .= "</filelist>\n";
  -		AxKit::Debug(8,"Generated file list: $output");
  +    my $r = AxKit::Apache->request;
  +    my $package = $AxKit::Cfg->DirHandlerClass();
  +    my $dirhandler = $self->{dirhandler_obj}
  +        || ($self->{dirhandler_obj} = $package->new($self));
  +    my $output = $dirhandler->get_strref();
  +    AxKit::Debug(8,"Generated file list: $$output") if (defined($$output));
   		return $output;
   	}
  -	return undef;
  -}
   
   sub decline {
       my $self = shift;
  @@ -207,6 +185,12 @@
   
   sub mtime {
       my $self = shift;
  +    if ($self->_is_dir and $AxKit::Cfg->HandleDirs()) {
  +        my $package = $AxKit::Cfg->DirHandlerClass();
  +        my $dirhandler = $self->{dirhandler_obj}
  +            || ($self->{dirhandler_obj} = $package->new($self));
  +        return $dirhandler->mtime();
  +    }
       return $self->{mtime} if defined $self->{mtime};
       return ($self->{mtime} = (stat(AxKit::FromUTF8($self->{file})))[9]);
   }
  @@ -233,7 +217,7 @@
       my $self = shift;
       if ($self->_is_dir()) {
           my $xml = $self->{dir_xml} || $self->get_dir_xml();
  -        return \$xml if $xml;
  +        return $xml if $$xml;
           throw Apache::AxKit::Exception::IO(
             -text => "directory $self->{file} cannot be read");
       }