X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FRecord.pm;h=5a07c1ab504fc481c252c107c050d2e7887a2f94;hb=5107a89928128b7b8e0fb93521fe2d857376141c;hp=67de071c61488bee0be5891f8183dffee838c0bb;hpb=c912b0f458e21880b1285f639ff42d73aaeafecd;p=freeside.git diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index 67de071c6..5a07c1ab5 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -10,6 +10,7 @@ use Locale::Country; use DBI qw(:sql_types); use DBIx::DBSchema 0.25; use FS::UID qw(dbh getotaker datasrc driver_name); +use FS::CurrentUser; use FS::Schema qw(dbdef); use FS::SearchCache; use FS::Msgcat qw(gettext); @@ -29,14 +30,12 @@ $me = '[FS::Record]'; $nowarn_identical = 0; -my $conf; my $rsa_module; my $rsa_loaded; my $rsa_encrypt; my $rsa_decrypt; FS::UID->install_callback( sub { - $conf = new FS::Conf; $File::CounterFile::DEFAULT_DIR = "/usr/local/etc/freeside/counters.". datasrc; } ); @@ -84,6 +83,8 @@ FS::Record - Database record objects $error = $record->ut_float('column'); $error = $record->ut_number('column'); $error = $record->ut_numbern('column'); + $error = $record->ut_snumber('column'); + $error = $record->ut_snumbern('column'); $error = $record->ut_money('column'); $error = $record->ut_text('column'); $error = $record->ut_textn('column'); @@ -389,7 +390,7 @@ sub qsearch { my %result; tie %result, "Tie::IxHash"; my @stuff = @{ $sth->fetchall_arrayref( {} ) }; - if($pkey) { + if ( $pkey && scalar(@stuff) && $stuff[0]->{$pkey} ) { %result = map { $_->{$pkey}, $_ } @stuff; } else { @result{@stuff} = @stuff; @@ -441,6 +442,7 @@ sub qsearch { } # Check for encrypted fields and decrypt them. + my $conf = new FS::Conf; if ($conf->exists('encryption') && eval 'defined(@FS::'. $table . '::encrypted_fields)') { foreach my $record (@return) { foreach my $field (eval '@FS::'. $table . '::encrypted_fields') { @@ -711,7 +713,8 @@ sub insert { # Encrypt before the database - if ($conf->exists('encryption') && defined(eval '@FS::'. $table . 'encrypted_fields')) { + my $conf = new FS::Conf; + if ($conf->exists('encryption') && defined(eval '@FS::'. $table . '::encrypted_fields')) { foreach my $field (eval '@FS::'. $table . '::encrypted_fields') { $self->{'saved'} = $self->getfield($field); $self->setfield($field, $self->enrypt($self->getfield($field))); @@ -721,18 +724,24 @@ sub insert { #false laziness w/delete my @real_fields = - grep defined($self->getfield($_)) && $self->getfield($_) ne "", + grep { defined($self->getfield($_)) && $self->getfield($_) ne "" } real_fields($table) ; my @values = map { _quote( $self->getfield($_), $table, $_) } @real_fields; #eslaf - my $statement = "INSERT INTO $table ( ". - join( ', ', @real_fields ). - ") VALUES (". - join( ', ', @values ). - ")" - ; + my $statement = "INSERT INTO $table "; + if ( @real_fields ) { + $statement .= + "( ". + join( ', ', @real_fields ). + ") VALUES (". + join( ', ', @values ). + ")" + ; + } else { + $statement .= 'DEFAULT VALUES'; + } warn "[debug]$me $statement\n" if $DEBUG > 1; my $sth = dbh->prepare($statement) or return dbh->errstr; @@ -757,7 +766,7 @@ sub insert { #my $i_sql = "SELECT $primary_key FROM $table WHERE oid = ?"; my $default = $self->dbdef_table->column($primary_key)->default; - unless ( $default =~ /^nextval\('"?([\w\.]+)"?'/i ) { + unless ( $default =~ /^nextval\(\(?'"?([\w\.]+)"?'/i ) { dbh->rollback if $FS::UID::AutoCommit; return "can't parse $table.$primary_key default value". " for sequence name: $default"; @@ -995,6 +1004,7 @@ sub replace { return $error if $error; # Encrypt for replace + my $conf = new FS::Conf; my $saved = {}; if ($conf->exists('encryption') && defined(eval '@FS::'. $new->table . 'encrypted_fields')) { foreach my $field (eval '@FS::'. $new->table . '::encrypted_fields') { @@ -1192,7 +1202,7 @@ sub _h_statement { $time ||= time; my @fields = - grep defined($self->getfield($_)) && $self->getfield($_) ne "", + grep { defined($self->getfield($_)) && $self->getfield($_) ne "" } real_fields($self->table); ; my @values = map { _quote( $self->getfield($_), $self->table, $_) } @fields; @@ -1280,6 +1290,25 @@ sub ut_snumber { ''; } +=item ut_snumbern COLUMN + +Check/untaint signed numeric data (whole numbers). If there is an error, +returns the error, otherwise returns false. + +=cut + +sub ut_snumbern { + my($self, $field) = @_; + $self->getfield($field) =~ /^(-?)\s*(\d*)$/ + or return "Illegal (numeric) $field: ". $self->getfield($field); + if ($1) { + return "Illegal (numeric) $field: ". $self->getfield($field) + unless $2; + } + $self->setfield($field, "$1$2"); + ''; +} + =item ut_number COLUMN Check/untaint simple numeric data (whole numbers). May not be null. If there @@ -1496,7 +1525,7 @@ Check/untaint zip codes. =cut -my @zip_reqd_countries = qw( CA ); #US implicit... +my @zip_reqd_countries = qw( AU CA US ); #CA, US implicit... sub ut_zip { my( $self, $field, $country ) = @_; @@ -1613,6 +1642,36 @@ sub ut_foreign_keyn { : ''; } +=item ut_agentnum_acl + +Checks this column as an agentnum, taking into account the current users's +ACLs. + +=cut + +sub ut_agentnum_acl { + my( $self, $field, $null_acl ) = @_; + + my $error = $self->ut_foreign_keyn($field, 'agent', 'agentnum'); + return "Illegal agentnum: $error" if $error; + + my $curuser = $FS::CurrentUser::CurrentUser; + + if ( $self->$field() ) { + + return "Access deined" + unless $curuser->agentnum($self->$field()); + + } else { + + return "Access denied" + unless $curuser->access_right($null_acl); + + } + + ''; + +} =item virtual_fields [ TABLE ] @@ -1635,7 +1694,8 @@ sub virtual_fields { "WHERE dbtable = '$table'"; my $dbh = dbh; my $result = $dbh->selectcol_arrayref($query); - confess $dbh->errstr if $dbh->err; + confess "Error executing virtual fields query: $query: ". $dbh->errstr + if $dbh->err; $virtual_fields_cache{$table} = $result; } @@ -1719,14 +1779,12 @@ sub _quote { ( $nullable ? ' NULL' : ' NOT NULL' ). ")\n" if $DEBUG > 2; - if ( $value eq '' && $column_type =~ /^int/ ) { - if ( $nullable ) { - 'NULL'; - } else { - cluck "WARNING: Attempting to set non-null integer $table.$column null; ". - "using 0 instead"; - 0; - } + if ( $value eq '' && $nullable ) { + 'NULL' + } elsif ( $value eq '' && $column_type =~ /^(int|numeric)/ ) { + cluck "WARNING: Attempting to set non-null integer $table.$column null; ". + "using 0 instead"; + 0; } elsif ( $value =~ /^\d+(\.\d+)?$/ && ! $column_type =~ /(char|binary|text)$/i ) { $value; @@ -1788,6 +1846,7 @@ sub encrypt { my ($self, $value) = @_; my $encrypted; + my $conf = new FS::Conf; if ($conf->exists('encryption')) { if ($self->is_encrypted($value)) { # Return the original value if it isn't plaintext. @@ -1821,6 +1880,7 @@ sub is_encrypted { sub decrypt { my ($self,$value) = @_; my $decrypted = $value; # Will return the original value if it isn't encrypted or can't be decrypted. + my $conf = new FS::Conf; if ($conf->exists('encryption') && $self->is_encrypted($value)) { $self->loadRSA; if (ref($rsa_decrypt) =~ /::RSA/) { @@ -1836,6 +1896,7 @@ sub loadRSA { #Initialize the Module $rsa_module = 'Crypt::OpenSSL::RSA'; # The Default + my $conf = new FS::Conf; if ($conf->exists('encryptionmodule') && $conf->config('encryptionmodule') ne '') { $rsa_module = $conf->config('encryptionmodule'); }