File Coverage

blib/lib/Chatbot/Alpha/Syntax.pm
Criterion Covered Total %
statement 6 96 6.2
branch 0 96 0.0
condition 0 3 0.0
subroutine 2 8 25.0
pod 6 6 100.0
total 14 209 6.7


line stmt bran cond sub pod time code
1             package Chatbot::Alpha::Syntax;
2              
3             our $VERSION = '0.4';
4              
5 1     1   7 use strict;
  1         1  
  1         49  
6 1     1   4 use warnings;
  1         2  
  1         1426  
7              
8             sub new {
9 0     0 1   my $proto = shift;
10 0   0       my $class = ref($proto) || $proto;
11              
12 0           my $self = {
13             debug => 0,
14             version => $VERSION,
15             deny => {},
16             allow => {},
17             denytype => 'alloy_all', # deny_all, allow_some, deny_some
18             cusdeny => 0,
19             syntax => 'strict',
20             };
21              
22 0           bless ($self,$class);
23 0           return $self;
24             }
25              
26             sub syntax {
27 0     0 1   my ($self,$syn) = @_;
28              
29 0 0         if ($syn =~ /^(loose|strict)$/i) {
30 0           $self->{syntax} = $syn;
31 0           return 1;
32             }
33              
34 0           return 0;
35             }
36              
37             sub deny_type {
38 0     0 1   my ($self,$type) = @_;
39              
40 0 0         if ($type =~ /^(alloy|deny)_(all|some)$/i) {
41 0           $self->{cusdeny} = 1;
42              
43 0           $type = lc($type);
44 0           $type =~ s/ //g;
45              
46 0           $self->{denytype} = $type;
47             }
48             else {
49 0           return 0;
50             }
51 0           return 1;
52             }
53              
54             sub deny {
55 0     0 1   my ($self,@commands) = @_;
56              
57             # Deny each command.
58 0           foreach my $cmd (@commands) {
59 0 0         delete $self->{allow}->{$cmd} if exists $self->{allow}->{$cmd};
60 0           $self->{deny}->{$cmd} = 1;
61             }
62              
63 0 0         $self->deny_type ('deny_some') unless $self->{cusdeny} == 1;
64             }
65              
66             sub allow {
67 0     0 1   my ($self,@commands) = @_;
68              
69             # Allow each command.
70 0           foreach my $cmd (@commands) {
71 0 0         delete $self->{deny}->{$cmd} if exists $self->{deny}->{$cmd};
72 0           $self->{allow}->{$cmd} = 1;
73             }
74              
75 0 0         $self->deny_type ('allow_some') unless $self->{cusdeny} == 1;
76             }
77              
78             sub check {
79 0     0 1   my ($self,$file) = @_;
80              
81 0 0         open (FILE, $file) or return 0;
82 0           my @data = ;
83 0           close (FILE);
84              
85             # Handle dos text files on Mac and Unix
86 0 0         if($/ ne "\r\n") {
87 0           local $/ = "\r\n";
88 0           chomp @data;
89             }
90              
91 0           chomp @data;
92              
93             # Go through each line.
94 0           my $num = 0;
95 0           foreach my $line (@data) {
96 0           $num++;
97 0 0         next if length $line == 0;
98 0 0         next if $line =~ /^\//;
99 0           $line =~ s/^\s+//g;
100 0           $line =~ s/^\t+//g;
101 0           $line =~ s/^\s//g;
102 0           $line =~ s/^\t//g;
103              
104 0           my ($cmd,$data) = split(//, $line, 2);
105 0           $data =~ s/^\s+//g;
106 0           $data =~ s/^\s//g;
107              
108 0 0         next unless length $cmd > 0;
109              
110             # Denied/Not allowed?
111 0 0         if ($self->{denytype} ne 'allow_all') {
    0          
112 0 0         if ($self->{denytype} eq 'deny_some') {
    0          
113 0 0         if (exists $self->{deny}->{$cmd}) {
114 0           die "Command $cmd is not allowed at $file line $num; ";
115             }
116             }
117             elsif ($self->{denytype} eq 'allow_some') {
118 0 0         if (!exists $self->{allow}->{$cmd}) {
119 0           die "Command $cmd not in allowlist at $file line $num; ";
120             }
121             }
122             }
123             elsif ($self->{denytype} eq 'deny_all') {
124 0           die "No commands allowed at $file line $num; ";
125             }
126              
127 0 0         if ($cmd eq '>') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
128 0           my @args = split(/\s+/, $data);
129 0 0         if (scalar(@args) != 2) {
130 0           die "Bad number of arguments in >LABEL at $file line $num; ";
131             }
132             }
133             elsif ($cmd eq '<') {
134 0           my @args = split(/\s+/, $data);
135 0 0         if (scalar(@args) != 1) {
136 0           die "Bad number of arguments in
137             }
138             }
139             elsif ($cmd eq '+') {
140             # On strict: must be lowercase, simplistic.
141 0 0         if ($self->{syntax} eq 'strict') {
    0          
142 0 0         if ($data =~ /[^a-z0-9 \*]/) {
143 0           die "+TRIGGERS must be lowercase alphanumeric "
144             . "while in 'strict' syntax at $file line $num; ";
145             }
146             }
147             elsif ($self->{syntax} eq 'loose') {
148 0 0         if ($data =~ /[^A-Za-z0-9 \*]/) {
149 0           warn "+TRIGGERS must be alphanumeric while in 'loose' "
150             . "syntax at $file line $num; ";
151             }
152             }
153             }
154             elsif ($cmd eq '%') {
155             # On strict: must be lowercase, simplistic.
156 0 0         if ($self->{syntax} eq 'strict') {
    0          
157 0 0         if ($data =~ /[^a-z0-9 ]/) {
158 0           die "+TRIGGERS must be lowercase alphanumeric "
159             . "while in 'strict' syntax at $file line $num; ";
160             }
161             }
162             elsif ($self->{syntax} eq 'loose') {
163 0 0         if ($data =~ /[^A-Za-z0-9 ]/) {
164 0           warn "+TRIGGERS must be alphanumeric while in 'loose' "
165             . "syntax at $file line $num; ";
166             }
167             }
168             }
169             elsif ($cmd eq '-') {
170 0 0         if (length $data == 0) {
171 0           die "Empty -RESPONSE data at $file line $num; ";
172             }
173             }
174             elsif ($cmd eq '^') {
175 0 0         if (length $data == 0) {
176 0           die "Empty ^CONTINUE data at $file line $num; ";
177             }
178             }
179             elsif ($cmd eq '@') {
180 0 0         if ($self->{syntax} eq 'strict') {
    0          
181 0 0         if ($data =~ /[^a-z0-9 \*\<\>]/) {
182 0           die "\@REDIRECTIONS must be lowercase alphanumeric "
183             . "while in 'strict' syntax at $file line $num; ";
184             }
185             }
186             elsif ($self->{syntax} eq 'loose') {
187 0 0         if ($data =~ /[^A-Za-z0-9 \*\<\>]/) {
188 0           die "\@REDIRECTIONS must be alphanumeric while in 'loose' "
189             . "syntax at $file line $num; ";
190             }
191             }
192             }
193             elsif ($cmd eq '*') {
194 0 0         if ($data !~ /^(.*?)=(.*?)::(.*?)$/i) {
195 0           die "Syntax error at *CONDITION at $file line $num; ";
196             }
197             }
198             elsif ($cmd eq '&') {
199 0 0         if (length $data == 0) {
200 0           die "Empty &HOLDER data at $file line $num; ";
201             }
202             }
203             elsif ($cmd eq '#') {
204 0 0         if (length $data == 0) {
205 0           die "Empty #CODE data at $file line $num; ";
206             }
207             }
208             elsif ($cmd eq '/') {
209             # Comment data.
210             }
211             elsif ($cmd eq '~') {
212             # A regexp. Leave it be.
213             }
214             else {
215 0           warn "Unknown command '$cmd' with data '$data' at $file line $num; ";
216             }
217             }
218              
219 0           return 1;
220             }
221              
222             1;
223             __END__