View | Details | Raw Unified | Return to bug 14620
Collapse All | Expand All

(-)a/Koha/Validation.pm (+138 lines)
Line 0 Link Here
1
package Koha::Validation;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
23
use C4::Context;
24
use Email::Valid;
25
26
use vars qw($VERSION);
27
28
=head1 NAME
29
30
Koha::Validation - validates inputs
31
32
=head1 SYNOPSIS
33
34
  use Koha::Validation
35
36
=head1 DESCRIPTION
37
38
This module lets you validate given inputs.
39
40
=head2 validate_email
41
42
Validates given email.
43
44
  Koha::Validation::validate_email("email@address.com");
45
46
returns: 1 if the given email is valid, 0 otherwise.
47
48
=cut
49
50
sub validate_email {
51
52
    my $address = shift;
53
54
    # make sure we are allowed to validate emails
55
    return 1 if not C4::Context->preference("ValidateEmailAddress");
56
    return 1 if not $address;
57
    return 0 if $address =~ /(^(\s))|((\s)$)/;
58
    return (not defined Email::Valid->address($address)) ? 0:1;
59
}
60
61
=head2 validate_phonenumber
62
63
Validates given phone number.
64
65
  Koha::Validation::validate_phonenumber(123456789);
66
67
returns: 1 if the given phone number is valid, 0 otherwise.
68
69
=cut
70
71
sub validate_phonenumber {
72
    my $phonenumber = shift;
73
74
    # make sure we are allowed to validate phone numbers
75
    return 1 if C4::Context->preference("ValidatePhoneNumber") eq "OFF";
76
    return 1 if not $phonenumber;
77
    return 0 if $phonenumber =~ /(^(\s))|((\s)$)/;
78
79
    my $regex = get_phonenumber_regex(C4::Context->preference("ValidatePhoneNumber"));
80
    return ($phonenumber !~ /$regex/) ? 0:1;
81
}
82
83
=head2 get_phonenumber_regex
84
85
Returns the used regex (according to ValidatePhoneNumber system preference) for phone numbers.
86
This is used to share the same regex between Perl scripts and JavaScript in templates.
87
88
  Koha::Validation::get_phonenumber_regex();
89
90
International phone numbers (ipn): http://regexlib.com/REDetails.aspx?regexp_id=3009
91
92
returns: the regex
93
94
=cut
95
96
sub get_phonenumber_regex {
97
    if (C4::Context->preference("ValidatePhoneNumber") eq "ipn") {
98
        return qr/^((\+)?[1-9]{1,2})?([-\s\.])?((\(\d{1,4}\))|\d{1,4})(([-\s\.])?[0-9]{1,12}){1,2}$/;
99
    }
100
    elsif (C4::Context->preference("ValidatePhoneNumber") eq "fin") {
101
        return qr/^((90[0-9]{3})?0|\+358\s?)(?!(100|20(0|2(0|[2-3])|9[8-9])|300|600|700|708|75(00[0-3]|(1|2)\d{2}|30[0-2]|32[0-2]|75[0-2]|98[0-2])))(4|50|10[1-9]|20(1|2(1|[4-9])|[3-9])|29|30[1-9]|71|73|75(00[3-9]|30[3-9]|32[3-9]|53[3-9]|83[3-9])|2|3|5|6|8|9|1[3-9])\s?(\d\s?){4,19}\d$/;
102
    }
103
104
    return "";
105
  }
106
107
108
=head2 use_validator
109
110
Validates given input with given validator.
111
112
  Koha::Validation::use_validator("phone", 123456789);
113
  Koha::Validation::use_validator("email", "email@address.com");
114
115
Currently supported validators are
116
  email, e-mail
117
  phone, phonenumber
118
119
returns: 1 if the given input is valid with the given validator, 0 otherwise.
120
121
=cut
122
123
sub use_validator {
124
    my ($validator, $input) = @_;
125
126
    if (not defined $validator or not defined $input) {
127
        warn "Subroutine must be called with validator and input";
128
        return 0;
129
    }
130
131
    return validate_email($input) if $validator eq "email" or $validator eq "e-mail";
132
    return validate_phonenumber($input) if $validator eq "phone" or $validator eq "phonenumber";
133
134
    warn "Validator not found";
135
    return 0;
136
}
137
138
1;
(-)a/installer/data/mysql/atomicupdate/bug_14620_email_and_phone_validations.sql (+2 lines)
Line 0 Link Here
1
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('ValidatePhoneNumber','OFF','ipn|fin|new|OFF','Validation of phone number on patrons.','Choice');
2
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('ValidateEmailAddress','0','','Validation of email address on patrons.','YesNo');
(-)a/installer/data/mysql/sysprefs.sql (+2 lines)
Lines 489-494 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
489
('UseQueryParser','0',NULL,'If enabled, try to use QueryParser for queries.','YesNo'),
489
('UseQueryParser','0',NULL,'If enabled, try to use QueryParser for queries.','YesNo'),
490
('UseTransportCostMatrix','0','','Use Transport Cost Matrix when filling holds','YesNo'),
490
('UseTransportCostMatrix','0','','Use Transport Cost Matrix when filling holds','YesNo'),
491
('UseWYSIWYGinSystemPreferences','0','','Show WYSIWYG editor when editing certain HTML system preferences.','YesNo'),
491
('UseWYSIWYGinSystemPreferences','0','','Show WYSIWYG editor when editing certain HTML system preferences.','YesNo'),
492
('ValidateEmailAddress','0','','Validation of email address on patrons.','YesNo'),
493
('ValidatePhoneNumber','OFF','ipn|fin|new|OFF','Validation of phone number on patrons.','Choice'),
492
('viewISBD','1','','Allow display of ISBD view of bibiographic records','YesNo'),
494
('viewISBD','1','','Allow display of ISBD view of bibiographic records','YesNo'),
493
('viewLabeledMARC','0','','Allow display of labeled MARC view of bibiographic records','YesNo'),
495
('viewLabeledMARC','0','','Allow display of labeled MARC view of bibiographic records','YesNo'),
494
('viewMARC','1','','Allow display of MARC view of bibiographic records','YesNo'),
496
('viewMARC','1','','Allow display of MARC view of bibiographic records','YesNo'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref (+15 lines)
Lines 153-158 Patrons: Link Here
153
               yes: Do
153
               yes: Do
154
               no: "Don't"
154
               no: "Don't"
155
         - charge a fee when a patron changes to a category with an enrollment fee.
155
         - charge a fee when a patron changes to a category with an enrollment fee.
156
     -
157
         - Use validator
158
         - pref: ValidatePhoneNumber
159
           choices:
160
               ipn: International Phone Numbers
161
               fin: Finnish Phone Numbers
162
               new: ...Not yet implemented...
163
               "OFF": none
164
         - to validate phone numbers on patrons.
165
     -
166
         - pref: ValidateEmailAddress
167
           choices:
168
               yes: Enable
169
               no: Disable
170
         - validation of email addresses on patrons.
156
    "Norwegian patron database":
171
    "Norwegian patron database":
157
     -
172
     -
158
         - pref: NorwegianPatronDBEnable
173
         - pref: NorwegianPatronDBEnable
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt (+67 lines)
Lines 34-41 Link Here
34
            }
34
            }
35
        [% END %]
35
        [% END %]
36
        $("#dateofbirth").datepicker({ maxDate: "-1D" });
36
        $("#dateofbirth").datepicker({ maxDate: "-1D" });
37
38
        var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
39
        $.validator.addMethod('phone', function(value) {
40
            value = value.trim();
41
            if (!value.trim()) {
42
                return 1;
43
            }
44
            else {
45
                return (value.match(/[% phone_regex %]/));
46
            }
47
        },
48
        MSG_INCORRECT_PHONE);
49
37
        $("#entryform").validate({
50
        $("#entryform").validate({
38
            rules: {
51
            rules: {
52
                [% IF ( ValidatePhoneNumber ) %]
53
                phone: {
54
                    phone: true
55
                },
56
                phonepro: {
57
                    phone: true
58
                },
59
                mobile: {
60
                    phone: true
61
                },
62
                SMSnumber: {
63
                    phone: true
64
                },
65
                B_phone: {
66
                    phone: true
67
                }[% IF ( ValidateEmailAddress ) %],[% END %]
68
                [% END %]
69
                [% IF ( ValidateEmailAddress ) %]
39
                email: {
70
                email: {
40
                    email: true
71
                    email: true
41
                },
72
                },
Lines 45-50 Link Here
45
                B_email: {
76
                B_email: {
46
                    email: true
77
                    email: true
47
                }
78
                }
79
                [% END %]
48
            },
80
            },
49
            submitHandler: function(form) {
81
            submitHandler: function(form) {
50
                $("body, form input[type='submit'], form button[type='submit'], form a").addClass('waiting');
82
                $("body, form input[type='submit'], form button[type='submit'], form a").addClass('waiting');
Lines 52-61 Link Here
52
                    return false;
84
                    return false;
53
                else
85
                else
54
                    form.beenSubmitted = true;
86
                    form.beenSubmitted = true;
87
                    [% IF ValidateEmailAddress %]
88
                        $("#email, #emailpro, #B_email").each(function(){
89
                            $(this).val($.trim($(this).val()));
90
                        });
91
                    [% END %]
92
                    [% IF ValidatePhoneNumber %]
93
                        $("#phone, #phonepro, #B_phone, #SMSnumber").each(function(){
94
                            $(this).val($.trim($(this).val()));
95
                        });
96
                    [% END %]
55
                    form.submit();
97
                    form.submit();
56
                }
98
                }
57
        });
99
        });
58
100
101
        [% IF ValidateEmailAddress %]
102
        $("#email, #emailpro, #B_email").on("change", function(){
103
            $(this).val($.trim($(this).val()));
104
        });
105
        [% END %]
106
        [% IF ValidatePhoneNumber %]
107
        $("#SMSnumber").on("change", function(){
108
            $(this).val($.trim($(this).val()));
109
        });
110
        $("#phone, #phonepro, #B_phone").on("change", function(){
111
            $(this).val($.trim($(this).val()));
112
        });
113
        [% END %]
59
        var mrform = $("#manual_restriction_form");
114
        var mrform = $("#manual_restriction_form");
60
        var mrlink = $("#add_manual_restriction");
115
        var mrlink = $("#add_manual_restriction");
61
        mrform.hide();
116
        mrform.hide();
Lines 255-260 Link Here
255
            [% IF ERROR_bad_email_alternative %]
310
            [% IF ERROR_bad_email_alternative %]
256
                <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
311
                <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
257
            [% END %]
312
            [% END %]
313
            [% IF ERROR_bad_phone %]
314
                <li id="ERROR_bad_phone">The primary phone is invalid.</li>
315
            [% END %]
316
            [% IF ERROR_bad_phone_secondary %]
317
                <li id="ERROR_bad_phone_secondary">The secondary phone is invalid.</li>
318
            [% END %]
319
            [% IF ERROR_bad_phone_alternative %]
320
                <li id="ERROR_bad_phone_alternative">The alternative phone is invalid.</li>
321
            [% END %]
322
            [% IF ERROR_bad_smsnumber %]
323
                <li id="ERROR_bad_smsnumber">The SMS number is invalid.</li>
324
            [% END %]
258
			</ul>
325
			</ul>
259
		</div>
326
		</div>
260
	[% END %]
327
	[% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt (+49 lines)
Lines 60-65 Link Here
60
                                [% IF field == "email" %]<li>Contact information: <a href="#borrower_email">primary email address</a></li>[% END %]
60
                                [% IF field == "email" %]<li>Contact information: <a href="#borrower_email">primary email address</a></li>[% END %]
61
                                [% IF field == "emailpro" %]<li>Contact information: <a href="#borrower_emailpro">secondary email address</a></li>[% END %]
61
                                [% IF field == "emailpro" %]<li>Contact information: <a href="#borrower_emailpro">secondary email address</a></li>[% END %]
62
                                [% IF field == "B_email" %]<li>Alternate address information: <a href="#borrower_B_email">email address</a></li>[% END %]
62
                                [% IF field == "B_email" %]<li>Alternate address information: <a href="#borrower_B_email">email address</a></li>[% END %]
63
                                [% IF field == "phone" %]<li>Contact information: <a href="#borrower_phone">primary phone</a></li>[% END %]
64
                                [% IF field == "phonepro" %]<li>Contact information: <a href="#borrower_phonepro">secondary phone</a></li>[% END %]
65
                                [% IF field == "mobile" %]<li>Contact information: <a href="#borrower_mobile">other phone</a></li>[% END %]
66
                                [% IF field == "B_phone" %]<li>Alternate address information: <a href="#borrower_B_phone">phone</a></li>[% END %]
63
                            [% END %]
67
                            [% END %]
64
                        </ul>
68
                        </ul>
65
                        Please correct the errors and resubmit.
69
                        Please correct the errors and resubmit.
Lines 822-829 Link Here
822
            [% ELSE %]
826
            [% ELSE %]
823
                $( "#borrower_dateofbirth" ).datepicker({ yearRange: "c-120:c" });
827
                $( "#borrower_dateofbirth" ).datepicker({ yearRange: "c-120:c" });
824
            [% END %]
828
            [% END %]
829
            var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
830
            $.validator.addMethod('phone', function(value) {
831
                if (!value.trim()) {
832
                    return 1;
833
                }
834
                else {
835
                    return (value.match(/[% phone_regex %]/));
836
                }
837
            },
838
            MSG_INCORRECT_PHONE);
825
            $("#memberentry-form").validate({
839
            $("#memberentry-form").validate({
826
                rules: {
840
                rules: {
841
                    [% IF ( ValidateEmailAddress ) %]
827
                    borrower_email: {
842
                    borrower_email: {
828
                        email: true
843
                        email: true
829
                    },
844
                    },
Lines 832-838 Link Here
832
                    },
847
                    },
833
                    borrower_B_email: {
848
                    borrower_B_email: {
834
                        email: true
849
                        email: true
850
                    }[% IF ( ValidatePhoneNumber ) %],[% END %]
851
                    [% END %]
852
                    [% IF ( ValidatePhoneNumber ) %]
853
                    borrower_phone: {
854
                        phone: true
855
                    },
856
                    borrower_phonepro: {
857
                        phone: true
858
                    },
859
                    borrower_mobile: {
860
                        phone: true
861
                    },
862
                    SMSnumber: {
863
                        phone: true
864
                    },
865
                    borrower_B_phone: {
866
                        phone: true
835
                    }
867
                    }
868
                    [% END %]
836
                },
869
                },
837
                submitHandler: function(form) {
870
                submitHandler: function(form) {
838
                    if (form.beenSubmitted) {
871
                    if (form.beenSubmitted) {
Lines 840-845 Link Here
840
                    }
873
                    }
841
                    else {
874
                    else {
842
                        form.beenSubmitted = true;
875
                        form.beenSubmitted = true;
876
                        [% IF ValidateEmailAddress %]
877
                        $("#borrower_email, #borrower_emailpro, #borrower_B_email").each(function(){
878
                            $(this).val($.trim($(this).val()));
879
                        });
880
                        [% END %]
881
                        [% IF ValidatePhoneNumber %]
882
                        $("#borrower_phone, #borrower_phonepro, #borrower_B_phone, #SMSnumber").each(function(){
883
                            $(this).val($.trim($(this).val()));
884
                        });
885
                        [% END %]
843
                        form.submit();
886
                        form.submit();
844
                    }
887
                    }
845
                },
888
                },
Lines 853-858 Link Here
853
                    error.css('width', 'auto');
896
                    error.css('width', 'auto');
854
                }
897
                }
855
            });
898
            });
899
            $("#borrower_email, #borrower_emailpro, #borrower_B_email").on("change", function(){
900
                $(this).val($.trim($(this).val()));
901
            });
902
            $("#borrower_phone, #borrower_phonepro, #borrower_B_phone").on("change", function(){
903
                $(this).val($.trim($(this).val()));
904
            });
856
        });
905
        });
857
    //]]>
906
    //]]>
858
    </script>
907
    </script>
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt (+56 lines)
Lines 149-155 Link Here
149
      }
149
      }
150
    });
150
    });
151
    $("#info_digests").tooltip();
151
    $("#info_digests").tooltip();
152
    var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
153
154
    $("fieldset.rows input, fieldset.rows select").addClass("noEnterSubmit");
155
156
    var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
157
    $.validator.addMethod('phone', function(value) {
158
        if (!value.trim()) {
159
            return 1;
160
        }
161
        else {
162
            return (value.match(/[% phone_regex %]/));
163
        }
164
    },
165
    MSG_INCORRECT_PHONE);
166
167
    $("form[name='opacmessaging']").validate({
168
        rules: {
169
            [% IF ( ValidatePhoneNumber ) %]
170
            SMSnumber: {
171
                phone: true
172
            }
173
            [% END %]
174
        },
175
        submitHandler: function(form) {
176
            $("body, form input[type='submit'], form button[type='submit'], form a").addClass('waiting');
177
            if (form.beenSubmitted) {
178
                return false;
179
            }
180
            else {
181
                form.beenSubmitted = true;
182
                [% IF ValidatePhoneNumber %]
183
                    $("#SMSnumber").each(function(){
184
                        $(this).val($.trim($(this).val()));
185
                    });
186
                [% END %]
187
                form.submit();
188
            }
189
        },
190
        errorPlacement: function(error, element) {
191
            offset = element.offset();
192
            error.insertAfter(element)
193
            error.addClass('error');  // add a class to the wrapper
194
            error.css('position', 'absolute');
195
            error.css('left', offset.left + element.outerWidth() + 10);
196
            error.css('top', offset.top);
197
            error.css('width', 'auto');
198
        }
199
    });
200
201
    [% IF ( ValidatePhoneNumber ) %]
202
    $("#SMSnumber").on("change", function(){
203
            $(this).val($.trim($(this).val()));
204
    });
205
    [% END %]
206
152
  });
207
  });
153
//]]>
208
//]]>
154
</script>
209
</script>
210
<script type="text/javascript" src="/opac-tmpl/bootstrap/lib/jquery/plugins/jquery.validate.min.js"></script>
155
[% END %]
211
[% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/lib/bootstrap/css/bootstrap.css (+24 lines)
Lines 6305-6307 button.close { Link Here
6305
    overflow: visible !important;
6305
    overflow: visible !important;
6306
  }
6306
  }
6307
}
6307
}
6308
.lang_icon {
6309
  padding-right: 5px;
6310
  vertical-align: baseline;
6311
  height: 11px;
6312
}
6313
#memberentry-form input.error,
6314
form[name=opacmessaging] input.error {
6315
  border-color: #c00;
6316
  box-shadow: 0 1px 1px #c00 inset, 0 0 8px #c00;
6317
  color: red; outline: 0 none;
6318
}
6319
#memberentry-form input.error:focus,
6320
form[name=opacmessaging] input.error:focus {
6321
  border-color: #c00;
6322
  box-shadow: 0 1px 1px #c00 inset, 0 0 8px #c00;
6323
  color: red;
6324
  outline: 0 none;
6325
}
6326
#memberentry-form label.error,
6327
form[name=opacmessaging] label.error {
6328
  color: #c00;
6329
  float: none;
6330
  font-size: 90%;
6331
}
(-)a/koha-tmpl/opac-tmpl/bootstrap/lib/bootstrap/css/bootstrap.min.css (-1 / +1 lines)
Lines 870-873 button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-ap Link Here
870
.hidden-desktop{display:none !important;}
870
.hidden-desktop{display:none !important;}
871
.visible-desktop{display:inherit !important;}
871
.visible-desktop{display:inherit !important;}
872
@media (min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important ;} .visible-tablet{display:inherit !important;} .hidden-tablet{display:none !important;}}@media (max-width:767px){.hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important;} .visible-phone{display:inherit !important;} .hidden-phone{display:none !important;}}.visible-print{display:none !important;}
872
@media (min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important ;} .visible-tablet{display:inherit !important;} .hidden-tablet{display:none !important;}}@media (max-width:767px){.hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important;} .visible-phone{display:inherit !important;} .hidden-phone{display:none !important;}}.visible-print{display:none !important;}
873
@media print{.visible-print{display:inherit !important;} .hidden-print{display:none !important;}}@media (max-width:767px){body{padding-left:20px;padding-right:20px;} .navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-left:-20px;margin-right:-20px;} .container-fluid{padding:0;} .dl-horizontal dt{float:none;clear:none;width:auto;text-align:left;} .dl-horizontal dd{margin-left:0;} .container{width:auto;} .row-fluid{width:100%;} .row,.thumbnails{margin-left:0;} .thumbnails>li{float:none;margin-left:0;} [class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{float:none;display:block;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .row-fluid [class*="offset"]:first-child{margin-left:0;} .input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto;} .controls-row [class*="span"]+[class*="span"]{margin-left:0;} .modal{position:fixed;top:20px;left:20px;right:20px;width:auto;margin:0;}.modal.fade{top:-100px;} .modal.fade.in{top:20px;}}@media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0);} .page-header h1 small{display:block;line-height:20px;} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc;} .form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-left:10px;padding-right:10px;} .media .pull-left,.media .pull-right{float:none;display:block;margin-bottom:10px;} .media-object{margin-right:0;margin-left:0;} .modal{top:10px;left:10px;right:10px;} .modal-header .close{padding:10px;margin:-10px;} .carousel-caption{position:static;}}@media (min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;} .row:after{clear:both;} [class*="span"]{float:left;min-height:1px;margin-left:20px;} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px;} .span12{width:724px;} .span11{width:662px;} .span10{width:600px;} .span9{width:538px;} .span8{width:476px;} .span7{width:414px;} .span6{width:352px;} .span5{width:290px;} .span4{width:228px;} .span3{width:166px;} .span2{width:104px;} .span1{width:42px;} .offset12{margin-left:764px;} .offset11{margin-left:702px;} .offset10{margin-left:640px;} .offset9{margin-left:578px;} .offset8{margin-left:516px;} .offset7{margin-left:454px;} .offset6{margin-left:392px;} .offset5{margin-left:330px;} .offset4{margin-left:268px;} .offset3{margin-left:206px;} .offset2{margin-left:144px;} .offset1{margin-left:82px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%;} .row-fluid .span12{width:100%;*width:99.94680851063829%;} .row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%;} .row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%;} .row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%;} .row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%;} .row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%;} .row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%;} .row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%;} .row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%;} .row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%;} .row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%;} .row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%;} .row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%;} .row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%;} .row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%;} .row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%;} .row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%;} .row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%;} .row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%;} .row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%;} .row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%;} .row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%;} .row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%;} .row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%;} .row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%;} .row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%;} .row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%;} .row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%;} .row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%;} .row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%;} .row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%;} .row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%;} .row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%;} .row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%;} .row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%;} .row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%;} input,textarea,.uneditable-input{margin-left:0;} .controls-row [class*="span"]+[class*="span"]{margin-left:20px;} input.span12,textarea.span12,.uneditable-input.span12{width:710px;} input.span11,textarea.span11,.uneditable-input.span11{width:648px;} input.span10,textarea.span10,.uneditable-input.span10{width:586px;} input.span9,textarea.span9,.uneditable-input.span9{width:524px;} input.span8,textarea.span8,.uneditable-input.span8{width:462px;} input.span7,textarea.span7,.uneditable-input.span7{width:400px;} input.span6,textarea.span6,.uneditable-input.span6{width:338px;} input.span5,textarea.span5,.uneditable-input.span5{width:276px;} input.span4,textarea.span4,.uneditable-input.span4{width:214px;} input.span3,textarea.span3,.uneditable-input.span3{width:152px;} input.span2,textarea.span2,.uneditable-input.span2{width:90px;} input.span1,textarea.span1,.uneditable-input.span1{width:28px;}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;} .row:after{clear:both;} [class*="span"]{float:left;min-height:1px;margin-left:30px;} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px;} .span12{width:1170px;} .span11{width:1070px;} .span10{width:970px;} .span9{width:870px;} .span8{width:770px;} .span7{width:670px;} .span6{width:570px;} .span5{width:470px;} .span4{width:370px;} .span3{width:270px;} .span2{width:170px;} .span1{width:70px;} .offset12{margin-left:1230px;} .offset11{margin-left:1130px;} .offset10{margin-left:1030px;} .offset9{margin-left:930px;} .offset8{margin-left:830px;} .offset7{margin-left:730px;} .offset6{margin-left:630px;} .offset5{margin-left:530px;} .offset4{margin-left:430px;} .offset3{margin-left:330px;} .offset2{margin-left:230px;} .offset1{margin-left:130px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%;} .row-fluid .span12{width:100%;*width:99.94680851063829%;} .row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%;} .row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%;} .row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%;} .row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%;} .row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%;} .row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%;} .row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%;} .row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%;} .row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%;} .row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%;} .row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%;} .row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%;} .row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%;} .row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%;} .row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%;} .row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%;} .row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%;} .row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%;} .row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%;} .row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%;} .row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%;} .row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%;} .row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%;} .row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%;} .row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%;} .row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%;} .row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%;} .row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%;} .row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%;} .row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%;} .row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%;} .row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%;} .row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%;} .row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%;} .row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%;} input,textarea,.uneditable-input{margin-left:0;} .controls-row [class*="span"]+[class*="span"]{margin-left:30px;} input.span12,textarea.span12,.uneditable-input.span12{width:1156px;} input.span11,textarea.span11,.uneditable-input.span11{width:1056px;} input.span10,textarea.span10,.uneditable-input.span10{width:956px;} input.span9,textarea.span9,.uneditable-input.span9{width:856px;} input.span8,textarea.span8,.uneditable-input.span8{width:756px;} input.span7,textarea.span7,.uneditable-input.span7{width:656px;} input.span6,textarea.span6,.uneditable-input.span6{width:556px;} input.span5,textarea.span5,.uneditable-input.span5{width:456px;} input.span4,textarea.span4,.uneditable-input.span4{width:356px;} input.span3,textarea.span3,.uneditable-input.span3{width:256px;} input.span2,textarea.span2,.uneditable-input.span2{width:156px;} input.span1,textarea.span1,.uneditable-input.span1{width:56px;} .thumbnails{margin-left:-30px;} .thumbnails>li{margin-left:30px;} .row-fluid .thumbnails{margin-left:0;}}@media (max-width:979px){body{padding-top:0;} .navbar-fixed-top,.navbar-fixed-bottom{position:static;} .navbar-fixed-top{margin-bottom:20px;} .navbar-fixed-bottom{margin-top:20px;} .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px;} .navbar .container{width:auto;padding:0;} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px;} .nav-collapse{clear:both;} .nav-collapse .nav{float:none;margin:0 0 10px;} .nav-collapse .nav>li{float:none;} .nav-collapse .nav>li>a{margin-bottom:2px;} .nav-collapse .nav>.divider-vertical{display:none;} .nav-collapse .nav .nav-header{color:#777777;text-shadow:none;} .nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .nav-collapse .dropdown-menu li+li a{margin-bottom:2px;} .nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2;} .navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999999;} .navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111111;} .nav-collapse.in .btn-group{margin-top:5px;padding:0;} .nav-collapse .dropdown-menu{position:static;top:auto;left:auto;float:none;display:none;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .nav-collapse .open>.dropdown-menu{display:block;} .nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none;} .nav-collapse .dropdown-menu .divider{display:none;} .nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none;} .nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);} .navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111111;border-bottom-color:#111111;} .navbar .nav-collapse .nav.pull-right{float:none;margin-left:0;} .nav-collapse,.nav-collapse.collapse{overflow:hidden;height:0;} .navbar .btn-navbar{display:block;} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px;}}@media (min-width:980px){.nav-collapse.collapse{height:auto !important;overflow:visible !important;}}
873
@media print{.visible-print{display:inherit !important;} .hidden-print{display:none !important;}}@media (max-width:767px){body{padding-left:20px;padding-right:20px;} .navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-left:-20px;margin-right:-20px;} .container-fluid{padding:0;} .dl-horizontal dt{float:none;clear:none;width:auto;text-align:left;} .dl-horizontal dd{margin-left:0;} .container{width:auto;} .row-fluid{width:100%;} .row,.thumbnails{margin-left:0;} .thumbnails>li{float:none;margin-left:0;} [class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{float:none;display:block;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .row-fluid [class*="offset"]:first-child{margin-left:0;} .input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto;} .controls-row [class*="span"]+[class*="span"]{margin-left:0;} .modal{position:fixed;top:20px;left:20px;right:20px;width:auto;margin:0;}.modal.fade{top:-100px;} .modal.fade.in{top:20px;}}@media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0);} .page-header h1 small{display:block;line-height:20px;} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc;} .form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-left:10px;padding-right:10px;} .media .pull-left,.media .pull-right{float:none;display:block;margin-bottom:10px;} .media-object{margin-right:0;margin-left:0;} .modal{top:10px;left:10px;right:10px;} .modal-header .close{padding:10px;margin:-10px;} .carousel-caption{position:static;}}@media (min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;} .row:after{clear:both;} [class*="span"]{float:left;min-height:1px;margin-left:20px;} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px;} .span12{width:724px;} .span11{width:662px;} .span10{width:600px;} .span9{width:538px;} .span8{width:476px;} .span7{width:414px;} .span6{width:352px;} .span5{width:290px;} .span4{width:228px;} .span3{width:166px;} .span2{width:104px;} .span1{width:42px;} .offset12{margin-left:764px;} .offset11{margin-left:702px;} .offset10{margin-left:640px;} .offset9{margin-left:578px;} .offset8{margin-left:516px;} .offset7{margin-left:454px;} .offset6{margin-left:392px;} .offset5{margin-left:330px;} .offset4{margin-left:268px;} .offset3{margin-left:206px;} .offset2{margin-left:144px;} .offset1{margin-left:82px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%;} .row-fluid .span12{width:100%;*width:99.94680851063829%;} .row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%;} .row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%;} .row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%;} .row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%;} .row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%;} .row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%;} .row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%;} .row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%;} .row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%;} .row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%;} .row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%;} .row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%;} .row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%;} .row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%;} .row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%;} .row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%;} .row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%;} .row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%;} .row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%;} .row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%;} .row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%;} .row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%;} .row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%;} .row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%;} .row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%;} .row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%;} .row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%;} .row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%;} .row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%;} .row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%;} .row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%;} .row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%;} .row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%;} .row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%;} .row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%;} input,textarea,.uneditable-input{margin-left:0;} .controls-row [class*="span"]+[class*="span"]{margin-left:20px;} input.span12,textarea.span12,.uneditable-input.span12{width:710px;} input.span11,textarea.span11,.uneditable-input.span11{width:648px;} input.span10,textarea.span10,.uneditable-input.span10{width:586px;} input.span9,textarea.span9,.uneditable-input.span9{width:524px;} input.span8,textarea.span8,.uneditable-input.span8{width:462px;} input.span7,textarea.span7,.uneditable-input.span7{width:400px;} input.span6,textarea.span6,.uneditable-input.span6{width:338px;} input.span5,textarea.span5,.uneditable-input.span5{width:276px;} input.span4,textarea.span4,.uneditable-input.span4{width:214px;} input.span3,textarea.span3,.uneditable-input.span3{width:152px;} input.span2,textarea.span2,.uneditable-input.span2{width:90px;} input.span1,textarea.span1,.uneditable-input.span1{width:28px;}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;} .row:after{clear:both;} [class*="span"]{float:left;min-height:1px;margin-left:30px;} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px;} .span12{width:1170px;} .span11{width:1070px;} .span10{width:970px;} .span9{width:870px;} .span8{width:770px;} .span7{width:670px;} .span6{width:570px;} .span5{width:470px;} .span4{width:370px;} .span3{width:270px;} .span2{width:170px;} .span1{width:70px;} .offset12{margin-left:1230px;} .offset11{margin-left:1130px;} .offset10{margin-left:1030px;} .offset9{margin-left:930px;} .offset8{margin-left:830px;} .offset7{margin-left:730px;} .offset6{margin-left:630px;} .offset5{margin-left:530px;} .offset4{margin-left:430px;} .offset3{margin-left:330px;} .offset2{margin-left:230px;} .offset1{margin-left:130px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%;} .row-fluid .span12{width:100%;*width:99.94680851063829%;} .row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%;} .row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%;} .row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%;} .row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%;} .row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%;} .row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%;} .row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%;} .row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%;} .row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%;} .row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%;} .row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%;} .row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%;} .row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%;} .row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%;} .row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%;} .row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%;} .row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%;} .row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%;} .row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%;} .row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%;} .row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%;} .row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%;} .row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%;} .row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%;} .row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%;} .row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%;} .row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%;} .row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%;} .row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%;} .row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%;} .row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%;} .row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%;} .row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%;} .row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%;} .row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%;} input,textarea,.uneditable-input{margin-left:0;} .controls-row [class*="span"]+[class*="span"]{margin-left:30px;} input.span12,textarea.span12,.uneditable-input.span12{width:1156px;} input.span11,textarea.span11,.uneditable-input.span11{width:1056px;} input.span10,textarea.span10,.uneditable-input.span10{width:956px;} input.span9,textarea.span9,.uneditable-input.span9{width:856px;} input.span8,textarea.span8,.uneditable-input.span8{width:756px;} input.span7,textarea.span7,.uneditable-input.span7{width:656px;} input.span6,textarea.span6,.uneditable-input.span6{width:556px;} input.span5,textarea.span5,.uneditable-input.span5{width:456px;} input.span4,textarea.span4,.uneditable-input.span4{width:356px;} input.span3,textarea.span3,.uneditable-input.span3{width:256px;} input.span2,textarea.span2,.uneditable-input.span2{width:156px;} input.span1,textarea.span1,.uneditable-input.span1{width:56px;} .thumbnails{margin-left:-30px;} .thumbnails>li{margin-left:30px;} .row-fluid .thumbnails{margin-left:0;}}@media (max-width:979px){body{padding-top:0;} .navbar-fixed-top,.navbar-fixed-bottom{position:static;} .navbar-fixed-top{margin-bottom:20px;} .navbar-fixed-bottom{margin-top:20px;} .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px;} .navbar .container{width:auto;padding:0;} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px;} .nav-collapse{clear:both;} .nav-collapse .nav{float:none;margin:0 0 10px;} .nav-collapse .nav>li{float:none;} .nav-collapse .nav>li>a{margin-bottom:2px;} .nav-collapse .nav>.divider-vertical{display:none;} .nav-collapse .nav .nav-header{color:#777777;text-shadow:none;} .nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .nav-collapse .dropdown-menu li+li a{margin-bottom:2px;} .nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2;} .navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999999;} .navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111111;} .nav-collapse.in .btn-group{margin-top:5px;padding:0;} .nav-collapse .dropdown-menu{position:static;top:auto;left:auto;float:none;display:none;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .nav-collapse .open>.dropdown-menu{display:block;} .nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none;} .nav-collapse .dropdown-menu .divider{display:none;} .nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none;} .nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);} .navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111111;border-bottom-color:#111111;} .navbar .nav-collapse .nav.pull-right{float:none;margin-left:0;} .nav-collapse,.nav-collapse.collapse{overflow:hidden;height:0;} .navbar .btn-navbar{display:block;} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px;}}@media (min-width:980px){.nav-collapse.collapse{height:auto !important;overflow:visible !important;}} #memberentry-form input.error, form[name=opacmessaging] input.error {border-color: #c00; box-shadow: 0 1px 1px #c00 inset, 0 0 8px #c00; color: red; outline: 0 none;} #memberentry-form input.error:focus, form[name=opacmessaging] input.error:focus {border-color: #c00; box-shadow: 0 1px 1px #c00 inset, 0 0 8px #c00; color: red; outline: 0 none;} #memberentry-form label.error, form[name=opacmessaging] label.error {color: #c00; float: none; font-size: 90%;}
(-)a/members/memberentry.pl (-16 / +21 lines)
Lines 41-52 use C4::Branch; # GetBranches Link Here
41
use C4::Form::MessagingPreferences;
41
use C4::Form::MessagingPreferences;
42
use Koha::Borrower::Debarments;
42
use Koha::Borrower::Debarments;
43
use Koha::DateUtils;
43
use Koha::DateUtils;
44
use Email::Valid;
44
use Koha::Validation;
45
use Module::Load;
45
use Module::Load;
46
if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) {
46
if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) {
47
    load Koha::NorwegianPatronDB, qw( NLGetSyncDataFromBorrowernumber );
47
    load Koha::NorwegianPatronDB, qw( NLGetSyncDataFromBorrowernumber );
48
}
48
}
49
49
50
use re 'regexp_pattern';
50
use vars qw($debug);
51
use vars qw($debug);
51
52
52
BEGIN {
53
BEGIN {
Lines 324-343 if ($op eq 'save' || $op eq 'insert'){ Link Here
324
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
325
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
325
  push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) );
326
  push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) );
326
327
327
  # Validate emails
328
  # validate emails
328
  my $emailprimary = $input->param('email');
329
  push (@errors, "ERROR_bad_email") if ($input->param('email') && !Koha::Validation::validate_email($input->param('email')));
329
  my $emailsecondary = $input->param('emailpro');
330
  push (@errors, "ERROR_bad_email_secondary") if ($input->param('emailpro') && !Koha::Validation::validate_email($input->param('emailpro')));
330
  my $emailalt = $input->param('B_email');
331
  push (@errors, "ERROR_bad_email_alternative") if ($input->param('B_email') && !Koha::Validation::validate_email($input->param('B_email')));
331
332
  # validate phone numbers
332
  if ($emailprimary) {
333
  push (@errors, "ERROR_bad_phone") if ($input->param('phone') && !Koha::Validation::validate_phonenumber($input->param('phone')));
333
      push (@errors, "ERROR_bad_email") if (!Email::Valid->address($emailprimary));
334
  push (@errors, "ERROR_bad_phone_secondary") if ($input->param('phonepro') && !Koha::Validation::validate_phonenumber($input->param('phonepro')));
334
  }
335
  push (@errors, "ERROR_bad_phone_alternative") if ($input->param('B_phone') && !Koha::Validation::validate_phonenumber($input->param('B_phone')));
335
  if ($emailsecondary) {
336
      push (@errors, "ERROR_bad_email_secondary") if (!Email::Valid->address($emailsecondary));
337
  }
338
  if ($emailalt) {
339
      push (@errors, "ERROR_bad_email_alternative") if (!Email::Valid->address($emailalt));
340
  }
341
336
342
  if (C4::Context->preference('ExtendedPatronAttributes')) {
337
  if (C4::Context->preference('ExtendedPatronAttributes')) {
343
    $extended_patron_attributes = parse_extended_patron_attributes($input);
338
    $extended_patron_attributes = parse_extended_patron_attributes($input);
Lines 365-371 if ( ($op eq 'modify' || $op eq 'insert' || $op eq 'save'|| $op eq 'duplicate') Link Here
365
# BZ 14683: Do not mixup mobile [read: other phone] with smsalertnumber
360
# BZ 14683: Do not mixup mobile [read: other phone] with smsalertnumber
366
my $sms = $input->param('SMSnumber');
361
my $sms = $input->param('SMSnumber');
367
if ( defined $sms ) {
362
if ( defined $sms ) {
368
    $newdata{smsalertnumber} = $sms;
363
    if (Koha::Validation::validate_phonenumber($sms)){
364
        $newdata{smsalertnumber} = $sms;
365
    } else {
366
        push (@errors, "ERROR_bad_smsnumber");
367
    }
369
}
368
}
370
369
371
###  Error checks should happen before this line.
370
###  Error checks should happen before this line.
Lines 663-668 if (C4::Context->preference('ExtendedPatronAttributes')) { Link Here
663
    patron_attributes_form($template, $borrowernumber);
662
    patron_attributes_form($template, $borrowernumber);
664
}
663
}
665
664
665
$template->param(
666
        ValidateEmailAddress => C4::Context->preference('ValidateEmailAddress'),
667
        ValidatePhoneNumber => C4::Context->preference('ValidatePhoneNumber') ne "OFF",
668
        phone_regex => regexp_pattern Koha::Validation::get_phonenumber_regex()
669
);
670
666
if (C4::Context->preference('EnhancedMessagingPreferences')) {
671
if (C4::Context->preference('EnhancedMessagingPreferences')) {
667
    if ($op eq 'add') {
672
    if ($op eq 'add') {
668
        C4::Form::MessagingPreferences::set_form_values({ categorycode => $categorycode }, $template);
673
        C4::Form::MessagingPreferences::set_form_values({ categorycode => $categorycode }, $template);
(-)a/opac/opac-memberentry.pl (-3 / +21 lines)
Lines 30-35 use C4::Branch qw(GetBranchesLoop); Link Here
30
use C4::Scrubber;
30
use C4::Scrubber;
31
use Email::Valid;
31
use Email::Valid;
32
use Koha::DateUtils;
32
use Koha::DateUtils;
33
use Koha::Validation;
34
35
use re 'regexp_pattern';
33
36
34
my $cgi = new CGI;
37
my $cgi = new CGI;
35
my $dbh = C4::Context->dbh;
38
my $dbh = C4::Context->dbh;
Lines 69-74 $template->param( Link Here
69
    member_titles     => GetTitles() || undef,
72
    member_titles     => GetTitles() || undef,
70
    branches          => GetBranchesLoop(),
73
    branches          => GetBranchesLoop(),
71
    OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
74
    OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
75
    ValidateEmailAddress   => C4::Context->preference('ValidateEmailAddress'),
76
    ValidatePhoneNumber    => (C4::Context->preference('ValidatePhoneNumber') ne "OFF"),
77
    phone_regex            => regexp_pattern Koha::Validation::get_phonenumber_regex()
72
);
78
);
73
79
74
if ( $action eq 'create' ) {
80
if ( $action eq 'create' ) {
Lines 308-320 sub CheckForInvalidFields { Link Here
308
    my $borrower = shift;
314
    my $borrower = shift;
309
    my @invalidFields;
315
    my @invalidFields;
310
    if ($borrower->{'email'}) {
316
    if ($borrower->{'email'}) {
311
        push(@invalidFields, "email") if (!Email::Valid->address($borrower->{'email'}));
317
        push(@invalidFields, "email") if (!Koha::Validation::validate_email($borrower->{'email'}));
312
    }
318
    }
313
    if ($borrower->{'emailpro'}) {
319
    if ($borrower->{'emailpro'}) {
314
        push(@invalidFields, "emailpro") if (!Email::Valid->address($borrower->{'emailpro'}));
320
        push(@invalidFields, "emailpro") if (!Koha::Validation::validate_email($borrower->{'emailpro'}));
315
    }
321
    }
316
    if ($borrower->{'B_email'}) {
322
    if ($borrower->{'B_email'}) {
317
        push(@invalidFields, "B_email") if (!Email::Valid->address($borrower->{'B_email'}));
323
        push(@invalidFields, "B_email") if (!Koha::Validation::validate_email($borrower->{'B_email'}));
324
    }
325
    if ($borrower->{'mobile'}) {
326
        push(@invalidFields, "mobile") if (!Koha::Validation::validate_phonenumber($borrower->{'mobile'}));
327
    }
328
    if ($borrower->{'phone'}) {
329
        push(@invalidFields, "phone") if (!Koha::Validation::validate_phonenumber($borrower->{'phone'}));
330
    }
331
    if ($borrower->{'phonepro'}) {
332
        push(@invalidFields, "phonepro") if (!Koha::Validation::validate_phonenumber($borrower->{'phonepro'}));
333
    }
334
    if ($borrower->{'B_phone'}) {
335
        push(@invalidFields, "B_phone") if (!Koha::Validation::validate_phonenumber($borrower->{'B_phone'}));
318
    }
336
    }
319
    return \@invalidFields;
337
    return \@invalidFields;
320
}
338
}
(-)a/opac/opac-messaging.pl (-1 / +13 lines)
Lines 31-36 use C4::Members; Link Here
31
use C4::Members::Messaging;
31
use C4::Members::Messaging;
32
use C4::Branch;
32
use C4::Branch;
33
use C4::Form::MessagingPreferences;
33
use C4::Form::MessagingPreferences;
34
use Koha::Validation;
35
36
use re 'regexp_pattern';
34
37
35
my $query = CGI->new();
38
my $query = CGI->new();
36
39
Lines 47-57 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
47
my $borrower = GetMemberDetails( $borrowernumber );
50
my $borrower = GetMemberDetails( $borrowernumber );
48
my $messaging_options = C4::Members::Messaging::GetMessagingOptions();
51
my $messaging_options = C4::Members::Messaging::GetMessagingOptions();
49
52
53
$template->param(
54
        ValidateEmailAddress   => C4::Context->preference('ValidateEmailAddress'),
55
        ValidatePhoneNumber    => (C4::Context->preference('ValidatePhoneNumber') ne "OFF"),
56
        phone_regex            => regexp_pattern Koha::Validation::get_phonenumber_regex()
57
);
50
if ( defined $query->param('modify') && $query->param('modify') eq 'yes' ) {
58
if ( defined $query->param('modify') && $query->param('modify') eq 'yes' ) {
51
    my $sms = $query->param('SMSnumber');
59
    my $sms = $query->param('SMSnumber');
52
    if ( defined $sms && ( $borrower->{'smsalertnumber'} // '' ) ne $sms ) {
60
    if ( defined $sms && ( $borrower->{'smsalertnumber'} // '' ) ne $sms ) {
61
62
        my $valid_smsnumber = Koha::Validation::validate_phonenumber($sms);
63
        $template->param( invalid_smsnumber => $valid_smsnumber );
64
53
        ModMember( borrowernumber => $borrowernumber,
65
        ModMember( borrowernumber => $borrowernumber,
54
                   smsalertnumber => $sms );
66
                   smsalertnumber => $sms ) if $valid_smsnumber;
55
        $borrower = GetMemberDetails( $borrowernumber );
67
        $borrower = GetMemberDetails( $borrowernumber );
56
    }
68
    }
57
69
(-)a/t/db_dependent/Validations.t (-1 / +184 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
$ENV{KOHA_PAGEOBJECT_DEBUG} = 1;
20
use Modern::Perl;
21
22
use Test::More;
23
use Try::Tiny; #Even Selenium::Remote::Driver uses Try::Tiny :)
24
25
use Koha::Auth::PermissionManager;
26
27
use t::lib::Page::Mainpage;
28
use t::lib::Page::Opac::OpacMain;
29
use t::lib::Page::Opac::OpacMemberentry;
30
use t::lib::Page::Members::Memberentry;
31
use t::lib::Page::Members::Moremember;
32
33
use t::lib::TestObjects::BorrowerFactory;
34
use t::lib::TestObjects::SystemPreferenceFactory;
35
36
##Setting up the test context
37
my $testContext = {};
38
39
my $password = '1234';
40
my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new();
41
my $borrowers = $borrowerFactory->createTestGroup([
42
            {firstname  => 'Testone',
43
             surname    => 'Testtwo',
44
             cardnumber => '1A01',
45
             branchcode => 'CPL',
46
             userid     => 'normal_user',
47
             password   => $password,
48
            },
49
            {firstname  => 'Testthree',
50
             surname    => 'Testfour',
51
             cardnumber => 'superuberadmin',
52
             branchcode => 'CPL',
53
             userid     => 'god',
54
             password   => $password,
55
            },
56
        ], undef, $testContext);
57
58
my $systempreferences = t::lib::TestObjects::SystemPreferenceFactory->createTestGroup([
59
            {preference => 'ValidateEmailAddress',
60
             value      => 1
61
            },
62
            {preference => 'ValidatePhoneNumber',
63
             value      => 'ipn',
64
            },
65
        ], undef, $testContext);
66
67
my $permissionManager = Koha::Auth::PermissionManager->new();
68
$permissionManager->grantPermissions($borrowers->{'superuberadmin'}, {superlibrarian => 'superlibrarian'});
69
70
eval {
71
    OpacValidations();
72
    StaffValidations();
73
};
74
75
if ($@) { #Catch all leaking errors and gracefully terminate.
76
    warn $@;
77
    tearDown();
78
    exit 1;
79
}
80
81
##All tests done, tear down test context
82
tearDown();
83
done_testing;
84
85
sub tearDown {
86
    t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext);
87
}
88
89
90
91
92
93
94
95
96
######################################################
97
    ###  STARTING TEST IMPLEMENTATIONS         ###
98
######################################################
99
sub setValidationsOff {
100
    C4::Context->set_preference('ValidateEmailAddress', 0);
101
    C4::Context->set_preference('ValidatePhoneNumber', 'OFF');
102
}
103
sub setValidationsOn {
104
    C4::Context->set_preference('ValidateEmailAddress', 1);
105
    C4::Context->set_preference('ValidatePhoneNumber', 'ipn');
106
}
107
108
sub OpacValidations {
109
    my $main = t::lib::Page::Opac::OpacMain->new({borrowernumber => $borrowers->{'1A01'}->borrowernumber});
110
111
    ok (0, "Email validation is OFF!") if (C4::Context->preference('ValidateEmailAddress') == 0);
112
    ok (0, "Phone validation is OFF") if C4::Context->preference('ValidatePhoneNumber') eq "OFF";
113
    $main
114
    ->doPasswordLogin($borrowers->{'1A01'}->userid(), $password)
115
    ->navigateYourPersonalDetails()
116
    ->setEmail("valid\@email.com") # test valid email
117
    ->submitForm(1) # expecting success
118
    ->navigateYourPersonalDetails()
119
    ->setEmail("invalidemail") # test invalid email
120
    ->submitForm(0) # expecting error
121
    ->navigateYourPersonalDetails()
122
    ->setPhone("+3585012345667") # test valid phone number
123
    ->submitForm(1) # expecting success
124
    ->navigateYourPersonalDetails()
125
    ->setPhone("1234phone56789") # test invalid phone number
126
    ->submitForm(0); # expecting error
127
128
    print "--Setting validations off--\n";
129
    setValidationsOff(); # set validations off from system prefs
130
    #then test validations again
131
    ok (0, "Email validation is ON!") if (C4::Context->preference('ValidateEmailAddress') == 1);
132
    ok (0, "Phone validation is ON!") if C4::Context->preference('ValidatePhoneNumber') ne "OFF";
133
134
    $main
135
    ->navigateYourPersonalDetails()
136
    ->setEmail("invalidemail_validations_off") # test invalid email
137
    ->submitForm(1) # expecting success
138
    ->navigateYourPersonalDetails()
139
    ->setPhone("1234phone56789_validations_off") # test invalid phone number
140
    ->submitForm(1); # expecting success
141
142
    setValidationsOn();
143
}
144
145
sub StaffValidations {
146
    my $memberentry = t::lib::Page::Members::Memberentry->new({borrowernumber => $borrowers->{'superuberadmin'}->borrowernumber, op => 'modify', destination => 'circ', categorycode => 'PT'});
147
148
    ok (0, "Email validation is OFF!") if (C4::Context->preference('ValidateEmailAddress') == 0);
149
    ok (0, "Phone validation is OFF") if C4::Context->preference('ValidatePhoneNumber') eq "OFF";
150
151
    $memberentry
152
    ->doPasswordLogin($borrowers->{'superuberadmin'}->userid(), $password)
153
    ->setEmail("valid\@email.com") # test valid email
154
    ->submitForm(1) # expecting success
155
    ->navigateEditPatron()
156
    ->setEmail("invalidemail") # test invalid email
157
    ->submitForm(0) # expecting error
158
    ->setEmail("")
159
    ->setPhone("+3585012345667") # test valid phone number
160
    ->submitForm(1) # expecting success
161
    ->navigateEditPatron()
162
    ->setPhone("1234phone56789") # test invalid phone number
163
    ->submitForm(0); # expecting error
164
165
    print "--Setting validations off--\n";
166
    setValidationsOff(); # set validations off from system prefs
167
    #then test validations again
168
169
    ok (0, "Email validation is ON!") if (C4::Context->preference('ValidateEmailAddress') == 1);
170
    ok (0, "Phone validation is ON!") if C4::Context->preference('ValidatePhoneNumber') ne "OFF";
171
172
    $memberentry
173
    ->setPhone("") # refreshing
174
    ->setEmail("") # the
175
    ->submitForm(1)    # page
176
    ->navigateEditPatron()
177
    ->setEmail("invalidemail_validations_off") # test invalid email
178
    ->submitForm(1) # expecting success
179
    ->navigateEditPatron()
180
    ->setPhone("1234phone56789_validations_off") # test invalid phone number
181
    ->submitForm(1); # expecting success
182
183
    setValidationsOn();
184
}

Return to bug 14620