diff -r -u Mail-IMAPClient-2.99_02/lib/Mail/IMAPClient.pm Mail-IMAPClient-2.99_02-NewSocket/lib/Mail/IMAPClient.pm
--- Mail-IMAPClient-2.99_02/lib/Mail/IMAPClient.pm 2007-10-26 11:46:16.000000000 +0200
+++ Mail-IMAPClient-2.99_02-NewSocket/lib/Mail/IMAPClient.pm 2007-11-09 16:33:13.260957272 +0100
@@ -108,7 +108,7 @@
# removed
sub EnableServerResponseInLiteral {undef}
-sub Socket(;$)
+sub RawSocket(;$)
{ my ($self, $sock) = @_;
defined $sock
or return $self->{Socket};
@@ -222,7 +222,14 @@
}
if($self->{Socket}) { $self->Socket($self->{Socket}) }
- elsif($self->{Server}) { return $self->connect }
+
+ if($self->{Rawsocket}) {
+ my $sock = delete $self->{Rawsocket};
+ # Ignore Rawsocket if Socket has already been set -- TODO carp/croak?
+ $self->RawSocket($sock) unless $self->{Socket};
+ }
+
+ if(!$self->{Socket} && $self->{Server}) { return $self->connect }
$self;
}
@@ -251,7 +258,16 @@
}
$self->_debug("Connected to $server");
- $self->Socket($sock);
+
+ return $self->Socket($sock);
+}
+
+sub Socket
+{ my ($self, $sock) = @_;
+ defined $sock
+ or return $self->{Socket};
+
+ $self->RawSocket($sock);
$self->State(Connected);
my $code;
@@ -261,18 +277,18 @@
{ $self->_record($self->Count, $o);
next unless $o->[TYPE] eq "OUTPUT";
- $code = $o->[DATA] =~ /^\*\s+(OK|BAD|NO|PREAUTH)/i ? $1 : undef;
+ $code = $o->[DATA] =~ /^\*\s+(OK|BAD|NO|PREAUTH)/i ? uc($1) : undef;
last LINE;
}
}
$code or return undef;
- if($code =~ /BYE|NO /)
+ if(($code eq 'BYE') || ($code eq 'NO'))
{ $self->State(Unconnected);
return undef;
}
- if($code =~ /PREAUTH/ )
+ if($code eq 'PREAUTH')
{ $self->State(Authenticated);
return $self;
}
@@ -1327,7 +1343,7 @@
my $litstring = $iBuffer;
- while($expected_size > length $iBuffer)
+ while($expected_size > length $litstring)
{ if($timeout)
{ # wait for data from the the IMAP socket.
my $rvec = 0;
@@ -1346,7 +1362,7 @@
if $fast_io && defined $self->{_fcntl};
my $ret = $self->_sysread($socket
- , \$litstring, $expected_size - $litstring, length $litstring);
+ , \$litstring, $expected_size - length $litstring, length $litstring);
$self->_debug("Received ret=$ret and buffer = " .
"\n$litstring<END>\nwhile processing LITERAL");
diff -r -u Mail-IMAPClient-2.99_02/lib/Mail/IMAPClient.pod Mail-IMAPClient-2.99_02-NewSocket/lib/Mail/IMAPClient.pod
--- Mail-IMAPClient-2.99_02/lib/Mail/IMAPClient.pod 2007-10-26 10:16:30.000000000 +0200
+++ Mail-IMAPClient-2.99_02-NewSocket/lib/Mail/IMAPClient.pod 2007-11-09 15:02:45.293133808 +0100
@@ -119,13 +119,40 @@
of setting an I<Authmechanism> you can just pass the authmechanism as
the first argument to AUTHENTICATE.
-=item Socket Parameter
+=item Socket, RawSocket Parameters
-The I<Socket> parameter holds a reference to the socket
-connection. Normally this is set for you by the L<connect> method, but
+Both parameters hold a reference to the socket connection.
+Normally this is set for you by the L<connect> method, but
if you are implementing an advanced authentication technique you may
choose to set up your own socket connection and then set this parameter
-manually, bypassing the B<connect> method completely.
+manually, bypassing the B<connect> method completely. This is also
+useful if you want to use L<IO::Socket::INET> alternatives, like
+L<IO::Socket::SSL>.
+
+The I<RawSocket> parameter simply records the socket to use for future
+operations, without attempting any interaction on it. In this case, you
+have to be sure to handle all the preliminar operations and to manually
+set the B<Mail::IMAPClient> object in sync with its actual status with
+respect to this socket (see below for additional parameters regarding
+this, especially the I<State> parameter).
+
+The I<Socket> parameter, instead, also attempts to carry on preliminar
+phases if the conditions apply. If both parameters are present, this
+takes the precedence over I<RawSocket>. It is primarily used to
+provide an alternative socket for communications, e.g. to use
+L<IO::Socket::SSL> instead of L<IO::Socket::INET> used by L<connect>
+by default.
+
+
+B< NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE>
+
+As of version 3 of this module, the I<Socket> parameter has changed
+semantics to make it more "DWIM". The I<RawSocket> parameter was
+introduced as a replacement for the I<Socket> parameter in older
+version.
+
+B< NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE>
+
=item State, Server, Proxy, Password, and User Parameters
@@ -3229,6 +3256,47 @@
This parameter has no affect on the B<search> method when B<search>
is called in a list context.
+=head2 RawSocket
+
+Example:
+
+ $Socket = $imap->RawSocket();
+ # or:
+ $imap->RawSocket($socket_fh);
+
+The I<RawSocket> method can be used to obtain the socket handle of the
+current connection (say, to do I/O on the connection that is not
+otherwise supported by B<Mail::IMAPClient>) or to replace the current
+socket with a new handle (for instance an SSL handle, see
+L<IO::Socket::SSL>, but be sure to see the L<Socket> method as well).
+
+If you supply a socket handle yourself, either by doing something like:
+
+ $imap=Mail::IMAPClient->new(RawSocket=>$sock, User => ... );
+
+or by doing something like:
+
+ $imap=Mail::IMAPClient->new(User => $user, Password => $pass, Server => $host);
+ # blah blah blah
+ $imap->RawSocket($ssl);
+
+then it will be up to you to establish the connection AND to
+authenticate, either via the L<login> method, or the fancier
+L<authenticate>, or, since you know so much anyway, by just doing raw
+I/O against the socket until you're logged in. If you do any of this
+then you should also set the L<State> parameter yourself to reflect the
+current state of the object (i.e. Connected, Authenticated, etc).
+
+Note that no operation will be attempted on the socket when this method
+is called. In particular, after the TCP connections towards the IMAP
+server is established, the protocol mandates the server to send an
+initial greeting message, and you will have to explicitly cope with
+this message before doing any other operation, e.g. trying to call
+L<login>. Caveat emptor.
+
+For a more DWIM approach to setting the socket see L<Socket>.
+
+
=head2 Readmethod IMAP, BUFFER, LENGTH, OFFSET
This parameter, if supplied, should contain a reference to a subroutine
@@ -3246,7 +3314,7 @@
Note that this method completely replaces reads from the connection
to the server, so if you define one of these then your subroutine will
have to actually do the read. It is for things like this that we have
-the L<Socket> parameter and eponymous accessor method.
+the L<RawSocket>, L<Socket> parameters and eponymous accessor methods.
Your I<Readmethod> will probably need to know more than this to do
whatever it does. It is recommended that you tuck all other pertinent
@@ -3292,6 +3360,14 @@
=head2 Socket
+B< NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE>
+
+The semantics of this method has changed as of version 3 of this module.
+If you need the old semantics, you now have to use L<RawSocket>.
+
+B< NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE>
+
+
Example:
$Socket = $imap->Socket();
@@ -3314,14 +3390,48 @@
# blah blah blah
$imap->Socket($ssl);
-then it will be up to you to establish the connection AND to
-authenticate, either via the L<login> method, or the fancier
-L<authenticate>, or, since you know so much anyway, by just doing raw
-I/O against the socket until you're logged in. If you do any of this
-then you should also set the L<State> parameter yourself to reflect the
-current state of the object (i.e. Connected, Authenticated, etc).
+then it will be up to you to establish the connection, i.e. make sure
+that C<$ssl> in the example is a valid and connected socket.
+
+This method is primarily used to provide a drop-in replacement for
+L<IO::Socket::INET>, used by L<connect> by default. In fact, this method
+is called by L<connect> itself after having established a suitable
+L<IO::Socket::INET> socket connection towards the target server; for
+this reason, this method also carries the normal operations associated
+with L<connect>, namely:
+
+=over
+
+=item *
+
+read the initial greeting message from the server;
+
+=item *
+
+call L<login> if the conditions apply (see L<connect> for details);
+
+=item *
+
+leave the I<Mail::IMAPClient> object in a suitable state.
+
+=back
+
+For these reasons, the following example will work "out of the box":
+
+ use IO::Socket::SSL;
+ my $imap = Mail::IMAPClient->new(
+ User => 'your-username',
+ Password => 'your-password',
+ Socket => IO::Socket::SSL->new(
+ Proto => 'tcp',
+ PeerAddr => 'some.imap.server',
+ PeerPort => 993, # IMAP over SSL standard port
+ ),
+ );
+
+If you need more control over the socket, e.g. you have to implement a fancier
+authentication method, see L<RawSocket>.
-=cut
=head2 Timeout
diff -r -u Mail-IMAPClient-2.99_02/t/basic.t Mail-IMAPClient-2.99_02-NewSocket/t/basic.t
--- Mail-IMAPClient-2.99_02/t/basic.t 2007-10-26 11:47:03.000000000 +0200
+++ Mail-IMAPClient-2.99_02-NewSocket/t/basic.t 2007-11-09 16:59:20.436710344 +0100
@@ -176,7 +176,7 @@
my $flaghash = $imap->flags(\@hits);
my $flagflag = 0;
foreach my $v ( values %$flaghash )
-{ $flagflag += grep /\\Deleted/, @$v;
+{ $flagflag++ if grep /\\Deleted/, @$v;
}
cmp_ok($flagflag, '==', scalar @hits);
@@ -187,9 +187,8 @@
$flaghash = $imap->flags(\@hits);
foreach my $v ( values %$flaghash )
-{ for my $f (@$v)
- { $flagflag -= 1 unless grep /\\Deleted/, $f;
- }
+{
+ $flagflag-- unless grep /\\Deleted/, @$v;
}
cmp_ok($flagflag, '==', 0);