sub init()

in lib/Mail/SpamAssassin.pm [1741:1922]


sub init {
  my ($self, $use_user_pref) = @_;

  # Allow init() to be called multiple times, but only run once.
  if (defined $self->{_initted}) {
    # If the PID changes, reseed the PRNG (if permitted) and the DNS ID counter
    if ($self->{_initted} != $$) {
      $self->{_initted} = $$;
      srand  if !$self->{skip_prng_reseeding};
      $self->{resolver}->reinit_post_fork();
    }
    return;
  }

  my $timer = $self->time_method("init");
  # Note that this PID has run init()
  $self->{_initted} = $$;

  # if spamd or other forking, wait for spamd_child_init
  if (!$self->{skip_prng_reseeding}) {
    $self->set_global_state_dir();
  }

  #fix spamd reading root prefs file
  if (!defined $use_user_pref) {
    $use_user_pref = 1;
  }

  if (!defined $self->{config_text}) {
    $self->{config_text} = '';

    # read a file called "init.pre" in site rules dir *before* all others;
    # even the system config.
    my $siterules = $self->{site_rules_filename};
    $siterules ||= $self->first_existing_path (@site_rules_path);

    my $sysrules = $self->{rules_filename};
    $sysrules ||= $self->first_existing_path (@default_rules_path);

    if ($siterules) {
      $self->{config_text} .= $self->read_pre($siterules, 'site rules pre files');
    }
    else {
      warn "config: could not find site rules directory\n";
    }

    if ($sysrules) {
      $self->{config_text} .= $self->read_pre($sysrules, 'sys rules pre files');
    }
    else {
      warn "config: could not find sys rules directory\n";
    }

    if ($sysrules) {
      my $cftext = $self->read_cf($sysrules, 'default rules dir');
      if ($self->{require_rules} && $cftext !~ /\S/) {
        die "config: no rules were found!  Do you need to run 'sa-update'?\n";
      }
      $self->{config_text} .= $cftext;
    }

    if (!$self->{languages_filename}) {
      $self->{languages_filename} = $self->find_rule_support_file("languages");
    }

    if ($siterules && !$self->{ignore_site_cf_files}) {
      $self->{config_text} .= $self->read_cf($siterules, 'site rules dir');
    }

    if ( $use_user_pref != 0 ) {
      $self->get_and_create_userstate_dir();

      # user prefs file
      my $fname = $self->{userprefs_filename};
      $fname ||= $self->first_existing_path (@default_userprefs_path);

      if (!$self->{dont_copy_prefs}) {
        # bug 4932: if the userprefs path doesn't exist, we need to make it, so
        # just use the last entry in the array as the default path.
        $fname ||= $self->sed_path($default_userprefs_path[-1]);

        my $stat_errn = stat($fname) ? 0 : 0+$!;
        if ($stat_errn == 0 && -f _) {
          # exists and is a regular file, nothing to do
        } elsif ($stat_errn == 0) {
          warn "config: default user preference file $fname is not a regular file\n";
        } elsif ($stat_errn != ENOENT) {
          warn "config: default user preference file $fname not accessible: $!\n";
        } elsif (!$self->create_default_prefs($fname)) {
          warn "config: failed to create default user preference file $fname\n";
        }
      }

      $self->{config_text} .= $self->read_cf($fname, 'user prefs file');
    }
  }

  if ($self->{pre_config_text}) {
    $self->{pre_config_text} .= "\n" unless $self->{pre_config_text} =~ /\n\z/;
    $self->{config_text} = "file start (pre_config_text)\n".
                           $self->{pre_config_text}.
                           "file end (pre_config_text)\n".
                           $self->{config_text};
  }
  if ($self->{post_config_text}) {
    $self->{post_config_text} .= "\n" unless $self->{post_config_text} =~ /\n\z/;
    $self->{config_text} .= "\n" unless $self->{config_text} =~ /\n\z/;
    $self->{config_text} .= "file start (post_config_text)\n".
                            $self->{post_config_text}.
                            "file end (post_config_text)\n";
  }

  if ($self->{config_text} !~ /\S/) {
    my $m = "config: no configuration text or files found! do you need to run 'sa-update'?\n";
    if ($self->{require_rules}) {
      die $m;
    } else {
      warn $m;
    }
  }

  # Go and parse the config!
  $self->{conf}->{main} = $self;
  if (would_log('dbg', 'config_text') > 1) {
    dbg('config_text: '.$self->{config_text});
  }
  $self->{conf}->parse_rules ($self->{config_text});
  $self->{conf}->finish_parsing(0);
  delete $self->{conf}->{main};	# to allow future GC'ing

  undef $self->{config_text};   # ensure it's actually freed
  delete $self->{config_text};

  if ($self->{require_rules} && !$self->{conf}->found_any_rules()) {
    die "config: no rules were found!  Do you need to run 'sa-update'?\n";
  }

  # Initialize the Bayes subsystem
  if ($self->{conf}->{use_bayes}) {
      require Mail::SpamAssassin::Bayes;
      $self->{bayes_scanner} = Mail::SpamAssassin::Bayes->new($self);
  }
  $self->{'learn_to_journal'} = $self->{conf}->{bayes_learn_to_journal};

  # Figure out/set our initial scoreset
  my $set = 0;
  $set |= 1 unless $self->{local_tests_only};
  $set |= 2 if $self->{bayes_scanner} && $self->{bayes_scanner}->is_scan_available() && $self->{conf}->{use_bayes_rules};
  $self->{conf}->set_score_set ($set);

  if ($self->{only_these_rules}) {
    $self->{conf}->trim_rules($self->{only_these_rules});
  }

  if (!$self->{timer_enabled}) {
    # enable timing implicitly if _TIMING_ is used in add_header templates
    foreach my $hf_ref (@{$self->{conf}->{'headers_ham'}},
                        @{$self->{conf}->{'headers_spam'}}) {
      if ($hf_ref->[1] =~ /_TIMING_/) { $self->timer_enable(); last }
    }
  }

  # should be called only after configuration has been parsed
  $self->{resolver} = Mail::SpamAssassin::DnsResolver->new($self);

  # load GeoDB if some plugin wants it
  if ($self->{geodb_wanted}) {
    eval '
      use Mail::SpamAssassin::GeoDB;
      $self->{geodb} = Mail::SpamAssassin::GeoDB->new({
        conf => $self->{conf}->{geodb},
        wanted => $self->{geodb_wanted},
      });
      1;
    ';
    if ($@ || !$self->{geodb}) {
      dbg("config: GeoDB disabled: $@");
    }
  }

  # TODO -- open DNS cache etc. if necessary
}