File Coverage

lib/Mozilla/IntermediateCerts.pm
Criterion Covered Total %
statement 54 58 93.1
branch 6 12 50.0
condition n/a
subroutine 12 12 100.0
pod 0 1 0.0
total 72 83 86.7


line stmt bran cond sub pod time code
1             package Mozilla::IntermediateCerts;
2              
3 1     1   187938 use strict;
  1         3  
  1         25  
4 1     1   4 use warnings;
  1         2  
  1         20  
5              
6 1     1   488 use utf8;
  1         13  
  1         4  
7 1     1   421 use Moo;
  1         8502  
  1         3  
8              
9 1     1   1563 use namespace::clean;
  1         7693  
  1         5  
10              
11 1     1   219 use LWP::UserAgent;
  1         2  
  1         24  
12 1     1   568 use Text::CSV;
  1         11327  
  1         42  
13 1     1   337 use Mozilla::IntermediateCerts::Cert;
  1         3  
  1         526  
14              
15             # ABSTRACT: Downloads and parses Mozilla intermediate certificates
16              
17             our $VERSION = 'v0.0003';
18              
19             =head1 NAME
20            
21             Mozilla::IntermediateCerts
22            
23             =head1 WARNING
24            
25             This module is in early development and may change.
26            
27             =head1 SYNOPSIS
28            
29             my $certs = Mozilla::IntermediateCerts->new;
30              
31             for my $cert ( $certs->certs )
32             {
33             ...
34             }
35              
36             or
37             my $certs = Mozilla::IntermediateCerts->new(
38             tmp_path => '/my/tmp/dir'
39             moz_int_cert_path => 'http://foo.com/certs.csv'
40             );
41             =cut
42            
43             =head1 DESCRIPTION
44              
45             This module downloads the latest Mozilla intermediate certificates list and parses it
46              
47             https://wiki.mozilla.org/CA/Intermediate_Certificates
48            
49             This is a work in progress and contains incomplete test code, methods are likely to be refactored, you have been warned.
50            
51             =head1 Args
52              
53             =cut
54              
55             =head2 tmp_path
56            
57             Set the directory where files are downloded to
58              
59             Default /tmp
60             =cut
61             has tmp_path => (
62             is => 'rw',
63             default => sub { '/tmp' }
64             );
65              
66              
67             =head2 moz_int_cert_path
68              
69             Set the URL for the the intermediate certificate file download
70              
71             Default https://ccadb-public.secure.force.com/mozilla/PublicAllIntermediateCertsWithPEMCSV
72             =cut
73             has moz_int_cert_path => (
74             is => 'rw',
75             default => sub { 'https://ccadb-public.secure.force.com/mozilla/PublicAllIntermediateCertsWithPEMCSV' }
76             );
77              
78              
79             =head1 Methods
80             =cut
81              
82              
83             has csv => ( is => 'rw' );
84              
85             =head2 certs
86              
87             Returns an arrayref of Mozilla::IntermediateCert objects
88             =cut
89              
90             has certs => ( is => 'rw' );
91              
92              
93             =head2 error
94              
95             Returns error message if an error occurs
96             =cut
97             has error => ( is => 'rw' );
98              
99             sub BUILD
100             {
101 6     6 0 67 my $self = shift;
102              
103 6 50       59 if ( $self->_download )
104             {
105 6 50       24 if ( $self->_parse_csv )
106             {
107 6         291 return 1;
108             }
109             }
110 0         0 return 0;
111             }
112              
113             =head2 _download
114              
115             Internal method to handle downloading the csv file
116             =cut
117             sub _download
118             {
119 6     6   23 my $self = shift;
120             eval
121 6         15 {
122 6         114 my $ua = LWP::UserAgent->new;
123 6         2490 $ua->agent("Perl - Mozilla::IntermediateCerts/$VERSION");
124 6         360 $ua->cookie_jar({});
125              
126 6         7826 my $req = HTTP::Request->new(GET => $self->moz_int_cert_path);
127 6         1088 my $res = $ua->request($req);
128              
129 6         43594 my $file = $self->tmp_path . '/' . time;
130 6 50       797 open my $fh, '>', $file or die "Could not save output $!";
131 6         81 print $fh $res->content;
132 6         1198 $self->csv( $file );
133             };
134 6 50       325 if ( $@ )
135             {
136 0         0 $self->{error} = "Unable to download certificate csv $@";
137 0         0 return 0;
138             }
139 6         25 return 1;
140             }
141              
142             =head2 _parse_csv
143              
144             Internal method to parse csv into array of Mozilla::IntermediateCerts::Cert objects
145             =cut
146             sub _parse_csv
147             {
148 6     6   13 my $self = shift;
149 6         17 my @certs;
150             eval
151 6         10 {
152 6         152 my $csv = Text::CSV->new({ binary => 1, decode_utf8 => 1 } );
153 1 50   1   20 open my $fh, '<:encoding(UTF-8)', $self->csv or die "Could not load CSV $!";
  1         7  
  1         18  
  6         2384  
154            
155 6         2693 $csv->column_names( $csv->getline( $fh ) );
156              
157 6         1082 while ( my $row = $csv->getline_hr( $fh ) )
158             {
159 60         56005 push @certs, Mozilla::IntermediateCerts::Cert->new( $row );
160             }
161             };
162 6 50       864 if ( $@ )
163             {
164 0         0 die "Failed to parse certificate csv $@";
165             }
166 6         98 $self->certs( \@certs );
167             }
168              
169              
170             =head1 SOURCE CODE
171              
172             The source code for this module is held in a public git repository on Gitlab https://gitlab.com/rnewsham/mozilla-intermediatecerts
173              
174             =head1 LICENSE AND COPYRIGHT
175            
176             Copyright (c) 2019 Richard Newsham
177            
178             This library is free software; you can redistribute it and/or
179             modify it under the same terms as Perl itself.
180            
181             =head1 BUGS AND LIMITATIONS
182            
183             See rt.cpan.org for current bugs, if any.
184            
185             =head1 INCOMPATIBILITIES
186            
187             None known.
188            
189             =head1 DEPENDENCIES
190              
191             Moo
192             LWP::UserAgent;
193             Text::CSV;
194             Mozilla::IntermediateCerts::Cert;
195             =cut
196              
197             1;