diff --git a/Changes b/Changes index 548c2cc..8858563 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,24 @@ Revision history for Perl extension POE::Component::SSLify. + +* 0.13 + + POD typo errors in SSLify_ContextCreate - thanks ASCENT! + +* 0.12 + + Kwalitee-related fixes + +* 0.11 + + allowed setting of client-side context ( $ctx ) object - thanks RT #34442 + + squashed typo in pod - thanks ASCENT! + + changed version check code to regexp for compatibility with SSLeay v1.33_01 - thanks Mark! + + added SSLify_ContextCreate helper function + + backported Net::SSLeay's removal of %Filenum_Objects hash * 0.10 diff --git a/MANIFEST b/MANIFEST index 801d991..1b76cbd 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,12 +1,20 @@ -Makefile.PL -MANIFEST -README -t/1_load.t -t/2_pod.t +Changes +examples/client.pl +examples/server.pl lib/POE/Component/SSLify.pm lib/POE/Component/SSLify/ClientHandle.pm lib/POE/Component/SSLify/ServerHandle.pm +Makefile.PL +MANIFEST +MANIFEST.SKIP META.yml -Changes -examples/server.pl -examples/client.pl +README +t/1_load.t +t/a_distribution.t +t/a_hasversion.t +t/a_kwalitee.t +t/a_manifest.t +t/a_minimumversion.t +t/a_pod.t +t/a_podcoverage.t +t/a_strict.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP new file mode 100644 index 0000000..f9e7dbb --- /dev/null +++ b/MANIFEST.SKIP @@ -0,0 +1,27 @@ +^.includepath +^.project +^.settings/ + +# Avoid version control files. +\B\.svn\b + +# Avoid Makemaker generated and utility files. +\bMANIFEST\.SKIP +\bMakefile$ +\bblib/ +\bMakeMaker-\d +\bpm_to_blib$ + +# Avoid Module::Build generated and utility files. +\bBuild$ +\b_build/ + +# Avoid temp and backup files. +~$ +\.old$ +\#$ +\b\.# +\.bak$ + +# our tarballs +\.tar\.gz$ diff --git a/META.yml b/META.yml index 3af09f0..5c09552 100644 --- a/META.yml +++ b/META.yml @@ -1,14 +1,24 @@ --- #YAML:1.0 name: POE-Component-SSLify -version: 0.10 -abstract: Makes using SSL in the world of POE easy! +version: 0.13 +abstract: Makes using SSL in the world of POE easy! license: perl -generated_by: ExtUtils::MakeMaker version 6.31 +author: + - Apocalypse +generated_by: ExtUtils::MakeMaker version 6.44 distribution_type: module requires: Net::SSLeay: 1.30 + Test::CheckManifest: 0 + Test::Distribution: 0 + Test::HasVersion: 0 + Test::Kwalitee: 0 + Test::MinimumVersion: 0 + Test::More: 0 + Test::Pod: 0 + Test::Pod::Coverage: 0 + Test::Strict: 0 + Test::UseAllModules: 0 meta-spec: - url: http://module-build.sourceforge.net/META-spec-v1.2.html - version: 1.2 -author: - - Apocalypse + url: http://module-build.sourceforge.net/META-spec-v1.3.html + version: 1.3 diff --git a/Makefile.PL b/Makefile.PL index 99197b5..940e4f5 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,17 +1,29 @@ -use ExtUtils::MakeMaker; -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. -WriteMakefile( - 'NAME' => 'POE::Component::SSLify', - 'VERSION_FROM' => 'lib/POE/Component/SSLify.pm', - 'PREREQ_PM' => { - 'Net::SSLeay' => '1.30', - }, - ( $] >= 5.005 ? # Add new keywords - ( - 'ABSTRACT_FROM' => 'lib/POE/Component/SSLify.pm', # retrieve abstract from module - 'AUTHOR' => 'Apocalypse ', - 'LICENSE' => 'perl', - ) : () - ), -); +use ExtUtils::MakeMaker; +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. +WriteMakefile( + 'NAME' => 'POE::Component::SSLify', + 'VERSION_FROM' => 'lib/POE/Component/SSLify.pm', + 'PREREQ_PM' => { + 'Net::SSLeay' => '1.30', + + # test stuff + 'Test::More' => 0, + 'Test::Distribution' => 0, + 'Test::Strict' => 0, + 'Test::HasVersion' => 0, + 'Test::CheckManifest' => 0, + 'Test::Kwalitee' => 0, + 'Test::MinimumVersion' => 0, + 'Test::Pod' => 0, + 'Test::Pod::Coverage' => 0, + 'Test::UseAllModules' => 0, + }, + ( $] >= 5.005 ? # Add new keywords + ( + 'ABSTRACT_FROM' => 'lib/POE/Component/SSLify.pm', # retrieve abstract from module + 'AUTHOR' => 'Apocalypse ', + 'LICENSE' => 'perl', + ) : () + ), +); diff --git a/README b/README index febe6ec..8bb5328 100644 --- a/README +++ b/README @@ -1,18 +1,19 @@ -POE-Component-SSLify -==================== - -This module makes Net::SSLeay's SSL sockets behave with POE :) - -INSTALLATION - -To install this module type the following: - - perl Makefile.PL - make - make test - make install - -MORE INFO - - # After installing: - perldoc POE::Component::SSLify +POE-Component-SSLify +==================== + +This module makes Net::SSLeay's SSL sockets behave with POE :) + +INSTALLATION + +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +MORE INFO + + # After installing: + perldoc POE::Component::SSLify + diff --git a/examples/server.pl b/examples/server.pl index a7fb076..f0c5416 100644 --- a/examples/server.pl +++ b/examples/server.pl @@ -2,7 +2,8 @@ use strict; use warnings; use POE; -use POE::Component::SSLify qw( Server_SSLify SSLify_Options ); +use Socket qw( inet_ntoa unpack_sockaddr_in ); +use POE::Component::SSLify qw( Server_SSLify SSLify_Options SSLify_GetCipher SSLify_GetSocket ); use POE::Wheel::ReadWrite; use POE::Wheel::SocketFactory; use POE::Driver::SysRW; @@ -12,7 +13,7 @@ 'inline_states' => { '_start' => sub { # Okay, set the SSL options - SSLify_Options( 'server.key', 'server.crt', 'default' ); + SSLify_Options( 'server.key', 'server.crt' ); # Set the alias $_[KERNEL]->alias_set( 'main' ); @@ -33,6 +34,9 @@ # SSLify it! $socket = Server_SSLify( $socket ); + + # testing stuff + warn "got connection from: " . inet_ntoa( ( unpack_sockaddr_in( getpeername( SSLify_GetSocket( $socket ) ) ) )[1] ) . " cipher type: " . SSLify_GetCipher( $socket ); # Hand it off to ReadWrite my $wheel = POE::Wheel::ReadWrite->new( diff --git a/lib/POE/Component/SSLify/ClientHandle.pm b/lib/POE/Component/SSLify/ClientHandle.pm index 99157d0..6e60b80 100644 --- a/lib/POE/Component/SSLify/ClientHandle.pm +++ b/lib/POE/Component/SSLify/ClientHandle.pm @@ -1,124 +1,78 @@ -# Declare our package -package POE::Component::SSLify::ClientHandle; - -# Standard stuff to catch errors -use strict qw(subs vars refs); # Make sure we can't mess up -use warnings FATAL => 'all'; # Enable warnings to catch errors - -# Initialize our version -# $Revision: 1247 $ -use vars qw( $VERSION ); -$VERSION = '0.04'; - -# Import the SSL death routines -use Net::SSLeay qw( die_now die_if_ssl_error ); - -# We inherit from ServerHandle -use vars qw( @ISA ); -@ISA = qw( POE::Component::SSLify::ServerHandle ); - -# Override TIEHANDLE because we create a CTX -sub TIEHANDLE { - my ( $class, $socket, $version, $options ) = @_; - - my $ctx; - if ( defined $version and ! ref $version ) { - if ( $version eq 'sslv2' ) { - $ctx = Net::SSLeay::CTX_v2_new(); - } elsif ( $version eq 'sslv3' ) { - $ctx = Net::SSLeay::CTX_v3_new(); - } elsif ( $version eq 'tlsv1' ) { - $ctx = Net::SSLeay::CTX_tlsv1_new(); - } elsif ( $version eq 'default' ) { - $ctx = Net::SSLeay::CTX_new(); - } else { - die "unknown SSL version: $version"; - } - } else { - $ctx = Net::SSLeay::CTX_new(); - } - $ctx || die_now( "Failed to create SSL_CTX $!" ); - - if ( defined $options ) { - Net::SSLeay::CTX_set_options( $ctx, $options ) and die_if_ssl_error( 'ssl ctx set options' ); - } - - my $ssl = Net::SSLeay::new( $ctx ) or die_now( "Failed to create SSL $!" ); - - my $fileno = fileno( $socket ); - - Net::SSLeay::set_fd( $ssl, $fileno ); # Must use fileno - - my $resp = Net::SSLeay::connect( $ssl ) or die_if_ssl_error( 'ssl connect' ); - - $POE::Component::SSLify::ServerHandle::Filenum_Object{ $fileno } = { - ssl => $ssl, - ctx => $ctx, - socket => $socket, - }; - - return bless \$fileno, $class; -} - -# Override close because it does not do CTX_Free, which is bad bad -sub CLOSE { - my $self = shift; - my $info = $self->_get_self(); - - # Thanks to Eric Waters -> closes RT #22372 - if ( $info ) { - Net::SSLeay::free( $info->{'ssl'} ); - Net::SSLeay::CTX_free( $info->{'ctx'} ); - close $info->{'socket'}; - } - delete $POE::Component::SSLify::ServerHandle::Filenum_Object{ $$self }; - return 1; -} - -# End of module -1; - -__END__ - -=head1 NAME - -POE::Component::SSLify::ClientHandle - client object for POE::Component::SSLify - -=head1 ABSTRACT - - See POE::Component::SSLify - -=head1 DESCRIPTION - - This is a subclass of Net::SSLeay::Handle because their read() and sysread() - does not cooperate well with POE. They block until length bytes are read from the - socket, and that is BAD in the world of POE... - - This subclass behaves exactly the same, except that it doesn't block :) - -=head1 SEE ALSO - -L - -=head1 AUTHOR - -Apocalypse Eapocal@cpan.orgE - -=head1 PROPS - - Original code is entirely Rocco Caputo ( Creator of POE ) -> I simply - packaged up the code into something everyone could use... - - From the PoCo::Client::HTTP code =] - # TODO - This code should probably become a POE::Kernel method, - # seeing as it's rather baroque and potentially useful in a number - # of places. - -=head1 COPYRIGHT AND LICENSE - -Copyright 2007 by Apocalypse/Rocco Caputo - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -=cut +# Declare our package +package POE::Component::SSLify::ClientHandle; +use strict; use warnings; + +# Initialize our version +use vars qw( $VERSION ); +$VERSION = (qw$LastChangedRevision: 7 $)[1]; + +# Import the SSL death routines +use Net::SSLeay qw( die_now die_if_ssl_error ); + +# We inherit from ServerHandle +use vars qw( @ISA ); +@ISA = qw( POE::Component::SSLify::ServerHandle ); + +# Override TIEHANDLE because we create a CTX +sub TIEHANDLE { + my ( $class, $socket, $version, $options, $ctx ) = @_; + + # create a context, if necessary + if ( ! defined $ctx ) { + $ctx = POE::Component::SSLify::createSSLcontext( undef, undef, $version, $options ); + } + + my $ssl = Net::SSLeay::new( $ctx ) or die_now( "Failed to create SSL $!" ); + + my $fileno = fileno( $socket ); + + Net::SSLeay::set_fd( $ssl, $fileno ); # Must use fileno + + my $resp = Net::SSLeay::connect( $ssl ) or die_if_ssl_error( 'ssl connect' ); + + my $self = bless { + 'ssl' => $ssl, + 'ctx' => $ctx, + 'socket' => $socket, + 'fileno' => $fileno, + 'client' => 1, + }, $class; + + return $self; +} + +# End of module +1; + +__END__ + +=head1 NAME + +POE::Component::SSLify::ClientHandle - client object for POE::Component::SSLify + +=head1 ABSTRACT + + See POE::Component::SSLify::ServerHandle + +=head1 DESCRIPTION + + This is a subclass of ServerHandle to accomodate clients setting custom context objects. + +=head1 SEE ALSO + +L + +L + +=head1 AUTHOR + +Apocalypse Eapocal@cpan.orgE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2008 by Apocalypse + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/POE/Component/SSLify/ServerHandle.pm b/lib/POE/Component/SSLify/ServerHandle.pm index 8306c30..badbb41 100644 --- a/lib/POE/Component/SSLify/ServerHandle.pm +++ b/lib/POE/Component/SSLify/ServerHandle.pm @@ -1,210 +1,202 @@ -# Declare our package -package POE::Component::SSLify::ServerHandle; - -# Standard stuff to catch errors -use strict qw(subs vars refs); # Make sure we can't mess up -use warnings FATAL => 'all'; # Enable warnings to catch errors - -# Initialize our version -# $Revision: 1247 $ -use vars qw( $VERSION ); -$VERSION = '0.04'; - -# Import the SSL death routines -use Net::SSLeay qw( die_now die_if_ssl_error ); - -# Argh, we actually copy over some stuff -our %Filenum_Object; #-- hash of hashes, keyed by fileno() - -# Ties the socket -sub TIEHANDLE { - my ( $class, $socket, $ctx ) = @_; - - my $ssl = Net::SSLeay::new( $ctx ) or die_now( "Failed to create SSL $!" ); - - my $fileno = fileno( $socket ); - - Net::SSLeay::set_fd( $ssl, $fileno ); - - my $err = Net::SSLeay::accept( $ssl ) and die_if_ssl_error( 'ssl accept' ); - - $Filenum_Object{ $fileno } = { - ssl => $ssl, - ctx => $ctx, - socket => $socket, - }; - - return bless \$fileno, $class; -} - -# Read something from the socket -sub READ { - # Get ourself! - my $self = shift; - - # Get the pointers to buffer, length, and the offset - my( $buf, $len, $offset ) = \( @_ ); - - # Get the actual ssl handle - my $ssl = $Filenum_Object{ $$self }->{'ssl'}; - - # If we have no offset, replace the buffer with some input - if ( ! defined $$offset ) { - $$buf = Net::SSLeay::read( $ssl, $$len ); - - # Are we done? - if ( defined $$buf ) { - return length( $$buf ); - } else { - # Nah, clear the buffer too... - $$buf = ""; - return; - } - } - - # Now, actually read the data - defined( my $read = Net::SSLeay::read( $ssl, $$len ) ) or return undef; - - # Figure out the buffer and offset - my $buf_len = length( $$buf ); - - # If our offset is bigger, pad the buffer - if ( $$offset > $buf_len ) { - $$buf .= chr( 0 ) x ( $$offset - $buf_len ); - } - - # Insert what we just read into the buffer - substr( $$buf, $$offset ) = $read; - - # All done! - return length( $read ); -} - -# Write some stuff to the socket -sub WRITE { - # Get ourself + buffer + length + offset to write - my( $self, $buf, $len, $offset ) = @_; - - # If we have nothing to offset, then start from the beginning - if ( ! defined $offset ) { - $offset = 0; - } - - # Okay, get the ssl handle - my $ssl = $Filenum_Object{ $$self }->{'ssl'}; - - # We count the number of characters written to the socket - my $wrote_len = Net::SSLeay::write( $ssl, substr( $buf, $offset, $len ) ); - - # Did we get an error or number of bytes written? - # Net::SSLeay::write() returns the number of bytes written, or -1 on error. - if ( $wrote_len < 0 ) { - # The normal syswrite() POE uses expects 0 here. - return 0; - } else { - # All done! - return $wrote_len; - } -} - -# Sets binmode on the socket -# Thanks to RT #27117 -sub BINMODE { - my $self = shift; - if (@_) { - my $mode = shift; - binmode $Filenum_Object{$$self}->{'socket'}, $mode; - } else { - binmode $Filenum_Object{$$self}->{'socket'}; - } -} - -# Closes the socket -sub CLOSE { - my $self = shift; - Net::SSLeay::free( $Filenum_Object{ $$self }->{'ssl'} ); - close $Filenum_Object{ $$self }->{'socket'}; - delete $Filenum_Object{ $$self }; - return 1; -} - -# Add DESTROY handler -sub DESTROY { - my $self = shift; - - # Did we already CLOSE? - if ( exists $Filenum_Object{ $$self } ) { - # Guess not... - $self->CLOSE(); - } -} - -sub FILENO { - return ${ $_[0] }; -} - -# Not implemented TIE's -sub READLINE { - die 'Not Implemented'; -} - -sub PRINT { - die 'Not Implemented'; -} - -# Returns our hash -sub _get_self { - return $Filenum_Object{ ${ $_[0] } }; -} - -# End of module -1; - -__END__ - -=head1 NAME - -POE::Component::SSLify::ServerHandle - server object for POE::Component::SSLify - -=head1 ABSTRACT - - See POE::Component::SSLify - -=head1 DESCRIPTION - - This is a subclass of Net::SSLeay::Handle because their read() and sysread() - does not cooperate well with POE. They block until length bytes are read from the - socket, and that is BAD in the world of POE... - - This subclass behaves exactly the same, except that it doesn't block :) - -=head2 DIFFERENCES - - This subclass doesn't know what to do with PRINT/READLINE, as they usually are not used in POE::Wheel operations... - -=head1 SEE ALSO - -L - -=head1 AUTHOR - -Apocalypse Eapocal@cpan.orgE - -=head1 PROPS - - Original code is entirely Rocco Caputo ( Creator of POE ) -> I simply - packaged up the code into something everyone could use... - - From the PoCo::Client::HTTP code for blocking sockets =] - # TODO - This code should probably become a POE::Kernel method, - # seeing as it's rather baroque and potentially useful in a number - # of places. - -=head1 COPYRIGHT AND LICENSE - -Copyright 2007 by Apocalypse/Rocco Caputo - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -=cut +# Declare our package +package POE::Component::SSLify::ServerHandle; +use strict; use warnings; + +# Initialize our version +use vars qw( $VERSION ); +$VERSION = (qw$LastChangedRevision: 7 $)[1]; + +# Import the SSL death routines +use Net::SSLeay qw( die_now die_if_ssl_error ); + +# Ties the socket +sub TIEHANDLE { + my ( $class, $socket, $ctx ) = @_; + + my $ssl = Net::SSLeay::new( $ctx ) or die_now( "Failed to create SSL $!" ); + + my $fileno = fileno( $socket ); + + Net::SSLeay::set_fd( $ssl, $fileno ); + + my $err = Net::SSLeay::accept( $ssl ) and die_if_ssl_error( 'ssl accept' ); + + my $self = bless { + 'ssl' => $ssl, + 'ctx' => $ctx, + 'socket' => $socket, + 'fileno' => $fileno, + }, $class; + + return $self; +} + +# Read something from the socket +sub READ { + # Get ourself! + my $self = shift; + + # Get the pointers to buffer, length, and the offset + my( $buf, $len, $offset ) = \( @_ ); + + # If we have no offset, replace the buffer with some input + if ( ! defined $$offset ) { + $$buf = Net::SSLeay::read( $self->{'ssl'}, $$len ); + + # Are we done? + if ( defined $$buf ) { + return length( $$buf ); + } else { + # Nah, clear the buffer too... + $$buf = ""; + return; + } + } + + # Now, actually read the data + defined( my $read = Net::SSLeay::read( $self->{'ssl'}, $$len ) ) or return undef; + + # Figure out the buffer and offset + my $buf_len = length( $$buf ); + + # If our offset is bigger, pad the buffer + if ( $$offset > $buf_len ) { + $$buf .= chr( 0 ) x ( $$offset - $buf_len ); + } + + # Insert what we just read into the buffer + substr( $$buf, $$offset ) = $read; + + # All done! + return length( $read ); +} + +# Write some stuff to the socket +sub WRITE { + # Get ourself + buffer + length + offset to write + my( $self, $buf, $len, $offset ) = @_; + + # If we have nothing to offset, then start from the beginning + if ( ! defined $offset ) { + $offset = 0; + } + + # We count the number of characters written to the socket + my $wrote_len = Net::SSLeay::write( $self->{'ssl'}, substr( $buf, $offset, $len ) ); + + # Did we get an error or number of bytes written? + # Net::SSLeay::write() returns the number of bytes written, or -1 on error. + if ( $wrote_len < 0 ) { + # The normal syswrite() POE uses expects 0 here. + return 0; + } else { + # All done! + return $wrote_len; + } +} + +# Sets binmode on the socket +# Thanks to RT #27117 +sub BINMODE { + my $self = shift; + if (@_) { + my $mode = shift; + binmode $self->{'socket'}, $mode; + } else { + binmode $self->{'socket'}; + } +} + +# Closes the socket +sub CLOSE { + my $self = shift; + if ( defined $self->{'socket'} ) { + Net::SSLeay::free( $self->{'ssl'} ); + close( $self->{'socket'} ); + undef $self->{'socket'}; + + # do we need to do CTX_free? + if ( exists $self->{'client'} ) { + Net::SSLeay::CTX_free( $self->{'ctx'} ); + } + } + + return 1; +} + +# Add DESTROY handler +sub DESTROY { + my $self = shift; + + # Did we already CLOSE? + if ( defined $self->{'socket'} ) { + # Guess not... + $self->CLOSE(); + } +} + +sub FILENO { + my $self = shift; + return $self->{'fileno'}; +} + +# Not implemented TIE's +sub READLINE { + die 'Not Implemented'; +} + +sub PRINT { + die 'Not Implemented'; +} + +# End of module +1; + +__END__ + +=head1 NAME + +POE::Component::SSLify::ServerHandle - server object for POE::Component::SSLify + +=head1 ABSTRACT + + See POE::Component::SSLify + +=head1 DESCRIPTION + + This is a subclass of Net::SSLeay::Handle because their read() and sysread() + does not cooperate well with POE. They block until length bytes are read from the + socket, and that is BAD in the world of POE... + + This subclass behaves exactly the same, except that it doesn't block :) + +=head2 DIFFERENCES + + This subclass doesn't know what to do with PRINT/READLINE, as they usually are not used in POE::Wheel operations... + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Apocalypse Eapocal@cpan.orgE + +=head1 PROPS + + Original code is entirely Rocco Caputo ( Creator of POE ) -> I simply + packaged up the code into something everyone could use... + + From the PoCo::Client::HTTP code for blocking sockets =] + # TODO - This code should probably become a POE::Kernel method, + # seeing as it's rather baroque and potentially useful in a number + # of places. + +=head1 COPYRIGHT AND LICENSE + +Copyright 2008 by Apocalypse/Rocco Caputo + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/POE/Component/SSLify.pm b/lib/POE/Component/SSLify.pm index 0241bd5..814fa09 100644 --- a/lib/POE/Component/SSLify.pm +++ b/lib/POE/Component/SSLify.pm @@ -1,400 +1,482 @@ -# Declare our package -package POE::Component::SSLify; - -# Standard stuff to catch errors -use strict qw(subs vars refs); # Make sure we can't mess up -use warnings FATAL => 'all'; # Enable warnings to catch errors - -# Initialize our version -# $Revision: 1248 $ -our $VERSION = '0.10'; - -# We need Net::SSLeay or all's a failure! -BEGIN { - eval { require Net::SSLeay }; - - # Check for errors... - if ( $@ ) { - # Oh boy! - die $@; - } else { - # Check to make sure the versions are what we want - if ( ! ( defined $Net::SSLeay::VERSION and - $Net::SSLeay::VERSION >= 1.30 ) ) { - # Argh... - die 'Please upgrade Net::SSLeay to 1.30+'; - } else { - # Finally, load our subclass :) - require POE::Component::SSLify::ClientHandle; - require POE::Component::SSLify::ServerHandle; - - # Initialize Net::SSLeay - Net::SSLeay::load_error_strings(); - Net::SSLeay::SSLeay_add_ssl_algorithms(); - Net::SSLeay::randomize(); - } - } -} - -# Do the exporting magic... -require Exporter; -use vars qw( @ISA @EXPORT_OK ); -@ISA = qw( Exporter ); -@EXPORT_OK = qw( Client_SSLify Server_SSLify SSLify_Options SSLify_GetCTX SSLify_GetCipher SSLify_GetSocket ); - -# Bring in some socket-related stuff -use Symbol qw( gensym ); -use POSIX qw( F_GETFL F_SETFL O_NONBLOCK EAGAIN EWOULDBLOCK ); - -# We need the server-side stuff -use Net::SSLeay qw( die_now die_if_ssl_error ); - -# The server-side CTX stuff -my $ctx = undef; - -# Helper sub to set blocking on a handle -sub Set_Blocking { - my $socket = shift; - - # Net::SSLeay needs blocking for setup. - # - # ActiveState Perl 5.8.0 dislikes the Win32-specific code to make - # a socket blocking, so we use IO::Handle's blocking(1) method. - # Perl 5.005_03 doesn't like blocking(), so we only use it in - # 5.8.0 and beyond. - if ( $] >= 5.008 and $^O eq 'MSWin32' ) { - # From IO::Handle POD - # If an error occurs blocking will return undef and $! will be set. - if ( ! $socket->blocking( 1 ) ) { - die "Unable to set blocking mode on socket: $!"; - } - } else { - # Make the handle blocking, the POSIX way. - if ( $^O ne 'MSWin32' ) { - # Get the old flags - my $flags = fcntl( $socket, F_GETFL, 0 ) or die "fcntl( $socket, F_GETFL, 0 ) fails: $!"; - - # Okay, we patiently wait until the socket turns blocking mode - until( fcntl( $socket, F_SETFL, $flags & ~O_NONBLOCK ) ) { - # What was the error? - if ( ! ( $! == EAGAIN or $! == EWOULDBLOCK ) ) { - # Fatal error... - die "fcntl( $socket, FSETFL, etc ) fails: $!"; - } - } - } else { - # Darned MSWin32 way... - # Do some ioctl magic here - # 126 is FIONBIO ( some docs say 0x7F << 16 ) - my $flag = "0"; - ioctl( $socket, 0x80000000 | ( 4 << 16 ) | ( ord( 'f' ) << 8 ) | 126, $flag ) or die "ioctl( $socket, FIONBIO, $flag ) fails: $!"; - } - } - - # All done! - return $socket; -} - -# Okay, the main routine here! -sub Client_SSLify { - # Get the socket + version + options - my( $socket, $version, $options ) = @_; - - # Validation... - if ( ! defined $socket ) { - die "Did not get a defined socket"; - } - - # Set blocking on - $socket = Set_Blocking( $socket ); - - # Now, we create the new socket and bind it to our subclass of Net::SSLeay::Handle - my $newsock = gensym(); - tie( *$newsock, 'POE::Component::SSLify::ClientHandle', $socket, $version, $options ) or die "Unable to tie to our subclass: $!"; - - # All done! - return $newsock; -} - -# Okay, the main routine here! -sub Server_SSLify { - # Get the socket! - my $socket = shift; - - # Validation... - if ( ! defined $socket ) { - die "Did not get a defined socket"; - } - - # If we don't have a ctx ready, we can't do anything... - if ( ! defined $ctx ) { - die 'Please do SSLify_Options() first'; - } - - # Set blocking on - $socket = Set_Blocking( $socket ); - - # Now, we create the new socket and bind it to our subclass of Net::SSLeay::Handle - my $newsock = gensym(); - tie( *$newsock, 'POE::Component::SSLify::ServerHandle', $socket, $ctx ) or die "Unable to tie to our subclass: $!"; - - # All done! - return $newsock; -} - -sub SSLify_Options { - # Get the key + cert + version + options - my( $key, $cert, $version, $options ) = @_; - - if ( defined $version and ! ref $version ) { - if ( $version eq 'sslv2' ) { - $ctx = Net::SSLeay::CTX_v2_new(); - } elsif ( $version eq 'sslv3' ) { - $ctx = Net::SSLeay::CTX_v3_new(); - } elsif ( $version eq 'tlsv1' ) { - $ctx = Net::SSLeay::CTX_tlsv1_new(); - } elsif ( $version eq 'default' ) { - $ctx = Net::SSLeay::CTX_new(); - } else { - die "unknown SSL version: $version"; - } - } else { - $ctx = Net::SSLeay::CTX_new(); - } - if ( ! defined $ctx ) { - die_now( "Failed to create SSL_CTX $!" ); - } - - # Set the default - if ( ! defined $options ) { - $options = &Net::SSLeay::OP_ALL; - } - - Net::SSLeay::CTX_set_options( $ctx, $options ) and die_if_ssl_error( 'ssl ctx set options' ); - - # Following will ask password unless private key is not encrypted - Net::SSLeay::CTX_use_RSAPrivateKey_file( $ctx, $key, &Net::SSLeay::FILETYPE_PEM ); - die_if_ssl_error( 'private key' ); - - # Set the cert file - Net::SSLeay::CTX_use_certificate_file( $ctx, $cert, &Net::SSLeay::FILETYPE_PEM ); - die_if_ssl_error( 'certificate' ); - - # All done! - return 1; -} - -# Returns the server-side CTX in case somebody wants to play with it -sub SSLify_GetCTX { - return $ctx; -} - -# Gives you the cipher type of a SSLified socket -sub SSLify_GetCipher { - my $sock = shift; - return Net::SSLeay::get_cipher( tied( *$sock )->_get_self()->{'ssl'} ); -} - -# Gives you the "Real" Socket to play with -sub SSLify_GetSocket { - my $sock = shift; - return tied( *$sock )->_get_self()->{'socket'}; -} - -# End of module -1; - -__END__ - -=head1 NAME - -POE::Component::SSLify - Makes using SSL in the world of POE easy! - -=head1 SYNOPSIS - -=head2 Client-side usage - - # Import the module - use POE::Component::SSLify qw( Client_SSLify ); - - # Create a normal SocketFactory wheel or something - my $factory = POE::Wheel::SocketFactory->new( ... ); - - # Converts the socket into a SSL socket POE can communicate with - eval { $socket = Client_SSLify( $socket ) }; - if ( $@ ) { - # Unable to SSLify it... - } - - # Now, hand it off to ReadWrite - my $rw = POE::Wheel::ReadWrite->new( - Handle => $socket, - ... - ); - - # Use it as you wish... - -=head2 Server-side usage - - # !!! Make sure you have a public key + certificate generated via Net::SSLeay's makecert.pl - # excellent howto: http://www.akadia.com/services/ssh_test_certificate.html - - # Import the module - use POE::Component::SSLify qw( Server_SSLify SSLify_Options ); - - # Set the key + certificate file - eval { SSLify_Options( 'server.key', 'server.crt' ) }; - if ( $@ ) { - # Unable to load key or certificate file... - } - - # Create a normal SocketFactory wheel or something - my $factory = POE::Wheel::SocketFactory->new( ... ); - - # Converts the socket into a SSL socket POE can communicate with - eval { $socket = Server_SSLify( $socket ) }; - if ( $@ ) { - # Unable to SSLify it... - } - - # Now, hand it off to ReadWrite - my $rw = POE::Wheel::ReadWrite->new( - Handle => $socket, - ... - ); - - # Use it as you wish... - -=head1 ABSTRACT - - Makes SSL use in POE a breeze! - -=head1 DESCRIPTION - -This component represents the standard way to do SSL in POE. - -=head1 NOTES - -=head2 Socket methods doesn't work - -The new socket this module gives you actually is some tied socket magic, so you cannot do stuff like -getpeername() or getsockname(). The only way to do it is to use SSLify_GetSocket and then operate on -the socket it returns. - -=head2 Dying everywhere... - -This module will die() if Net::SSLeay could not be loaded or it is not the version we want. So, it is recommended -that you check for errors and not use SSL, like so: - - eval { use POE::Component::SSLify }; - if ( $@ ) { - $sslavailable = 0; - } else { - $sslavailable = 1; - } - - # Make socket SSL! - if ( $sslavailable ) { - eval { $socket = POE::Component::SSLify::Client_SSLify( $socket ) }; - if ( $@ ) { - # Unable to SSLify the socket... - } - } - -=head1 FUNCTIONS - -=head2 Client_SSLify - - Accepts a socket, returns a brand new socket SSLified - - Optionally accepts the SSL version + CTX options - Client_SSLify( $socket, $version, $options ); - - Known versions: - * sslv2 - * sslv3 - * tlsv1 - * default - - By default we use the version: default - - By default we don't set any options - -=head2 Server_SSLify - - Accepts a socket, returns a brand new socket SSLified - - NOTE: SSLify_Options must be set first! - -=head2 SSLify_Options - - Accepts the location of the SSL key + certificate files and does it's job - - Optionally accepts the SSL version + CTX options - SSLify_Options( $key, $cert, $version, $options ); - - Known versions: - * sslv2 - * sslv3 - * tlsv1 - * default - - By default we use the version: default - - By default we use the options: &Net::SSLeay::OP_ALL - -=head2 SSLify_GetCTX - - Returns the server-side CTX in case you wanted to play around with it :) - -=head2 SSLify_GetCipher - - Returns the cipher used by the SSLified socket - - Example: - print "SSL Cipher is: " . SSLify_GetCipher( $sslified_sock ) . "\n"; - -=head2 SSLify_GetSocket - - Returns the actual socket used by the SSLified socket, useful for stuff like getpeername()/getsockname() - - Example: - print "Remote IP is: " . ( unpack_sockaddr_in( getpeername( SSLify_GetSocket( $sslified_sock ) ) ) )[0] . "\n"; - -=head1 EXPORT - - Stuffs all the 4 functions in @EXPORT_OK so you have to request them directly - -=head1 BUGS - -On Win32 platforms SSL support is pretty shaky, please help me out with detailed error descriptions if it happens to you! - -=head1 SEE ALSO - -L - -L - -=head1 AUTHOR - -Apocalypse Eapocal@cpan.orgE - -=head1 PROPS - - Original code is entirely Rocco Caputo ( Creator of POE ) -> I simply - packaged up the code into something everyone could use and accepted the burden - of maintaining it :) - - From the PoCo::Client::HTTP code =] - # TODO - This code should probably become a POE::Kernel method, - # seeing as it's rather baroque and potentially useful in a number - # of places. - -=head1 COPYRIGHT AND LICENSE - -Copyright 2007 by Apocalypse/Rocco Caputo - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -=cut +# Declare our package +package POE::Component::SSLify; +use strict; use warnings; + +# Initialize our version $LastChangedRevision: 7 $ +use vars qw( $VERSION ); +$VERSION = '0.13'; + +# We need Net::SSLeay or all's a failure! +BEGIN { + eval { require Net::SSLeay }; + + # Check for errors... + if ( $@ ) { + # Oh boy! + die $@; + } else { + # Check to make sure the versions are what we want + if ( ! ( defined $Net::SSLeay::VERSION and + $Net::SSLeay::VERSION =~ /^1\.3/ ) ) { + warn 'Please upgrade Net::SSLeay to v1.30+ installed: v' . $Net::SSLeay::VERSION; + } + + # Finally, load our subclass :) + require POE::Component::SSLify::ClientHandle; + require POE::Component::SSLify::ServerHandle; + + # Initialize Net::SSLeay + Net::SSLeay::load_error_strings(); + Net::SSLeay::SSLeay_add_ssl_algorithms(); + Net::SSLeay::randomize(); + } +} + +# Do the exporting magic... +require Exporter; +use vars qw( @ISA @EXPORT_OK ); +@ISA = qw( Exporter ); +@EXPORT_OK = qw( Client_SSLify Server_SSLify SSLify_Options SSLify_GetCTX SSLify_GetCipher SSLify_GetSocket SSLify_ContextCreate ); + +# Bring in some socket-related stuff +use Symbol qw( gensym ); +use POSIX qw( F_GETFL F_SETFL O_NONBLOCK EAGAIN EWOULDBLOCK ); + +# We need the server-side stuff +use Net::SSLeay qw( die_now die_if_ssl_error ); + +# The server-side CTX stuff +my $ctx = undef; + +# Helper sub to set blocking on a handle +sub Set_Blocking { + my $socket = shift; + + # Net::SSLeay needs blocking for setup. + # + # ActiveState Perl 5.8.0 dislikes the Win32-specific code to make + # a socket blocking, so we use IO::Handle's blocking(1) method. + # Perl 5.005_03 doesn't like blocking(), so we only use it in + # 5.8.0 and beyond. + if ( $] >= 5.008 and $^O eq 'MSWin32' ) { + # From IO::Handle POD + # If an error occurs blocking will return undef and $! will be set. + if ( ! $socket->blocking( 1 ) ) { + die "Unable to set blocking mode on socket: $!"; + } + } else { + # Make the handle blocking, the POSIX way. + if ( $^O ne 'MSWin32' ) { + # Get the old flags + my $flags = fcntl( $socket, F_GETFL, 0 ) or die "fcntl( $socket, F_GETFL, 0 ) fails: $!"; + + # Okay, we patiently wait until the socket turns blocking mode + until( fcntl( $socket, F_SETFL, $flags & ~O_NONBLOCK ) ) { + # What was the error? + if ( ! ( $! == EAGAIN or $! == EWOULDBLOCK ) ) { + # Fatal error... + die "fcntl( $socket, FSETFL, etc ) fails: $!"; + } + } + } else { + # Darned MSWin32 way... + # Do some ioctl magic here + # 126 is FIONBIO ( some docs say 0x7F << 16 ) + my $flag = "0"; + ioctl( $socket, 0x80000000 | ( 4 << 16 ) | ( ord( 'f' ) << 8 ) | 126, $flag ) or die "ioctl( $socket, FIONBIO, $flag ) fails: $!"; + } + } + + # All done! + return $socket; +} + +# Okay, the main routine here! +sub Client_SSLify { + # Get the socket + version + options + ctx + my( $socket, $version, $options, $ctx ) = @_; + + # Validation... + if ( ! defined $socket ) { + die "Did not get a defined socket"; + } + + # Set blocking on + $socket = Set_Blocking( $socket ); + + # Now, we create the new socket and bind it to our subclass of Net::SSLeay::Handle + my $newsock = gensym(); + tie( *$newsock, 'POE::Component::SSLify::ClientHandle', $socket, $version, $options, $ctx ) or die "Unable to tie to our subclass: $!"; + + # All done! + return $newsock; +} + +# Okay, the main routine here! +sub Server_SSLify { + # Get the socket! + my $socket = shift; + + # Validation... + if ( ! defined $socket ) { + die "Did not get a defined socket"; + } + + # If we don't have a ctx ready, we can't do anything... + if ( ! defined $ctx ) { + die 'Please do SSLify_Options() first'; + } + + # Set blocking on + $socket = Set_Blocking( $socket ); + + # Now, we create the new socket and bind it to our subclass of Net::SSLeay::Handle + my $newsock = gensym(); + tie( *$newsock, 'POE::Component::SSLify::ServerHandle', $socket, $ctx ) or die "Unable to tie to our subclass: $!"; + + # All done! + return $newsock; +} + +sub SSLify_ContextCreate { + # Get the key + cert + version + options + my( $key, $cert, $version, $options ) = @_; + + return createSSLcontext( $key, $cert, $version, $options ); +} + +sub SSLify_Options { + # Get the key + cert + version + options + my( $key, $cert, $version, $options ) = @_; + + # sanity + if ( ! defined $key or ! defined $cert ) { + die 'no key/cert specified'; + return; + } + + # Set the default + if ( ! defined $options ) { + $options = &Net::SSLeay::OP_ALL; + } + + # set the context, possibly overwriting the previous one + if ( defined $ctx ) { + Net::SSLeay::CTX_free( $ctx ); + undef $ctx; + } + $ctx = createSSLcontext( $key, $cert, $version, $options ); + + # all done! + return 1; +} + +sub createSSLcontext { + my( $key, $cert, $version, $options ) = @_; + + my $context; + if ( defined $version and ! ref $version ) { + if ( $version eq 'sslv2' ) { + $context = Net::SSLeay::CTX_v2_new(); + } elsif ( $version eq 'sslv3' ) { + $context = Net::SSLeay::CTX_v3_new(); + } elsif ( $version eq 'tlsv1' ) { + $context = Net::SSLeay::CTX_tlsv1_new(); + } elsif ( $version eq 'default' ) { + $context = Net::SSLeay::CTX_new(); + } else { + die "unknown SSL version: $version"; + return; + } + } else { + $context = Net::SSLeay::CTX_new(); + } + if ( ! defined $context ) { + die_now( "Failed to create SSL_CTX $!" ); + return; + } + + # do we need to set options? + if ( defined $options ) { + Net::SSLeay::CTX_set_options( $context, $options ) and die_if_ssl_error( 'ssl ctx set options' ); + } + + # do we need to set key/etc? + if ( defined $key ) { + # Following will ask password unless private key is not encrypted + Net::SSLeay::CTX_use_RSAPrivateKey_file( $context, $key, &Net::SSLeay::FILETYPE_PEM ); + die_if_ssl_error( 'private key' ); + } + + # Set the cert file + if ( defined $cert ) { + Net::SSLeay::CTX_use_certificate_file( $context, $cert, &Net::SSLeay::FILETYPE_PEM ); + die_if_ssl_error( 'certificate' ); + } + + # All done! + return $context; +} + +# Returns the server-side CTX in case somebody wants to play with it +sub SSLify_GetCTX { + my $sock = shift; + if ( ! defined $sock ) { + return $ctx; + } else { + return tied( *$sock )->{'ctx'}; + } +} + +# Gives you the cipher type of a SSLified socket +sub SSLify_GetCipher { + my $sock = shift; + return Net::SSLeay::get_cipher( tied( *$sock )->{'ssl'} ); +} + +# Gives you the "Real" Socket to play with +sub SSLify_GetSocket { + my $sock = shift; + return tied( *$sock )->{'socket'}; +} + +# End of module +1; + +__END__ + +=head1 NAME + +POE::Component::SSLify - Makes using SSL in the world of POE easy! + +=head1 SYNOPSIS + +=head2 Client-side usage + + # Import the module + use POE::Component::SSLify qw( Client_SSLify ); + + # Create a normal SocketFactory wheel or something + my $factory = POE::Wheel::SocketFactory->new( ... ); + + # Converts the socket into a SSL socket POE can communicate with + eval { $socket = Client_SSLify( $socket ) }; + if ( $@ ) { + # Unable to SSLify it... + } + + # Now, hand it off to ReadWrite + my $rw = POE::Wheel::ReadWrite->new( + Handle => $socket, + ... + ); + + # Use it as you wish... + +=head2 Server-side usage + + # !!! Make sure you have a public key + certificate generated via Net::SSLeay's makecert.pl + # excellent howto: http://www.akadia.com/services/ssh_test_certificate.html + + # Import the module + use POE::Component::SSLify qw( Server_SSLify SSLify_Options ); + + # Set the key + certificate file + eval { SSLify_Options( 'server.key', 'server.crt' ) }; + if ( $@ ) { + # Unable to load key or certificate file... + } + + # Create a normal SocketFactory wheel or something + my $factory = POE::Wheel::SocketFactory->new( ... ); + + # Converts the socket into a SSL socket POE can communicate with + eval { $socket = Server_SSLify( $socket ) }; + if ( $@ ) { + # Unable to SSLify it... + } + + # Now, hand it off to ReadWrite + my $rw = POE::Wheel::ReadWrite->new( + Handle => $socket, + ... + ); + + # Use it as you wish... + +=head1 ABSTRACT + + Makes SSL use in POE a breeze! + +=head1 DESCRIPTION + +This component represents the standard way to do SSL in POE. + +=head1 NOTES + +=head2 Socket methods doesn't work + +The new socket this module gives you actually is some tied socket magic, so you cannot do stuff like +getpeername() or getsockname(). The only way to do it is to use SSLify_GetSocket and then operate on +the socket it returns. + +=head2 Dying everywhere... + +This module will die() if Net::SSLeay could not be loaded or it is not the version we want. So, it is recommended +that you check for errors and not use SSL, like so: + + eval { use POE::Component::SSLify }; + if ( $@ ) { + $sslavailable = 0; + } else { + $sslavailable = 1; + } + + # Make socket SSL! + if ( $sslavailable ) { + eval { $socket = POE::Component::SSLify::Client_SSLify( $socket ) }; + if ( $@ ) { + # Unable to SSLify the socket... + } + } + +=head2 Mixing Server/Client in the same program + + Some users have reported success, others failure when they tried to utilize SSLify in both roles. This + would require more investigation, so please tread carefully if you need to use it! + +=head1 FUNCTIONS + +=head2 Client_SSLify + + Accepts a socket, returns a brand new socket SSLified. Optionally accepts SSL + context data. + my $socket = shift; # get the socket from somewhere + $socket = Client_SSLify( $socket ); # the default + $socket = Client_SSLify( $socket, $version, $options ); # sets more options for the context + $socket = Client_SSLify( $socket, undef, undef, $ctx ); # pass in a custom context + + If $ctx is defined, SSLify will ignore other args. If $ctx isn't defined, SSLify + will create it from the $version + $options parameters. + + Known versions: + * sslv2 + * sslv3 + * tlsv1 + * default + + By default we use the version: default + + By default we don't set any options + + NOTE: The way to have a client socket with proper certificates set up is: + my $socket = shift; # get the socket from somewhere + my $ctx = SSLify_ContextCreate( 'server.key', 'server.crt' ); + $socket = Client_SSLify( $socket, undef, undef, $ctx ); + + BEWARE: If you passed in a CTX, SSLify will do Net::SSLeay::CTX_free( $ctx ) when the + socket is destroyed. This means you cannot reuse contexts! + +=head2 Server_SSLify + + Accepts a socket, returns a brand new socket SSLified + my $socket = shift; # get the socket from somewhere + $socket = Server_SSLify( $socket ); + + NOTE: SSLify_Options must be set first! + +=head2 SSLify_Options + + Accepts the location of the SSL key + certificate files and does it's job + + Optionally accepts the SSL version + CTX options + SSLify_Options( $key, $cert, $version, $options ); + + Known versions: + * sslv2 + * sslv3 + * tlsv1 + * default + + By default we use the version: default + + By default we use the options: &Net::SSLeay::OP_ALL + +=head2 SSLify_GetCTX + + Returns the server-side CTX in case you wanted to play around with it :) + + If passed in a socket, it will return that socket's $ctx instead of the global. + my $ctx = SSLify_GetCTX(); # get the one set via SSLify_Options + my $ctx = SSLify_GetCTX( $sslified_sock ); # get the one in the object + +=head2 SSLify_GetCipher + + Returns the cipher used by the SSLified socket + + Example: + print "SSL Cipher is: " . SSLify_GetCipher( $sslified_sock ) . "\n"; + +=head2 SSLify_GetSocket + + Returns the actual socket used by the SSLified socket, useful for stuff like getpeername()/getsockname() + + Example: + print "Remote IP is: " . inet_ntoa( ( unpack_sockaddr_in( getpeername( SSLify_GetSocket( $sslified_sock ) ) ) )[1] ) . "\n"; + +=head2 SSLify_ContextCreate + + Accepts some options, and returns a brand-new SSL context object ( $ctx ) + my $ctx = SSLify_ContextCreate(); + my $ctx = SSLify_ContextCreate( $key, $cert ); + my $ctx = SSLify_ContextCreate( $key, $cert, $version, $options ); + + Known versions: + * sslv2 + * sslv3 + * tlsv1 + * default + + By default we use the version: default + + By default we don't set any options + + By default we don't use the SSL key + certificate files + +=head1 EXPORT + + Stuffs all of the above functions in @EXPORT_OK so you have to request them directly + +=head1 BUGS + +On Win32 platforms SSL support is pretty shaky, please help me out with detailed error descriptions if it happens to you! + +=head1 SEE ALSO + +L + +L + +=head1 AUTHOR + +Apocalypse Eapocal@cpan.orgE + +=head1 PROPS + + Original code is entirely Rocco Caputo ( Creator of POE ) -> I simply + packaged up the code into something everyone could use and accepted the burden + of maintaining it :) + + From the PoCo::Client::HTTP code =] + # TODO - This code should probably become a POE::Kernel method, + # seeing as it's rather baroque and potentially useful in a number + # of places. + +=head1 COPYRIGHT AND LICENSE + +Copyright 2008 by Apocalypse/Rocco Caputo + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/t/1_load.t b/t/1_load.t index 3df0636..a9909ab 100644 --- a/t/1_load.t +++ b/t/1_load.t @@ -1,4 +1,5 @@ -use Test::More tests => 1; +#!/usr/bin/perl -# Test the load! -use_ok('POE::Component::SSLify'); +# Import the stuff +use Test::UseAllModules; +BEGIN { all_uses_ok(); } diff --git a/t/2_pod.t b/t/2_pod.t deleted file mode 100644 index 437887a..0000000 --- a/t/2_pod.t +++ /dev/null @@ -1,4 +0,0 @@ -use Test::More; -eval "use Test::Pod 1.00"; -plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; -all_pod_files_ok(); diff --git a/t/a_distribution.t b/t/a_distribution.t new file mode 100644 index 0000000..27f7831 --- /dev/null +++ b/t/a_distribution.t @@ -0,0 +1,15 @@ +#!/usr/bin/perl + +use Test::More; + +# AUTHOR test +if ( not $ENV{TEST_AUTHOR} ) { + plan skip_all => 'Author test. Sent $ENV{TEST_AUTHOR} to a true value to run.'; +} else { + eval "require Test::Distribution"; + if ( $@ ) { + plan skip_all => 'Test::Distribution required for validating the dist'; + } else { + Test::Distribution->import( not => 'podcover' ); + } +} diff --git a/t/a_hasversion.t b/t/a_hasversion.t new file mode 100644 index 0000000..9491779 --- /dev/null +++ b/t/a_hasversion.t @@ -0,0 +1,15 @@ +#!/usr/bin/perl + +use Test::More; + +# AUTHOR test +if ( not $ENV{TEST_AUTHOR} ) { + plan skip_all => 'Author test. Sent $ENV{TEST_AUTHOR} to a true value to run.'; +} else { + eval "use Test::HasVersion"; + if ( $@ ) { + plan skip_all => 'Test::HasVersion required for testing for version numbers'; + } else { + all_pm_version_ok(); + } +} diff --git a/t/a_kwalitee.t b/t/a_kwalitee.t new file mode 100644 index 0000000..930ea87 --- /dev/null +++ b/t/a_kwalitee.t @@ -0,0 +1,15 @@ +#!/usr/bin/perl + +use Test::More; + +# AUTHOR test +if ( not $ENV{TEST_AUTHOR} ) { + plan skip_all => 'Author test. Sent $ENV{TEST_AUTHOR} to a true value to run.'; +} else { + eval "require Test::Kwalitee"; + if ( $@ ) { + plan skip_all => 'Test::Kwalitee required for measuring the kwalitee'; + } else { + Test::Kwalitee->import(); + } +} diff --git a/t/a_manifest.t b/t/a_manifest.t new file mode 100644 index 0000000..6addbd5 --- /dev/null +++ b/t/a_manifest.t @@ -0,0 +1,17 @@ +#!/usr/bin/perl + +use Test::More; + +# AUTHOR test +if ( not $ENV{TEST_AUTHOR} ) { + plan skip_all => 'Author test. Sent $ENV{TEST_AUTHOR} to a true value to run.'; +} else { + eval "use Test::CheckManifest"; + if ( $@ ) { + plan skip_all => 'Test::CheckManifest required for validating the MANIFEST'; + } else { + ok_manifest( { + 'filter' => [ qr/\.svn/, qr/\.tar\.gz$/, ], + } ); + } +} diff --git a/t/a_minimumversion.t b/t/a_minimumversion.t new file mode 100644 index 0000000..491341c --- /dev/null +++ b/t/a_minimumversion.t @@ -0,0 +1,15 @@ +#!/usr/bin/perl + +use Test::More; + +# AUTHOR test +if ( not $ENV{TEST_AUTHOR} ) { + plan skip_all => 'Author test. Sent $ENV{TEST_AUTHOR} to a true value to run.'; +} else { + eval "use Test::MinimumVersion"; + if ( $@ ) { + plan skip_all => 'Test::MinimumVersion required to test minimum perl version'; + } else { + all_minimum_version_ok('5.008'); + } +} diff --git a/t/a_pod.t b/t/a_pod.t new file mode 100644 index 0000000..44929c1 --- /dev/null +++ b/t/a_pod.t @@ -0,0 +1,15 @@ +#!/usr/bin/perl + +use Test::More; + +# AUTHOR test +if ( not $ENV{TEST_AUTHOR} ) { + plan skip_all => 'Author test. Sent $ENV{TEST_AUTHOR} to a true value to run.'; +} else { + eval "use Test::Pod"; + if ( $@ ) { + plan skip_all => 'Test::Pod required for testing POD'; + } else { + all_pod_files_ok(); + } +} diff --git a/t/a_podcoverage.t b/t/a_podcoverage.t new file mode 100644 index 0000000..117fb06 --- /dev/null +++ b/t/a_podcoverage.t @@ -0,0 +1,17 @@ +#!/usr/bin/perl + +use Test::More; + +# AUTHOR test +if ( not $ENV{TEST_AUTHOR} ) { + plan skip_all => 'Author test. Sent $ENV{TEST_AUTHOR} to a true value to run.'; +} else { + eval "use Test::Pod::Coverage"; + if ( $@ ) { + plan skip_all => "Test::Pod::Coverage required for testing POD coverage"; + } else { + # XXX not used now + #all_pod_coverage_ok( 'lib/'); + plan skip_all => 'not done yet'; + } +} diff --git a/t/a_strict.t b/t/a_strict.t new file mode 100644 index 0000000..021cb78 --- /dev/null +++ b/t/a_strict.t @@ -0,0 +1,15 @@ +#!/usr/bin/perl + +use Test::More; + +# AUTHOR test +if ( not $ENV{TEST_AUTHOR} ) { + plan skip_all => 'Author test. Sent $ENV{TEST_AUTHOR} to a true value to run.'; +} else { + eval "use Test::Strict"; + if ( $@ ) { + plan skip_all => 'Test::Strict required to test strictness'; + } else { + all_perl_files_ok( 'lib/' ); + } +}