File Coverage

blib/lib/Email/Enkoder.pm
Criterion Covered Total %
statement 63 63 100.0
branch 14 14 100.0
condition 9 11 81.8
subroutine 9 9 100.0
pod 5 5 100.0
total 100 102 98.0


line stmt bran cond sub pod time code
1 1     1   57234 use strictures;
  1         2  
  1         8  
2              
3             package Email::Enkoder;
4              
5 1     1   77 use 5.010;
  1         2  
  1         31  
6 1     1   692 use Sub::Exporter::Simple qw' enkode enkode_mail ';
  1         32537  
  1         8  
7 1     1   197 use utf8;
  1         2  
  1         9  
8              
9             our $VERSION = '1.120831'; # VERSION
10              
11             # ABSTRACT: obfuscate email or html with randomized javascript
12              
13             #
14             # This file is part of Email-Enkoder
15             #
16             #
17             # Christian Walde has dedicated the work to the Commons by waiving all of his
18             # or her rights to the work worldwide under copyright law and all related or
19             # neighboring legal rights he or she had in the work, to the extent allowable by
20             # law.
21             #
22             # Works under CC0 do not require attribution. When citing the work, you should
23             # not imply endorsement by the author.
24             #
25              
26             my $default_enkoders = [
27             {
28             perl => sub { reverse @_ },
29             js => ";kode=kode.split('').reverse().join('')",
30             },
31             {
32             perl => sub {
33             my ( $string ) = @_;
34             for my $i ( 0 .. ( length( $string ) / 2 - 1 ) ) {
35             $i *= 2;
36             my $left = substr $string, $i, 1;
37             my $right = substr $string, $i + 1, 1;
38             substr $string, $i, 1, $right;
39             substr $string, $i + 1, 1, $left;
40             }
41             return $string;
42             },
43             js => (
44             ";x='';for(i=0;i<(kode.length-1);i+=2){"
45             . "x+=kode.charAt(i+1)+kode.charAt(i)"
46             . "}kode=x+(i
47             )
48             },
49             {
50             perl => sub {
51             my ( $str ) = @_;
52             my @chars = split //, $str;
53             for ( @chars ) {
54             my $ord = ord $_;
55             $ord += 3;
56             $_ = chr $ord;
57             }
58             my $result = join '', @chars;
59             return $result;
60             },
61             js => (
62             ";x='';for(i=0;i
63             . "c=kode.charCodeAt(i)-3;x+=String.fromCharCode(c)"
64             . "}kode=x"
65             )
66             },
67             ];
68              
69              
70             sub enkode_mail {
71 2     2 1 389 my ( $email, $options ) = @_;
72              
73 2   66     15 $options->{link_text} //= $email;
74 2 100       11 $_ = defined $_ ? qq| $_| : '' for $options->{link_attributes};
75 2 100       12 $_ = defined $_ ? qq|?subject=$_| : '' for $options->{subject};
76              
77 2         11 $email = qq|{link_attributes}>$options->{link_text}|;
78 2         6 my $link = enkode( $email, $options );
79              
80 2         7 return $link;
81             }
82              
83              
84             sub enkode {
85 7     7 1 1878 my ( $html, $options ) = @_;
86              
87 7   66     35 $options->{enkoders} ||= enkoders();
88 7   100     22 $options->{max_length} ||= 1024;
89              
90 7         15 my $js = js_dbl_quote( $html );
91 7         22 $js = qq|document.write($js);|;
92              
93 7 100       33 $options->{max_length} = 1 + length $js if $options->{max_length} <= length $js;
94              
95 7         9 my $script_html;
96              
97 7         20 while ( $options->{max_length} > length $js ) {
98 21   100     72 my $idx = $options->{enkoder_index} // int rand @{ $options->{enkoders} };
  18         160  
99 21         97 $js = $options->{enkoders}[$idx]{perl}->( $js );
100 21         63 $js = js_dbl_quote( $js );
101 21         120 $js = qq|kode=$js$options->{enkoders}[$idx]{js}|;
102 21         45 my $js_variable = js_wrap_quote( js_dbl_quote( $js ), 79 );
103              
104 21         187 $script_html = qq|
105            
112             |;
113 21         389 $script_html =~ s/^ +//mg;
114 21 100       212 last if length $script_html > $options->{max_length};
115             }
116              
117 7         195 return $script_html;
118             }
119              
120              
121 6     6 1 58 sub enkoders { $default_enkoders }
122              
123              
124             sub js_wrap_quote {
125 22     22 1 509 my ( $str, $max_line_length ) = @_;
126              
127 22         31 $max_line_length -= 3;
128 22         24 my $inQ;
129 22         28 my $esc = 0;
130 22         22 my $lineLen = 0;
131 22         31 my $result = '';
132 22         23 my $chunk = '';
133              
134 22         81 while ( length $str ) {
135 7837         7550 my $chunk = '';
136 7837 100       17784 if ( $str =~ /^\\[0-7]{3}/ ) {
    100          
137 1         2 $chunk = substr $str, 0, 4;
138 1         3 substr $str, 0, 4, '';
139             }
140             elsif ( $str =~ /^\\./ ) {
141 608         921 $chunk = substr $str, 0, 2;
142 608         1115 substr $str, 0, 2, '';
143             }
144             else {
145 7228         9325 $chunk = substr $str, 0, 1;
146 7228         11810 substr $str, 0, 1, '';
147             }
148              
149 7837 100       14508 if ( ( $lineLen + length $chunk ) >= $max_line_length ) {
150 108         139 $result .= qq|"+\n"|;
151 108         123 $lineLen = 1;
152             }
153              
154 7837         8011 $lineLen += length $chunk;
155 7837         25345 $result .= $chunk;
156             }
157              
158 22         130 return $result;
159             }
160              
161              
162             sub js_dbl_quote {
163 49     49 1 78 my ( $in ) = @_;
164 49         1309 $in =~ s/([\\"])/\\$1/g;
165 49         196 return qq|"$in"|;
166             }
167              
168             1;
169              
170             __END__