#================================================================= # imp_servdb.pm # Mark Pruett - 06/12/2000 # # These routines handle actual database access. This module can # be replaced by other modules that access other database # back-ends. Replacement modules should retain the same functions # and parameter semantics. # # This module supports the RDB database format, which should be # sufficient for all intranet and most moderate-traffic intranet # sites. #================================================================= use db_RDB; $db_dir = ""; $db_locations_file = ""; $db_aliases_file = ""; $db_geography_file = ""; $db_geopref_file = ""; $db_backup_table = 0; $rdbdir = "/usr/local/bin"; #----------------------------------------------------------------- # Initialize some module-global variables based on configuration # values or hard-coded defaults. #----------------------------------------------------------------- sub impdb_init { my (%DBCONF) = @_; if (defined ($DBCONF{"DB_DIR"})) { $db_dir = $DBCONF{"DB_DIR"}; } else { $db_dir = "/tmp"; # MLP: probably not a good default... } if (defined ($DBCONF{"DB_DEF_LOC_FILE"})) { $db_locations_file = $DBCONF{"DB_DEF_LOC_FILE"}; } else { $db_locations_file = "locations.rdb"; } $db_aliases_file = "aliases.rdb"; $db_geography_file = "geography.rdb"; $db_geopref_file = "geo_preference.rdb"; if (defined ($DBCONF{"RDBDIR"})) { $rdbdir = $DBCONF{"RDBDIR"}; } } #----------------------------------------------------------------- # Given a table "token" return the actual table name. #----------------------------------------------------------------- sub impdb_get_table_name { my ($tbl_token) = @_; my $name; if ($tbl_token eq "geography") { $name = $db_geography_file; } elsif ($tbl_token eq "geo_preference") { $name = $db_geopref_file; } elsif ($tbl_token eq "aliases") { $name = $db_aliases_file; } elsif ($tbl_token eq "locations") { $name = $db_locations_file; } return $name; } #----------------------------------------------------------------- # Read the entire aliases table and return in recs array. #----------------------------------------------------------------- sub impdb_get_aliases_records { my @recs; my $row = 0; my $filename = "$db_dir/$db_aliases_file"; # Check for table write lock, wait a few seconds if necessary. if (! db_wait_for_unlock ($filename, 10)) { return undef; } my %al_tbl = db_get_table ("cat $filename"); for ($i=0; $i < $al_tbl{NUM_RECORDS}; $i++) { $recs[$i]->{"alias"} = db_get_field ("alias", $i, %al_tbl); $recs[$i]->{"canonical_name"} = db_get_field ("canonical_name", $i, %al_tbl); } return @recs; } #----------------------------------------------------------------- # Read the entire geography table and return in recs array. #----------------------------------------------------------------- sub impdb_get_geography_records { my @recs; my $row = 0; my $filename = "$db_dir/$db_geography_file"; # Check for table write lock, wait a few seconds if necessary. if (! db_wait_for_unlock ($filename, 10)) { return undef; } my %geo_tbl = db_get_table ("cat $filename"); for ($i=0; $i < $geo_tbl{NUM_RECORDS}; $i++) { $recs[$i]->{"geo_code"} = db_get_field ("geo_code", $i, %geo_tbl); $recs[$i]->{"geo_description"} = db_get_field ("geo_description", $i, %geo_tbl); } return @recs; } #----------------------------------------------------------------- # Read the geo_preferences table and return in recs array. #----------------------------------------------------------------- sub impdb_get_geopref_records { my @recs; my $filename = "$db_dir/$db_geopref_file"; # Check for table write lock, wait a few seconds if necessary. if (! db_wait_for_unlock ($filename, 10)) { return undef; } my %geopref_tbl = db_get_table ("cat $filename"); for ($i=0; $i < $geopref_tbl{NUM_RECORDS}; $i++) { $recs[$i]->{"gpid"} = db_get_field ("gpid", $i, %geopref_tbl); $recs[$i]->{"geo_code"} = db_get_field ("geo_code", $i, %geopref_tbl); $recs[$i]->{"table_name"} = db_get_field ("table_name", $i, %geopref_tbl); } return @recs; } #----------------------------------------------------------------- # Return all records that match canonical name in all geo_preference # tables. Return in rec array. # # Note: this does not return the records in any particular prefer- # ence order. #----------------------------------------------------------------- sub impdb_get_printer_records { my ($canonical_name, $language) = @_; my @recs; my $row = 0; @geopref = impdb_get_geopref_records (); for ($j=0; $j <= $#geopref; $j++) { $table_name = $geopref[$j]->{"table_name"}; $geo_code = $geopref[$j]->{"geo_code"}; if (! db_wait_for_unlock ("$db_dir/$table_name", 10)) { next; } my %locations_tbl = db_get_table ("cat $db_dir/$table_name"); for ($i=0; $i < $locations_tbl{NUM_RECORDS}; $i++) { $val = db_get_field ("printer_id", $i, %locations_tbl); if ($val eq $canonical_name) { # If no language was specified, or the language matches the db. my $db_language = db_get_field ("language", $i, %locations_tbl); if ((! defined $language) || ($language eq $db_language)) { $recs[$row]->{"geo_code"} = $geo_code; $recs[$row]->{"package_name"} = db_get_field ("package_name", $i, %locations_tbl); $recs[$row]->{"location_url"} = db_get_field ("location_url", $i, %locations_tbl); $recs[$row]->{"language"} = db_get_field ("language", $i, %locations_tbl); $recs[$row]->{"gpg_version"} = db_get_field ("gpg_version", $i, %locations_tbl); $recs[$row]->{"gpg_sig"} = db_get_field ("gpg_sig", $i, %locations_tbl); $recs[$row]->{"gpg_crc"} = db_get_field ("gpg_crc", $i, %locations_tbl); } $row++; } } } return @recs; } #----------------------------------------------------------------- # Given a table name, an id (either an exact name or a partial # name), a boolean indicating theat the match should be partial # or exact, and the language string (en for english, etc.), return # an array of records that match the ID. #----------------------------------------------------------------- sub impdb_query_printer_records { my ($table_name, $partial_id, $exact, $language) = @_; my @recs; my $row = 0; my $i; my $testpartial = $partial_id; if (! db_wait_for_unlock ("$db_dir/$table_name", 10)) { return undef; } # We need to do some transformations on the partial_id # if we're doing a partial match. These transforms # will convert normal file-globbing-style wildcards # (* and ?) into equivalent perl regexps. if ($exact != 1) { # Special case: if $testpartial is blank, then # convert it to "*" to match everything. $testpartial = "*" if ($testpartial eq ""); # Convert "*" to ".*" $testpartial =~ s/\*/\.\*/g; # convert (for example) "???" to ".{3}" while ($testpartial =~ /(\?+)/) { $count = length($1); $testpartial =~ s/(\?+)/\.{$count}/; } } my %locations_tbl = db_get_table ("cat $db_dir/$table_name | $rdbdir/sorttbl printer_id"); for ($i=0; $i < $locations_tbl{NUM_RECORDS}; $i++) { $val = db_get_field ("printer_id", $i, %locations_tbl); $matched = 0; if ($exact == 1) { if ($val eq $partial_id) { $matched = 1; } } else { my $testval = $val; # Squeeze out white space: $testval =~ s/ //g; $testpartial =~ s/ //g; if ($testval =~ /^$testpartial$/i ) { $matched = 1; } } if ($matched == 1) { my $db_language = db_get_field ("language", $i, %locations_tbl); # If no language was specified, or the language matches the db. if ((! defined $language) || ($language eq $db_language)) { $recs[$row]->{"printer_id"} = $val; $recs[$row]->{"table_name"} = $table_name; $recs[$row]->{"package_name"} = db_get_field ("package_name", $i, %locations_tbl); $recs[$row]->{"location_url"} = db_get_field ("location_url", $i, %locations_tbl); $recs[$row]->{"language"} = db_get_field ("language", $i, %locations_tbl); $recs[$row]->{"gpg_version"} = db_get_field ("gpg_version", $i, %locations_tbl); $recs[$row]->{"gpg_sig"} = db_get_field ("gpg_sig", $i, %locations_tbl); $recs[$row]->{"gpg_crc"} = db_get_field ("gpg_crc", $i, %locations_tbl); $row++; } } } return @recs; } #----------------------------------------------------------------- # Given an alias name, find the matching canonical printer name. # The latter name is the "master key" for subsequent table look-ups. #----------------------------------------------------------------- sub impdb_get_alias_record { my ($alias) = @_; my $filename = "$db_dir/$db_aliases_file"; # Check for table write lock, wait a few seconds if necessary. if (! db_wait_for_unlock ($filename, 10)) { return undef; } my $name = ""; my %alias_tbl = db_get_table ("cat $filename"); # search for alias match to $alias my $row = db_find_record ("alias", $alias, %alias_tbl); if ($row >= 0) { $name = db_get_field ("canonical_name", $row, %alias_tbl); } return $name; } #----------------------------------------------------------------- # Add a record to the location table. #----------------------------------------------------------------- sub impdb_add_location_record { my ($prn_id, $fldstr, $valstr, $table_name) = @_; my $rc = 1; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # If there are no records, then this is a new table, so # we'll build the necessary data structures. if ($rdb{"NUM_RECORDS"} == 0) { %rdb = db_new_table ("# New Location Table", $fldstr, "20\t25\t100"); } # Check if record already exists with this printer_id my $row = db_find_record ("printer_id", $prn_id, %rdb); # If no existing record, then add. if ($row == -1) { %rdb = db_add_record ("", $fldstr, $valstr, %rdb); # Write table $rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); } return $rc; } #----------------------------------------------------------------- # Add a record to the aliases table. #----------------------------------------------------------------- sub impdb_add_aliases_record { my ($alias_fname, $alias_fvalue, $fldstr, $valstr, $table_name) = @_; my $rc = 1; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # Check if record already exists with this printer_id my $row = db_find_record ($alias_fname, $alias_fvalue, %rdb); # If no existing record, then add. if ($row == -1) { %rdb = db_add_record ("", $fldstr, $valstr, %rdb); # Write table $rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); } return $rc; } #----------------------------------------------------------------- # Add a record to the geopref table. #----------------------------------------------------------------- sub impdb_add_geopref_record { my ($geopref_fname, $geopref_fvalue, $fldstr, $valstr, $table_name) = @_; my $rc = 1; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # Check if record already exists with this unique id my $row = db_find_record ($geopref_fname, $geopref_fvalue, %rdb); # If no existing record, then add. if ($row == -1) { %rdb = db_add_record ("$geopref_fname", $fldstr, $valstr, %rdb); # Write table $rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); } return $rc; } #----------------------------------------------------------------- # Add a record to the geography table. #----------------------------------------------------------------- sub impdb_add_geography_record { my ($autoinc_fname, $fldstr, $valstr, $table_name) = @_; my $rc = 1; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # Check if record already exists with this geo_description my $row = db_find_record ("geo_description", $valstr, %rdb); # If no existing record, then add. if ($row == -1) { %rdb = db_add_record ($autoinc_fname, $fldstr, $valstr, %rdb); # Write table $rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); } return $rc; } #----------------------------------------------------------------- # Edit an existing geography record. #----------------------------------------------------------------- sub impdb_edit_geography_record { my ($target_fname, $target_fvalue, $fldstr, $valstr, $table_name) = @_; my $rc = 1; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # Find the record that has this geo_code. my $row = db_find_record ($target_fname, $target_fvalue, %rdb); # If record exists, edit. if ($row >= 0) { %rdb = db_edit_record ($row, $fldstr, $valstr, %rdb); # Write table $rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); } return $rc; } #----------------------------------------------------------------- # Edit an existing geopref record. #----------------------------------------------------------------- sub impdb_edit_geopref_record { my ($target_fname, $target_fvalue, $fldstr, $valstr, $table_name) = @_; my $rc = 1; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # Check if record already exists with this printer_id my $row = db_find_record ($target_fname, $target_fvalue, %rdb); # If record exists, edit. if ($row >= 0) { %rdb = db_edit_record ($row, $fldstr, $valstr, %rdb); # Write table $rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); } return $rc; } #----------------------------------------------------------------- # Edit an existing aliases record. #----------------------------------------------------------------- sub impdb_edit_aliases_record { my ($target_fname, $target_fvalue, $fldstr, $valstr, $table_name) = @_; my $rc = 1; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # Check if record already exists with this printer_id my $row = db_find_record ($target_fname, $target_fvalue, %rdb); # If record exists, edit. if ($row >= 0) { %rdb = db_edit_record ($row, $fldstr, $valstr, %rdb); # Write table $rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); } return $rc; } #----------------------------------------------------------------- # Edit an existing locations record. #----------------------------------------------------------------- sub impdb_edit_locations_record { my ($target_fname, $target_fvalue, $fldstr, $valstr, $table_name) = @_; my $rc = 1; # 1 = failure, 0 = success # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # Check if record already exists with this printer_id my $row = db_find_record ($target_fname, $target_fvalue, %rdb); # If record exists, edit. if ($row >= 0) { %rdb = db_edit_record ($row, $fldstr, $valstr, %rdb); # Write table $rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); } return $rc; } #----------------------------------------------------------------- # Delete an existing locations record. #----------------------------------------------------------------- sub impdb_delete_locations_record { my ($fname, $fvalue, $table_name) = @_; my $rc = 0; my $write_rc; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # Check if record already exists with this printer_id ($rc, %rdb) = db_delete_record ($fname, $fvalue, %rdb); # Write table ($rc contains number of records deleted). if ($rc > 0) { $write_rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); if ($write_rc != 0) { $rc = 0; } } return $rc; } #----------------------------------------------------------------- # Delete an existing geography record. #----------------------------------------------------------------- sub impdb_delete_geography_record { my ($fname, $fvalue, $table_name) = @_; my $rc = 0; my $write_rc; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # Check if record already exists with this printer_id ($rc, %rdb) = db_delete_record ($fname, $fvalue, %rdb); # Write table ($rc contains number of records deleted). if ($rc > 0) { $write_rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); if ($write_rc != 0) { $rc = 0; } } return $rc; } #----------------------------------------------------------------- # Delete an existing geopref record. #----------------------------------------------------------------- sub impdb_delete_geopref_record { my ($fname, $fvalue, $table_name) = @_; my $rc = 0; my $write_rc; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # If record matches, delete it ($rc, %rdb) = db_delete_record ($fname, $fvalue, %rdb); # Write table ($rc contains number of records deleted). if ($rc > 0) { $write_rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); if ($write_rc != 0) { $rc = 0; } } return $rc; } #----------------------------------------------------------------- # Delete an existing aliases record. #----------------------------------------------------------------- sub impdb_delete_aliases_record { my ($fname, $fvalue, $table_name) = @_; my $rc = 0; my $write_rc; # Read the table my %rdb = db_get_table ("cat $db_dir/$table_name"); # If record matches, delete it ($rc, %rdb) = db_delete_record ($fname, $fvalue, %rdb); # Write table ($rc contains number of records deleted). if ($rc > 0) { $write_rc = write_rdb_table ("$db_dir/$table_name", $db_backup_table, %rdb); if ($write_rc != 0) { $rc = 0; } } return $rc; } #----------------------------------------------------------------- # Read a table and return it "as-is". #----------------------------------------------------------------- sub impdb_get_table { my ($tabname) = @_; my $filename = "$db_dir/$tabname"; # Check for table write lock, wait a few seconds if necessary. if (! db_wait_for_unlock ($filename, 10)) { return undef; } my %tbl = db_get_table ("cat $filename"); return %tbl; } #----------------------------------------------------------------- #----------------------------------------------------------------- sub impdb_dump_table { my (%rdb) = @_; my $order = ($rdb{ORDER}); # COMMENTS my $comments = $rdb{COMMENTS}; for ($idx=0; $idx <= $#$comments; $idx++) { print $comments->[$idx]."\n"; } # FIELD NAMES $textout = $order->[0]; for ($fld=1; $fld <= $#$order; $fld++) { $textout .= "\t".$order->[$fld]; } print $textout."\n"; # FIELD TYPES $textout = $rdb{FIELDS}->{$order->[0]}->{FTYPE}; for ($fld=1; $fld <= $#$order; $fld++) { $textout .= "\t".$rdb{FIELDS}->{$order->[$fld]}->{FTYPE}; } print $textout."\n"; # DATA my $rec; for ($rec=0; $rec <= ($rdb{NUM_RECORDS}-1); $rec++) { if ((! defined($rdb{DELETED}->[$rec])) || ($rdb{DELETED}->[$rec] != 1)) { $textout = $rdb{FIELDS}->{$order->[0]}->{VALUE}->[$rec]; for ($fld=1; $fld <= $#$order; $fld++) { $textout .= "\t".$rdb{FIELDS}->{$order->[$fld]}->{VALUE}->[$rec]; } print $textout."\n"; } } } 1;