+ # basic checks using Data::Password;
+ # options for Data::Password
+ $DICTIONARY = 4; # minimum length of disallowed words
+ $MINLEN = $conf->config('passwordmin') || 6;
+ $MAXLEN = $conf->config('passwordmax') || 12;
+ $GROUPS = 4; # must have all 4 'character groups': numbers, symbols, uppercase, lowercase
+ # other options use the defaults listed below:
+ # $FOLLOWING = 3; # disallows more than 3 chars in a row, by alphabet or keyboard (ie abcd or asdf)
+ # $SKIPCHAR = undef; # set to true to skip checking for bad characters
+ # # lists of disallowed words
+ # @DICTIONARIES = qw( /usr/share/dict/web2 /usr/share/dict/words /usr/share/dict/linux.words );
+
+ my $error = IsBadPassword($password);
+ $error = 'must contain at least one each of numbers, symbols, and lowercase and uppercase letters'
+ if $error eq 'contains less than 4 character groups'; # avoid confusion
+ $error = 'Invalid password - ' . $error if $error;
+ return $error if $error;
+
+ #check against service fields
+ $error = $self->password_svc_check($password);
+ return $error if $error;
+
+ return '' unless $self->get($self->primary_key); # for validating new passwords pre-insert
+
+ #check against customer fields
+ my $cust_main = $self->cust_main;
+ if ($cust_main) {
+ my @words;
+ # words from cust_main
+ foreach my $field ( qw( last first daytime night fax mobile ) ) {
+ push @words, split(/\W/,$cust_main->get($field));
+ }
+ # words from cust_location
+ foreach my $loc ($cust_main->cust_location) {
+ foreach my $field ( qw(address1 address2 city county state zip) ) {
+ push @words, split(/\W/,$loc->get($field));
+ }
+ }
+ # words from cust_contact & contact_phone
+ foreach my $contact (map { $_->contact } $cust_main->cust_contact) {
+ foreach my $field ( qw(last first) ) {
+ push @words, split(/\W/,$contact->get($field));
+ }
+ # not hugely useful right now, hyphenless stored values longer than password max,
+ # but max will probably be increased eventually...
+ foreach my $phone ( qsearch('contact_phone', {'contactnum' => $contact->contactnum}) ) {
+ push @words, split(/\W/,$phone->get('phonenum'));
+ }
+ }
+ # do the actual checking
+ foreach my $word (@words) {
+ next unless length($word) > 2;
+ if ($password =~ /$word/i) {
+ return qq(Password contains account information '$word');
+ }
+ }
+ }