File Coverage

blib/lib/ENV/Util.pm
Criterion Covered Total %
statement 51 56 91.0
branch 16 28 57.1
condition 11 18 61.1
subroutine 7 7 100.0
pod 3 3 100.0
total 88 112 78.5


line stmt bran cond sub pod time code
1             package ENV::Util;
2 4     4   280795 use strict;
  4         37  
  4         119  
3 4     4   76 use warnings;
  4         10  
  4         3737  
4              
5             our $VERSION = 0.02;
6              
7             sub import {
8 4     4   41 my ($pkg, $cmd, @args) = @_;
9 4 50       5715 return if !defined $cmd;
10 0 0       0 if ($cmd eq '-load_dotenv') {
11 0         0 load_dotenv(@args)
12             }
13             else {
14 0         0 local($!, $^E);
15 0         0 my ($pkg, $file, $line) = caller(1);
16 0         0 die "invalid import action for $pkg in $file line $line.";
17             }
18             }
19              
20             sub prefix2hash {
21 2     2 1 1496 my ($prefix) = @_;
22 2 100       7 $prefix = '' unless defined $prefix;
23 2         5 my $start_index = length($prefix);
24 2         12 my %options = map { lc(substr($_, $start_index)) => $ENV{$_} } grep index($_, $prefix) == 0, keys %ENV;
  5         23  
25 2         12 return %options;
26             }
27              
28             sub load_dotenv {
29 1     1 1 114 my ($filename) = @_;
30 1 50       4 $filename = '.env' unless defined $filename;
31 1 50       22 return unless -f $filename;
32              
33 1 50   1   34 open my $fh, '<:raw:encoding(UTF-8)', $filename
  1         6  
  1         3  
  1         6  
34             or die "unable to open env file '$filename': $!";
35              
36 1         12101 my @lines;
37 1         3 { local $!; @lines = <$fh> }
  1         15  
  1         40  
38 1         31 my %env;
39 1         3 foreach my $line (@lines) {
40             # code heavily inspired by Dotenv.pm (BooK++)
41 14 100       67 if (my ($k, $v) = $line =~ m{
42             \A\s*
43             (?: export \s+ )? # the 'export' keyword is optional
44             ( [a-zA-Z_][a-zA-Z0-9_]+ ) # POSIX convention for env variable names
45             (?: \s* = \s* )
46             (
47             '[^']*(?:\\'|[^']*)*' # single quoted value
48             |"[^"]*(?:\\"|[^"]*)*" # or double quoted value
49             | [^\#\r\n]+ # or unquoted value
50             )?
51             \s* (?: \# .* )? # inline comment
52             \z}sx
53             ) {
54 6 50       13 $v = '' unless defined $v;
55 6         33 $v =~ s/\s*\z//;
56              
57             # single and double quotes semantics
58 6 100 100     34 if ( $v =~ s/\A(['"])(.*)\1\z/$2/ && $1 eq '"' ) {
59 1         6 $v =~ s/\\n/\n/g;
60 1         4 $v =~ s/\\//g;
61             }
62 6         19 $env{$k} = $v;
63             }
64             }
65 1         19 %ENV = (%env, %ENV);
66 1         24 return;
67             }
68              
69             sub redacted_env {
70 1     1 1 107 my (%opts) = @_;
71 1 50       4 if (!$opts{rules}) {
72             $opts{rules} = [
73             {
74 1         8 key => qr(USER|ID|NAME|MAIL|ACC|TOKEN|PASS|PW|SECRET|KEY|ACCESS|PIN|SSN|CARD|IP),
75             mask => '',
76             },
77             {
78             value => qr(\@|:|=),
79             mask => '',
80             },
81             ]
82             }
83 1         2 my %redacted;
84             ENVKEY:
85 1         9 foreach my $k (keys %ENV) {
86 5         7 my $v = $ENV{$k};
87 5         6 foreach my $rule (@{ $opts{rules} }) {
  5         12  
88 7 100 100     62 if ( ($rule->{key} && $k =~ $rule->{key})
      66        
      66        
89             || ($rule->{value} && $v =~ $rule->{value})
90             ) {
91 3 50 33     21 if ( ($rule->{key} && $k =~ $rule->{key}) ) {
    0 0        
92             } elsif($rule->{value} && $v =~ $rule->{value}) {
93             }
94 3 50       9 next ENVKEY if $rule->{drop};
95 3         7 $v = $rule->{mask};
96 3         8 last;
97             }
98             }
99 5         11 $redacted{$k} = $v;
100             }
101 1         10 return %redacted;
102             }
103              
104             1;
105             __END__