File Coverage

blib/lib/Authen/DigestMD5.pm
Criterion Covered Total %
statement 27 108 25.0
branch 0 28 0.0
condition 0 3 0.0
subroutine 9 25 36.0
pod n/a
total 36 164 21.9


line stmt bran cond sub pod time code
1             package Authen::DigestMD5;
2              
3 1     1   24104 use 5.006;
  1         4  
  1         59  
4              
5             our $VERSION = '0.04';
6              
7             package Authen::DigestMD5::Packet;
8 1     1   7 use strict;
  1         2  
  1         30  
9 1     1   4 use warnings;
  1         7  
  1         7610  
10              
11             my %quote=map{$_=>1} qw(username realm nonce cnonce digest-uri qop cipher);
12              
13             sub _quote($$) {
14 0     0     shift;
15 0           my ($k, $v)=@_;
16 0 0         return () unless defined $v;
17 0 0         if ($quote{$k}) {
18 0           $v =~ s/([\\"])/\\$1/g;
19 0           return qq|$k="$v"|;
20             }
21 0           "$k=$v";
22             }
23              
24             sub _split {
25 0     0     shift;
26 0           my $str=shift;
27 0           my %pair;
28 0           while ($str=~/\G\s*([\w\-]+)\s*=\s*("([^\\"]+|\\.)*"|[^,]+)\s*(?:,|$)/g) {
29 0           $pair{$1}=$2;
30             }
31 0           my ($k, $v);
32 0           while(($k, $v)=each %pair) {
33 0 0         if ($v=~/^"(.*)"$/) {
34 0           $v=$1;
35 0           $v=~s/\\(.)/$1/g;
36 0           $pair{$k}=$v;
37             }
38             }
39             %pair
40 0           }
41              
42             sub _join {
43 0     0     my $this=shift;
44 0           my %pair=@_;
45 0           delete $pair{password};
46 0           join(',', map { $this->_quote($_, $pair{$_}) } sort keys %pair)
  0            
47             }
48              
49             sub new {
50 0     0     my $class=shift;
51 0 0         my $input=shift if @_ & 1;
52 0           my $this={ @_ };
53 0           bless $this, $class;
54 0 0         $this->input($input) if defined $input;
55 0           return $this;
56             }
57              
58             sub clone {
59 0     0     my $this=shift;
60 0           my $clone={ %$this };
61 0           bless $clone, ref($this);
62             }
63              
64             sub _public {
65 0     0     my $this=shift;
66 0           return grep /^[a-z]/i, keys(%$this);
67             }
68              
69             sub input {
70 0     0     my ($this, $str)=@_;
71 0 0         return unless defined $str;
72 0           $this->set($this->_split($str));
73             }
74              
75             sub output {
76 0     0     my $this=shift;
77 0           return $this->_join(map { $_, $this->{$_} } $this->_public);
  0            
78             }
79              
80             sub set {
81 0     0     my $this=shift;
82 0           while (@_) {
83 0           my $k=shift;
84 0           my $v=shift;
85 0           $this->{$k}=$v;
86             }
87             }
88              
89             sub get {
90 0     0     my $this=shift;
91             return wantarray
92 0 0         ? (map { $this->{$_} } @_)
  0            
93             : $this->{$_[0]};
94             }
95              
96             sub reset {
97 0     0     my $this=shift;
98 0           for my $k ($this->_public) {
99 0           delete $this->{$k}
100             }
101             }
102              
103             package Authen::DigestMD5::Request;
104             our @ISA=qw(Authen::DigestMD5::Packet);
105              
106 1     1   9 use strict;
  1         2  
  1         33  
107 1     1   5 use warnings;
  1         2  
  1         96  
108              
109             sub auth_ok {
110 0     0     my $this=shift;
111 0           return defined $this->{rspauth};
112             }
113              
114             package Authen::DigestMD5::Response;
115             our @ISA=qw(Authen::DigestMD5::Packet);
116              
117 1     1   5 use strict;
  1         2  
  1         29  
118 1     1   6 use warnings;
  1         2  
  1         26  
119              
120 1     1   6 use Digest::MD5 qw(md5_hex md5);
  1         2  
  1         81  
121 1     1   5 use Carp;
  1         2  
  1         666  
122              
123             sub new {
124 0     0     my $this=shift->SUPER::new(@_);
125 0           $this->{_nc}={};
126 0           return $this;
127             }
128              
129             sub _public {
130 0     0     my $this=shift;
131 0 0         return grep { $_=~/^[a-z]/i and
  0            
132             $_ ne 'password' } keys(%$this);
133             }
134              
135             sub got_request {
136 0     0     my $this=shift;
137 0           my $req=shift;
138             # $this->{_r}=$req;
139 0           for my $k (qw(nonce realm charset)) {
140 0 0         $this->{$k}=$req->{$k} if exists $req->{$k};
141             }
142             #$this->{nc}=sprintf("%08d", ++$this->{_nc}{$req->{nonce}})
143             # if exists $req->{nonce};
144 0 0         if (exists $req->{qop}) {
145 0           my @qop=split(/\s*,\s*/, $req->{qop});
146 0 0         if (grep {$_ eq 'auth-int'} @qop) {
  0 0          
  0            
147 0           $this->{qop}='auth-int'
148             }
149             elsif (grep {$_ eq 'auth'} @qop) {
150 0           $this->{qop}='auth'
151             }
152 0           else { croak "not supported qop found ($req->{qop})" }
153             }
154             }
155              
156             sub add_digest {
157 0     0     my $this=shift;
158              
159 0           $this->{cnonce}=md5_hex(join(':', time, rand, $$));
160             # unless defined $this->{cnonce};
161              
162 0 0         $this->{nc}=sprintf("%08d", ++$this->{_nc}{$this->{nonce}})
163             if exists $this->{nonce};
164              
165 0           my %pair=((map { $_, $this->{$_} } $this->_public), @_);
  0            
166              
167 0           my $A1=join (":",
168             md5(join (":", @pair{qw(username realm password)}, )),
169             @pair{qw(nonce cnonce)} );
170              
171 0           my $A2 = "AUTHENTICATE:" . $pair{'digest-uri'};
172              
173 0 0 0       $A2 .= ":00000000000000000000000000000000"
174             if (defined $pair{'qop'} and
175             $pair{'qop'} =~ /^auth-(conf|int)$/);
176              
177 0           $this->{response} =
178             md5_hex(join (":", md5_hex($A1),
179             @pair{qw(nonce nc cnonce qop)},
180             md5_hex($A2)) );
181             }
182              
183              
184             1;
185             __END__