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.092002';
3 3     3   462 use Carp;
  3         4  
  3         175  
4 3     3   381 use strictures 2;
  3         1110  
  3         90  
5              
6 3     3   1086 use parent 'Exporter::Tiny';
  3         436  
  3         26  
7             our @EXPORT = qw/
8             matches_mask
9             normalize_mask
10             parse_user
11             /;
12              
13 3     3   5829 use IRC::Toolkit::Case;
  3         4  
  3         23  
14              
15              
16             sub matches_mask {
17             ## Imported from IRC::Utils:
18 3     3 1 5 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         8 $quoted =~ s/\\\*/[\x01-\xFF]{0,}/g;
24 3         3 $quoted =~ s/\\\?/[\x01-\xFF]{1,1}/g;
25              
26 3         5 !! ( uc_irc($nuh, $casemap) =~ /^$quoted$/ )
27             }
28              
29             sub normalize_mask {
30 7     7 1 11 my ($orig) = @_;
31 7 50       12 confess "normalize_mask expected a mask" unless defined $orig;
32              
33             ## Inlined with some tweaks from IRC::Utils
34              
35             ## **+ --> *
36 7         11 $orig =~ s/\*{2,}/*/g;
37              
38 7         6 my ($piece, @mask);
39 7 100 100     28 if ( index($orig, '!') == -1 && index($orig, '@') > -1) {
40             # no nick, add '*'
41 4         4 $piece = $orig;
42 4         5 @mask = '*';
43             } else {
44 3         7 ($mask[0], $piece) = split /!/, $orig, 2;
45             }
46              
47             ## user/host
48 7 100       10 if (defined $piece) {
49 6         6 $piece =~ s/!//g;
50 6         12 @mask[1, 2] = split /@/, $piece, 2;
51             }
52 7 100       12 $mask[2] =~ s/@//g if defined $mask[2];
53              
54 7 100 100     53 $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 477 my ($full) = @_;
62              
63 2 50       6 confess "parse_user() called with no arguments"
64             unless defined $full;
65              
66 2         8 my ($nick, $user, $host) = split /[!@]/, $full;
67              
68 2 100       12 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