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

(-)a/Koha/Validation.pm (+140 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 0 if not defined $address;
57
    return (not defined Email::Valid->address($address)) ? 0:1; 
58
}
59
60
=head2 validate_phonenumber
61
62
Validates given phone number.
63
64
  Koha::Validation::validate_phonenumber(123456789);
65
  
66
returns: 1 if the given phone number is valid, 0 otherwise.
67
68
=cut
69
70
sub validate_phonenumber {
71
    my $phonenumber = shift;
72
    
73
    $phonenumber =~ s/\s+//g;
74
    
75
    # make sure we are allowed to validate phone numbers
76
    return 1 if C4::Context->preference("ValidatePhoneNumber") eq "OFF";
77
    return 1 if $phonenumber eq "";
78
    return 0 if not defined $phonenumber;
79
    
80
    my $regex = get_phonenumber_regex(C4::Context->preference("ValidatePhoneNumber"));
81
    #die $regex;
82
    return ($phonenumber !~ /$regex/) ? 0:1;
83
}
84
85
=head2 get_phonenumber_regex
86
87
Returns the used regex (according to ValidatePhoneNumber system preference) for phone numbers.
88
This is used to share the same regex between Perl scripts and JavaScript in templates.
89
90
  Koha::Validation::get_phonenumber_regex();
91
  
92
International phone numbers (ipn): http://regexlib.com/REDetails.aspx?regexp_id=3009
93
94
returns: the regex
95
96
=cut
97
98
sub get_phonenumber_regex {
99
    if (C4::Context->preference("ValidatePhoneNumber") eq "ipn") {
100
        return qr/^((\+)?[1-9]{1,2})?([-\s\.])?((\(\d{1,4}\))|\d{1,4})(([-\s\.])?[0-9]{1,12}){1,2}$/;
101
    }
102
    elsif (C4::Context->preference("ValidatePhoneNumber") eq "fin") {
103
        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,20}$/;
104
    }
105
    
106
    return "";
107
  }
108
109
110
=head2 use_validator
111
112
Validates given input with given validator.
113
114
  Koha::Validation::use_validator("phone", 123456789);
115
  Koha::Validation::use_validator("email", "email@address.com");
116
117
Currently supported validators are
118
  email, e-mail
119
  phone, phonenumber
120
  
121
returns: 1 if the given input is valid with the given validator, 0 otherwise.
122
123
=cut
124
125
sub use_validator {
126
    my ($validator, $input) = @_;
127
    
128
    if (not defined $validator or not defined $input) {
129
        warn "Subroutine must be called with validator and input";
130
        return 0;
131
    }
132
    
133
    return validate_email($input) if $validator eq "email" or $validator eq "e-mail";
134
    return validate_phonenumber($input) if $validator eq "phone" or $validator eq "phonenumber";
135
    
136
    warn "Validator not found";
137
    return 0;
138
}
139
140
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 470-475 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
470
('UseKohaPlugins','0','','Enable or disable the ability to use Koha Plugins.','YesNo'),
470
('UseKohaPlugins','0','','Enable or disable the ability to use Koha Plugins.','YesNo'),
471
('UseQueryParser','0',NULL,'If enabled, try to use QueryParser for queries.','YesNo'),
471
('UseQueryParser','0',NULL,'If enabled, try to use QueryParser for queries.','YesNo'),
472
('UseTransportCostMatrix','0','','Use Transport Cost Matrix when filling holds','YesNo'),
472
('UseTransportCostMatrix','0','','Use Transport Cost Matrix when filling holds','YesNo'),
473
('ValidateEmailAddress','0','','Validation of email address on patrons.','YesNo'),
474
('ValidatePhoneNumber','OFF','ipn|fin|new|OFF','Validation of phone number on patrons.','Choice'),
473
('viewISBD','1','','Allow display of ISBD view of bibiographic records','YesNo'),
475
('viewISBD','1','','Allow display of ISBD view of bibiographic records','YesNo'),
474
('viewLabeledMARC','0','','Allow display of labeled MARC view of bibiographic records','YesNo'),
476
('viewLabeledMARC','0','','Allow display of labeled MARC view of bibiographic records','YesNo'),
475
('viewMARC','1','','Allow display of MARC view of bibiographic records','YesNo'),
477
('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 (+44 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 254-259 Link Here
254
            [% IF ERROR_bad_email_alternative %]
286
            [% IF ERROR_bad_email_alternative %]
255
                <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
287
                <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
256
            [% END %]
288
            [% END %]
289
            [% IF ERROR_bad_phone %]
290
                <li id="ERROR_bad_phone">The primary phone is invalid.</li>
291
            [% END %]
292
            [% IF ERROR_bad_phone_secondary %]
293
                <li id="ERROR_bad_phone_secondary">The secondary phone is invalid.</li>
294
            [% END %]
295
            [% IF ERROR_bad_phone_alternative %]
296
                <li id="ERROR_bad_phone_alternative">The alternative phone is invalid.</li>
297
            [% END %]
298
            [% IF ERROR_bad_smsnumber %]
299
                <li id="ERROR_bad_smsnumber">The SMS number is invalid.</li>
300
            [% END %]
257
			</ul>
301
			</ul>
258
		</div>
302
		</div>
259
	[% END %]
303
	[% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt (+33 lines)
Lines 57-62 Link Here
57
                                [% IF field == "email" %]<li>Contact information: <a href="#borrower_email">primary email address</a></li>[% END %]
57
                                [% IF field == "email" %]<li>Contact information: <a href="#borrower_email">primary email address</a></li>[% END %]
58
                                [% IF field == "emailpro" %]<li>Contact information: <a href="#borrower_emailpro">secondary email address</a></li>[% END %]
58
                                [% IF field == "emailpro" %]<li>Contact information: <a href="#borrower_emailpro">secondary email address</a></li>[% END %]
59
                                [% IF field == "B_email" %]<li>Alternate address information: <a href="#borrower_B_email">email address</a></li>[% END %]
59
                                [% IF field == "B_email" %]<li>Alternate address information: <a href="#borrower_B_email">email address</a></li>[% END %]
60
                                [% IF field == "phone" %]<li>Contact information: <a href="#borrower_phone">primary phone</a></li>[% END %]
61
                                [% IF field == "phonepro" %]<li>Contact information: <a href="#borrower_phonepro">secondary phone</a></li>[% END %]
62
                                [% IF field == "mobile" %]<li>Contact information: <a href="#borrower_mobile">other phone</a></li>[% END %]
63
                                [% IF field == "B_phone" %]<li>Alternate address information: <a href="#borrower_B_phone">phone</a></li>[% END %]
60
                            [% END %]
64
                            [% END %]
61
                        </ul>
65
                        </ul>
62
                        Please correct the errors and resubmit.
66
                        Please correct the errors and resubmit.
Lines 819-826 Link Here
819
            [% ELSE %]
823
            [% ELSE %]
820
                $( "#borrower_dateofbirth" ).datepicker({ yearRange: "c-120:c" });
824
                $( "#borrower_dateofbirth" ).datepicker({ yearRange: "c-120:c" });
821
            [% END %]
825
            [% END %]
826
            var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
827
            $.validator.addMethod('phone', function(value) {
828
                if (!value.trim()) {
829
                    return 1;
830
                }
831
                else {
832
                    return (value.match(/[% phone_regex %]/));
833
                }
834
            },
835
            MSG_INCORRECT_PHONE);
822
            $("#memberentry-form").validate({
836
            $("#memberentry-form").validate({
823
                rules: {
837
                rules: {
838
                    [% IF ( ValidateEmailAddress ) %]
824
                    borrower_email: {
839
                    borrower_email: {
825
                        email: true
840
                        email: true
826
                    },
841
                    },
Lines 829-835 Link Here
829
                    },
844
                    },
830
                    borrower_B_email: {
845
                    borrower_B_email: {
831
                        email: true
846
                        email: true
847
                    }[% IF ( ValidatePhoneNumber ) %],[% END %]
848
                    [% END %]
849
                    [% IF ( ValidatePhoneNumber ) %]
850
                    borrower_phone: {
851
                        phone: true
852
                    },
853
                    borrower_phonepro: {
854
                        phone: true
855
                    },
856
                    borrower_mobile: {
857
                        phone: true
858
                    },
859
                    SMSnumber: {
860
                        phone: true
861
                    },
862
                    borrower_B_phone: {
863
                        phone: true
832
                    }
864
                    }
865
                    [% END %]
833
                },
866
                },
834
                submitHandler: function(form) {
867
                submitHandler: function(form) {
835
                    if (form.beenSubmitted) {
868
                    if (form.beenSubmitted) {
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt (+45 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
                form.submit();
183
            }
184
        },
185
        errorPlacement: function(error, element) {
186
            offset = element.offset();
187
            error.insertAfter(element)
188
            error.addClass('error');  // add a class to the wrapper
189
            error.css('position', 'absolute');
190
            error.css('left', offset.left + element.outerWidth() + 10);
191
            error.css('top', offset.top);
192
            error.css('width', 'auto');
193
        }
194
    });
195
    
152
  });
196
  });
153
//]]>
197
//]]>
154
</script>
198
</script>
199
<script type="text/javascript" src="/opac-tmpl/bootstrap/lib/jquery/plugins/jquery.validate.min.js"></script>
155
[% END %]
200
[% 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 / +22 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 327-346 if ($op eq 'save' || $op eq 'insert'){ Link Here
327
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
328
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
328
  push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) );
329
  push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) );
329
330
330
  # Validate emails
331
  # validate emails
331
  my $emailprimary = $input->param('email');
332
  push (@errors, "ERROR_bad_email") if ($input->param('email') && !Koha::Validation::validate_email($input->param('email')));
332
  my $emailsecondary = $input->param('emailpro');
333
  push (@errors, "ERROR_bad_email_secondary") if ($input->param('emailpro') && !Koha::Validation::validate_email($input->param('emailpro')));
333
  my $emailalt = $input->param('B_email');
334
  push (@errors, "ERROR_bad_email_alternative") if ($input->param('B_email') && !Koha::Validation::validate_email($input->param('B_email')));
334
335
  # validate phone numbers
335
  if ($emailprimary) {
336
  push (@errors, "ERROR_bad_phone") if ($input->param('phone') && !Koha::Validation::validate_phonenumber($input->param('phone')));
336
      push (@errors, "ERROR_bad_email") if (!Email::Valid->address($emailprimary));
337
  push (@errors, "ERROR_bad_phone_secondary") if ($input->param('phonepro') && !Koha::Validation::validate_phonenumber($input->param('phonepro')));
337
  }
338
  push (@errors, "ERROR_bad_phone_alternative") if ($input->param('B_phone') && !Koha::Validation::validate_phonenumber($input->param('B_phone')));
338
  if ($emailsecondary) {
339
      push (@errors, "ERROR_bad_email_secondary") if (!Email::Valid->address($emailsecondary));
340
  }
341
  if ($emailalt) {
342
      push (@errors, "ERROR_bad_email_alternative") if (!Email::Valid->address($emailalt));
343
  }
344
339
345
  if (C4::Context->preference('ExtendedPatronAttributes')) {
340
  if (C4::Context->preference('ExtendedPatronAttributes')) {
346
    $extended_patron_attributes = parse_extended_patron_attributes($input);
341
    $extended_patron_attributes = parse_extended_patron_attributes($input);
Lines 372-378 if ( Link Here
372
        or $input->param('SMSnumber') ne $newdata{'mobile'}
367
        or $input->param('SMSnumber') ne $newdata{'mobile'}
373
        )
368
        )
374
) {
369
) {
375
    $newdata{smsalertnumber} = $input->param('SMSnumber');
370
    if (Koha::Validation::validate_phonenumber($input->param('SMSnumber'))){
371
        $newdata{smsalertnumber} = $input->param('SMSnumber');
372
    } else {
373
        push (@errors, "ERROR_bad_smsnumber");
374
    }
375
    
376
}
376
}
377
377
378
###  Error checks should happen before this line.
378
###  Error checks should happen before this line.
Lines 681-686 if (C4::Context->preference('ExtendedPatronAttributes')) { Link Here
681
    patron_attributes_form($template, $borrowernumber);
681
    patron_attributes_form($template, $borrowernumber);
682
}
682
}
683
683
684
$template->param(
685
        ValidateEmailAddress => C4::Context->preference('ValidateEmailAddress'),
686
        ValidatePhoneNumber => C4::Context->preference('ValidatePhoneNumber') ne "OFF",
687
        phone_regex => regexp_pattern Koha::Validation::get_phonenumber_regex()
688
);
689
684
if (C4::Context->preference('EnhancedMessagingPreferences')) {
690
if (C4::Context->preference('EnhancedMessagingPreferences')) {
685
    if ($op eq 'add') {
691
    if ($op eq 'add') {
686
        C4::Form::MessagingPreferences::set_form_values({ categorycode => $categorycode }, $template);
692
        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 299-311 sub CheckForInvalidFields { Link Here
299
    my $borrower = shift;
304
    my $borrower = shift;
300
    my @invalidFields;
305
    my @invalidFields;
301
    if ($borrower->{'email'}) {
306
    if ($borrower->{'email'}) {
302
        push(@invalidFields, "email") if (!Email::Valid->address($borrower->{'email'}));
307
        push(@invalidFields, "email") if (!Koha::Validation::validate_email($borrower->{'email'}));
303
    }
308
    }
304
    if ($borrower->{'emailpro'}) {
309
    if ($borrower->{'emailpro'}) {
305
        push(@invalidFields, "emailpro") if (!Email::Valid->address($borrower->{'emailpro'}));
310
        push(@invalidFields, "emailpro") if (!Koha::Validation::validate_email($borrower->{'emailpro'}));
306
    }
311
    }
307
    if ($borrower->{'B_email'}) {
312
    if ($borrower->{'B_email'}) {
308
        push(@invalidFields, "B_email") if (!Email::Valid->address($borrower->{'B_email'}));
313
        push(@invalidFields, "B_email") if (!Koha::Validation::validate_email($borrower->{'B_email'}));
314
    }
315
    if ($borrower->{'mobile'}) {
316
        push(@invalidFields, "mobile") if (!Koha::Validation::validate_phonenumber($borrower->{'mobile'}));
317
    }
318
    if ($borrower->{'phone'}) {
319
        push(@invalidFields, "phone") if (!Koha::Validation::validate_phonenumber($borrower->{'phone'}));
320
    }
321
    if ($borrower->{'phonepro'}) {
322
        push(@invalidFields, "phonepro") if (!Koha::Validation::validate_phonenumber($borrower->{'phonepro'}));
323
    }
324
    if ($borrower->{'B_phone'}) {
325
        push(@invalidFields, "B_phone") if (!Koha::Validation::validate_phonenumber($borrower->{'B_phone'}));
309
    }
326
    }
310
    return \@invalidFields;
327
    return \@invalidFields;
311
}
328
}
(-)a/opac/opac-messaging.pl (-2 / +13 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 48-57 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
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
54
$template->param(
55
        ValidateEmailAddress   => C4::Context->preference('ValidateEmailAddress'),
56
        ValidatePhoneNumber    => (C4::Context->preference('ValidatePhoneNumber') ne "OFF"),
57
        phone_regex            => regexp_pattern Koha::Validation::get_phonenumber_regex()  
58
);
51
if ( defined $query->param('modify') && $query->param('modify') eq 'yes' ) {
59
if ( defined $query->param('modify') && $query->param('modify') eq 'yes' ) {
52
60
    
61
    my $valid_smsnumber = Koha::Validation::validate_phonenumber($query->param('SMSnumber'));
62
    $template->param( invalid_smsnumber => $valid_smsnumber );
63
    
53
    # If they've modified the SMS number, record it.
64
    # If they've modified the SMS number, record it.
54
    if ( ( defined $query->param('SMSnumber') ) && ( $query->param('SMSnumber') ne $borrower->{'mobile'} ) ) {
65
    if ( ( defined $query->param('SMSnumber') ) && ( $query->param('SMSnumber') ne $borrower->{'mobile'} ) && $valid_smsnumber ) {
55
        ModMember( borrowernumber => $borrowernumber,
66
        ModMember( borrowernumber => $borrowernumber,
56
                   smsalertnumber => $query->param('SMSnumber') );
67
                   smsalertnumber => $query->param('SMSnumber') );
57
        $borrower = GetMemberDetails( $borrowernumber );
68
        $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