File Coverage

lib/Egg/Plugin/Filter.pm
Criterion Covered Total %
statement 18 76 23.6
branch 0 40 0.0
condition 0 16 0.0
subroutine 6 12 50.0
pod 1 1 100.0
total 25 145 17.2


line stmt bran cond sub pod time code
1             package Egg::Plugin::Filter;
2             #
3             # Masatoshi Mizuno E<lt>lusheE<64>cpan.orgE<gt>
4             #
5             # $Id: Filter.pm 337 2008-05-14 12:30:09Z lushe $
6             #
7 1     1   568 use strict;
  1         2  
  1         41  
8 1     1   5 use warnings;
  1         3  
  1         29  
9 1     1   5 use HTML::Entities;
  1         4  
  1         87  
10 1     1   6 use Carp qw/croak/;
  1         3  
  1         2360  
11              
12             our $VERSION= '3.01';
13              
14             my $EGG= 0;
15             my $VAL= 1;
16             my $ARG= 2;
17              
18             our %Filters= (
19             trim=> sub {
20             return 0 unless defined(${$_[$VAL]});
21             ${$_[$VAL]}=~s{^\s+} []s;
22             ${$_[$VAL]}=~s{\s+$} []s;
23             },
24             hold=> sub {
25             ${$_[$VAL]}=~s{\s+} []sg if defined(${$_[$VAL]});
26             },
27             hold_crlf=> sub {
28             ${$_[$VAL]}=~tr/\n//d if defined(${$_[$VAL]});
29             },
30             hold_tab=> sub {
31             ${$_[$VAL]}=~tr/\t//d if defined(${$_[$VAL]});
32             },
33             hold_blank=> sub {
34             ${$_[$VAL]}=~s{ +} []sg if defined(${$_[$VAL]});
35             },
36             hold_html=> sub {
37             ${$_[$VAL]}=~s{<.+?>} []sg if defined(${$_[$VAL]});
38             },
39             strip=> sub {
40             ${$_[$VAL]}=~s{\s+} [ ]sg if defined(${$_[$VAL]});
41             },
42             strip_blank=> sub {
43             ${$_[$VAL]}=~s{ +} [ ]sg if defined(${$_[$VAL]});
44             },
45             strip_tab=> sub {
46             ${$_[$VAL]}=~s{\t+} [ ]sg if defined(${$_[$VAL]});
47             },
48             strip_html=> sub {
49             ${$_[$VAL]}=~s{<.+?>} [ ]sg if defined(${$_[$VAL]});
50             },
51             strip_crlf=> sub {
52             ${$_[$VAL]}=~s{\n+} [ ]sg if defined(${$_[$VAL]});
53             },
54             crlf=> sub {
55             return 0 unless defined(${$_[$VAL]});
56             my $re= "\n" x
57             ( $_[$ARG]->[0] ? (($_[$ARG]->[0]=~/(\d+)/)[0] || 2 ): 2 );
58             ${$_[$VAL]}=~s{\n\n+} [$re]sge;
59             },
60             escape_html=> sub {
61             ${$_[$VAL]}= &__escape_html(${$_[$VAL]}) if defined(${$_[$VAL]});
62             },
63             digit=> sub {
64             ${$_[$VAL]}=~s{\D} []g if defined(${$_[$VAL]});
65             },
66             alphanum=> sub {
67             ${$_[$VAL]}=~s{\W} []g if defined(${$_[$VAL]});
68             },
69             integer=> sub {
70             return 0 unless defined(${$_[$VAL]});
71             ${$_[$VAL]}=~tr/0-9+-//dc;
72             ${$_[$VAL]}= ${$_[$VAL]}=~/^([\-\+]?\d+)/ ? $1: undef;
73             },
74             pos_integer=> sub {
75             return 0 unless defined(${$_[$VAL]});
76             ${$_[$VAL]}=~tr/0-9+//dc;
77             ${$_[$VAL]}= ${$_[$VAL]}=~/^(\+?\d+)/ ? $1: undef;
78             },
79             neg_integer=> sub {
80             return 0 unless defined(${$_[$VAL]});
81             ${$_[$VAL]}=~tr/0-9-//dc;
82             ${$_[$VAL]}= ${$_[$VAL]}=~/^(\-?\d+)/ ? $1: undef;
83             },
84             decimal=> sub {
85             return 0 unless defined(${$_[$VAL]});
86             ${$_[$VAL]}=~tr/,/./; ${$_[$VAL]}=~tr/0-9.+-//dc;
87             ${$_[$VAL]}= ${$_[$VAL]}=~/^([\-\+]?\d+\.?\d*)/ ? $1: undef;
88             },
89             pos_decimal=> sub {
90             return 0 unless defined(${$_[$VAL]});
91             ${$_[$VAL]}=~tr/,/./; ${$_[$VAL]}=~tr/0-9.+//dc;
92             ${$_[$VAL]}= ${$_[$VAL]}=~/^(\+?\d+\.?\d*)/ ? $1: undef;
93             },
94             neg_decimal=> sub {
95             return 0 unless defined(${$_[$VAL]});
96             ${$_[$VAL]}=~tr/,/./; ${$_[$VAL]}=~tr/0-9.-//dc;
97             ${$_[$VAL]}= ${$_[$VAL]}=~/^(\-?\d+\.?\d*)/ ? $1: undef;
98             },
99             dollars=> sub {
100             return 0 unless defined(${$_[$VAL]});
101             ${$_[$VAL]}=~tr/,/./; ${$_[$VAL]}=~tr/0-9.+-//dc;
102             ${$_[$VAL]}= ${$_[$VAL]}=~/(\d+\.?\d?\d?)/ ? $1: undef;
103             },
104             phone=> sub {
105             ${$_[$VAL]}=~s/[^\d,\(\)\.\s,\-#]//g if defined(${$_[$VAL]});
106             },
107             sql_wildcard=> sub {
108             ${$_[$VAL]}=~tr/*/%/ if defined(${$_[$VAL]});
109             },
110             quotemeta=> sub {
111             ${$_[$VAL]}= quotemeta(${$_[$VAL]}) if defined(${$_[$VAL]});
112             },
113             uc=> sub {
114             ${$_[$VAL]}= uc(${$_[$VAL]}) || "";
115             },
116             ucfirst=> sub {
117             ${$_[$VAL]}= ucfirst(${$_[$VAL]}) || "";
118             },
119             lc=> sub {
120             ${$_[$VAL]}= lc(${$_[$VAL]}) || "";
121             },
122             lc_email=> sub {
123             return 0 unless ${$_[$VAL]};
124             ${$_[$VAL]}=~s{\s+} []sg;
125             ${$_[$VAL]}=~s{(.+?\@)([^\@]+)$} [$1. lc($2)]e;
126             },
127             uri=> sub {
128             return 0 unless ${$_[$VAL]};
129             require URI;
130             ${$_[$VAL]}=~s{\s+} []sg;
131             my $uri= URI->new(${$_[$VAL]});
132             ${$_[$VAL]}= $uri->canonical;
133             },
134             regex=> sub {
135             return 0 unless defined(${$_[$VAL]});
136             for (@{$_[$ARG]}) { ${$_[$VAL]}=~s{$_} []sg }
137             },
138             );
139              
140             $Filters{hold_space} = $Filters{hold_blank};
141             $Filters{strip_space} = $Filters{strip_blank};
142             $Filters{url} = $Filters{uri};
143             $Filters{email} = $Filters{lc_email};
144             $Filters{int} = $Filters{integer};
145              
146 0     0     sub _filters { \%Filters }
147              
148             sub _setup {
149 0     0     my($e)= @_;
150 0   0       my $config= $e->config->{plugin_filter} ||= {};
151 0 0         if ($config->{plugins}) {
152 0 0         for my $name (ref($config->{plugins}) eq 'ARRAY'
  0            
153             ? @{$config->{plugins}}: $config->{plugins}) {
154 0 0         my $pkg= $name=~m{^\++(.+)} ? $1
155             : __PACKAGE__. "::Plugin::$name";
156 0 0         $pkg->require or die __PACKAGE__.": Error: $@";
157 0 0         if (my $code= $pkg->can('_filters')) {
    0          
158 0   0       my $hash= $code->($pkg, $e) || next;
159 0           @Filters{keys %$hash}= values %$hash;
160             } elsif (my $setup= $pkg->can('_setup_filters')) {
161 0           $setup->($pkg, $e);
162             }
163             }
164             }
165 0 0         unless ($e->isa('Egg::Plugin::Encode')) {
166 0           my $class= $e->global->{request_class};
167 0   0       my $code = $class->can('parameters') || \&Egg::Request::parameters;
168 1     1   6 no strict 'refs'; ## no critic.
  1         2  
  1         27  
169 1     1   5 no warnings 'redefine';
  1         2  
  1         848  
170 0           *{"${class}::parameters"}= sub {
171 0   0 0     $_[0]->{parameters} ||= do {
172 0   0       my $pm= $code->(@_) || {};
173 0           while (my($key, $v)) {
174 0 0         next unless defined($v);
175 0 0         if (ref($v) eq 'ARRAY') {
176 0           for (@$v) { tr/\r//d }
  0            
177 0           $pm->{$key}= $v;
178             } else {
179 0           $pm->{$key}=~tr/\r//d;
180             }
181             }
182 0           $pm;
183             };
184 0           };
185             }
186 0           $e->next::method;
187             }
188             sub filter {
189 0 0   0 1   my $e= shift; $_[0] || die q{ I want filter attr. };
  0            
190 0 0 0       my($args, $pm)= ref($_[0]) eq 'HASH'
191             ? (shift, (shift || $e->request->params))
192             : ({@_}, $e->request->params);
193             MAINFILTER:
194 0           while (my($key, $config)= each %$args) {
195 0 0         if ($key=~m{\[}) {
196 0           my($a, @item)= __parse($key);
197 0 0         exists($pm->{$a}) and croak qq{ '$a' already exists. };
198 0 0         $pm->{$a}= join '', map{defined($_) ? $_: ""}@{$pm}{@item};
  0            
  0            
199 0           $key= $a;
200             }
201 0 0         next unless $pm->{$key};
202 0           QUERYPARAM:
203 0 0         for (ref($pm->{$key}) eq 'ARRAY' ? @{$pm->{$key}}: $pm->{$key}) {
204 0           my $value= \$_;
205             FILTERPIECE:
206 0           for my $piece (@$config) {
207 0 0         my($name, @args)= $piece=~m{\[} ? __parse($piece): ($piece, ());
208 0   0       my $func= $Filters{$name} || die qq{ '$name' filter is empty. };
209 0           eval { $func->($e, $value, \@args) };
  0            
210 0 0         $@ and die __PACKAGE__. ": $@";
211             }
212             }
213             }
214 0           $pm;
215             }
216             sub __parse {
217 0 0   0     $_[0]=~m{^([^\[]+)\[(.+)} || croak qq{ filter error - '$_[0]' };
218 0           my($n, $p)= ($1, $2);
219 0           $p=~s{\]\s*$} [];
220 0           my @tmp;
221 0 0         eval "\@tmp = ($p)"; $@ and croak $@; ## no critic.
  0            
222 0           ($n, @tmp);
223             }
224 0     0     sub __escape_html { &HTML::Entities::encode_entities(shift, q{'"&<>}) }
225              
226             1;
227              
228             __END__
229              
230             =head1 NAME
231              
232             Egg::Plugin::Filter - Plugin to regularize input data.
233              
234             =head1 SYNOPSIS
235              
236             use Egg qw/ Filter /;
237            
238             # The received form data is filtered.
239             $e->filter(
240             myname => [qw/ hold_html abs_strip trim /],
241             address=> [qw/ hold_html crlf:2 abs_strip trim /],
242             tel => [qw/ hold phone /],
243             );
244              
245             # Cookie is filtered.
246             my $cookie= $e->filter( {
247             nick_name=> [qw/ strip_html abs_strip trim /],
248             email => [qw/ hold_html hold /],
249             }, $e->request->cookies );
250              
251             =head1 DESCRIPTION
252              
253             It is a plugin target to remove the problem part from data input to the form.
254              
255             An original filter can be defined in %Filters.
256              
257             package MyApp;
258             use Egg qw/ Filter /;
259            
260             {
261             my $filter= \%Egg::Plugin::Filter::Filters;
262            
263             $filter->{myfilter}= sub {
264             my($e, $value, $arg)= @_;
265             ..........
266             ...
267             };
268             };
269              
270             Those filters cannot be used when overwriting because the filter of default is
271             defined in %Filters beforehand.
272              
273             The name of the defined key becomes the name of the filter.
274              
275             The object of the project and the value of the object parameter are passed for
276             the set CODE reference. Moreover, when it is being made to have in the argument
277             by the filter, it is passed by the third element.
278              
279             There is especially no return value needing.
280              
281             =head1 METHODS
282              
283             =head2 filter ( [ATTR_HASH], [PARAM_HASH] )
284              
285             The filter is processed.
286              
287             ATTR_HASH is a filter setting, and the key is a name of the processed parameter.
288             The value enumerates the name of the filter with ARRAY.
289              
290             $e->filter(
291             param_name1 => [qw/ strip space trim /],
292             param_name2 => [qw/ strip_html space trim /],
293             param_name3 => [qw/ strip_html crlf:3 trim /],
294             );
295              
296             The thing that connects the values of the parameter and processes it can be
297             done.
298              
299             $e->filter(
300             'anyparam[qw/ param_name1 param_name2 /]' => [qw/ strip space trim /],
301             );
302              
303             It is processed being made 'anyparam' to connect 'param_name1' and 'param_name2'
304             by this.
305              
306             When the argument can be given to the filter, the argument can be passed according
307             to points like the connection of parameters.
308              
309             $e->filter(
310             param1 => ["regex['^\s+', '\s+$]"],
311             );
312              
313             The processed parameter is passed to PARAM_HASH.
314             When this is unspecification, $e-E<gt>request-E<gt>params is used.
315              
316             =head1 FILTERS
317              
318             =head2 trim
319              
320             The space character in the back and forth is deleted.
321              
322             =head2 hold
323              
324             The space character is completely deleted.
325              
326             =head2 hold_crlf
327              
328             It is 'hold' in the object only as for changing line and the tab.
329              
330             =head2 hold_tab
331              
332             The tab is deleted.
333              
334             =head2 hold_blank
335              
336             Consecutive half angle space is settled in one.
337              
338             Alias is 'hold_space'.
339              
340             =head2 hold_html
341              
342             The character string seen the HTML tag is deleted.
343              
344             =head2 strip
345              
346             The continuousness of the space character is substituted for one half angle
347             space.
348              
349             =head2 strip_blank
350              
351             The continuousness of half angle space is substituted for one half angle space.
352              
353             Alias is 'strip_space'.
354              
355             =head2 strip_tab
356              
357             Continuousness in the tab is substituted for one half angle space.
358              
359             =head2 strip_html
360              
361             The character string seen the HTML tag is substituted for one half angle space.
362              
363             =head2 strip_crlf
364              
365             It is 'strip' for changing line and the tab.
366              
367             =head2 crlf [NUM]
368              
369             A consecutive changing line is settled in NUM piece. The tab is deleted.
370              
371             Default when NUM is omitted is 2.
372              
373             param1 => [qw/ crlf[3] /]
374              
375             =head2 escape_html
376              
377             It is 'encode_entities' of L<HTML::Entities>.
378              
379             =head2 digit
380              
381             It deletes it excluding the normal-width figure.
382              
383             =head2 alphanum
384              
385             It deletes it excluding the alphanumeric character.
386              
387             =head2 integer
388              
389             It deletes it excluding the integer.
390              
391             =head2 pos_integer
392              
393             It deletes it excluding the positive integer.
394              
395             =head2 neg_integer
396              
397             It deletes it excluding the negative integer.
398              
399             =head2 decimal
400              
401             It deletes it excluding the integer including small number of people.
402              
403             =head2 pos_decimal
404              
405             It deletes it excluding a positive integer including small number of people.
406              
407             =head2 neg_decimal
408              
409             It deletes it excluding a negative integer including small number of people.
410              
411             =head2 dollars
412              
413             It deletes it excluding the figure that can be used with dollar currency.
414              
415             =head2 phone
416              
417             The character that cannot be used by the telephone number is deleted.
418              
419             =head2 sql_wildcard
420              
421             '*' is substituted for '%'.
422              
423             =head2 quotemeta
424              
425             Quotemeta is done.
426              
427             =head2 uc
428              
429             uc is done.
430              
431             =head2 ucfirst
432              
433             ucfirst is done.
434              
435             =head2 lc
436              
437             lc is done.
438              
439             =head2 lc_email
440              
441             The domain name part in the mail address is converted into the small letter.
442              
443             MyName@DOMAIN.COM => MyName@domain.com
444              
445             Alias is 'email'.
446              
447             =head2 uri
448              
449             The domain name part of URL is converted into the small letter.
450              
451             http://MYDOMAIN.COM/Hoge/Boo.html => http://mydomain.com/Hoge/Boo.html
452              
453             Alias is 'url'.
454              
455             =head2 regex ([REGEXP])
456              
457             The part that matches to the regular expression specified for REGEXP is deleted.
458             REGEXP is two or more contact.
459              
460             param1 => ["regex['abc', 'xyz']"],
461              
462             =head1 SEE ALSO
463              
464             L<Egg::Release>,
465             L<HTML::Entities>,
466             L<URI>,
467              
468             =head1 AUTHOR
469              
470             Masatoshi Mizuno E<lt>lusheE<64>cpan.orgE<gt>
471              
472             =head1 COPYRIGHT AND LICENSE
473              
474             Copyright (C) 2008 Bee Flag, Corp. E<lt>L<http://egg.bomcity.com/>E<gt>.
475              
476             This library is free software; you can redistribute it and/or modify
477             it under the same terms as Perl itself, either Perl version 5.8.6 or,
478             at your option, any later version of Perl 5 you may have available.
479              
480             =cut
481