File Coverage

blib/lib/IRC/Toolkit/Masks.pm
Criterion Covered Total %
statement 35 35 100.0
branch 15 18 83.3
condition 10 12 83.3
subroutine 7 7 100.0
pod 3 3 100.0
total 70 75 93.3


line stmt bran cond sub pod time code
1             package IRC::Toolkit::Masks;
2             $IRC::Toolkit::Masks::VERSION = '0.092001';
3 3     3   574 use Carp;
  3         4  
  3         226  
4 3     3   478 use strictures 2;
  3         1249  
  3         137  
5              
6 3     3   1436 use parent 'Exporter::Tiny';
  3         487  
  3         19  
7             our @EXPORT = qw/
8             matches_mask
9             normalize_mask
10             parse_user
11             /;
12              
13 3     3   6744 use IRC::Toolkit::Case;
  3         5  
  3         28  
14              
15              
16             sub matches_mask {
17             ## Imported from IRC::Utils:
18 3     3 1 6 my ($mask, $nuh, $casemap) = @_;
19 3 50 33     14 confess "Expected a mask, a string to match, and optional casemap"
20             unless length $mask and defined $nuh;
21              
22 3         7 my $quoted = quotemeta uc_irc $mask, $casemap;
23 3         10 $quoted =~ s/\\\*/[\x01-\xFF]{0,}/g;
24 3         4 $quoted =~ s/\\\?/[\x01-\xFF]{1,1}/g;
25              
26 3         6 !! ( uc_irc($nuh, $casemap) =~ /^$quoted$/ )
27             }
28              
29             sub normalize_mask {
30 7     7 1 19 my ($orig) = @_;
31 7 50       17 confess "normalize_mask expected a mask" unless defined $orig;
32              
33             ## Inlined with some tweaks from IRC::Utils
34              
35             ## **+ --> *
36 7         16 $orig =~ s/\*{2,}/*/g;
37              
38 7         5 my ($piece, @mask);
39 7 100 100     32 if ( index($orig, '!') == -1 && index($orig, '@') > -1) {
40             # no nick, add '*'
41 4         5 $piece = $orig;
42 4         6 @mask = '*';
43             } else {
44 3         8 ($mask[0], $piece) = split /!/, $orig, 2;
45             }
46              
47             ## user/host
48 7 100       13 if (defined $piece) {
49 6         7 $piece =~ s/!//g;
50 6         15 @mask[1, 2] = split /@/, $piece, 2;
51             }
52 7 100       13 $mask[2] =~ s/@//g if defined $mask[2];
53              
54 7 100 100     59 $mask[0]
    100 100        
55             # defined+length is annoying but elsewise we get fatal warnings on 5.10
56             . '!' . (defined $mask[1] && length $mask[1] ? $mask[1] : '*' )
57             . '@' . (defined $mask[2] && length $mask[2] ? $mask[2] : '*' )
58             }
59              
60             sub parse_user {
61 2     2 1 801 my ($full) = @_;
62              
63 2 50       6 confess "parse_user() called with no arguments"
64             unless defined $full;
65              
66 2         9 my ($nick, $user, $host) = split /[!@]/, $full;
67              
68 2 100       14 wantarray ? ($nick, $user, $host) : $nick
69             }
70              
71              
72             1;
73              
74             =pod
75              
76             =head1 NAME
77              
78             IRC::Toolkit::Masks - IRC mask-related utilities
79              
80             =head1 SYNOPSIS
81              
82             use IRC::Toolkit::Masks;
83            
84             my $mask = '*!avenj@*.cobaltirc.org';
85             my $full = 'avenj!avenj@eris.cobaltirc.org';
86             my $casemap = 'rfc1459';
87             if ( matches_mask($mask, $full, $casemap) ) {
88             ...
89             }
90              
91             my $bmask = normalize_mask( 'somenick' ); # somenick!*@*
92             my $bmask = normalize_mask( 'user@host' ); # *!user@host
93              
94             my ($nick, $user, $host) = parse_user( $full );
95             my $nick = parse_user( $full );
96              
97             =head1 DESCRIPTION
98              
99             IRC mask manipulation utilities derived from L.
100              
101             =head2 matches_mask
102              
103             Takes an IRC mask, a string to match it against, and an optional IRC casemap
104             (see L).
105              
106             Returns boolean true if the match applies successfully.
107              
108             =head2 normalize_mask
109              
110             Takes an IRC mask and returns the "normalized" version of the mask.
111              
112             =head2 parse_user
113              
114             Splits an IRC mask into components.
115              
116             Returns all available pieces (nickname, username, and host, if applicable) in
117             list context.
118              
119             Returns just the nickname in scalar context.
120              
121             =head1 AUTHOR
122              
123             Mask-matching and normalization code derived from L,
124             copyright Chris Williams, HINRIK et al.
125              
126             Jon Portnoy
127              
128             =cut
129