home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / TieBucketBrigade.pm < prev    next >
Encoding:
Perl POD Document  |  2004-02-18  |  6.1 KB  |  242 lines

  1. package Apache::TieBucketBrigade;
  2.  
  3. use 5.006001;
  4.  
  5. use strict;
  6. use warnings;
  7.  
  8. use Apache::Connection ();
  9. use APR::Bucket ();
  10. use APR::Brigade ();
  11. use APR::Util ();
  12. use APR::Const -compile => qw(SUCCESS EOF);
  13. use Apache::Const -compile => qw(OK MODE_GETLINE);
  14. use IO::WrapTie;
  15.  
  16. our @ISA = qw(IO::WrapTie::Slave);
  17.  
  18. our $VERSION = '0.03';
  19.  
  20. sub TIEHANDLE {
  21.     my $invocant = shift;
  22.     my $connection = shift;
  23.     my $class = ref($invocant) || $invocant;
  24.     my $self = {                            
  25.         @_,
  26.     };
  27.     bless $self, $class;
  28.     $self->{bbin} = APR::Brigade->new($connection->pool,
  29.                                       $connection->bucket_alloc);
  30.     $self->{bbout} = APR::Brigade->new($connection->pool,
  31.                                        $connection->bucket_alloc);
  32.     $self->{connection} = $connection;
  33.     return $self;
  34. }
  35.  
  36. sub PRINT {
  37.     my $self = shift;
  38.     my $bucket;
  39.     foreach my $line (@_) {
  40.         $bucket = APR::Bucket->new($line);
  41.         $self->{bbout}->insert_tail($bucket);
  42.     }
  43.     my $bkt = APR::Bucket::flush_create($self->{connection}->bucket_alloc);
  44.     $self->{bbout}->insert_tail($bkt);
  45.     $self->{connection}->output_filters->pass_brigade($self->{bbout});
  46. }
  47.  
  48. sub WRITE {
  49.     my $self = shift;
  50.     my ($buf, $len, $offset) = @_;
  51.     return undef unless $self->PRINT(substr($buf, $offset, $len));
  52.     return length substr($buf, $offset, $len);
  53. }
  54.  
  55. sub PRINTF {
  56.     my $self = shift;
  57.     my $fmt = shift;
  58.     $self->PRINT(sprintf($fmt, @_));
  59. }
  60.  
  61. sub READLINE {
  62.     my $self = shift;
  63.     my $out;
  64.     my $last = 0;
  65.     while (1) {
  66.         my $rv = $self->{connection}->input_filters->get_brigade(
  67.             $self->{bbin}, Apache::MODE_GETLINE);
  68.         if ($rv != APR::SUCCESS && $rv != APR::EOF) {
  69.             my $error = APR::strerror($rv);
  70.             warn __PACKAGE__ . ": get_brigade: $error\n";
  71.             last;
  72.         }
  73.         last if $self->{bbin}->empty;
  74.         while (!$self->{bbin}->empty) {
  75.             my $bucket = $self->{bbin}->first;
  76.             $bucket->remove;
  77.             last if ($bucket->is_eos);
  78.             my $data;
  79.             my $status = $bucket->read($data);
  80.             $out .= $data;
  81.             last unless $status == APR::SUCCESS;
  82.             if (defined $data) {
  83.                 $last++ if $data =~ /[\r\n]+$/;
  84.                 last if $last;
  85.             }
  86.         }
  87.         last if $last;
  88.     }
  89.     $self->{bbin}->destroy;
  90.     return undef unless defined $out;
  91.     return undef if $out =~ /^[\r\n]+$/;
  92.     return $out if $out =~ /[\r\n]+$/;
  93.     return $out;
  94. }
  95.  
  96. sub GETC {
  97.     my $self = shift;
  98.     my $char;
  99.     $self->READ($char, 1, 0);
  100.     return undef unless $char;
  101.     return $char;
  102. }
  103.  
  104. sub READ {
  105. #this buffers however man unused bytes are read from the bucket
  106. #brigade into $self->{'_buffer'}.  Repeated calls should retreive anything
  107. #left in the buffer before more stuff is received
  108.     my $self = shift;
  109.     my $bufref = \$_[0];
  110.     my (undef, $len, $offset) = @_;
  111.     my $out = $self->{'_buffer'} if defined $self->{buffer};
  112.     my $last = 0;
  113.     while (1) {
  114.         my $rv = $self->{connection}->input_filters->get_brigade(
  115.             $self->{bbin}, Apache::MODE_GETLINE);
  116.         if ($rv != APR::SUCCESS && $rv != APR::EOF) {
  117.             my $error = APR::strerror($rv);
  118.             warn __PACKAGE__ . ": get_brigade: $error\n";
  119.             last;
  120.         }
  121.         last if $self->{bbin}->empty;
  122.         while (!$self->{bbin}->empty) {
  123.             my $bucket = $self->{bbin}->first;
  124.             $bucket->remove;
  125.             $last++ and last if ($bucket->is_eos);
  126.             my $data;
  127.             my $status = $bucket->read($data);
  128.             $out .= $data;
  129.             $last++ and last unless $status == APR::SUCCESS;
  130.             $last++ and last unless defined $data;
  131.             if (defined $out) {
  132.                 $last++ if length $out >= $len;
  133.                 last if $last;
  134.             }
  135.         }
  136.         last if $last;
  137.     }
  138.     $self->{bbin}->destroy;
  139.     if (length $out > $len) {
  140.         $self->{'_buffer'} = substr $out, $len + $offset;
  141.         $out = substr $out, $offset, $len;
  142.     }
  143.     $$bufref .= $out;
  144.     return length $out
  145. }
  146.  
  147. sub CLOSE {
  148.     my $self = shift;
  149.     $self->{socket}->close;
  150. }
  151.  
  152. sub OPEN {
  153.    return shift;
  154. }
  155.  
  156. sub FILENO {
  157. #pretends to be STDIN so that IO::Select will work
  158.     shift;
  159.     return 0;
  160. }
  161.  
  162. 1;
  163.  
  164. package IO::WrapTie::Master;
  165. #this is some sketchy shit
  166.  
  167. no warnings;
  168.  
  169. *IO::WrapTie::Master::autoflush = sub {
  170.     shift;
  171.     return !$_[0];
  172. };
  173.  
  174. *IO::WrapTie::Master::blocking = sub {
  175. #why of course I'm non blocking
  176.    shift;
  177.    return !$_[0];
  178. };
  179.  
  180. use warnings;
  181.  
  182. 1;
  183.  
  184.  
  185. 1;
  186. __END__
  187.  
  188. =head1 NAME
  189.  
  190. Apache::TieBucketBrigade - Perl extension which ties an IO::Handle to Apache's
  191. Bucket Brigade so you can use standard filehandle type operations on the 
  192. brigade.
  193.  
  194. =head1 SYNOPSIS
  195.  
  196.   use Apache::Connection ();
  197.   use Apache::Const -compile => 'OK';
  198.   use Apache::TieBucketBrigade;
  199.   
  200.   sub handler { 
  201.       my $FH = Apache::TieBucketBrigade->new_tie($c);
  202.       my @stuff = <$FH>;
  203.       print $FH "stuff goes out too";
  204.       $FH->print("it's and IO::Handle too!!!");
  205.       Apache::OK;
  206.   }
  207.  
  208. =head1 DESCRIPTION
  209.  
  210. This module has one usefull method "new_tie" which takes an Apache connection
  211. object and returns a tied IO::Handle object.  It should be used inside a 
  212. mod_perl protocol handler to make dealing with the bucket brigade bitz 
  213. easier.  For reasons of my own, FILENO will pretend to be STDIN so you may
  214. need to keep this in mind.  Also IO::Handle::autoflush and IO::Handle::blocking
  215. are essentially noops.
  216.  
  217. =head2 EXPORT
  218.  
  219. None
  220.  
  221.  
  222. =head1 SEE ALSO
  223.  
  224. IO::Stringy
  225. mod_perl
  226. IO::Handle
  227.  
  228. =head1 AUTHOR
  229.  
  230. mock E<lt>mock@obscurity.orgE<gt>
  231.  
  232. =head1 COPYRIGHT AND LICENSE
  233.  
  234. Copyright (C) 2004 by Will Whittaker and Ken Simpson
  235.  
  236. This library is free software; you can redistribute it and/or modify
  237. it under the same terms as Perl itself, either Perl version 5.8.2 or,
  238. at your option, any later version of Perl 5 you may have available.
  239.  
  240.  
  241. =cut
  242.