diff options
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS/Conf.pm | 263 | ||||
-rw-r--r-- | FS/FS/Cron/bill.pm | 3 | ||||
-rw-r--r-- | FS/FS/Record.pm | 35 | ||||
-rw-r--r-- | FS/FS/Schema.pm | 17 | ||||
-rw-r--r-- | FS/FS/UID.pm | 29 | ||||
-rw-r--r-- | FS/FS/conf.pm | 114 | ||||
-rw-r--r-- | FS/FS/cust_bill.pm | 28 | ||||
-rw-r--r-- | FS/FS/cust_main.pm | 12 | ||||
-rw-r--r-- | FS/FS/part_export/prizm.pm | 6 | ||||
-rw-r--r-- | FS/FS/part_export/shellcommands.pm | 13 | ||||
-rw-r--r-- | FS/FS/part_pkg/base_delayed.pm | 51 | ||||
-rw-r--r-- | FS/FS/part_pkg/base_rate.pm | 102 | ||||
-rw-r--r-- | FS/FS/part_pkg/voip_cdr.pm | 2 | ||||
-rw-r--r-- | FS/FS/svc_acct.pm | 378 | ||||
-rwxr-xr-x | FS/FS/svc_broadband.pm | 2 | ||||
-rw-r--r-- | FS/MANIFEST | 4 | ||||
-rwxr-xr-x | FS/bin/freeside-delete-addr_blocks | 31 | ||||
-rwxr-xr-x | FS/bin/freeside-init-config | 92 | ||||
-rw-r--r-- | FS/bin/freeside-selfservice-server | 7 | ||||
-rwxr-xr-x | FS/bin/freeside-setup | 25 | ||||
-rwxr-xr-x | FS/bin/freeside-upgrade | 6 | ||||
-rw-r--r-- | FS/t/conf.t | 5 | ||||
-rw-r--r-- | FS/t/cust_pkg_option.t | 5 |
23 files changed, 270 insertions, 960 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 5f7cb8fec..1c552a4bd 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -1,14 +1,13 @@ package FS::Conf; -use vars qw($base_dir @config_items @card_types $DEBUG ); -use MIME::Base64; +use vars qw($default_dir $base_dir @config_items @card_types $DEBUG ); +use IO::File; +use File::Basename; use FS::ConfItem; use FS::ConfDefaults; -use FS::conf; -use FS::Record qw(qsearch qsearchs); -use FS::UID qw(dbh); $base_dir = '%%%FREESIDE_CONF%%%'; +$default_dir = '%%%FREESIDE_CONF%%%'; $DEBUG = 0; @@ -21,8 +20,13 @@ FS::Conf - Freeside configuration values use FS::Conf; + $conf = new FS::Conf "/config/directory"; + + $FS::Conf::default_dir = "/config/directory"; $conf = new FS::Conf; + $dir = $conf->dir; + $value = $conf->config('key'); @list = $conf->config('key'); $bool = $conf->exists('key'); @@ -42,19 +46,39 @@ but this may change in the future. =over 4 -=item new +=item new [ DIRECTORY ] -Create a new configuration object. +Create a new configuration object. A directory arguement is required if +$FS::Conf::default_dir has not been set. =cut sub new { - my($proto) = @_; + my($proto,$dir) = @_; my($class) = ref($proto) || $proto; - my($self) = { 'base_dir' => $base_dir }; + my($self) = { 'dir' => $dir || $default_dir, + 'base_dir' => $base_dir, + }; bless ($self, $class); } +=item dir + +Returns the conf directory. + +=cut + +sub dir { + my($self) = @_; + my $dir = $self->{dir}; + -e $dir or die "FATAL: $dir doesn't exist!"; + -d $dir or die "FATAL: $dir isn't a directory!"; + -r $dir or die "FATAL: Can't read $dir!"; + -x $dir or die "FATAL: $dir not searchable (executable)!"; + $dir =~ /^(.*)$/; + $1; +} + =item base_dir Returns the base directory. By default this is /usr/local/etc/freeside. @@ -78,29 +102,20 @@ Returns the configuration value or values (depending on context) for key. =cut -sub _config { - my($self,$name,$agent)=@_; - my $hashref = { 'name' => $name }; - if (defined($agent) && $agent) { - $hashref->{agent} = $agent; - } - local $FS::Record::conf = undef; # XXX evil hack prevents recursion - my $cv = FS::Record::qsearchs('conf', $hashref); - if (!$cv && exists($hashref->{agent})) { - delete($hashref->{agent}); - $cv = FS::Record::qsearchs('conf', $hashref); - } - return $cv; -} - sub config { - my($self,$name,$agent)=@_; - my $cv = $self->_config($name, $agent) or return; - + my($self,$file)=@_; + my($dir)=$self->dir; + my $fh = new IO::File "<$dir/$file" or return; if ( wantarray ) { - split "\n", $cv->value; + map { + /^(.*)$/ + or die "Illegal line (array context) in $dir/$file:\n$_\n"; + $1; + } <$fh>; } else { - (split("\n", $cv->value))[0]; + <$fh> =~ /^(.*)$/ + or die "Illegal line (scalar context) in $dir/$file:\n$_\n"; + $1; } } @@ -111,9 +126,12 @@ Returns the exact scalar value for key. =cut sub config_binary { - my($self,$name,$agent)=@_; - my $cv = $self->_config($name, $agent) or return; - decode_base64($cv->value); + my($self,$file)=@_; + my($dir)=$self->dir; + my $fh = new IO::File "<$dir/$file" or return; + local $/; + my $content = <$fh>; + $content; } =item exists KEY @@ -124,8 +142,9 @@ is undefined. =cut sub exists { - my($self,$name,$agent)=@_; - defined($self->_config($name, $agent)); + my($self,$file)=@_; + my($dir) = $self->dir; + -e "$dir/$file"; } =item config_orbase KEY SUFFIX @@ -136,11 +155,11 @@ KEY_SUFFIX, if it exists, otherwise for KEY =cut sub config_orbase { - my( $self, $name, $suffix ) = @_; - if ( $self->exists("${name}_$suffix") ) { - $self->config("${name}_$suffix"); + my( $self, $file, $suffix ) = @_; + if ( $self->exists("${file}_$suffix") ) { + $self->config("${file}_$suffix"); } else { - $self->config($name); + $self->config($file); } } @@ -151,8 +170,12 @@ Creates the specified configuration key if it does not exist. =cut sub touch { - my($self, $name, $agent) = @_; - $self->set($name, '', $agent); + my($self, $file) = @_; + my $dir = $self->dir; + unless ( $self->exists($file) ) { + warn "[FS::Conf] TOUCH $file\n" if $DEBUG; + system('touch', "$dir/$file"); + } } =item set KEY VALUE @@ -162,41 +185,23 @@ Sets the specified configuration key to the given value. =cut sub set { - my($self, $name, $value, $agent) = @_; + my($self, $file, $value) = @_; + my $dir = $self->dir; $value =~ /^(.*)$/s; $value = $1; - - warn "[FS::Conf] SET $file\n" if $DEBUG; - - my $old = FS::Record::qsearchs('conf', {name => $name, agent => $agent}); - my $new = new FS::conf { $old ? $old->hash - : ('name' => $name, 'agent' => $agent) - }; - $new->value($value); - - my $error; - if ($old) { - $error = $new->replace($old); - } else { - $error = $new->insert; + unless ( join("\n", @{[ $self->config($file) ]}) eq $value ) { + warn "[FS::Conf] SET $file\n" if $DEBUG; +# warn "$dir" if is_tainted($dir); +# warn "$dir" if is_tainted($file); + chmod 0644, "$dir/$file"; + my $fh = new IO::File ">$dir/$file" or return; + chmod 0644, "$dir/$file"; + print $fh "$value\n"; } - - die "error setting configuration value: $error \n" - if $error; - -} - -=item set_binary KEY VALUE - -Sets the specified configuration key to an exact scalar value which -can be retrieved with config_binary. - -=cut - -sub set_binary { - my($self,$name, $value, $agent)=@_; - $self->set($name, encode_base64($value), $agent); } +#sub is_tainted { +# return ! eval { join('',@_), kill 0; 1; }; +# } =item delete KEY @@ -205,23 +210,11 @@ Deletes the specified configuration key. =cut sub delete { - my($self, $name, $agent) = @_; - if ( my $cv = FS::Record::qsearchs('conf', {name => $name, agent => $agent}) ) { + my($self, $file) = @_; + my $dir = $self->dir; + if ( $self->exists($file) ) { warn "[FS::Conf] DELETE $file\n"; - - my $oldAutoCommit = $FS::UID::AutoCommit; - local $FS::UID::AutoCommit = 0; - my $dbh = dbh; - - my $error = $cv->delete; - - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - die "error setting configuration value: $error \n" - } - - $dbh->commit or die $dbh->errstr if $oldAutoCommit; - + unlink "$dir/$file"; } } @@ -237,68 +230,65 @@ sub config_items { #quelle kludge @config_items, ( map { + my $basename = basename($_); + $basename =~ /^(.*)$/; + $basename = $1; new FS::ConfItem { - 'key' => $_->name, + 'key' => $basename, 'section' => 'billing', 'description' => 'Alternate template file for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.', 'type' => 'textarea', } - } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_template!_%' ESCAPE '!'") + } glob($self->dir. '/invoice_template_*') ), ( map { + my $basename = basename($_); + $basename =~ /^(.*)$/; + $basename = $1; new FS::ConfItem { - 'key' => '$_->name', - 'section' => 'billing', #? - 'description' => 'An image to include in some types of invoices', - 'type' => 'binary', - } - } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'logo!_%.png' ESCAPE '!'") - ), - ( map { - new FS::ConfItem { - 'key' => $_->name, + 'key' => $basename, 'section' => 'billing', 'description' => 'Alternate HTML template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.', 'type' => 'textarea', } - } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_html!_%' ESCAPE '!'") + } glob($self->dir. '/invoice_html_*') ), ( map { - ($latexname = $_->name ) =~ s/latex/html/; + my $basename = basename($_); + $basename =~ /^(.*)$/; + $basename = $1; + ($latexname = $basename ) =~ s/latex/html/; new FS::ConfItem { - 'key' => $_->name, + 'key' => $basename, 'section' => 'billing', 'description' => "Alternate Notes section for HTML invoices. Defaults to the same data in $latexname if not specified.", 'type' => 'textarea', } - } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_htmlnotes!_%' ESCAPE '!'") + } glob($self->dir. '/invoice_htmlnotes_*') ), ( map { + my $basename = basename($_); + $basename =~ /^(.*)$/; + $basename = $1; new FS::ConfItem { - 'key' => $_->name, + 'key' => $basename, 'section' => 'billing', 'description' => 'Alternate LaTeX template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.', 'type' => 'textarea', } - } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_latex!_%' ESCAPE '!'") - ), - ( map { - new FS::ConfItem { - 'key' => '$_->name', - 'section' => 'billing', #? - 'description' => 'An image to include in some types of invoices', - 'type' => 'binary', - } - } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'logo!_%.eps' ESCAPE '!'") + } glob($self->dir. '/invoice_latex_*') ), ( map { + my $basename = basename($_); + $basename =~ /^(.*)$/; + $basename = $1; new FS::ConfItem { - 'key' => $_->name, + 'key' => $basename, 'section' => 'billing', 'description' => 'Alternate Notes section for LaTeX typeset PostScript invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.', 'type' => 'textarea', } - } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_latexnotes!_%' ESCAPE '!'") + } glob($self->dir. '/invoice_latexnotes_*') ); } @@ -1852,6 +1842,26 @@ httemplate/docs/config.html 'type' => 'checkbox', }, + #these should become per-user... + { + 'key' => 'vonage-username', + 'section' => '', + 'description' => 'Vonage Click2Call username (see <a href="https://secure.click2callu.com/">https://secure.click2callu.com/</a>)', + 'type' => 'text', + }, + { + 'key' => 'vonage-password', + 'section' => '', + 'description' => 'Vonage Click2Call username (see <a href="https://secure.click2callu.com/">https://secure.click2callu.com/</a>)', + 'type' => 'text', + }, + { + 'key' => 'vonage-fromnumber', + 'section' => '', + 'description' => 'Vonage Click2Call number (see <a href="https://secure.click2callu.com/">https://secure.click2callu.com/</a>)', + 'type' => 'text', + }, + { 'key' => 'echeck-nonus', 'section' => 'billing', @@ -2036,27 +2046,6 @@ httemplate/docs/config.html }, { - 'key' => 'logo.png', - 'section' => 'billing', #? - 'description' => 'An image to include in some types of invoices', - 'type' => 'binary', - }, - - { - 'key' => 'logo.eps', - 'section' => 'billing', #? - 'description' => 'An image to include in some types of invoices', - 'type' => 'binary', - }, - - { - 'key' => 'selfservice-ignore_quantity', - 'section' => '', - 'description' => 'Ignores service quantity restrictions in self-service context. Strongly not recommended - just set your quantities correctly in the first place.', - 'type' => 'checkbox', - }, - - { 'key' => 'disable_setup_suspended_pkgs', 'section' => 'billing', 'description' => 'Disables charging of setup fees for suspended packages.', diff --git a/FS/FS/Cron/bill.pm b/FS/FS/Cron/bill.pm index 4d77fd08d..fb9e5499d 100644 --- a/FS/FS/Cron/bill.pm +++ b/FS/FS/Cron/bill.pm @@ -94,8 +94,7 @@ END } $cust_main->ncancelled_pkgs ) { - my $action = $cust_pkg->part_pkg->option('recur_action') || 'suspend'; - my $error = $cust_pkg->$action(); + my $error = $cust_pkg->suspend; warn "Error suspending package ". $cust_pkg->pkgnum. " for custnum ". $cust_main->custnum. ": $error" diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index 0afe3ecd1..913e44e21 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -1339,41 +1339,6 @@ sub ut_floatn { } } -=item ut_sfloat COLUMN - -Check/untaint signed floating point numeric data: 1.1, 1, 1.1e10, 1e10. -May not be null. If there is an error, returns the error, otherwise returns -false. - -=cut - -sub ut_sfloat { - my($self,$field)=@_ ; - ($self->getfield($field) =~ /^(-?\d+\.\d+)$/ || - $self->getfield($field) =~ /^(-?\d+)$/ || - $self->getfield($field) =~ /^(-?\d+\.\d+[eE]-?\d+)$/ || - $self->getfield($field) =~ /^(-?\d+[eE]-?\d+)$/) - or return "Illegal or empty (float) $field: ". $self->getfield($field); - $self->setfield($field,$1); - ''; -} -=item ut_sfloatn COLUMN - -Check/untaint signed floating point numeric data: 1.1, 1, 1.1e10, 1e10. May be -null. If there is an error, returns the error, otherwise returns false. - -=cut - -sub ut_sfloatn { - my( $self, $field ) = @_; - if ( $self->getfield($field) =~ /^()$/ ) { - $self->setfield($field,''); - ''; - } else { - $self->ut_sfloat($field); - } -} - =item ut_snumber COLUMN Check/untaint signed numeric data (whole numbers). If there is an error, diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 84078fad8..3b7030693 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -842,9 +842,8 @@ sub tables_hashref { 'svc_acct' => { 'columns' => [ 'svcnum', 'int', '', '', '', '', - 'username', 'varchar', '', $username_len, '', '', - '_password', 'varchar', '', 512, '', '', - '_password_encoding', 'varchar', 'NULL', $char_d, '', '', + 'username', 'varchar', '', $username_len, '', '', #unique (& remove dup code) + '_password', 'varchar', '', 72, '', '', #13 for encryped pw's plus ' *SUSPENDED* (md5 passwords can be 34, blowfish 60) 'sec_phrase', 'varchar', 'NULL', $char_d, '', '', 'popnum', 'int', 'NULL', '', '', '', 'uid', 'int', 'NULL', '', '', '', @@ -1687,18 +1686,6 @@ sub tables_hashref { 'index' => [], }, - 'conf' => { - 'columns' => [ - 'confnum', 'serial', '', '', '', '', - 'agentnum', 'int', 'NULL', '', '', '', - 'name', 'varchar', '', $char_d, '', '', - 'value', 'varchar', 'NULL', '', '', '', # Pg specific - ], - 'primary_key' => 'confnum', - 'unique' => [ [ 'agentnum', 'name' ]], - 'index' => [], - }, - # name type nullability length default local #'new_table' => { diff --git a/FS/FS/UID.pm b/FS/FS/UID.pm index da573a698..8dd928ec7 100644 --- a/FS/FS/UID.pm +++ b/FS/FS/UID.pm @@ -4,7 +4,7 @@ use strict; use vars qw( @ISA @EXPORT_OK $cgi $dbh $freeside_uid $user $conf_dir $secrets $datasrc $db_user $db_pass %callback @callback - $driver_name $AutoCommit $callback_hack + $driver_name $AutoCommit ); use subs qw( getsecrets cgisetotaker @@ -12,7 +12,7 @@ use subs qw( use Exporter; use Carp qw(carp croak cluck confess); use DBI; -use IO::File; +use FS::Conf; use FS::CurrentUser; @ISA = qw(Exporter); @@ -24,7 +24,6 @@ $freeside_uid = scalar(getpwnam('freeside')); $conf_dir = "%%%FREESIDE_CONF%%%/"; $AutoCommit = 1; #ours, not DBI -$callback_hack = 0; =head1 NAME @@ -105,15 +104,13 @@ sub forksuidsetup { FS::CurrentUser->load_user($user); - unless($callback_hack) { - foreach ( keys %callback ) { - &{$callback{$_}}; - # breaks multi-database installs # delete $callback{$_}; #run once - } - - &{$_} foreach @callback; + foreach ( keys %callback ) { + &{$callback{$_}}; + # breaks multi-database installs # delete $callback{$_}; #run once } + &{$_} foreach @callback; + $dbh; } @@ -278,11 +275,11 @@ the `/usr/local/etc/freeside/mapsecrets' file. sub getsecrets { my($setuser) = shift; $user = $setuser if $setuser; + my($conf) = new FS::Conf $conf_dir; - if ( -e "$conf_dir/mapsecrets" ) { + if ( $conf->exists('mapsecrets') ) { die "No user!" unless $user; - my($line) = grep /^\s*($user|\*)\s/, - map { /^(.*)$/; $1 } readline(new IO::File "$conf_dir/mapsecrets"); + my($line) = grep /^\s*($user|\*)\s/, $conf->config('mapsecrets'); confess "User $user not found in mapsecrets!" unless $line; $line =~ /^\s*($user|\*)\s+(.*)$/; $secrets = $2; @@ -292,9 +289,9 @@ sub getsecrets { $secrets = 'secrets'; } - ($datasrc, $db_user, $db_pass) = - map { /^(.*)$/; $1 } readline(new IO::File "$conf_dir/$secrets") - or die "Can't get secrets: $secrets: $!\n"; + ($datasrc, $db_user, $db_pass) = $conf->config($secrets) + or die "Can't get secrets: $secrets: $!\n"; + $FS::Conf::default_dir = $conf_dir. "/conf.$datasrc"; undef $driver_name; ($datasrc, $db_user, $db_pass); } diff --git a/FS/FS/conf.pm b/FS/FS/conf.pm deleted file mode 100644 index 6126372cc..000000000 --- a/FS/FS/conf.pm +++ /dev/null @@ -1,114 +0,0 @@ -package FS::conf; - -use strict; -use vars qw( @ISA ); -use FS::Record qw( qsearch qsearchs ); - -@ISA = qw(FS::Record); - -=head1 NAME - -FS::conf - Object methods for conf records - -=head1 SYNOPSIS - - use FS::conf; - - $record = new FS::conf \%hash; - $record = new FS::conf { 'column' => 'value' }; - - $error = $record->insert; - - $error = $new_record->replace($old_record); - - $error = $record->delete; - - $error = $record->check; - -=head1 DESCRIPTION - -An FS::conf object represents a configuration value. FS::conf inherits from -FS::Record. The following fields are currently supported: - -=over 4 - -=item confnum - primary key - -=item agentnum - the agent to which this configuration value applies - -=item name - the name of the configuration value - -=item value - the configuration value - - -=back - -=head1 METHODS - -=over 4 - -=item new HASHREF - -Creates a new configuration value. To add the example to the database, see L<"insert">. - -Note that this stores the hash reference, not a distinct copy of the hash it -points to. You can ask the object for a copy with the I<hash> method. - -=cut - -sub table { 'conf'; } - -=item insert - -Adds this record to the database. If there is an error, returns the error, -otherwise returns false. - -=cut - -=item delete - -Delete this record from the database. - -=cut - -=item replace OLD_RECORD - -Replaces the OLD_RECORD with this one in the database. If there is an error, -returns the error, otherwise returns false. - -=cut - -=item check - -Checks all fields to make sure this is a valid configuration value. If there is -an error, returns the error, otherwise returns false. Called by the insert -and replace methods. - -=cut - -sub check { - my $self = shift; - - my $error = - $self->ut_numbern('confnum') - || $self->ut_foreign_keyn('agentnum', 'agent', 'agentnum') - || $self->ut_text('name') - || $self->ut_anything('value') - ; - return $error if $error; - - $self->SUPER::check; -} - -=back - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::Record>, schema.html from the base documentation. - -=cut - -1; - diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 13174487d..844d1b867 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -1827,8 +1827,7 @@ sub print_text { =item print_latex [ TIME [ , TEMPLATE ] ] Internal method - returns a filename of a filled-in LaTeX template for this -invoice (Note: add ".tex" to get the actual filename), and a filename of -an associated logo (with the .eps extension included). +invoice (Note: add ".tex" to get the actual filename). See print_ps and print_pdf for methods that return PostScript and PDF output. @@ -1910,7 +1909,6 @@ sub print_latex { 'quantity' => 1, 'terms' => $conf->config('invoice_default_terms') || 'Payable upon receipt', #'notes' => join("\n", $conf->config('invoice_latexnotes') ), - # better hang on to conf_dir for a while 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc", ); @@ -2136,22 +2134,6 @@ sub print_latex { } my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc; - my $lh = new File::Temp( TEMPLATE => 'invoice.'. $self->invnum. '.XXXXXXXX', - DIR => $dir, - SUFFIX => '.eps', - UNLINK => 0, - ) or die "can't open temp file: $!\n"; - - if ($template && $conf->exists("logo_${template}.eps")) { - print $lh $conf->config_binary("logo_${template}.eps") - or die "can't write temp file: $!\n"; - }else{ - print $lh $conf->config_binary('logo.eps') - or die "can't write temp file: $!\n"; - } - close $lh; - $invoice_data{'logo_file'} = $lh->filename; - my $fh = new File::Temp( TEMPLATE => 'invoice.'. $self->invnum. '.XXXXXXXX', DIR => $dir, SUFFIX => '.tex', @@ -2167,7 +2149,7 @@ sub print_latex { close $fh; $fh->filename =~ /^(.*).tex$/ or die "unparsable filename: ". $fh->filename; - return ($1, $invoice_data{'logo_file'}); + return $1; } @@ -2185,7 +2167,7 @@ L<Time::Local> and L<Date::Parse> for conversion functions. sub print_ps { my $self = shift; - my ($file, $lfile) = $self->print_latex(@_); + my $file = $self->print_latex(@_); my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc; chdir($dir); @@ -2204,7 +2186,6 @@ sub print_ps { or die "can't open $file.ps: $! (error in LaTeX template?)\n"; unlink("$file.dvi", "$file.log", "$file.aux", "$file.ps", "$file.tex"); - unlink("$lfile"); my $ps = ''; while (<POSTSCRIPT>) { @@ -2231,7 +2212,7 @@ L<Time::Local> and L<Date::Parse> for conversion functions. sub print_pdf { my $self = shift; - my ($file, $lfile) = $self->print_latex(@_); + my $file = $self->print_latex(@_); my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc; chdir($dir); @@ -2259,7 +2240,6 @@ sub print_pdf { or die "can't open $file.pdf: $! (error in LaTeX template?)\n"; unlink("$file.dvi", "$file.log", "$file.aux", "$file.pdf", "$file.tex"); - unlink("$lfile"); my $pdf = ''; while (<PDF>) { diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index f6270e1d4..4066b8f4b 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -417,7 +417,7 @@ sub start_copy_skel { #'mg_watchlist_header.watchlist_header_id' => { 'mg_watchlist_details.watchlist_details_id' }, #'mg_user_grid_header.grid_header_id' => { 'mg_user_grid_details.user_grid_details_id' }, #'mg_portfolio_header.portfolio_header_id' => { 'mg_portfolio_trades.portfolio_trades_id' => { 'mg_portfolio_trades_positions.portfolio_trades_positions_id' } }, - my @tables = eval(join('\n',$conf->config('cust_main-skeleton_tables'))); + my @tables = eval($conf->config_binary('cust_main-skeleton_tables')); die $@ if $@; _copy_skel( 'cust_main', #tablename @@ -4115,8 +4115,7 @@ sub fuzzy_search { Accepts the following options: I<search>, the string to search for. The string will be searched for as a customer number, phone number, name or company name, as an exact, or, in some cases, a substring or fuzzy match (see the source code -for the exact heuristics used); I<no_fuzzy_on_exact>, causes smart_search to -skip fuzzy matching when an exact match is found. +for the exact heuristics used). Any additional options are treated as an additional qualifier on the search (i.e. I<agentnum>). @@ -4133,7 +4132,6 @@ sub smart_search { my @cust_main = (); - my $skip_fuzzy = delete $options{'no_fuzzy_on_exact'}; my $search = delete $options{'search'}; ( my $alphanum_search = $search ) =~ s/\W//g; @@ -4271,7 +4269,7 @@ sub smart_search { #always do substring & fuzzy, #getting complains searches are not returning enough - unless ( @cust_main && $skip_fuzzy ) { #no exact match, trying substring/fuzzy + #unless ( @cust_main ) { #no exact match, trying substring/fuzzy #still some false laziness w/ search/cust_main.cgi @@ -4332,7 +4330,7 @@ sub smart_search { FS::cust_main->fuzzy_search( { $field => $value }, @fuzopts ); } - } + #} #eliminate duplicates my %saw = (); @@ -4722,7 +4720,7 @@ sub batch_charge { =item notify CUSTOMER_OBJECT TEMPLATE_NAME OPTIONS -Sends a templated email notification to the customer (see L<Text::Template>). +Sends a templated email notification to the customer (see L<Text::Template). OPTIONS is a hash and may include diff --git a/FS/FS/part_export/prizm.pm b/FS/FS/part_export/prizm.pm index ca02b8f3e..711888d1f 100644 --- a/FS/FS/part_export/prizm.pm +++ b/FS/FS/part_export/prizm.pm @@ -43,7 +43,7 @@ sub _export_insert { my $cust_main = $svc->cust_svc->cust_pkg->cust_main; - my $err_or_som = $self->prizm_command('CustomerIfService', 'getCustomers', + my $err_or_som = $self->prizm_command(CustomerIfService, 'getCustomers', ['import_id'], [$cust_main->custnum], ['='], @@ -118,7 +118,7 @@ sub _export_insert { $err_or_som = $self->prizm_command('NetworkIfService', 'addProvisionedElement', $networkid, $svc->mac_addr, - $name, # we fix this below (bug in prizm?) + $name . " " . $svc->description, $location, $contact, sprintf("%032X", $svc->authkey), @@ -141,7 +141,7 @@ sub _export_insert { $svc->latitude, $svc->longitude, $svc->altitude, - $name . " " . $svc->description, + $name, $location, $contact, ); diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm index 29e0a5799..b43033405 100644 --- a/FS/FS/part_export/shellcommands.pm +++ b/FS/FS/part_export/shellcommands.pm @@ -157,13 +157,12 @@ old_ for replace operations): <LI><code>$username</code> <LI><code>$_password</code> <LI><code>$quoted_password</code> - unencrypted password, already quoted for the shell (do not add additional quotes). - <LI><code>$crypt_password</code> - encrypted password. When used on the command line (rather than STDIN), it will be quoted for the shell already (do not add additional quotes). - <LI><code>$ldap_password</code> - Password in LDAP/RFC2307 format (for example, "{PLAIN}himom", "{CRYPT}94pAVyK/4oIBk" or "{MD5}5426824942db4253f87a1009fd5d2d4"). When used on the command line (rather than STDIN), it will be quoted for the shell already (do not add additional quotes). + <LI><code>$crypt_password</code> - encrypted password. When used on the command line (rather than STDIN), it will be already quoted for the shell (do not add additional quotes). <LI><code>$uid</code> <LI><code>$gid</code> - <LI><code>$finger</code> - GECOS. When used on the command line (rather than STDIN), it will be quoted for the shell already (do not add additional quotes). - <LI><code>$first</code> - First name of GECOS. When used on the command line (rather than STDIN), it will be quoted for the shell already (do not add additional quotes). - <LI><code>$last</code> - Last name of GECOS. When used on the command line (rather than STDIN), it will be quoted for the shell already (do not add additional quotes). + <LI><code>$finger</code> - GECOS. When used on the command line (rather than STDIN), it will be already quoted for the shell (do not add additional quotes). + <LI><code>$first</code> - First name of GECOS. When used on the command line (rather than STDIN), it will be already quoted for the shell (do not add additional quotes). + <LI><code>$last</code> - Last name of GECOS. When used on the command line (rather than STDIN), it will be already quoted for the shell (do not add additional quotes). <LI><code>$dir</code> - home directory <LI><code>$shell</code> <LI><code>$quota</code> @@ -250,7 +249,6 @@ sub _export_command { $quoted_password = shell_quote $_password; $crypt_password = $svc_acct->crypt_password( $self->option('crypt') ); - $ldap_password = $svc_acct->ldap_password( $self->option('crypt') ); @radius_groups = $svc_acct->radius_groups; @@ -293,7 +291,6 @@ sub _export_command { $last = shell_quote $last; $finger = shell_quote $finger; $crypt_password = shell_quote $crypt_password; - $ldap_password = shell_quote $ldap_password; my $command_string = eval(qq("$command")); @@ -323,7 +320,6 @@ sub _export_replace { $new_domain = $new->domain; $new_crypt_password = $new->crypt_password( $self->option('crypt') ); - $new_ldap_password = $new->ldap_password( $self->option('crypt') ); @old_radius_groups = $old->radius_groups; @new_radius_groups = $new->radius_groups; @@ -361,7 +357,6 @@ sub _export_replace { $new_last = shell_quote $new_last; $new_finger = shell_quote $new_finger; $new_crypt_password = shell_quote $new_crypt_password; - $new_ldap_password = shell_quote $new_ldap_password; my $command_string = eval(qq("$command")); diff --git a/FS/FS/part_pkg/base_delayed.pm b/FS/FS/part_pkg/base_delayed.pm deleted file mode 100644 index ddd4caf73..000000000 --- a/FS/FS/part_pkg/base_delayed.pm +++ /dev/null @@ -1,51 +0,0 @@ -package FS::part_pkg::base_delayed; - -use strict; -use vars qw(@ISA %info); -#use FS::Record qw(qsearch qsearchs); -use FS::part_pkg::base_rate; - -@ISA = qw(FS::part_pkg::base_rate); - -%info = ( - 'name' => 'Free (or setup fee) for X days, then base rate'. - ' (anniversary billing)', - 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'free_days' => { 'name' => 'Initial free days', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring base fee for this package', - 'default' => 0, - }, - 'recur_notify' => { 'name' => 'Number of days before recurring billing'. - 'commences to notify customer. (0 means '. - 'no warning)', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - }, - 'fieldorder' => [ 'free_days', 'setup_fee', 'recur_fee', 'recur_notify', - 'unused_credit' - ], - #'setup' => '\'my $d = $cust_pkg->bill || $time; $d += 86400 * \' + what.free_days.value + \'; $cust_pkg->bill($d); $cust_pkg_mod_flag=1; \' + what.setup_fee.value', - #'recur' => 'what.recur_fee.value', - 'weight' => 50, -); - -sub calc_setup { - my($self, $cust_pkg, $time ) = @_; - - my $d = $cust_pkg->bill || $time; - $d += 86400 * $self->option('free_days'); - $cust_pkg->bill($d); - - $self->option('setup_fee'); -} - -1; diff --git a/FS/FS/part_pkg/base_rate.pm b/FS/FS/part_pkg/base_rate.pm deleted file mode 100644 index 9e64184ab..000000000 --- a/FS/FS/part_pkg/base_rate.pm +++ /dev/null @@ -1,102 +0,0 @@ -package FS::part_pkg::base_rate; - -use strict; -use vars qw(@ISA %info); -#use FS::Record qw(qsearch); -use FS::part_pkg; - -@ISA = qw(FS::part_pkg); - -%info = ( - 'name' => 'Base rate (anniversary billing, Times units ordered)', - 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring Base fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - 'externalid' => { 'name' => 'Optional External ID', - 'default' => '', - }, - }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', - 'externalid' ], - 'weight' => 10, -); - -sub calc_setup { - my($self, $cust_pkg, $sdate, $details ) = @_; - - my $i = 0; - my $count = $self->option( 'additional_count', 'quiet' ) || 0; - while ($i < $count) { - push @$details, $self->option( 'additional_info' . $i++ ); - } - - $self->option('setup_fee'); -} - -sub calc_recur { - my($self, $cust_pkg) = @_; - $self->reset_usage($cust_pkg); - $self->base_recur($cust_pkg); -} - -sub base_recur { - my($self, $cust_pkg) = @_; - my $units = $cust_pkg->option('units') ? $cust_pkg->option('units') : 1 ; - # default to 1 if not found - sprintf("%.2f", - ($self->option('recur_fee') * $units ) - ); -} - -sub calc_remain { - my ($self, $cust_pkg) = @_; - my $time = time; #should be able to pass this in for credit calculation - my $next_bill = $cust_pkg->getfield('bill') || 0; - my $last_bill = $cust_pkg->last_bill || 0; - return 0 if ! $self->base_recur - || ! $self->option('unused_credit', 1) - || ! $last_bill - || ! $next_bill - || $next_bill < $time; - - my %sec = ( - 'h' => 3600, # 60 * 60 - 'd' => 86400, # 60 * 60 * 24 - 'w' => 604800, # 60 * 60 * 24 * 7 - 'm' => 2629744, # 60 * 60 * 24 * 365.2422 / 12 - ); - - $self->freq =~ /^(\d+)([hdwm]?)$/ - or die 'unparsable frequency: '. $self->freq; - my $freq_sec = $1 * $sec{$2||'m'}; - return 0 unless $freq_sec; - - sprintf("%.2f", $self->base_recur * ( $next_bill - $time ) / $freq_sec ); - -} - -sub is_free_options { - qw( setup_fee recur_fee ); -} - -sub is_prepaid { - 0; #no, we're postpaid -} - -sub reset_usage { - my($self, $cust_pkg) = @_; - my %values = map { $_, $self->option($_) } - grep { $self->option($_, 'hush') } - qw(seconds upbytes downbytes totalbytes); - $cust_pkg->set_usage(\%values); -} - -1; diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm index 2341fd020..500a1b0a4 100644 --- a/FS/FS/part_pkg/voip_cdr.pm +++ b/FS/FS/part_pkg/voip_cdr.pm @@ -130,7 +130,7 @@ sub calc_recur { ### my( $to_or_from, $number ); - if ( $cdr->dst =~ /^(\+?1)?8([02-8])\1/ ) { #tollfree call + if ( $cdr->dst =~ /^(\+?1)?8[02-8]{2}/ ) { #tollfree call $to_or_from = 'from'; $number = $cdr->src; } else { #regular call diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index 3a625f791..f7b76e7b4 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -8,6 +8,8 @@ use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles $username_noperiod $username_nounderscore $username_nodash $username_uppercase $username_percent $password_noampersand $password_noexclamation + $welcome_template $welcome_from + $welcome_subject $welcome_subject_template $welcome_mimetype $warning_template $warning_from $warning_subject $warning_mimetype $warning_cc $smtpmachine @@ -19,7 +21,6 @@ use Fcntl qw(:flock); use Date::Format; use Crypt::PasswdMD5 1.2; use Data::Dumper; -use Authen::Passphrase; use FS::UID qw( datasrc ); use FS::Conf; use FS::Record qw( qsearch qsearchs fields dbh dbdef ); @@ -64,6 +65,24 @@ $FS::UID::callback{'FS::svc_acct'} = sub { $password_noampersand = $conf->exists('password-noexclamation'); $password_noexclamation = $conf->exists('password-noexclamation'); $dirhash = $conf->config('dirhash') || 0; + if ( $conf->exists('welcome_email') ) { + $welcome_template = new Text::Template ( + TYPE => 'ARRAY', + SOURCE => [ map "$_\n", $conf->config('welcome_email') ] + ) or warn "can't create welcome email template: $Text::Template::ERROR"; + $welcome_from = $conf->config('welcome_email-from'); # || 'your-isp-is-dum' + $welcome_subject = $conf->config('welcome_email-subject') || 'Welcome'; + $welcome_subject_template = new Text::Template ( + TYPE => 'STRING', + SOURCE => $welcome_subject, + ) or warn "can't create welcome email subject template: $Text::Template::ERROR"; + $welcome_mimetype = $conf->config('welcome_email-mimetype') || 'text/plain'; + } else { + $welcome_template = ''; + $welcome_from = ''; + $welcome_subject = ''; + $welcome_mimetype = ''; + } if ( $conf->exists('warning_email') ) { $warning_template = new Text::Template ( TYPE => 'ARRAY', @@ -152,8 +171,6 @@ FS::svc_Common. The following fields are currently supported: =item _password - generated if blank -=item _password_encoding - plain, crypt, ldap (or empty for autodetection) - =item sec_phrase - security phrase =item popnum - Point of presence (see L<FS::svc_acct_pop>) @@ -447,7 +464,6 @@ sub insert { if ( $cust_pkg ) { my $cust_main = $cust_pkg->cust_main; - my $agentnum = $cust_main->agentnum; if ( $conf->exists('emailinvoiceautoalways') || $conf->exists('emailinvoiceauto') @@ -459,25 +475,7 @@ sub insert { } #welcome email - my ($to,$welcome_template,$welcome_from,$welcome_subject,$welcome_subject_template,$welcome_mimetype) - = ('','','','','',''); - - if ( $conf->exists('welcome_email', $agentnum) ) { - $welcome_template = new Text::Template ( - TYPE => 'ARRAY', - SOURCE => [ map "$_\n", $conf->config('welcome_email', $agentnum) ] - ) or warn "can't create welcome email template: $Text::Template::ERROR"; - $welcome_from = $conf->config('welcome_email-from', $agentnum); - # || 'your-isp-is-dum' - $welcome_subject = $conf->config('welcome_email-subject', $agentnum) - || 'Welcome'; - $welcome_subject_template = new Text::Template ( - TYPE => 'STRING', - SOURCE => $welcome_subject, - ) or warn "can't create welcome email subject template: $Text::Template::ERROR"; - $welcome_mimetype = $conf->config('welcome_email-mimetype', $agentnum) - || 'text/plain'; - } + my $to = ''; if ( $welcome_template && $cust_pkg ) { my $to = join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list ); if ( $to ) { @@ -885,9 +883,6 @@ sub check { || $self->ut_snumbern('upbytes') || $self->ut_snumbern('downbytes') || $self->ut_snumbern('totalbytes') - || $self->ut_enum( '_password_encoding', - [ '', qw( plain crypt ldap ) ] - ) ; return $error if $error; @@ -919,6 +914,12 @@ sub check { unless ( $username_ampersand ) { $recref->{username} =~ /\&/ and return gettext('illegal_username'); } + if ( $password_noampersand ) { + $recref->{_password} =~ /\&/ and return gettext('illegal_password'); + } + if ( $password_noexclamation ) { + $recref->{_password} =~ /\!/ and return gettext('illegal_password'); + } unless ( $username_percent ) { $recref->{username} =~ /\%/ and return gettext('illegal_username'); } @@ -948,7 +949,7 @@ sub check { $recref->{shell} = (grep $_ eq $recref->{shell}, @shells)[0]; } else { return "Illegal shell \`". $self->shell. "\'; ". - "shells configuration value contains: @shells"; + $conf->dir. "/shells contains: @shells"; } } else { $recref->{shell} = '/bin/sync'; @@ -1026,92 +1027,36 @@ sub check { $self->ut_textn($_); } - if ( $recref->{_password_encoding} eq 'ldap' ) { - - if ( $recref->{_password} =~ /^(\{[\w\-]+\})(!?.{0,64})$/ ) { - $recref->{_password} = uc($1).$2; - } else { - return 'Illegal (ldap-encoded) password: '. $recref->{_password}; - } - - } elsif ( $recref->{_password_encoding} eq 'crypt' ) { - - if ( $recref->{_password} =~ - #/^(\$\w+\$.*|[\w\+\/]{13}|_[\w\+\/]{19}|\*)$/ - /^(!!?)?(\$\w+\$.*|[\w\+\/]{13}|_[\w\+\/]{19}|\*)$/ - ) { - - $recref->{_password} = $1.$2; - - } else { - return 'Illegal (crypt-encoded) password'; - } - - } elsif ( $recref->{_password_encoding} eq 'plain' ) { - - #generate a password if it is blank - $recref->{_password} = join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) ) - unless length( $recref->{_password} ); - - if ( $recref->{_password} =~ /^([^\t\n]{$passwordmin,$passwordmax})$/ ) { - $recref->{_password} = $1; - } else { - return gettext('illegal_password'). " $passwordmin-$passwordmax ". - FS::Msgcat::_gettext('illegal_password_characters'). - ": ". $recref->{_password}; - } - - if ( $password_noampersand ) { - $recref->{_password} =~ /\&/ and return gettext('illegal_password'); - } - if ( $password_noexclamation ) { - $recref->{_password} =~ /\!/ and return gettext('illegal_password'); - } - + #generate a password if it is blank + $recref->{_password} = join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) ) + unless ( $recref->{_password} ); + + #if ( $recref->{_password} =~ /^((\*SUSPENDED\* )?)([^\t\n]{4,16})$/ ) { + if ( $recref->{_password} =~ /^((\*SUSPENDED\* |!!?)?)([^\t\n]{$passwordmin,$passwordmax})$/ ) { + $recref->{_password} = $1.$3; + #uncomment this to encrypt password immediately upon entry, or run + #bin/crypt_pw in cron to give new users a window during which their + #password is available to techs, for faxing, etc. (also be aware of + #radius issues!) + #$recref->{password} = $1. + # crypt($3,$saltset[int(rand(64))].$saltset[int(rand(64))] + #; + } elsif ( $recref->{_password} =~ /^((\*SUSPENDED\* |!!?)?)([\w\.\/\$\;\+]{13,64})$/ ) { + $recref->{_password} = $1.$3; + } elsif ( $recref->{_password} eq '*' ) { + $recref->{_password} = '*'; + } elsif ( $recref->{_password} eq '!' ) { + $recref->{_password} = '!'; + } elsif ( $recref->{_password} eq '!!' ) { + $recref->{_password} = '!!'; } else { - - #carp "warning: _password_encoding unspecified\n"; - - #generate a password if it is blank - unless ( length( $recref->{_password} ) ) { - - $recref->{_password} = - join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) ); - $recref->{_password_encoding} = 'plain'; - - } else { - - #if ( $recref->{_password} =~ /^((\*SUSPENDED\* )?)([^\t\n]{4,16})$/ ) { - if ( $recref->{_password} =~ /^((\*SUSPENDED\* |!!?)?)([^\t\n]{$passwordmin,$passwordmax})$/ ) { - $recref->{_password} = $1.$3; - $recref->{_password_encoding} = 'plain'; - } elsif ( $recref->{_password} =~ - /^((\*SUSPENDED\* |!!?)?)([\w\.\/\$\;\+]{13,64})$/ - ) { - $recref->{_password} = $1.$3; - $recref->{_password_encoding} = 'crypt'; - } elsif ( $recref->{_password} eq '*' ) { - $recref->{_password} = '*'; - $recref->{_password_encoding} = 'crypt'; - } elsif ( $recref->{_password} eq '!' ) { - $recref->{_password_encoding} = 'crypt'; - $recref->{_password} = '!'; - } elsif ( $recref->{_password} eq '!!' ) { - $recref->{_password} = '!!'; - $recref->{_password_encoding} = 'crypt'; - } else { - #return "Illegal password"; - return gettext('illegal_password'). " $passwordmin-$passwordmax ". - FS::Msgcat::_gettext('illegal_password_characters'). - ": ". $recref->{_password}; - } - - } - + #return "Illegal password"; + return gettext('illegal_password'). " $passwordmin-$passwordmax ". + FS::Msgcat::_gettext('illegal_password_characters'). + ": ". $recref->{_password}; } $self->SUPER::check; - } =item _check_system @@ -1963,42 +1908,23 @@ sub check_password { #self-service and pay up ( my $password = $self->_password ) =~ s/^\*SUSPENDED\* //; - if ( $self->_password_encoding eq 'ldap' ) { - - my $auth = from_rfc2307 Authen::Passphrase $self->_password; - return $auth->match($check_password); - - } elsif ( $self->_password_encoding eq 'crypt' ) { - - my $auth = from_crypt Authen::Passphrase $self->_password; - return $auth->match($check_password); - - } elsif ( $self->_password_encoding eq 'plain' ) { - - return $check_password eq $password; - + #eventually should check a "password-encoding" field + if ( $password =~ /^(\*|!!?)$/ ) { #no self-service login + return 0; + } elsif ( length($password) < 13 ) { #plaintext + $check_password eq $password; + } elsif ( length($password) == 13 ) { #traditional DES crypt + crypt($check_password, $password) eq $password; + } elsif ( $password =~ /^\$1\$/ ) { #MD5 crypt + unix_md5_crypt($check_password, $password) eq $password; + } elsif ( $password =~ /^\$2a?\$/ ) { #Blowfish + warn "Can't check password: Blowfish encryption not yet supported, svcnum". + $self->svcnum. "\n"; + 0; } else { - - #XXX this could be replaced with Authen::Passphrase stuff - - if ( $password =~ /^(\*|!!?)$/ ) { #no self-service login - return 0; - } elsif ( length($password) < 13 ) { #plaintext - $check_password eq $password; - } elsif ( length($password) == 13 ) { #traditional DES crypt - crypt($check_password, $password) eq $password; - } elsif ( $password =~ /^\$1\$/ ) { #MD5 crypt - unix_md5_crypt($check_password, $password) eq $password; - } elsif ( $password =~ /^\$2a?\$/ ) { #Blowfish - warn "Can't check password: Blowfish encryption not yet supported, ". - "svcnum ". $self->svcnum. "\n"; - 0; - } else { - warn "Can't check password: Unrecognized encryption for svcnum ". - $self->svcnum. "\n"; - 0; - } - + warn "Can't check password: Unrecognized encryption for svcnum ". + $self->svcnum. "\n"; + 0; } } @@ -2019,40 +1945,14 @@ database. sub crypt_password { my $self = shift; - - if ( $self->_password_encoding eq 'ldap' ) { - - if ( $self->_password =~ /^\{(PLAIN|CLEARTEXT)\}(.+)$/ ) { - my $plain = $2; - - #XXX this could be replaced with Authen::Passphrase stuff - - my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; - if ( $encryption eq 'crypt' ) { - crypt( - $self->_password, - $saltset[int(rand(64))].$saltset[int(rand(64))] - ); - } elsif ( $encryption eq 'md5' ) { - unix_md5_crypt( $self->_password ); - } elsif ( $encryption eq 'blowfish' ) { - croak "unknown encryption method $encryption"; - } else { - croak "unknown encryption method $encryption"; - } - - } elsif ( $self->_password =~ /^\{CRYPT\}(.+)$/ ) { - $1; - } - - } elsif ( $self->_password_encoding eq 'crypt' ) { - - return $self->_password; - - } elsif ( $self->_password_encoding eq 'plain' ) { - - #XXX this could be replaced with Authen::Passphrase stuff - + #eventually should check a "password-encoding" field + if ( length($self->_password) == 13 + || $self->_password =~ /^\$(1|2a?)\$/ + || $self->_password =~ /^(\*|NP|\*LK\*|!!?)$/ + ) + { + $self->_password; + } else { my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; if ( $encryption eq 'crypt' ) { crypt( @@ -2066,44 +1966,14 @@ sub crypt_password { } else { croak "unknown encryption method $encryption"; } - - } else { - - if ( length($self->_password) == 13 - || $self->_password =~ /^\$(1|2a?)\$/ - || $self->_password =~ /^(\*|NP|\*LK\*|!!?)$/ - ) - { - $self->_password; - } else { - - #XXX this could be replaced with Authen::Passphrase stuff - - my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; - if ( $encryption eq 'crypt' ) { - crypt( - $self->_password, - $saltset[int(rand(64))].$saltset[int(rand(64))] - ); - } elsif ( $encryption eq 'md5' ) { - unix_md5_crypt( $self->_password ); - } elsif ( $encryption eq 'blowfish' ) { - croak "unknown encryption method $encryption"; - } else { - croak "unknown encryption method $encryption"; - } - - } - } - } =item ldap_password [ DEFAULT_ENCRYPTION_TYPE ] Returns an encrypted password in "LDAP" format, with a curly-bracked prefix -describing the format, for example, "{PLAIN}himom", "{CRYPT}94pAVyK/4oIBk" or -"{MD5}5426824942db4253f87a1009fd5d2d4". +describing the format, for example, "{CRYPT}94pAVyK/4oIBk" or +"{PLAIN-MD5}5426824942db4253f87a1009fd5d2d4f". The optional DEFAULT_ENCRYPTION_TYPE is not yet used, but the idea is for it to work the same as the B</crypt_password> method. @@ -2113,71 +1983,33 @@ to work the same as the B</crypt_password> method. sub ldap_password { my $self = shift; #eventually should check a "password-encoding" field - - if ( $self->_password_encoding eq 'ldap' ) { - - return $self->_password; - - } elsif ( $self->_password_encoding eq 'crypt' ) { - - if ( length($self->_password) == 13 ) { #crypt - return '{CRYPT}'. $self->_password; - } elsif ( $self->_password =~ /^\$1\$(.*)$/ && length($1) == 31 ) { #passwdMD5 - return '{MD5}'. $1; - #} elsif ( $self->_password =~ /^\$2a?\$(.*)$/ ) { #Blowfish - # die "Blowfish encryption not supported in this context, svcnum ". - # $self->svcnum. "\n"; - } else { - warn "encryption method not (yet?) supported in LDAP context"; - return '{CRYPT}*'; #unsupported, should not auth - } - - } elsif ( $self->_password_encoding eq 'plain' ) { - + if ( length($self->_password) == 13 ) { #crypt + return '{CRYPT}'. $self->_password; + } elsif ( $self->_password =~ /^\$1\$(.*)$/ && length($1) == 31 ) { #passwdMD5 + return '{MD5}'. $1; + } elsif ( $self->_password =~ /^\$2a?\$(.*)$/ ) { #Blowfish + die "Blowfish encryption not supported in this context, svcnum ". + $self->svcnum. "\n"; + } elsif ( $self->_password =~ /^(\w{48})$/ ) { #LDAP SSHA + return '{SSHA}'. $1; + } elsif ( $self->_password =~ /^(\w{64})$/ ) { #LDAP NS-MTA-MD5 + return '{NS-MTA-MD5}'. $1; + } else { #plaintext return '{PLAIN}'. $self->_password; - - #return '{CLEARTEXT}'. $self->_password; #? - - } else { - - if ( length($self->_password) == 13 ) { #crypt - return '{CRYPT}'. $self->_password; - } elsif ( $self->_password =~ /^\$1\$(.*)$/ && length($1) == 31 ) { #passwdMD5 - return '{MD5}'. $1; - } elsif ( $self->_password =~ /^\$2a?\$(.*)$/ ) { #Blowfish - warn "Blowfish encryption not supported in this context, svcnum ". - $self->svcnum. "\n"; - return '{CRYPT}*'; - - #are these two necessary anymore? - } elsif ( $self->_password =~ /^(\w{48})$/ ) { #LDAP SSHA - return '{SSHA}'. $1; - } elsif ( $self->_password =~ /^(\w{64})$/ ) { #LDAP NS-MTA-MD5 - return '{NS-MTA-MD5}'. $1; - - } else { #plaintext - return '{PLAIN}'. $self->_password; - - #return '{CLEARTEXT}'. $self->_password; #? - - #XXX this could be replaced with Authen::Passphrase stuff if it gets used - #my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; - #if ( $encryption eq 'crypt' ) { - # return '{CRYPT}'. crypt( - # $self->_password, - # $saltset[int(rand(64))].$saltset[int(rand(64))] - # ); - #} elsif ( $encryption eq 'md5' ) { - # unix_md5_crypt( $self->_password ); - #} elsif ( $encryption eq 'blowfish' ) { - # croak "unknown encryption method $encryption"; - #} else { - # croak "unknown encryption method $encryption"; - #} - } - + #my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; + #if ( $encryption eq 'crypt' ) { + # return '{CRYPT}'. crypt( + # $self->_password, + # $saltset[int(rand(64))].$saltset[int(rand(64))] + # ); + #} elsif ( $encryption eq 'md5' ) { + # unix_md5_crypt( $self->_password ); + #} elsif ( $encryption eq 'blowfish' ) { + # croak "unknown encryption method $encryption"; + #} else { + # croak "unknown encryption method $encryption"; + #} } - } =item domain_slash_username diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm index 473cd5705..e5803513b 100755 --- a/FS/FS/svc_broadband.pm +++ b/FS/FS/svc_broadband.pm @@ -202,7 +202,7 @@ sub check { || $self->ut_hexn('auth_key') || $self->ut_coordn('latitude', -90, 90) || $self->ut_coordn('longitude', -180, 180) - || $self->ut_sfloatn('altitude') + || $self->ut_floatn('altitude') || $self->ut_textn('vlan_profile') ; return $error if $error; diff --git a/FS/MANIFEST b/FS/MANIFEST index 6a4c1ce75..82f106412 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -126,8 +126,6 @@ FS/part_pkg/sqlradacct_hour.pm FS/part_pkg/subscription.pm FS/part_pkg/voip_sqlradacct.pm FS/part_pkg/voip_cdr.pm -FS/part_pkg/base_rate.pm -FS/part_pkg/base_delayed.pm FS/part_pop_local.pm FS/part_referral.pm FS/part_svc.pm @@ -373,5 +371,3 @@ FS/reason_type.pm t/reason_type.t FS/cust_pkg_option.pm t/cust_pkg_option.t -FS/conf.pm -t/conf.t diff --git a/FS/bin/freeside-delete-addr_blocks b/FS/bin/freeside-delete-addr_blocks deleted file mode 100755 index a7e99766a..000000000 --- a/FS/bin/freeside-delete-addr_blocks +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/perl -Tw - -use strict; -use vars qw( $user $block @blocks ); -use FS::UID qw(adminsuidsetup); -use FS::Record qw(qsearch); -use FS::addr_block; -use FS::svc_broadband; - -$user = shift or die &usage; -&adminsuidsetup( $user ); - -@blocks = qsearch('addr_block', {} ); -die "No address blocks" unless (scalar(@blocks) > 0); - -foreach $block (@blocks) { - my @devices = qsearch('svc_broadband', { 'blocknum' => $block->blocknum } ); - if (@devices) { - print "Skipping block " . $block->ip_gateway . " / " . $block->ip_netmask; - print "\n"; - }else{ - print "Deleting block " . $block->ip_gateway . " / " . $block->ip_netmask; - print "\n"; - $block->delete; - } -} - - -sub usage { - "Usage:\n freeside-delete-addr_blocks user \n"; -} diff --git a/FS/bin/freeside-init-config b/FS/bin/freeside-init-config deleted file mode 100755 index a186d1a85..000000000 --- a/FS/bin/freeside-init-config +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/perl -Tw - -use strict; -use vars qw($opt_u $opt_f $opt_v); -use Getopt::Std; -use IO::File; -use FS::UID qw(adminsuidsetup checkeuid dbh); -use FS::CurrentUser; -use FS::Record qw(qsearch); - - -die "Not running uid freeside!" unless checkeuid(); - -getopts("u:vf"); -my $dir = shift or die &usage; - -$FS::CurrentUser::upgrade_hack = 1; -adminsuidsetup $opt_u; #$user; - -$|=1; - -my $conf = new FS::Conf; -if (!scalar(qsearch('conf', {})) || $opt_f) { - - foreach my $item ( $conf->config_items() ) { - insert_config_item($item,$dir); - } - - # ugly pseudo false laziness with Conf.pm - foreach my $item ( map { my $basename = basename($_); - $basename =~ /^(.*)$/; - $basename = $1; - new FS::ConfItem { - 'key' => $basename, - 'type' => '', - } - } glob($dir. '/invoice_template_*'), - glob($dir. '/invoice_html_*'), - glob($dir. '/invoice_htmlnotes_*'), - glob($dir. '/invoice_latex_*'), - glob($dir. '/invoice_latexnotes_*') - ) { - - insert_config_item($item,$dir); - - } - - foreach my $item ( map { my $basename = basename($_); - $basename =~ /^(.*)$/; - $basename = $1; - new FS::ConfItem { - 'key' => $basename, - 'type' => 'binary', - } - } glob($dir. '/logo_*.png'), - glob($dir. '/logo_*.eps') - ) { - - insert_config_item($item,$dir); - - } - -} - -warn "Freeside database initialized - committing transaction\n" if $opt_v; - -dbh->commit or die dbh->errstr; -dbh->disconnect or die dbh->errstr; - -warn "Configuration initialization committed successfully\n" if $opt_v; - -sub insert_config_item { - local $/; - my ($item,$dir) = @_; - my $key = $item->key; - if (-e "$dir/$key") { - warn "Inserting $key\n" if $opt_v; - my $value = readline(new IO::File "$dir/$key"); - if ($item->type eq 'binary'){ - $conf->set_binary($key, $value); - }else{ - $conf->set($key, $value); - } - } -} - -sub usage { - die "Usage:\n freeside-init-config directory [ -v ] [ -f ]\n" - # [ -u user ] for devel/multi-db installs -} - -1; diff --git a/FS/bin/freeside-selfservice-server b/FS/bin/freeside-selfservice-server index 205f1c3ab..187bc1469 100644 --- a/FS/bin/freeside-selfservice-server +++ b/FS/bin/freeside-selfservice-server @@ -16,7 +16,8 @@ use FS::UID qw(adminsuidsetup forksuidsetup); use FS::ClientAPI; use FS::Conf; -use FS::cust_svc; +use FS::cust_bill; +use FS::cust_pkg; $FREESIDE_LOG = "%%%FREESIDE_LOG%%%"; $FREESIDE_LOCK = "%%%FREESIDE_LOCK%%%"; @@ -57,10 +58,6 @@ logfile("$FREESIDE_LOG/selfservice.$machine.log"); daemonize2(); my $conf = new FS::Conf; -if ( $conf->exists('selfservice-ignore_quantity') ) { - $FS::cust_svc::ignore_quantity = 1; - $FS::cust_svc::ignore_quantity = 1; #now it is used twice. -} my $clientd = "/usr/local/sbin/freeside-selfservice-clientd"; #better name? diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup index ed737b395..ddc210f50 100755 --- a/FS/bin/freeside-setup +++ b/FS/bin/freeside-setup @@ -19,12 +19,9 @@ die "Not running uid freeside!" unless checkeuid(); # map { lc($FS::raddb::attrib{$_}) => $_ } keys %FS::raddb::attrib; getopts("u:vd:"); -my $config_dir = shift || 'conf' ; -$config_dir =~ /^([\w.:=]+)$/ - or die "unacceptable configuration directory name"; -$config_dir = $1; +#my $user = shift or die &usage; -getsecrets($opt_u); +getsecrets($opt_u); #$user); #needs to match FS::Record my($dbdef_file) = "%%%FREESIDE_CONF%%%/dbdef.". datasrc; @@ -91,9 +88,7 @@ $dbdef->save($dbdef_file); ### $FS::CurrentUser::upgrade_hack = 1; -$FS::UID::callback_hack = 1; my $dbh = adminsuidsetup $opt_u; #$user; -$FS::UID::callback_hack = 0; #create tables $|=1; @@ -110,20 +105,6 @@ dbdef_create($dbh, $dbdef_file); delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload reload_dbdef($dbdef_file); -warn "Freeside schema initialized - commiting transaction\n" if $opt_v; - -$dbh->commit or die $dbh->errstr; -$dbh->disconnect or die $dbh->errstr; - -warn "Database schema committed successfully\n" if $opt_v; - -my $init_config = "freeside-init-config"; -$init_config .= " -v" if $opt_v; -$init_config .= " -u $opt_u" if $opt_u; -$init_config .= " $config_dir"; -system "$init_config" ; - -$dbh = adminsuidsetup $opt_u; create_initial_data('domain' => $opt_d); warn "Freeside database initialized - commiting transaction\n" if $opt_v; @@ -140,7 +121,7 @@ sub dbdef_create { # reverse engineer the schema from the DB and save to file } sub usage { - die "Usage:\n freeside-setup -d domain.name [ -v ] [ config/dir ]\n" + die "Usage:\n freeside-setup -d domain.name [ -v ]\n" # [ -u user ] for devel/multi-db installs } diff --git a/FS/bin/freeside-upgrade b/FS/bin/freeside-upgrade index b3ac2d151..b2943524b 100755 --- a/FS/bin/freeside-upgrade +++ b/FS/bin/freeside-upgrade @@ -54,12 +54,6 @@ dbdef_create($dbh, $dbdef_file); $dbh->disconnect or die $dbh->errstr; -unless ( $DRY_RUN ) { - my $init_config = "freeside-init-config -u $user "; - $init_config .= "%%%FREESIDE_CONF%%%/conf.". datasrc; - system "$init_config" ; -} - ### sub dbdef_create { # reverse engineer the schema from the DB and save to file diff --git a/FS/t/conf.t b/FS/t/conf.t deleted file mode 100644 index 5e52079f6..000000000 --- a/FS/t/conf.t +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN { $| = 1; print "1..1\n" } -END {print "not ok 1\n" unless $loaded;} -use FS::conf; -$loaded=1; -print "ok 1\n"; diff --git a/FS/t/cust_pkg_option.t b/FS/t/cust_pkg_option.t deleted file mode 100644 index 12314bf80..000000000 --- a/FS/t/cust_pkg_option.t +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN { $| = 1; print "1..1\n" } -END {print "not ok 1\n" unless $loaded;} -use FS::cust_pkg_option; -$loaded=1; -print "ok 1\n"; |