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 477-482 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
477
('UseQueryParser','0',NULL,'If enabled, try to use QueryParser for queries.','YesNo'),
477
('UseQueryParser','0',NULL,'If enabled, try to use QueryParser for queries.','YesNo'),
478
('UseTransportCostMatrix','0','','Use Transport Cost Matrix when filling holds','YesNo'),
478
('UseTransportCostMatrix','0','','Use Transport Cost Matrix when filling holds','YesNo'),
479
('UseWYSIWYGinSystemPreferences','0','','Show WYSIWYG editor when editing certain HTML system preferences.','YesNo'),
479
('UseWYSIWYGinSystemPreferences','0','','Show WYSIWYG editor when editing certain HTML system preferences.','YesNo'),
480
('ValidateEmailAddress','0','','Validation of email address on patrons.','YesNo'),
481
('ValidatePhoneNumber','OFF','ipn|fin|new|OFF','Validation of phone number on patrons.','Choice'),
480
('viewISBD','1','','Allow display of ISBD view of bibiographic records','YesNo'),
482
('viewISBD','1','','Allow display of ISBD view of bibiographic records','YesNo'),
481
('viewLabeledMARC','0','','Allow display of labeled MARC view of bibiographic records','YesNo'),
483
('viewLabeledMARC','0','','Allow display of labeled MARC view of bibiographic records','YesNo'),
482
('viewMARC','1','','Allow display of MARC view of bibiographic records','YesNo'),
484
('viewMARC','1','','Allow display of MARC view of bibiographic records','YesNo'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref (+16 lines)
Lines 138-143 Patrons: Link Here
138
               yes: Allow
138
               yes: Allow
139
               no: "Don't allow"
139
               no: "Don't allow"
140
         - librarians to discharge borrowers and borrowers to request a discharge.
140
         - librarians to discharge borrowers and borrowers to request a discharge.
141
     -
142
         - Use validator
143
         - pref: ValidatePhoneNumber
144
           choices:
145
               ipn: International Phone Numbers
146
               fin: Finnish Phone Numbers
147
               new: ...Not yet implemented...
148
               "OFF": none
149
         - to validate phone numbers on patrons.
150
     -
151
         - pref: ValidateEmailAddress
152
           choices:
153
               yes: Enable
154
               no: Disable
155
         - validation of email addresses on patrons.
156
141
    "Norwegian patron database":
157
    "Norwegian patron database":
142
     -
158
     -
143
         - pref: NorwegianPatronDBEnable
159
         - 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 254-259 Link Here
254
            [% IF ERROR_bad_email_alternative %]
309
            [% IF ERROR_bad_email_alternative %]
255
                <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
310
                <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
256
            [% END %]
311
            [% END %]
312
            [% IF ERROR_bad_phone %]
313
                <li id="ERROR_bad_phone">The primary phone is invalid.</li>
314
            [% END %]
315
            [% IF ERROR_bad_phone_secondary %]
316
                <li id="ERROR_bad_phone_secondary">The secondary phone is invalid.</li>
317
            [% END %]
318
            [% IF ERROR_bad_phone_alternative %]
319
                <li id="ERROR_bad_phone_alternative">The alternative phone is invalid.</li>
320
            [% END %]
321
            [% IF ERROR_bad_smsnumber %]
322
                <li id="ERROR_bad_smsnumber">The SMS number is invalid.</li>
323
            [% END %]
257
			</ul>
324
			</ul>
258
		</div>
325
		</div>
259
	[% END %]
326
	[% 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 (+59 lines)
Lines 27-32 Link Here
27
                    [% IF ( settings_updated ) %]
27
                    [% IF ( settings_updated ) %]
28
                        <div class="alert alert-success"><h4>Settings updated</h4></div>
28
                        <div class="alert alert-success"><h4>Settings updated</h4></div>
29
                    [% END %]
29
                    [% END %]
30
                    [% IF ( invalid_smsnumber ) %]
31
                        <div class="alert alert-error"><h4>Invalid SMS number</h4></div>
32
                    [% END %]
30
                    <form action="/cgi-bin/koha/opac-messaging.pl" method="get" name="opacmessaging">
33
                    <form action="/cgi-bin/koha/opac-messaging.pl" method="get" name="opacmessaging">
31
                        <input type="hidden" name="modify" value="yes" />
34
                        <input type="hidden" name="modify" value="yes" />
32
35
Lines 149-155 Link Here
149
      }
152
      }
150
    });
153
    });
151
    $("#info_digests").tooltip();
154
    $("#info_digests").tooltip();
155
    var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
156
157
    $("fieldset.rows input, fieldset.rows select").addClass("noEnterSubmit");
158
159
    var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
160
    $.validator.addMethod('phone', function(value) {
161
        if (!value.trim()) {
162
            return 1;
163
        }
164
        else {
165
            return (value.match(/[% phone_regex %]/));
166
        }
167
    },
168
    MSG_INCORRECT_PHONE);
169
170
    $("form[name='opacmessaging']").validate({
171
        rules: {
172
            [% IF ( ValidatePhoneNumber ) %]
173
            SMSnumber: {
174
                phone: true
175
            }
176
            [% END %]
177
        },
178
        submitHandler: function(form) {
179
            $("body, form input[type='submit'], form button[type='submit'], form a").addClass('waiting');
180
            if (form.beenSubmitted) {
181
                return false;
182
            }
183
            else {
184
                form.beenSubmitted = true;
185
                [% IF ValidatePhoneNumber %]
186
                    $("#SMSnumber").each(function(){
187
                        $(this).val($.trim($(this).val()));
188
                    });
189
                [% END %]
190
                form.submit();
191
            }
192
        },
193
        errorPlacement: function(error, element) {
194
            offset = element.offset();
195
            error.insertAfter(element)
196
            error.addClass('error');  // add a class to the wrapper
197
            error.css('position', 'absolute');
198
            error.css('left', offset.left + element.outerWidth() + 10);
199
            error.css('top', offset.top);
200
            error.css('width', 'auto');
201
        }
202
    });
203
204
    [% IF ( ValidatePhoneNumber ) %]
205
    $("#SMSnumber").on("change", function(){
206
            $(this).val($.trim($(this).val()));
207
    });
208
    [% END %]
209
152
  });
210
  });
153
//]]>
211
//]]>
154
</script>
212
</script>
213
<script type="text/javascript" src="/opac-tmpl/bootstrap/lib/jquery/plugins/jquery.validate.min.js"></script>
155
[% END %]
214
[% 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 42-53 use C4::Branch; # GetBranches Link Here
42
use C4::Form::MessagingPreferences;
42
use C4::Form::MessagingPreferences;
43
use Koha::Borrower::Debarments;
43
use Koha::Borrower::Debarments;
44
use Koha::DateUtils;
44
use Koha::DateUtils;
45
use Email::Valid;
45
use Koha::Validation;
46
use Module::Load;
46
use Module::Load;
47
if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) {
47
if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) {
48
    load Koha::NorwegianPatronDB, qw( NLGetSyncDataFromBorrowernumber );
48
    load Koha::NorwegianPatronDB, qw( NLGetSyncDataFromBorrowernumber );
49
}
49
}
50
50
51
use re 'regexp_pattern';
51
use vars qw($debug);
52
use vars qw($debug);
52
53
53
BEGIN {
54
BEGIN {
Lines 328-347 if ($op eq 'save' || $op eq 'insert'){ Link Here
328
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
329
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
329
  push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) );
330
  push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) );
330
331
331
  # Validate emails
332
  # validate emails
332
  my $emailprimary = $input->param('email');
333
  push (@errors, "ERROR_bad_email") if ($input->param('email') && !Koha::Validation::validate_email($input->param('email')));
333
  my $emailsecondary = $input->param('emailpro');
334
  push (@errors, "ERROR_bad_email_secondary") if ($input->param('emailpro') && !Koha::Validation::validate_email($input->param('emailpro')));
334
  my $emailalt = $input->param('B_email');
335
  push (@errors, "ERROR_bad_email_alternative") if ($input->param('B_email') && !Koha::Validation::validate_email($input->param('B_email')));
335
336
  # validate phone numbers
336
  if ($emailprimary) {
337
  push (@errors, "ERROR_bad_phone") if ($input->param('phone') && !Koha::Validation::validate_phonenumber($input->param('phone')));
337
      push (@errors, "ERROR_bad_email") if (!Email::Valid->address($emailprimary));
338
  push (@errors, "ERROR_bad_phone_secondary") if ($input->param('phonepro') && !Koha::Validation::validate_phonenumber($input->param('phonepro')));
338
  }
339
  push (@errors, "ERROR_bad_phone_alternative") if ($input->param('B_phone') && !Koha::Validation::validate_phonenumber($input->param('B_phone')));
339
  if ($emailsecondary) {
340
      push (@errors, "ERROR_bad_email_secondary") if (!Email::Valid->address($emailsecondary));
341
  }
342
  if ($emailalt) {
343
      push (@errors, "ERROR_bad_email_alternative") if (!Email::Valid->address($emailalt));
344
  }
345
340
346
  if (C4::Context->preference('ExtendedPatronAttributes')) {
341
  if (C4::Context->preference('ExtendedPatronAttributes')) {
347
    $extended_patron_attributes = parse_extended_patron_attributes($input);
342
    $extended_patron_attributes = parse_extended_patron_attributes($input);
Lines 369-375 if ( ($op eq 'modify' || $op eq 'insert' || $op eq 'save'|| $op eq 'duplicate') Link Here
369
# BZ 14683: Do not mixup mobile [read: other phone] with smsalertnumber
364
# BZ 14683: Do not mixup mobile [read: other phone] with smsalertnumber
370
my $sms = $input->param('SMSnumber');
365
my $sms = $input->param('SMSnumber');
371
if ( defined $sms ) {
366
if ( defined $sms ) {
372
    $newdata{smsalertnumber} = $sms;
367
    if (Koha::Validation::validate_phonenumber($sms)){
368
        $newdata{smsalertnumber} = $sms;
369
    } else {
370
        push (@errors, "ERROR_bad_smsnumber");
371
    }
373
}
372
}
374
373
375
###  Error checks should happen before this line.
374
###  Error checks should happen before this line.
Lines 678-683 if (C4::Context->preference('ExtendedPatronAttributes')) { Link Here
678
    patron_attributes_form($template, $borrowernumber);
677
    patron_attributes_form($template, $borrowernumber);
679
}
678
}
680
679
680
$template->param(
681
        ValidateEmailAddress => C4::Context->preference('ValidateEmailAddress'),
682
        ValidatePhoneNumber => C4::Context->preference('ValidatePhoneNumber') ne "OFF",
683
        phone_regex => regexp_pattern Koha::Validation::get_phonenumber_regex()
684
);
685
681
if (C4::Context->preference('EnhancedMessagingPreferences')) {
686
if (C4::Context->preference('EnhancedMessagingPreferences')) {
682
    if ($op eq 'add') {
687
    if ($op eq 'add') {
683
        C4::Form::MessagingPreferences::set_form_values({ categorycode => $categorycode }, $template);
688
        C4::Form::MessagingPreferences::set_form_values({ categorycode => $categorycode }, $template);
(-)a/opac/opac-memberentry.pl (-4 / +21 lines)
Lines 28-34 use C4::Form::MessagingPreferences; Link Here
28
use Koha::Borrower::Modifications;
28
use Koha::Borrower::Modifications;
29
use C4::Branch qw(GetBranchesLoop);
29
use C4::Branch qw(GetBranchesLoop);
30
use C4::Scrubber;
30
use C4::Scrubber;
31
use Email::Valid;
31
use Koha::Validation;
32
33
use re 'regexp_pattern';
32
34
33
my $cgi = new CGI;
35
my $cgi = new CGI;
34
my $dbh = C4::Context->dbh;
36
my $dbh = C4::Context->dbh;
Lines 68-73 $template->param( Link Here
68
    member_titles     => GetTitles() || undef,
70
    member_titles     => GetTitles() || undef,
69
    branches          => GetBranchesLoop(),
71
    branches          => GetBranchesLoop(),
70
    OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
72
    OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
73
    ValidateEmailAddress   => C4::Context->preference('ValidateEmailAddress'),
74
    ValidatePhoneNumber    => (C4::Context->preference('ValidatePhoneNumber') ne "OFF"),
75
    phone_regex            => regexp_pattern Koha::Validation::get_phonenumber_regex()
71
);
76
);
72
77
73
if ( $action eq 'create' ) {
78
if ( $action eq 'create' ) {
Lines 307-319 sub CheckForInvalidFields { Link Here
307
    my $borrower = shift;
312
    my $borrower = shift;
308
    my @invalidFields;
313
    my @invalidFields;
309
    if ($borrower->{'email'}) {
314
    if ($borrower->{'email'}) {
310
        push(@invalidFields, "email") if (!Email::Valid->address($borrower->{'email'}));
315
        push(@invalidFields, "email") if (!Koha::Validation::validate_email($borrower->{'email'}));
311
    }
316
    }
312
    if ($borrower->{'emailpro'}) {
317
    if ($borrower->{'emailpro'}) {
313
        push(@invalidFields, "emailpro") if (!Email::Valid->address($borrower->{'emailpro'}));
318
        push(@invalidFields, "emailpro") if (!Koha::Validation::validate_email($borrower->{'emailpro'}));
314
    }
319
    }
315
    if ($borrower->{'B_email'}) {
320
    if ($borrower->{'B_email'}) {
316
        push(@invalidFields, "B_email") if (!Email::Valid->address($borrower->{'B_email'}));
321
        push(@invalidFields, "B_email") if (!Koha::Validation::validate_email($borrower->{'B_email'}));
322
    }
323
    if ($borrower->{'mobile'}) {
324
        push(@invalidFields, "mobile") if (!Koha::Validation::validate_phonenumber($borrower->{'mobile'}));
325
    }
326
    if ($borrower->{'phone'}) {
327
        push(@invalidFields, "phone") if (!Koha::Validation::validate_phonenumber($borrower->{'phone'}));
328
    }
329
    if ($borrower->{'phonepro'}) {
330
        push(@invalidFields, "phonepro") if (!Koha::Validation::validate_phonenumber($borrower->{'phonepro'}));
331
    }
332
    if ($borrower->{'B_phone'}) {
333
        push(@invalidFields, "B_phone") if (!Koha::Validation::validate_phonenumber($borrower->{'B_phone'}));
317
    }
334
    }
318
    return \@invalidFields;
335
    return \@invalidFields;
319
}
336
}
(-)a/opac/opac-messaging.pl (-2 / +11 lines)
Lines 32-37 use C4::Members; Link Here
32
use C4::Members::Messaging;
32
use C4::Members::Messaging;
33
use C4::Branch;
33
use C4::Branch;
34
use C4::Form::MessagingPreferences;
34
use C4::Form::MessagingPreferences;
35
use Koha::Validation;
36
37
use re 'regexp_pattern';
35
38
36
my $query = CGI->new();
39
my $query = CGI->new();
37
40
Lines 47-56 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
47
50
48
my $borrower = GetMemberDetails( $borrowernumber );
51
my $borrower = GetMemberDetails( $borrowernumber );
49
my $messaging_options = C4::Members::Messaging::GetMessagingOptions();
52
my $messaging_options = C4::Members::Messaging::GetMessagingOptions();
50
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
);
51
if ( defined $query->param('modify') && $query->param('modify') eq 'yes' ) {
58
if ( defined $query->param('modify') && $query->param('modify') eq 'yes' ) {
52
    my $sms = $query->param('SMSnumber');
59
    my $sms = $query->param('SMSnumber');
53
    if ( defined $sms && ( $borrower->{'smsalertnumber'} // '' ) ne $sms ) {
60
    my $valid_smsnumber = Koha::Validation::validate_phonenumber($sms);
61
    $template->param(invalid_smsnumber => 1) if not $valid_smsnumber;
62
    if ( defined $sms && ( $borrower->{'smsalertnumber'} // '' ) ne $sms && $valid_smsnumber) {
54
        ModMember( borrowernumber => $borrowernumber,
63
        ModMember( borrowernumber => $borrowernumber,
55
                   smsalertnumber => $sms );
64
                   smsalertnumber => $sms );
56
        $borrower = GetMemberDetails( $borrowernumber );
65
        $borrower = GetMemberDetails( $borrowernumber );
(-)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