File Coverage

lib/Params/Validate/XS.xs
Criterion Covered Total %
statement 640 732 87.4
branch 786 1452 54.1
condition n/a
subroutine n/a
pod n/a
total 1426 2184 65.2


line stmt bran cond sub pod time code
1             /* Copyright (c) 2000-2012 Dave Rolsky and Ilya Martynov */
2              
3             #include "EXTERN.h"
4             #include "perl.h"
5             #include "XSUB.h"
6             #define NEED_PL_parser
7             #define NEED_caller_cx
8             #define NEED_eval_pv
9             #define NEED_load_module
10             #define NEED_sv_2pv_flags
11             #define NEED_vload_module
12             #include "ppport.h"
13              
14             #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
15             #define INLINE inline
16             #else
17             #define INLINE
18             #endif
19              
20             /* type constants */
21             #define SCALAR 1
22             #define ARRAYREF 2
23             #define HASHREF 4
24             #define CODEREF 8
25             #define GLOB 16
26             #define GLOBREF 32
27             #define SCALARREF 64
28             #define UNKNOWN 128
29             #define UNDEF 256
30             #define OBJECT 512
31              
32             #define HANDLE (GLOB | GLOBREF)
33             #define BOOLEAN (SCALAR | UNDEF)
34              
35             /* return data macros */
36             #define RETURN_ARRAY(ret) \
37             STMT_START \
38             { \
39             I32 i; \
40             switch(GIMME_V) \
41             { \
42             case G_VOID: \
43             return; \
44             case G_ARRAY: \
45             EXTEND(SP, av_len(ret) + 1); \
46             for(i = 0; i <= av_len(ret); i++) \
47             { \
48             PUSHs(*av_fetch(ret, i, 1)); \
49             } \
50             break; \
51             case G_SCALAR: \
52             XPUSHs(sv_2mortal(newRV_inc((SV*) ret))); \
53             break; \
54             } \
55             } STMT_END \
56              
57             #define RETURN_HASH(ret) \
58             STMT_START \
59             { \
60             HE* he; \
61             I32 keys; \
62             switch(GIMME_V) \
63             { \
64             case G_VOID: \
65             return; \
66             case G_ARRAY: \
67             keys = hv_iterinit(ret); \
68             EXTEND(SP, keys * 2); \
69             while ((he = hv_iternext(ret))) \
70             { \
71             PUSHs(HeSVKEY_force(he)); \
72             PUSHs(HeVAL(he)); \
73             } \
74             break; \
75             case G_SCALAR: \
76             XPUSHs(sv_2mortal(newRV_inc((SV*) ret))); \
77             break; \
78             } \
79             } STMT_END
80              
81              
82             static SV *module;
83 0           void peek(SV *thing)
84             {
85 0 0         if (NULL == module) {
86 0           module = newSVpv("Devel::Peek", 0);
87 0           load_module(PERL_LOADMOD_NOIMPORT, module, NULL);
88             }
89              
90             {
91 0           dSP;
92 0           ENTER;
93 0           SAVETMPS;
94              
95 0 0         PUSHMARK(SP);
96 0 0         XPUSHs(thing);
97 0           PUTBACK;
98              
99 0           (void)call_pv("Devel::Peek::Dump", G_VOID);
100              
101             SPAGAIN;
102              
103             PUTBACK;
104 0 0         FREETMPS;
105 0           LEAVE;
106             }
107 0           }
108              
109             INLINE static bool
110 6918           no_validation() {
111             SV* no_v;
112              
113 6918           no_v = get_sv("Params::Validate::NO_VALIDATION", 0);
114 6918 50         if (! no_v)
115 0           croak("Cannot retrieve $Params::Validate::NO_VALIDATION\n");
116              
117 6918 50         return SvTRUE(no_v);
    50          
    0          
    100          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
118             }
119              
120             /* return type string that corresponds to typemask */
121             INLINE static SV*
122 56           typemask_to_string(IV mask) {
123             SV* buffer;
124             IV empty = 1;
125              
126 56           buffer = sv_2mortal(newSVpv("", 0));
127              
128 56 100         if (mask & SCALAR) {
129 12           sv_catpv(buffer, "scalar");
130             empty = 0;
131             }
132 56 100         if (mask & ARRAYREF) {
133 16 50         sv_catpv(buffer, empty ? "arrayref" : " arrayref");
134             empty = 0;
135             }
136 56 100         if (mask & HASHREF) {
137 6 100         sv_catpv(buffer, empty ? "hashref" : " hashref");
138             empty = 0;
139             }
140 56 100         if (mask & CODEREF) {
141 2 50         sv_catpv(buffer, empty ? "coderef" : " coderef");
142             empty = 0;
143             }
144 56 100         if (mask & GLOB) {
145 6 50         sv_catpv(buffer, empty ? "glob" : " glob");
146             empty = 0;
147             }
148 56 100         if (mask & GLOBREF) {
149 8 100         sv_catpv(buffer, empty ? "globref" : " globref");
150             empty = 0;
151             }
152 56 100         if (mask & SCALARREF) {
153 2 50         sv_catpv(buffer, empty ? "scalarref" : " scalarref");
154             empty = 0;
155             }
156 56 100         if (mask & UNDEF) {
157 2 50         sv_catpv(buffer, empty ? "undef" : " undef");
158             empty = 0;
159             }
160 56 100         if (mask & OBJECT) {
161 6 50         sv_catpv(buffer, empty ? "object" : " object");
162             empty = 0;
163             }
164 56 50         if (mask & UNKNOWN) {
165 0 0         sv_catpv(buffer, empty ? "unknown" : " unknown");
166             empty = 0;
167             }
168              
169 56           return buffer;
170             }
171              
172             /* compute numberic datatype for variable */
173             INLINE static IV
174 2126           get_type(SV* sv) {
175             IV type = 0;
176              
177 2126 100         if (SvTYPE(sv) == SVt_PVGV) {
178             return GLOB;
179             }
180 2115 100         if (!SvOK(sv)) {
    50          
    50          
181             return UNDEF;
182             }
183 2109 100         if (!SvROK(sv)) {
184             return SCALAR;
185             }
186              
187 56 50         switch (SvTYPE(SvRV(sv))) {
188             case SVt_NULL:
189             case SVt_IV:
190             case SVt_NV:
191             case SVt_PV:
192             #if PERL_VERSION <= 10
193             case SVt_RV:
194             #endif
195             case SVt_PVMG:
196             case SVt_PVIV:
197             case SVt_PVNV:
198             #if PERL_VERSION <= 8
199             case SVt_PVBM:
200             #elif PERL_VERSION >= 11
201             case SVt_REGEXP:
202             #endif
203             type = SCALARREF;
204             break;
205             case SVt_PVAV:
206             type = ARRAYREF;
207             break;
208             case SVt_PVHV:
209             type = HASHREF;
210             break;
211             case SVt_PVCV:
212             type = CODEREF;
213             break;
214             case SVt_PVGV:
215             type = GLOBREF;
216             break;
217             /* Perl 5.10 has a bunch of new types that I don't think will ever
218             actually show up here (I hope), but not handling them makes the
219             C compiler cranky. */
220             default:
221             type = UNKNOWN;
222             break;
223             }
224              
225 56 50         if (type) {
226 56 100         if (sv_isobject(sv)) return type | OBJECT;
227             return type;
228             }
229              
230             /* Getting here should not be possible */
231             return UNKNOWN;
232             }
233              
234             /* get an article for given string */
235             INLINE static const char*
236 62           article(SV* string) {
237             STRLEN len;
238             char* rawstr;
239              
240 62 100         rawstr = SvPV(string, len);
241 62 50         if (len) {
242 62 100         switch(rawstr[0]) {
    100          
243             case 'a':
244             case 'e':
245             case 'i':
246             case 'o':
247             case 'u':
248             return "an";
249             }
250             }
251              
252 50           return "a";
253             }
254              
255             char *
256 87           string_representation(SV* value) {
257 87 100         if(SvOK(value)) {
    50          
    50          
258 80 100         return (void *)form("\"%s\"", SvPV_nolen(value));
259             }
260             else {
261             return (void *)"undef";
262             }
263             }
264              
265             /* raises exception either using user-defined callback or using
266             built-in method */
267             static void
268 155           validation_failure(SV* message, HV* options) {
269             SV** temp;
270             SV* on_fail;
271              
272 155 100         if ((temp = hv_fetch(options, "on_fail", 7, 0))) {
273 13 50         SvGETMAGIC(*temp);
274 13           on_fail = *temp;
275             }
276             else {
277             on_fail = NULL;
278             }
279              
280             {
281 155           dSP;
282 155           ENTER;
283 155           SAVETMPS;
284 155 50         PUSHMARK(SP);
285 155 50         mXPUSHs(message);
286 155           PUTBACK;
287              
288             /* use user defined callback if available */
289 155 100         if (on_fail) {
290 13           call_sv(on_fail, G_DISCARD);
291             }
292             else {
293             /* by default resort to Carp::confess for error reporting */
294 142           call_pv("Carp::confess", G_DISCARD);
295             }
296              
297             /* We shouldn't get here if the thing we just called dies, but it
298             doesn't hurt to be careful. */
299             SPAGAIN;
300             PUTBACK;
301 0 0         FREETMPS;
302 0           LEAVE;
303             }
304              
305 0           return;
306             }
307              
308             /* get called subroutine fully qualified name */
309             static SV*
310 148           get_caller(HV* options) {
311             SV** temp;
312              
313 148 100         if ((temp = hv_fetch(options, "called", 6, 0))) {
314 1 50         SvGETMAGIC(*temp);
315 1           SvREFCNT_inc(*temp);
316 1           return *temp;
317             }
318             else {
319             IV frame;
320             SV *caller;
321             #if PERL_VERSION >= 14
322             const PERL_CONTEXT *cx;
323             GV *cvgv;
324             # else
325             SV *buffer;
326             #endif
327              
328 147 100         if ((temp = hv_fetch(options, "stack_skip", 10, 0))) {
329 13 50         SvGETMAGIC(*temp);
330 13 50         frame = SvIV(*temp);
331             }
332             else {
333             frame = 1;
334             }
335              
336             #if PERL_VERSION >= 14
337 147 50         if (frame > 0) {
338 147           frame--;
339             }
340              
341 147           cx = caller_cx(frame, NULL);
342              
343 147 50         if (cx) {
344 147           switch (CxTYPE(cx)) {
345             case CXt_EVAL:
346 37           caller = newSVpv("\"eval\"", 6);
347 37           break;
348             case CXt_SUB:
349 110           cvgv = CvGV(cx->blk_sub.cv);
350 110           caller = newSV(0);
351 110 50         if (cvgv && isGV(cvgv)) {
    50          
352 110           gv_efullname4(caller, cvgv, NULL, 1);
353             }
354             break;
355             default:
356 0           caller = newSVpv("(unknown)", 9);
357 0           break;
358             }
359             }
360             else {
361 0           caller = newSVpv("(unknown)", 9);
362             }
363             #else
364             buffer = sv_2mortal(newSVpvf("(caller(%d))[3]", (int) frame));
365              
366             caller = eval_pv(SvPV_nolen(buffer), 1);
367             if (SvTYPE(caller) == SVt_NULL) {
368             sv_setpv(caller, "(unknown");
369             }
370              
371             /* This will be decremented by the code that asked for this value, but
372             we need to do this here because the return value of caller() is
373             mortal and has a refcnt of 1. */
374             SvREFCNT_inc(caller);
375             #endif
376              
377             return caller;
378             }
379             }
380              
381             /* $value->isa alike validation */
382             static IV
383 44           validate_isa(SV* value, SV* package, char* id, HV* options) {
384             IV ok = 1;
385              
386 44 50         if (! value) {
387             return 0;
388             }
389              
390 44 50         SvGETMAGIC(value);
391 84 100         if (SvOK(value) && (sv_isobject(value) || (SvPOK(value) && ! looks_like_number(value)))) {
    50          
    50          
    100          
    100          
    50          
392 40           dSP;
393              
394             SV* ret;
395             IV count;
396              
397 40           ENTER;
398 40           SAVETMPS;
399              
400 40 50         PUSHMARK(SP);
401 40 50         EXTEND(SP, 2);
402 40           PUSHs(value);
403 40           PUSHs(package);
404 40           PUTBACK;
405              
406 40           count = call_method("isa", G_SCALAR);
407              
408 40 50         if (! count)
409 0           croak("Calling isa did not return a value");
410              
411 40           SPAGAIN;
412              
413 40           ret = POPs;
414 40 50         SvGETMAGIC(ret);
415              
416 40 50         ok = SvTRUE(ret);
    50          
    0          
    50          
    0          
    0          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
417              
418 40           PUTBACK;
419 40 50         FREETMPS;
420 40           LEAVE;
421             }
422             else {
423             ok = 0;
424             }
425              
426 44 100         if (! ok) {
427 18           SV *caller = get_caller(options);
428 18           SV* buffer = newSVpvf(id, string_representation(value));
429 18           sv_catpv(buffer, " to ");
430 18           sv_catsv(buffer, caller);
431             SvREFCNT_dec(caller);
432 18           sv_catpv(buffer, " was not ");
433 18           sv_catpv(buffer, article(package));
434 18           sv_catpv(buffer, " '");
435 18           sv_catsv(buffer, package);
436 18           sv_catpv(buffer, "' (it is ");
437 18 100         if ( SvOK(value) ) {
    50          
    50          
438 16           sv_catpv(buffer, article(value));
439 16           sv_catpv(buffer, " ");
440 16           sv_catsv(buffer, value);
441             }
442             else {
443 2           sv_catpv(buffer, "undef");
444             }
445 18           sv_catpv(buffer, ")\n");
446 18           validation_failure(buffer, options);
447             }
448              
449             return 1;
450             }
451              
452             static IV
453 40           validate_can(SV* value, SV* method, char* id, HV* options) {
454             IV ok = 1;
455              
456 40 50         if (! value) {
457             return 0;
458             }
459              
460 40 50         SvGETMAGIC(value);
461 76 100         if (SvOK(value) && (sv_isobject(value) || (SvPOK(value) && ! looks_like_number(value)))) {
    50          
    50          
    100          
    100          
    50          
462 36           dSP;
463              
464             SV* ret;
465             IV count;
466              
467 36           ENTER;
468 36           SAVETMPS;
469              
470 36 50         PUSHMARK(SP);
471 36 50         EXTEND(SP, 2);
472 36           PUSHs(value);
473 36           PUSHs(method);
474 36           PUTBACK;
475              
476 36           count = call_method("can", G_SCALAR);
477              
478 36 50         if (! count)
479 0           croak("Calling can did not return a value");
480              
481 36           SPAGAIN;
482              
483 36           ret = POPs;
484 36 50         SvGETMAGIC(ret);
485              
486 36 50         ok = SvTRUE(ret);
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    100          
    50          
    100          
    50          
    0          
    100          
    50          
487              
488 36           PUTBACK;
489 36 50         FREETMPS;
490 36           LEAVE;
491             }
492             else {
493             ok = 0;
494             }
495              
496 40 100         if (! ok) {
497 17           SV* buffer = newSVpvf(id, string_representation(value));
498 17           SV *caller = get_caller(options);
499 17           sv_catpv(buffer, " to ");
500 17           sv_catsv(buffer, caller);
501             SvREFCNT_dec(caller);
502 17           sv_catpv(buffer, " does not have the method: '");
503 17           sv_catsv(buffer, method);
504 17           sv_catpv(buffer, "'\n");
505 17           validation_failure(buffer, options);
506             }
507              
508             return 1;
509             }
510              
511             /* validates specific parameter using supplied parameter specification */
512             static IV
513 3264           validate_one_param(SV* value, SV* params, HV* spec, char* id, HV* options, IV* untaint) {
514             SV** temp;
515             IV i;
516              
517             /*
518             HE* he;
519             hv_iterinit(spec);
520              
521             while (he = hv_iternext(spec)) {
522             STRLEN len;
523             char* key = HePV(he, len);
524             int ok = 0;
525             int j;
526             for ( j = 0; j < VALID_KEY_COUNT; j++ ) {
527             if ( strcmp( key, valid_keys[j] ) == 0) {
528             ok = 1;
529             break;
530             }
531             }
532              
533             if ( ! ok ) {
534             SV* buffer = sv_2mortal(newSVpv("\"",0));
535             sv_catpv( buffer, key );
536             sv_catpv( buffer, "\" is not an allowed validation spec key\n");
537             validation_failure(buffer, options);
538             }
539             }
540             */
541              
542             /* check type */
543 3264 100         if ((temp = hv_fetch(spec, "type", 4, 0))) {
544             IV type;
545              
546 4254 100         if ( ! ( SvOK(*temp)
    50          
    50          
    50          
    50          
547 2127 100         && looks_like_number(*temp)
548 0 0         && SvIV(*temp) > 0 ) ) {
549              
550 2           SV* buffer = newSVpvf(id, string_representation(value));
551 2           sv_catpv( buffer, " has a type specification which is not a number. It is ");
552 2 100         if ( SvOK(*temp) ) {
    50          
    50          
553 1           sv_catpv( buffer, "a string - " );
554 1           sv_catsv( buffer, *temp );
555             }
556             else {
557 1           sv_catpv( buffer, "undef");
558             }
559 2           sv_catpv( buffer, ".\n Use the constants exported by Params::Validate to declare types." );
560              
561 2           validation_failure(buffer, options);
562             }
563              
564 2126 50         SvGETMAGIC(*temp);
565 2126           type = get_type(value);
566 2126 50         if (! (type & SvIV(*temp))) {
    100          
567 28           SV* buffer = newSVpvf(id, string_representation(value));
568 28           SV *caller = get_caller(options);
569             SV* is;
570             SV* allowed;
571              
572 28           sv_catpv(buffer, " to ");
573 28           sv_catsv(buffer, caller);
574             SvREFCNT_dec(caller);
575 28           sv_catpv(buffer, " was ");
576 28           is = typemask_to_string(type);
577 28 50         allowed = typemask_to_string(SvIV(*temp));
578 28           sv_catpv(buffer, article(is));
579 28           sv_catpv(buffer, " '");
580 28           sv_catsv(buffer, is);
581 28           sv_catpv(buffer, "', which is not one of the allowed types: ");
582 28           sv_catsv(buffer, allowed);
583 28           sv_catpv(buffer, "\n");
584              
585 28           validation_failure(buffer, options);
586             }
587             }
588              
589             /* check isa */
590 3234 100         if ((temp = hv_fetch(spec, "isa", 3, 0))) {
591 40 50         SvGETMAGIC(*temp);
592              
593 40 100         if (SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
    50          
594             AV* array = (AV*) SvRV(*temp);
595              
596 10 100         for(i = 0; i <= av_len(array); i++) {
597             SV* package;
598              
599 8           package = *av_fetch(array, i, 1);
600 8 50         if (! package) {
601             return 0;
602             }
603              
604 8 50         SvGETMAGIC(package);
605 8 50         if (! validate_isa(value, package, id, options)) {
606             return 0;
607             }
608             }
609             }
610             else {
611 36 50         if (! validate_isa(value, *temp, id, options)) {
612             return 0;
613             }
614             }
615             }
616              
617             /* check can */
618 3216 100         if ((temp = hv_fetch(spec, "can", 3, 0))) {
619 30 50         SvGETMAGIC(*temp);
620 30 100         if (SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
    50          
621             AV* array = (AV*) SvRV(*temp);
622              
623 26 100         for (i = 0; i <= av_len(array); i++) {
624             SV* method;
625              
626 22           method = *av_fetch(array, i, 1);
627 22 50         if (! method) {
628             return 0;
629             }
630              
631 22 50         SvGETMAGIC(method);
632              
633 22 50         if (! validate_can(value, method, id, options)) {
634             return 0;
635             }
636             }
637             }
638             else {
639 18 50         if (! validate_can(value, *temp, id, options)) {
640             return 0;
641             }
642             }
643             }
644              
645             /* let callbacks to do their tests */
646 3199 100         if ((temp = hv_fetch(spec, "callbacks", 9, 0))) {
647             HE* he;
648              
649 3039 50         SvGETMAGIC(*temp);
650 3039 50         if (!(SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVHV)) {
    50          
651 0           SV* buffer = newSVpv("'callbacks' validation parameter for '", 0);
652 0           SV *caller = get_caller(options);
653              
654 0           sv_catsv(buffer, caller);
655             SvREFCNT_dec(caller);
656 0           sv_catpv(buffer, " must be a hash reference\n");
657 0           validation_failure(buffer, options);
658             }
659              
660 3039           hv_iterinit((HV*) SvRV(*temp));
661 6063 100         while ((he = hv_iternext((HV*) SvRV(*temp)))) {
662             SV* ret;
663             IV ok;
664             IV count;
665             SV *err;
666              
667 3043 50         if (!(SvROK(HeVAL(he)) && SvTYPE(SvRV(HeVAL(he))) == SVt_PVCV)) {
    50          
668 0           SV* buffer = newSVpv("callback '", 0);
669 0           SV *caller = get_caller(options);
670              
671 0 0         sv_catsv(buffer, HeSVKEY_force(he));
    0          
    0          
672 0           sv_catpv(buffer, "' for ");
673 0           sv_catsv(buffer, caller);
674             SvREFCNT_dec(caller);
675 0           sv_catpv(buffer, " is not a subroutine reference\n");
676 0           validation_failure(buffer, options);
677             }
678              
679             {
680 3043           dSP;
681 3043           ENTER;
682 3043           SAVETMPS;
683              
684 3043 50         PUSHMARK(SP);
685 3043 50         EXTEND(SP, 2);
686 3043           PUSHs(value);
687 3043           mPUSHs(newRV_inc(params));
688 3043           PUTBACK;
689              
690             /* local $@ = q{}; */
691 3043           save_scalar(PL_errgv);
692 3043 50         sv_setpv(ERRSV, "");
693              
694 3043           count = call_sv(SvRV(HeVAL(he)), G_EVAL|G_SCALAR);
695              
696 3043           SPAGAIN;
697              
698 3043 50         if (!count) {
699 0           croak("Validation callback did not return anything");
700             }
701              
702 3043           ret = POPs;
703 3043 50         SvGETMAGIC(ret);
704 3043 50         ok = SvTRUE(ret);
    50          
    0          
    100          
    50          
    50          
    100          
    50          
    100          
    100          
    50          
    100          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
705              
706 3043           err = newSV(0);
707 3043 50         SvSetSV_nosteal(err, ERRSV);
    50          
    50          
708              
709 3043           PUTBACK;
710 3043 50         FREETMPS;
711 3043           LEAVE;
712              
713 3043 100         if (! ok) {
714 19 100         if (SvROK(err)) {
715 1           validation_failure(err, options);
716             }
717             else {
718 18           SV* buffer = newSVpvf(id, string_representation(value));
719 18           SV *caller = get_caller(options);
720              
721 18           sv_catpv(buffer, " to ");
722 18           sv_catsv(buffer, caller);
723             SvREFCNT_dec(caller);
724 18           sv_catpv(buffer, " did not pass the '");
725 18 50         sv_catsv(buffer, HeSVKEY_force(he));
    50          
    50          
726 18           sv_catpv(buffer, "' callback");
727 18 100         if (SvCUR(err) > 0) {
728 4           sv_catpv(buffer, ": ");
729 4           sv_catsv(buffer, err);
730             }
731 18           sv_catpv(buffer, "\n");
732 18           validation_failure(buffer, options);
733             }
734             }
735             else {
736             SvREFCNT_dec(err);
737             }
738             }
739             }
740             }
741              
742 3180 100         if ((temp = hv_fetch(spec, "regex", 5, 0))) {
743 9           dSP;
744              
745             IV has_regex = 0;
746             IV ok;
747              
748 9 50         SvGETMAGIC(*temp);
749 9 100         if (SvPOK(*temp)) {
750             has_regex = 1;
751             }
752 6 50         else if (SvROK(*temp)) {
753             SV* svp;
754              
755 6           svp = (SV*)SvRV(*temp);
756              
757             #if PERL_VERSION <= 10
758             if (SvMAGICAL(svp) && mg_find(svp, PERL_MAGIC_qr)) {
759             has_regex = 1;
760             }
761             #else
762 6 50         if (SvTYPE(svp) == SVt_REGEXP) {
763             has_regex = 1;
764             }
765             #endif
766             }
767              
768 9 50         if (!has_regex) {
769 0           SV* buffer = newSVpv("'regex' validation parameter for '", 0);
770 0           SV *caller = get_caller(options);
771              
772 0           sv_catsv(buffer, caller);
773             SvREFCNT_dec(caller);
774 0           sv_catpv(buffer, " must be a string or qr// regex\n");
775 0           validation_failure(buffer, options);
776             }
777              
778 9 50         PUSHMARK(SP);
779 9 50         EXTEND(SP, 2);
780 9           PUSHs(value);
781 9           PUSHs(*temp);
782 9           PUTBACK;
783 9           call_pv("Params::Validate::XS::_check_regex_from_xs", G_SCALAR);
784 9           SPAGAIN;
785 9 50         ok = POPi;
786 9           PUTBACK;
787              
788 9 100         if (! ok) {
789 4           SV* buffer = newSVpvf(id, string_representation(value));
790 4           SV *caller = get_caller(options);
791              
792 4           sv_catpv(buffer, " to ");
793 4           sv_catsv(buffer, caller);
794             SvREFCNT_dec(caller);
795 4           sv_catpv(buffer, " did not pass regex check\n");
796 4           validation_failure(buffer, options);
797             }
798             }
799              
800 3176 50         if ((temp = hv_fetch(spec, "untaint", 7, 0))) {
801 0 0         if (SvTRUE(*temp)) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
802 0           *untaint = 1;
803             }
804             }
805              
806             return 1;
807             }
808              
809             /* merges one hash into another (not deep copy) */
810             static void
811 42           merge_hashes(HV* in, HV* out) {
812             HE* he;
813              
814 42           hv_iterinit(in);
815 163 100         while ((he = hv_iternext(in))) {
816 121 50         if (!hv_store_ent(out, HeSVKEY_force(he),
    50          
    50          
    50          
817             SvREFCNT_inc(HeVAL(he)), HeHASH(he))) {
818 0           SvREFCNT_dec(HeVAL(he));
819 0           croak("Cannot add new key to hash");
820             }
821             }
822 42           }
823              
824             /* convert array to hash */
825             static IV
826 3334           convert_array2hash(AV* in, HV* options, HV* out) {
827             IV i;
828             I32 len;
829              
830 3334           len = av_len(in);
831 3334 100         if (len > -1 && len % 2 != 1) {
    100          
832 3           SV* buffer = newSVpv("Odd number of parameters in call to ", 0);
833 3           SV *caller = get_caller(options);
834              
835 3           sv_catsv(buffer, caller);
836             SvREFCNT_dec(caller);
837 3           sv_catpv(buffer, " when named parameters were expected\n");
838              
839 3334           validation_failure(buffer, options);
840             }
841              
842 6791 100         for (i = 0; i <= av_len(in); i += 2) {
843             SV* key;
844             SV* value;
845              
846 3460           key = *av_fetch(in, i, 1);
847 3460 50         if (! key) {
848 0           continue;
849             }
850              
851 3460 100         SvGETMAGIC(key);
852              
853             /* We need to make a copy because if the array was @_, then the
854             values in the array are marked as readonly, which causes
855             problems when the hash being made gets returned to the
856             caller. */
857 3460           value = sv_2mortal( newSVsv( *av_fetch(in, i + 1, 1) ) );
858              
859 3460 50         if (value) {
860 3460 50         SvGETMAGIC(value);
861             }
862              
863 3460 50         if (! hv_store_ent(out, key, SvREFCNT_inc(value), 0)) {
864             SvREFCNT_dec(value);
865 0           croak("Cannot add new key to hash");
866             }
867             }
868              
869 3331           return 1;
870             }
871              
872             /* get current Params::Validate options */
873             static HV*
874 3427           get_options(HV* options) {
875             HV* OPTIONS;
876             HV* ret;
877             HE *he;
878             HV *stash;
879             SV* pkg;
880             SV *pkg_options;
881              
882 3427           ret = (HV*) sv_2mortal((SV*) newHV());
883              
884             /* get package specific options */
885 3427           stash = CopSTASH(PL_curcop);
886 3427 50         pkg = sv_2mortal(newSVpv(HvNAME(stash), 0));
    50          
    50          
    0          
    50          
    50          
887              
888 3427           OPTIONS = get_hv("Params::Validate::OPTIONS", 1);
889 3427 100         if ((he = hv_fetch_ent(OPTIONS, pkg, 0, 0))) {
890 40           pkg_options = HeVAL(he);
891 40 50         SvGETMAGIC(pkg_options);
892 40 50         if (SvROK(pkg_options) && SvTYPE(SvRV(pkg_options)) == SVt_PVHV) {
    50          
893 40 100         if (options) {
894 2           merge_hashes((HV*) SvRV(pkg_options), ret);
895             }
896             else {
897             return (HV*) SvRV(pkg_options);
898             }
899             }
900             }
901 3389 100         if (options) {
902 40           merge_hashes(options, ret);
903             }
904              
905             return ret;
906             }
907              
908             static SV*
909 108           normalize_one_key(SV* key, SV* normalize_func, SV* strip_leading, IV ignore_case) {
910             SV* copy;
911             STRLEN len_sl;
912             STRLEN len;
913             char *rawstr_sl;
914             char *rawstr;
915              
916 108           copy = sv_2mortal(newSVsv(key));
917              
918             /* if normalize_func is provided, ignore the other options */
919 108 100         if (normalize_func) {
920 9           dSP;
921              
922             SV* normalized;
923              
924 9 50         PUSHMARK(SP);
925 9 50         XPUSHs(copy);
926 9           PUTBACK;
927 9 50         if (! call_sv(SvRV(normalize_func), G_SCALAR)) {
928 0           croak("The normalize_keys callback did not return anything");
929             }
930 9           SPAGAIN;
931 9           normalized = POPs;
932 9           PUTBACK;
933              
934 9 100         if (! SvOK(normalized)) {
    50          
    50          
935 1 50         croak("The normalize_keys callback did not return a defined value when normalizing the key '%s'", SvPV_nolen(copy));
936             }
937              
938             return normalized;
939             }
940 99 50         else if (ignore_case || strip_leading) {
941 99 100         if (ignore_case) {
942             STRLEN i;
943              
944 42 50         rawstr = SvPV(copy, len);
945 168 100         for (i = 0; i < len; i++) {
946             /* should this account for UTF8 strings? */
947 126 100         *(rawstr + i) = toLOWER(*(rawstr + i));
948             }
949             }
950              
951 99 100         if (strip_leading) {
952 81 100         rawstr_sl = SvPV(strip_leading, len_sl);
953 81 50         rawstr = SvPV(copy, len);
954              
955 81 100         if (len > len_sl && strnEQ(rawstr_sl, rawstr, len_sl)) {
    100          
956 3           copy = sv_2mortal(newSVpvn(rawstr + len_sl, len - len_sl));
957             }
958             }
959             }
960              
961             return copy;
962             }
963              
964             static HV*
965 100           normalize_hash_keys(HV* p, SV* normalize_func, SV* strip_leading, IV ignore_case) {
966             SV* normalized;
967             HE* he;
968             HV* norm_p;
969              
970 100 100         if (!normalize_func && !ignore_case && !strip_leading) {
    50          
971             return p;
972             }
973              
974 100           norm_p = (HV*) sv_2mortal((SV*) newHV());
975 100           hv_iterinit(p);
976 206 100         while ((he = hv_iternext(p))) {
977 108           normalized =
978 108 50         normalize_one_key(HeSVKEY_force(he), normalize_func, strip_leading, ignore_case);
    50          
    50          
979              
980 107 100         if (hv_fetch_ent(norm_p, normalized, 0, 0)) {
981 2 50         croak("The normalize_keys callback returned a key that already exists, '%s', when normalizing the key '%s'",
    50          
982 2 50         SvPV_nolen(normalized), SvPV_nolen(HeSVKEY_force(he)));
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
983             }
984              
985 106 50         if (! hv_store_ent(norm_p, normalized, SvREFCNT_inc(HeVAL(he)), 0)) {
986 0           SvREFCNT_dec(HeVAL(he));
987 0           croak("Cannot add new key to hash");
988             }
989             }
990             return norm_p;
991             }
992              
993             static IV
994 35           validate_pos_depends(AV* p, AV* specs, HV* options) {
995             IV p_idx;
996             SV** depends;
997             SV** p_spec;
998              
999 61 100         for (p_idx = 0; p_idx <= av_len(p); p_idx++) {
1000 44           p_spec = av_fetch(specs, p_idx, 0);
1001              
1002 44 100         if (p_spec != NULL && SvROK(*p_spec) &&
    100          
    50          
1003 19           SvTYPE(SvRV(*p_spec)) == SVt_PVHV) {
1004              
1005 19           depends = hv_fetch((HV*) SvRV(*p_spec), "depends", 7, 0);
1006              
1007 19 100         if (! depends) {
1008             return 1;
1009             }
1010              
1011 3 100         if (SvROK(*depends)) {
1012 1           croak("Arguments to 'depends' for validate_pos() must be a scalar");
1013             }
1014              
1015 2 50         if (av_len(p) < SvIV(*depends) -1) {
    100          
1016 1           SV *buffer =
1017 1 50         newSVpvf("Parameter #%d depends on parameter #%d, which was not given",
1018 1           (int) p_idx + 1,
1019 0           (int) SvIV(*depends));
1020              
1021 1           validation_failure(buffer, options);
1022             }
1023             }
1024             }
1025              
1026             return 1;
1027             }
1028              
1029             static IV
1030 3157           validate_named_depends(HV* p, HV* specs, HV* options) {
1031             HE* he;
1032             HE* he1;
1033             SV* buffer;
1034             SV** depends_value;
1035             AV* depends_list;
1036             SV* depend_name;
1037             SV* temp;
1038             I32 d_idx;
1039              
1040             /* the basic idea here is to iterate through the parameters
1041             * (which we assumed to have already gone through validation
1042             * via validate_one_param()), and the check to see if that
1043             * parameter contains a "depends" spec. If it does, we'll
1044             * check if that parameter specified by depends exists in p
1045             */
1046 3157           hv_iterinit(p);
1047 6339 100         while ((he = hv_iternext(p))) {
1048 3186 50         he1 = hv_fetch_ent(specs, HeSVKEY_force(he), 0, HeHASH(he));
    50          
    50          
1049              
1050 3186 100         if (he1 && SvROK(HeVAL(he1)) &&
    100          
    50          
1051 3117           SvTYPE(SvRV(HeVAL(he1))) == SVt_PVHV) {
1052              
1053 3117 100         if (hv_exists((HV*) SvRV(HeVAL(he1)), "depends", 7)) {
1054              
1055 6           depends_value = hv_fetch((HV*) SvRV(HeVAL(he1)), "depends", 7, 0);
1056              
1057 6 50         if (! depends_value) {
1058             return 1;
1059             }
1060              
1061 6 100         if (! SvROK(*depends_value)) {
1062 2           depends_list = (AV*) sv_2mortal((SV*) newAV());
1063 2           temp = sv_2mortal(newSVsv(*depends_value));
1064 2           av_push(depends_list,SvREFCNT_inc(temp));
1065             }
1066 4 100         else if (SvTYPE(SvRV(*depends_value)) == SVt_PVAV) {
1067             depends_list = (AV*) SvRV(*depends_value);
1068             }
1069             else {
1070 1           croak("Arguments to 'depends' must be a scalar or arrayref");
1071             }
1072              
1073 3189 100         for (d_idx =0; d_idx <= av_len(depends_list); d_idx++) {
1074              
1075 7           depend_name = *av_fetch(depends_list, d_idx, 0);
1076              
1077             /* first check if the parameter to which this
1078             * depends on was given to us
1079             */
1080 7 50         if (!hv_exists(p, SvPV_nolen(depend_name),
    100          
1081             SvCUR(depend_name))) {
1082             /* oh-oh, the parameter that this parameter
1083             * depends on is not available. Let's first check
1084             * if this is even valid in the spec (i.e., the
1085             * spec actually contains a spec for such parameter)
1086             */
1087 3 50         if (!hv_exists(specs, SvPV_nolen(depend_name),
    50          
1088             SvCUR(depend_name))) {
1089              
1090 0           buffer =
1091 0           sv_2mortal(newSVpv("Following parameter specified in depends for '", 0));
1092              
1093 0 0         sv_catsv(buffer, HeSVKEY_force(he1));
    0          
    0          
1094 0           sv_catpv(buffer, "' does not exist in spec: ");
1095 0           sv_catsv(buffer, depend_name);
1096              
1097 0 0         croak("%s", SvPV_nolen(buffer));
1098             }
1099             /* if we got here, the spec was correct. we just
1100             * need to issue a regular validation failure
1101             */
1102 3           buffer = newSVpv( "Parameter '", 0);
1103 3 50         sv_catsv(buffer, HeSVKEY_force(he1));
    50          
    50          
1104 3           sv_catpv(buffer, "' depends on parameter '");
1105 3           sv_catsv(buffer, depend_name);
1106 3           sv_catpv(buffer, "', which was not given");
1107 3           validation_failure(buffer, options);
1108             }
1109             }
1110             }
1111             }
1112             }
1113             return 1;
1114             }
1115              
1116             void
1117 3229           apply_defaults(HV *ret, HV *p, HV *specs, AV *missing) {
1118             HE* he;
1119             SV** temp;
1120              
1121 3229           hv_iterinit(specs);
1122 6584 100         while ((he = hv_iternext(specs))) {
1123             HV* spec;
1124             SV* val;
1125              
1126 3355           val = HeVAL(he);
1127              
1128             /* get extended param spec if available */
1129 3355 50         if (val && SvROK(val) && SvTYPE(SvRV(val)) == SVt_PVHV) {
    100          
    50          
1130 3249           spec = (HV*) SvRV(val);
1131             }
1132             else {
1133             spec = NULL;
1134             }
1135              
1136             /* test for parameter existence */
1137 3355 50         if (hv_exists_ent(p, HeSVKEY_force(he), HeHASH(he))) {
    50          
    50          
    100          
1138 3284           continue;
1139             }
1140              
1141             /* parameter may not be defined but we may have default */
1142 71 100         if (spec && (temp = hv_fetch(spec, "default", 7, 0))) {
    100          
1143             SV* value;
1144              
1145 17 50         SvGETMAGIC(*temp);
1146 17           value = sv_2mortal(newSVsv(*temp));
1147              
1148             /* make sure that parameter is put into return hash */
1149 17 100         if (GIMME_V != G_VOID) {
    100          
1150 16 50         if (!hv_store_ent(ret, HeSVKEY_force(he),
    50          
    50          
    50          
1151             SvREFCNT_inc(value), HeHASH(he))) {
1152             SvREFCNT_dec(value);
1153 0           croak("Cannot add new key to hash");
1154             }
1155             }
1156              
1157 17           continue;
1158             }
1159              
1160             /* find if missing parameter is mandatory */
1161 54 100         if (! no_validation()) {
1162             SV** temp;
1163              
1164 38 100         if (spec) {
1165 25 100         if ((temp = hv_fetch(spec, "optional", 8, 0))) {
1166 13 50         SvGETMAGIC(*temp);
1167              
1168 13 50         if (SvTRUE(*temp)) continue;
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
1169             }
1170             }
1171 13 50         else if (!SvTRUE(HeVAL(he))) {
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1172 2           continue;
1173             }
1174 3378 50         av_push(missing, SvREFCNT_inc(HeSVKEY_force(he)));
    50          
    50          
1175             }
1176             }
1177 3229           }
1178              
1179             static IV
1180 3342           validate(HV* p, HV* specs, HV* options, HV* ret) {
1181             AV* missing;
1182             AV* unmentioned;
1183             HE* he;
1184             HE* he1;
1185             SV* hv;
1186             SV* hv1;
1187             IV ignore_case = 0;
1188             SV* strip_leading = NULL;
1189             IV allow_extra = 0;
1190             SV** temp;
1191             SV* normalize_func = NULL;
1192 3342           AV* untaint_keys = (AV*) sv_2mortal((SV*) newAV());
1193             IV i;
1194              
1195 3342 100         if ((temp = hv_fetch(options, "ignore_case", 11, 0))) {
1196 56 50         SvGETMAGIC(*temp);
1197 56 50         ignore_case = SvTRUE(*temp);
    50          
    0          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1198             }
1199              
1200 3342 100         if ((temp = hv_fetch(options, "strip_leading", 13, 0))) {
1201 38 50         SvGETMAGIC(*temp);
1202 38 50         if (SvOK(*temp)) strip_leading = *temp;
    0          
    0          
1203             }
1204              
1205 3342 100         if ((temp = hv_fetch(options, "normalize_keys", 14, 0))) {
1206 42 50         SvGETMAGIC(*temp);
1207 42 100         if(SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVCV) {
    50          
1208             normalize_func = *temp;
1209             }
1210             }
1211              
1212 3342 100         if (normalize_func || ignore_case || strip_leading) {
    100          
1213 51           p = normalize_hash_keys(p, normalize_func, strip_leading, ignore_case);
1214 49           specs = normalize_hash_keys(specs, normalize_func, strip_leading, ignore_case);
1215             }
1216              
1217             /* short-circuit everything else when no_validation is true */
1218 3340 100         if (no_validation()) {
1219 76 100         if (GIMME_V != G_VOID) {
    50          
1220 191 100         while ((he = hv_iternext(p))) {
1221 115           hv = HeVAL(he);
1222 115 50         if (! hv) {
1223 0           continue;
1224             }
1225              
1226 115 50         SvGETMAGIC(hv);
1227              
1228             /* put the parameter into return hash */
1229 115 50         if (!hv_store_ent(ret, HeSVKEY_force(he), SvREFCNT_inc(hv),
    50          
    50          
    50          
1230             HeHASH(he))) {
1231             SvREFCNT_dec(hv);
1232 115           croak("Cannot add new key to hash");
1233             }
1234             }
1235 76           apply_defaults(ret, p, specs, NULL);
1236             }
1237              
1238             return 1;
1239             }
1240              
1241 3264 100         if ((temp = hv_fetch(options, "allow_extra", 11, 0))) {
1242 34 50         SvGETMAGIC(*temp);
1243 34 50         allow_extra = SvTRUE(*temp);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1244             }
1245              
1246             /* find extra parameters and validate good parameters */
1247 3264           unmentioned = (AV*) sv_2mortal((SV*) newAV());
1248              
1249 3264           hv_iterinit(p);
1250 6475 100         while ((he = hv_iternext(p))) {
1251 3318           hv = HeVAL(he);
1252 3318 50         if (! hv) {
1253 0           continue;
1254             }
1255              
1256 3318 50         SvGETMAGIC(hv);
1257              
1258             /* put the parameter into return hash */
1259 3318 100         if (GIMME_V != G_VOID) {
    100          
1260 3236 50         if (!hv_store_ent(ret, HeSVKEY_force(he), SvREFCNT_inc(hv),
    50          
    50          
    50          
1261             HeHASH(he))) {
1262             SvREFCNT_dec(hv);
1263 0           croak("Cannot add new key to hash");
1264             }
1265             }
1266              
1267             /* check if this parameter is defined in spec and if it is
1268             then validate it using spec */
1269 3318 50         he1 = hv_fetch_ent(specs, HeSVKEY_force(he), 0, HeHASH(he));
    50          
    50          
1270 3318 100         if(he1) {
1271 3287           hv1 = HeVAL(he1);
1272 3287 100         if (SvROK(hv1) && SvTYPE(SvRV(hv1)) == SVt_PVHV) {
    50          
1273             char* buffer;
1274             HV* spec;
1275 3215           IV untaint = 0;
1276              
1277             spec = (HV*) SvRV(hv1);
1278 3215 50         buffer = form("The '%s' parameter (%%s)", HePV(he, PL_na));
    0          
1279              
1280 3215 50         if (! validate_one_param(hv, (SV*) p, spec, buffer, options, &untaint))
1281 0           return 0;
1282              
1283             /* The value stored here is meaningless, we're just tracking
1284             keys to untaint later */
1285 3134 50         if (untaint) {
1286 3134 0         av_push(untaint_keys, SvREFCNT_inc(HeSVKEY_force(he1)));
    0          
    0          
1287             }
1288             }
1289             }
1290 31 100         else if (! allow_extra) {
1291 52 50         av_push(unmentioned, SvREFCNT_inc(HeSVKEY_force(he)));
    50          
    50          
1292             }
1293              
1294 3237 100         if (av_len(unmentioned) > -1) {
1295 26           SV* buffer = newSVpv("The following parameter", 0);
1296 26           SV *caller = get_caller(options);
1297              
1298 26 50         if (av_len(unmentioned) != 0) {
1299 0           sv_catpv(buffer, "s were ");
1300             }
1301             else {
1302 26           sv_catpv(buffer, " was ");
1303             }
1304 26           sv_catpv(buffer, "passed in the call to ");
1305 26           sv_catsv(buffer, caller);
1306             SvREFCNT_dec(caller);
1307 26           sv_catpv(buffer, " but ");
1308 26 50         if (av_len(unmentioned) != 0) {
1309 0           sv_catpv(buffer, "were ");
1310             }
1311             else {
1312 26           sv_catpv(buffer, "was ");
1313             }
1314 26           sv_catpv(buffer, "not listed in the validation options: ");
1315 52 100         for(i = 0; i <= av_len(unmentioned); i++) {
1316 26           sv_catsv(buffer, *av_fetch(unmentioned, i, 1));
1317 26 50         if (i < av_len(unmentioned)) {
1318 0           sv_catpv(buffer, " ");
1319             }
1320             }
1321 26           sv_catpv(buffer, "\n");
1322              
1323 3237           validation_failure(buffer, options);
1324             }
1325             }
1326              
1327 3157           validate_named_depends(p, specs, options);
1328              
1329             /* find missing parameters */
1330 3153           missing = (AV*) sv_2mortal((SV*) newAV());
1331              
1332 3153           apply_defaults(ret, p, specs, missing);
1333              
1334 3153 100         if (av_len(missing) > -1) {
1335             SV *buffer;
1336             SV *caller;
1337              
1338 13           sortsv(AvARRAY(missing), 1 + av_len(missing), Perl_sv_cmp);
1339 13           buffer = newSVpv("Mandatory parameter", 0);
1340 13           caller = get_caller(options);
1341              
1342 13 100         if (av_len(missing) > 0) {
1343 13           sv_catpv(buffer, "s ");
1344             }
1345             else {
1346 9           sv_catpv(buffer, " ");
1347             }
1348              
1349 36 100         for(i = 0; i <= av_len(missing); i++) {
1350 46 50         sv_catpvf(buffer, "'%s'",
1351 46           SvPV_nolen(*av_fetch(missing, i, 0)));
1352 23 100         if (i < av_len(missing)) {
1353 10           sv_catpv(buffer, ", ");
1354             }
1355             }
1356 13           sv_catpv(buffer, " missing in call to ");
1357 13           sv_catsv(buffer, caller);
1358             SvREFCNT_dec(caller);
1359 13           sv_catpv(buffer, "\n");
1360              
1361 13           validation_failure(buffer, options);
1362             }
1363              
1364 3140 100         if (GIMME_V != G_VOID) {
    100          
1365 3108 50         for (i = 0; i <= av_len(untaint_keys); i++) {
1366 0 0         SvTAINTED_off(HeVAL(hv_fetch_ent(p, *av_fetch(untaint_keys, i, 0), 0, 0)));
1367             }
1368             }
1369              
1370             return 1;
1371             }
1372              
1373             static SV*
1374 21           validate_pos_failure(IV pnum, IV min, IV max, HV* options) {
1375             SV* buffer;
1376             SV** temp;
1377             IV allow_extra;
1378              
1379 21 50         if ((temp = hv_fetch(options, "allow_extra", 11, 0))) {
1380 0 0         SvGETMAGIC(*temp);
1381 0 0         allow_extra = SvTRUE(*temp);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1382             }
1383             else {
1384             allow_extra = 0;
1385             }
1386              
1387 21           buffer = newSViv(pnum + 1);
1388 21 100         if (pnum != 0) {
1389 19           sv_catpv(buffer, " parameters were passed to ");
1390             }
1391             else {
1392 2           sv_catpv(buffer, " parameter was passed to ");
1393             }
1394 21           sv_catsv(buffer, get_caller(options));
1395 21           sv_catpv(buffer, " but ");
1396 21 50         if (!allow_extra) {
1397 21 100         if (min != max) {
1398 16           sv_catpvf(buffer, "%d - %d", (int) min + 1, (int) max + 1);
1399             }
1400             else {
1401 5           sv_catpvf(buffer, "%d", (int) max + 1);
1402             }
1403             }
1404             else {
1405 0           sv_catpvf(buffer, "at least %d", (int) min + 1);
1406             }
1407 21 50         if ((allow_extra ? min : max) != 0) {
    100          
1408 18           sv_catpv(buffer, " were expected\n");
1409             }
1410             else {
1411 3           sv_catpv(buffer, " was expected\n");
1412             }
1413              
1414 21           return buffer;
1415             }
1416              
1417             /* Given a single parameter spec and a corresponding complex spec form
1418             of it (which must be false if the spec is not complex), return true
1419             says that the parameter is options. */
1420             static bool
1421 125           spec_says_optional(SV* spec, IV complex_spec) {
1422             SV** temp;
1423              
1424 125 100         if (complex_spec) {
1425 78 100         if ((temp = hv_fetch((HV*) SvRV(spec), "optional", 8, 0))) {
1426 29 50         SvGETMAGIC(*temp);
1427 29 50         if (!SvTRUE(*temp))
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
1428             return FALSE;
1429             }
1430             else {
1431             return FALSE;
1432             }
1433             }
1434             else {
1435 47 50         if (SvTRUE(spec)) {
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
1436             return FALSE;
1437             }
1438             }
1439             return TRUE;
1440             }
1441              
1442             static IV
1443 82           validate_pos(AV* p, AV* specs, HV* options, AV* ret) {
1444             char* buffer;
1445             SV* value;
1446             SV* spec = NULL;
1447             SV** temp;
1448             IV i;
1449             IV complex_spec = 0;
1450             IV allow_extra;
1451             /* Index of highest-indexed required parameter known so far, or -1
1452             if no required parameters are known yet. */
1453             IV min = -1;
1454 82           AV* untaint_indexes = (AV*) sv_2mortal((SV*) newAV());
1455              
1456 82 100         if (no_validation()) {
1457 25           IV spec_count = av_len(specs);
1458 25           IV p_count = av_len(p);
1459 25           IV max = spec_count > p_count ? spec_count : p_count;
1460              
1461 25 100         if (GIMME_V == G_VOID) {
    50          
1462             return 1;
1463             }
1464              
1465 87 100         for (i = 0; i <= max; i++) {
1466 62 100         if (i <= spec_count) {
1467 58           spec = *av_fetch(specs, i, 1);
1468 58 50         if (spec) {
1469 58 50         SvGETMAGIC(spec);
1470             }
1471 58 100         complex_spec = (SvROK(spec) && SvTYPE(SvRV(spec)) == SVt_PVHV);
    50          
1472             }
1473              
1474 62 100         if (i <= av_len(p)) {
1475 36           value = *av_fetch(p, i, 1);
1476 36 50         SvGETMAGIC(value);
1477 36           av_push(ret, SvREFCNT_inc(value));
1478 26 100         } else if (complex_spec &&
    100          
1479 15           (temp = hv_fetch((HV*) SvRV(spec), "default", 7, 0))) {
1480 6 50         SvGETMAGIC(*temp);
1481 6           av_push(ret, SvREFCNT_inc(*temp));
1482             }
1483             }
1484             return 1;
1485             }
1486              
1487             /* iterate through all parameters and validate them */
1488 140 100         for (i = 0; i <= av_len(specs); i++) {
1489 105           spec = *av_fetch(specs, i, 1);
1490 105 50         if (! spec) {
1491 0           continue;
1492             }
1493 105 50         SvGETMAGIC(spec);
1494 105 100         complex_spec = (SvROK(spec) && SvTYPE(SvRV(spec)) == SVt_PVHV);
    50          
1495              
1496             /* Unless the current spec refers to an optional argument, update
1497             our notion of the index of the highest-idexed required
1498             parameter. */
1499 105 100         if (! spec_says_optional(spec, complex_spec) ) {
1500             min = i;
1501             }
1502              
1503 105 100         if (i <= av_len(p)) {
1504 72           value = *av_fetch(p, i, 1);
1505 72 100         SvGETMAGIC(value);
1506              
1507 72 100         if (complex_spec) {
1508 49           IV untaint = 0;
1509              
1510 49           buffer = form("Parameter #%d (%%s)", (int)i + 1);
1511              
1512 49 50         if (! validate_one_param(value, (SV*) p, (HV*) SvRV(spec), buffer, options, &untaint)) {
1513 0           return 0;
1514             }
1515              
1516 42 50         if (untaint) {
1517 42           av_push(untaint_indexes, newSViv(i));
1518             }
1519             }
1520              
1521 65 100         if (GIMME_V != G_VOID) {
    100          
1522 54           av_push(ret, SvREFCNT_inc(value));
1523             }
1524              
1525 33 100         } else if (complex_spec &&
    100          
1526 21           (temp = hv_fetch((HV*) SvRV(spec), "default", 7, 0))) {
1527 7 50         SvGETMAGIC(*temp);
1528              
1529 7 100         if (GIMME_V != G_VOID) {
    50          
1530 7           av_store(ret, i, SvREFCNT_inc(*temp));
1531             }
1532              
1533             }
1534             else {
1535 26 100         if (i == min) {
1536             /* We don't have as many arguments as the arg spec requires. */
1537             SV* buffer;
1538              
1539             /* Look forward through remaining argument specifications to
1540             find the last non-optional one, so we can correctly report the
1541             number of arguments required. */
1542 23 100         for (i++ ; i <= av_len(specs); i++) {
1543 20           spec = *av_fetch(specs, i, 1);
1544 20 50         if (! spec) {
1545 0           continue;
1546             }
1547              
1548 20 50         SvGETMAGIC(spec);
1549 20 100         complex_spec = (SvROK(spec) && SvTYPE(SvRV(spec)) == SVt_PVHV);
    50          
1550 20 100         if (! spec_says_optional(spec, complex_spec)) {
1551             min = i;
1552             }
1553 20 100         if (min != i)
1554             break;
1555             }
1556              
1557 15           buffer = validate_pos_failure(av_len(p), min, av_len(specs), options);
1558              
1559 15           validation_failure(buffer, options);
1560             }
1561             }
1562             }
1563              
1564 35           validate_pos_depends(p, specs, options);
1565              
1566             /* test for extra parameters */
1567 33 100         if (av_len(p) > av_len(specs)) {
1568 8 100         if ((temp = hv_fetch(options, "allow_extra", 11, 0))) {
1569 2 50         SvGETMAGIC(*temp);
1570 2 50         allow_extra = SvTRUE(*temp);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
1571             }
1572             else {
1573             allow_extra = 0;
1574             }
1575 8 100         if (allow_extra) {
1576             /* put all additional parameters into return array */
1577 2 50         if (GIMME_V != G_VOID) {
    50          
1578 4 100         for(i = av_len(specs) + 1; i <= av_len(p); i++) {
1579 2           value = *av_fetch(p, i, 1);
1580 2 50         if (value) {
1581 2 50         SvGETMAGIC(value);
1582 2           av_push(ret, SvREFCNT_inc(value));
1583             }
1584             else {
1585 0           av_push(ret, &PL_sv_undef);
1586             }
1587             }
1588             }
1589             }
1590             else {
1591 6           SV* buffer = validate_pos_failure(av_len(p), min, av_len(specs), options);
1592 6           validation_failure(buffer, options);
1593             }
1594             }
1595              
1596 27 100         if (GIMME_V != G_VOID) {
    100          
1597 22 50         for (i = 0; i <= av_len(untaint_indexes); i++) {
1598 0 0         SvTAINTED_off(*av_fetch(p, SvIV(*av_fetch(untaint_indexes, i, 0)), 0));
    0          
1599             }
1600             }
1601              
1602             return 1;
1603             }
1604              
1605             MODULE = Params::Validate::XS PACKAGE = Params::Validate::XS
1606              
1607             void
1608             validate(p, specs)
1609             SV* p
1610             SV* specs
1611              
1612             PROTOTYPE: \@$
1613              
1614             PPCODE:
1615              
1616             HV* ret = NULL;
1617             AV* pa;
1618             HV* ph;
1619             HV* options;
1620             IV ok;
1621              
1622 3319 100         if (no_validation() && GIMME_V == G_VOID) {
    100          
    100          
1623 10           XSRETURN(0);
1624             }
1625              
1626 3309 50         SvGETMAGIC(p);
1627 3309 50         if (! (SvROK(p) && SvTYPE(SvRV(p)) == SVt_PVAV)) {
    50          
1628 0           croak("Expecting array reference as first parameter");
1629             }
1630              
1631 3309 50         SvGETMAGIC(specs);
1632 3309 50         if (! (SvROK(specs) && SvTYPE(SvRV(specs)) == SVt_PVHV)) {
    50          
1633 0           croak("Expecting hash reference as second parameter");
1634             }
1635              
1636 3309           pa = (AV*) SvRV(p);
1637             ph = NULL;
1638 3309 100         if (av_len(pa) == 0) {
1639             /* we were called as validate( @_, ... ) where @_ has a
1640             single element, a hash reference */
1641             SV* value;
1642              
1643 11           value = *av_fetch(pa, 0, 1);
1644 11 50         if (value) {
1645 11 50         SvGETMAGIC(value);
1646 11 100         if (SvROK(value) && SvTYPE(SvRV(value)) == SVt_PVHV) {
    50          
1647             ph = (HV*) SvRV(value);
1648             }
1649             }
1650             }
1651              
1652 3309           options = get_options(NULL);
1653              
1654 3309 100         if (! ph) {
1655 3301           ph = (HV*) sv_2mortal((SV*) newHV());
1656              
1657 3301           PUTBACK;
1658 3301           ok = convert_array2hash(pa, options, ph);
1659 3298           SPAGAIN;
1660              
1661 3298 50         if (!ok) {
1662 0           XSRETURN(0);
1663             }
1664             }
1665 3306 100         if (GIMME_V != G_VOID) {
    100          
1666 3239           ret = (HV*) sv_2mortal((SV*) newHV());
1667             }
1668              
1669 3306           PUTBACK;
1670 3306           ok = validate(ph, (HV*) SvRV(specs), options, ret);
1671 3189           SPAGAIN;
1672              
1673 3189 50         if (! ok) {
1674 0           XSRETURN(0);
1675             }
1676              
1677 6416 100         RETURN_HASH(ret);
    50          
    50          
    50          
    50          
    50          
    100          
    50          
1678              
1679             void
1680             validate_pos(p, ...)
1681             SV* p
1682              
1683             PROTOTYPE: \@@
1684              
1685             PPCODE:
1686              
1687             AV* specs;
1688             AV* ret = NULL;
1689             IV i;
1690             IV ok;
1691              
1692 78 100         if (no_validation() && GIMME_V == G_VOID) {
    50          
    50          
1693 0           XSRETURN(0);
1694             }
1695              
1696 78 50         SvGETMAGIC(p);
1697 78 50         if (!SvROK(p) || !(SvTYPE(SvRV(p)) == SVt_PVAV)) {
    50          
1698 0           croak("Expecting array reference as first parameter");
1699             }
1700              
1701 78           specs = (AV*) sv_2mortal((SV*) newAV());
1702 78           av_extend(specs, items);
1703 257 100         for(i = 1; i < items; i++) {
1704 179 50         if (!av_store(specs, i - 1, SvREFCNT_inc(ST(i)))) {
1705 0           SvREFCNT_dec(ST(i));
1706 0           croak("Cannot store value in array");
1707             }
1708             }
1709              
1710 78 100         if (GIMME_V != G_VOID) {
    100          
1711 71           ret = (AV*) sv_2mortal((SV*) newAV());
1712             }
1713              
1714 78           PUTBACK;
1715 78           ok = validate_pos((AV*) SvRV(p), specs, get_options(NULL), ret);
1716 49           SPAGAIN;
1717              
1718 49 50         if (! ok) {
1719 0           XSRETURN(0);
1720             }
1721              
1722 117 100         RETURN_ARRAY(ret);
    50          
    50          
    100          
    50          
1723              
1724             void
1725             validate_with(...)
1726              
1727             PPCODE:
1728              
1729             HV* p;
1730             SV* params;
1731             SV* spec;
1732             IV i;
1733             IV ok;
1734              
1735 45 100         if (no_validation() && GIMME_V == G_VOID) XSRETURN(0);
    50          
    100          
1736              
1737             /* put input list into hash */
1738 40           p = (HV*) sv_2mortal((SV*) newHV());
1739 149 100         for(i = 0; i < items; i += 2) {
1740             SV* key;
1741             SV* value;
1742              
1743 109           key = ST(i);
1744 109 50         if (i + 1 < items) {
1745 109           value = ST(i + 1);
1746             }
1747             else {
1748             value = &PL_sv_undef;
1749             }
1750 109 50         if (! hv_store_ent(p, key, SvREFCNT_inc(value), 0)) {
1751             SvREFCNT_dec(value);
1752 0           croak("Cannot add new key to hash");
1753             }
1754             }
1755              
1756 40           params = *hv_fetch(p, "params", 6, 1);
1757 40 50         SvGETMAGIC(params);
1758 40           spec = *hv_fetch(p, "spec", 4, 1);
1759 40 50         SvGETMAGIC(spec);
1760              
1761 40 50         if (SvROK(spec) && SvTYPE(SvRV(spec)) == SVt_PVAV) {
    100          
1762 4 50         if (SvROK(params) && SvTYPE(SvRV(params)) == SVt_PVAV) {
    50          
1763             AV* ret = NULL;
1764              
1765 4 50         if (GIMME_V != G_VOID) {
    100          
1766 2           ret = (AV*) sv_2mortal((SV*) newAV());
1767             }
1768              
1769 4           PUTBACK;
1770 4           ok = validate_pos((AV*) SvRV(params), (AV*) SvRV(spec), get_options(p), ret);
1771 3           SPAGAIN;
1772              
1773 3 50         if (! ok) {
1774 0           XSRETURN(0);
1775             }
1776              
1777 7 50         RETURN_ARRAY(ret);
    50          
    50          
    100          
    0          
1778             }
1779             else {
1780 0           croak("Expecting array reference in 'params'");
1781             }
1782             }
1783 36 50         else if (SvROK(spec) && SvTYPE(SvRV(spec)) == SVt_PVHV) {
    50          
1784             HV* hv;
1785             HV* ret = NULL;
1786             HV* options;
1787              
1788 36           options = get_options(p);
1789              
1790 36 50         if (SvROK(params) && SvTYPE(SvRV(params)) == SVt_PVHV) {
    100          
1791             hv = (HV*) SvRV(params);
1792             }
1793 35 50         else if (SvROK(params) && SvTYPE(SvRV(params)) == SVt_PVAV) {
    50          
1794             I32 hv_set = 0;
1795              
1796             /* Check to see if we have a one element array
1797             containing a hash reference */
1798 35 100         if (av_len((AV*) SvRV(params)) == 0) {
1799             SV** first_elem;
1800              
1801 2           first_elem = av_fetch((AV*) SvRV(params), 0, 0);
1802              
1803 2 50         if (first_elem && SvROK(*first_elem) &&
    50          
    50          
1804 2           SvTYPE(SvRV(*first_elem)) == SVt_PVHV) {
1805              
1806             hv = (HV*) SvRV(*first_elem);
1807             hv_set = 1;
1808             }
1809             }
1810              
1811 35 100         if (! hv_set) {
1812 33           hv = (HV*) sv_2mortal((SV*) newHV());
1813              
1814 33           PUTBACK;
1815 33           ok = convert_array2hash((AV*) SvRV(params), options, hv);
1816 33           SPAGAIN;
1817              
1818 33 50         if (!ok) {
1819 0           XSRETURN(0);
1820             }
1821             }
1822             }
1823             else {
1824 0           croak("Expecting array or hash reference in 'params'");
1825             }
1826              
1827 36 50         if (GIMME_V != G_VOID) {
    100          
1828 33           ret = (HV*) sv_2mortal((SV*) newHV());
1829             }
1830              
1831 36           PUTBACK;
1832 36           ok = validate(hv, (HV*) SvRV(spec), options, ret);
1833 27           SPAGAIN;
1834              
1835 27 50         if (! ok) {
1836 0           XSRETURN(0);
1837             }
1838              
1839 52 50         RETURN_HASH(ret);
    50          
    50          
    50          
    50          
    50          
    100          
    50          
1840             }
1841             else {
1842 0           croak("Expecting array or hash reference in 'spec'");
1843             }