forked from HPR/hpr-tools
		
	
		
			
	
	
		
			649 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			649 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | #!/usr/bin/env perl | ||
|  | #=============================================================================== | ||
|  | # | ||
|  | #         FILE: edit_host | ||
|  | # | ||
|  | #        USAGE: ./edit_host [-help] [-debug=N] [-[no]update] [-config=FILE] | ||
|  | #               [-[no]espeak_name] [-hostid=id] [-[no]regex] host_name | ||
|  | # | ||
|  | #  DESCRIPTION: A simple editor for the HPR hosts table | ||
|  | # | ||
|  | #      OPTIONS: --- | ||
|  | # REQUIREMENTS: --- | ||
|  | #         BUGS: --- | ||
|  | #        NOTES: DBI::MariaDB was here for a while then reverted to DBI::mysql. | ||
|  | #               Had to revert this script onn 2023-01-22. | ||
|  | #       AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com | ||
|  | #      VERSION: 0.0.7 | ||
|  | #      CREATED: 2018-04-07 22:05:06 | ||
|  | #     REVISION: 2023-01-22 14:06:48 | ||
|  | # | ||
|  | #=============================================================================== | ||
|  | 
 | ||
|  | use 5.010; | ||
|  | use strict; | ||
|  | use warnings; | ||
|  | use utf8; | ||
|  | 
 | ||
|  | use Getopt::Long; | ||
|  | use Pod::Usage; | ||
|  | 
 | ||
|  | use Config::General; | ||
|  | use File::Temp; | ||
|  | use File::Slurper qw{ read_text }; | ||
|  | use SQL::Abstract; | ||
|  | use DBI; | ||
|  | 
 | ||
|  | use Data::Dumper; | ||
|  | 
 | ||
|  | # | ||
|  | # Version number (manually incremented) | ||
|  | # | ||
|  | our $VERSION = '0.0.7'; | ||
|  | 
 | ||
|  | # | ||
|  | # Script and directory names | ||
|  | # | ||
|  | ( my $PROG = $0 ) =~ s|.*/||mx; | ||
|  | ( my $DIR  = $0 ) =~ s|/?[^/]*$||mx; | ||
|  | $DIR = '.' unless $DIR; | ||
|  | 
 | ||
|  | #------------------------------------------------------------------------------- | ||
|  | # Declarations | ||
|  | #------------------------------------------------------------------------------- | ||
|  | # | ||
|  | # Constants and other declarations | ||
|  | # | ||
|  | my $basedir    = "$ENV{HOME}/HPR/Database"; | ||
|  | my $configfile = "$basedir/.hpr_db.cfg"; | ||
|  | 
 | ||
|  | # | ||
|  | # Declarations | ||
|  | # | ||
|  | my ( $dbh, $sth1, $h1, $rc ); | ||
|  | my ( $host_name, %changes ); | ||
|  | 
 | ||
|  | # | ||
|  | # Enable Unicode mode | ||
|  | # | ||
|  | binmode STDOUT, ":encoding(UTF-8)"; | ||
|  | binmode STDERR, ":encoding(UTF-8)"; | ||
|  | 
 | ||
|  | # | ||
|  | # Options and arguments | ||
|  | # | ||
|  | my %options; | ||
|  | Options( \%options ); | ||
|  | 
 | ||
|  | # | ||
|  | # Default help | ||
|  | # | ||
|  | pod2usage( -msg => "Version $VERSION\n", -exitval => 1 ) | ||
|  |     if ( $options{'help'} ); | ||
|  | 
 | ||
|  | # | ||
|  | # Collect options | ||
|  | # | ||
|  | my $DEBUG = ( $options{'debug'} ? $options{'debug'} : 0 ); | ||
|  | 
 | ||
|  | my $cfgfile | ||
|  |     = ( defined( $options{config} ) ? $options{config} : $configfile ); | ||
|  | 
 | ||
|  | my $updatedb = ( defined( $options{'updatedb'} ) ? $options{'updatedb'} : 0 ); | ||
|  | my $regexp = ( defined( $options{'regexp'} ) ? $options{'regexp'} : 0 ); | ||
|  | 
 | ||
|  | my $email   = ( defined( $options{'email'} )   ? $options{'email'}   : 0 ); | ||
|  | my $profile = ( defined( $options{'profile'} ) ? $options{'profile'} : 0 ); | ||
|  | my $espeak_name | ||
|  |     = ( defined( $options{'espeak_name'} ) ? $options{'espeak_name'} : 0 ); | ||
|  | 
 | ||
|  | # | ||
|  | # There must be at least one field to change | ||
|  | # | ||
|  | die "Select one of -email, -profile and -espeak_name\n" | ||
|  |     unless ( $email || $profile || $espeak_name ); | ||
|  | 
 | ||
|  | # | ||
|  | # Was a host id provided (through an option)? | ||
|  | # | ||
|  | my $hostid = $options{'hostid'}; | ||
|  | 
 | ||
|  | # | ||
|  | # Deal with the two routes: one via the unique host id, and the other vai the | ||
|  | # less unique host name | ||
|  | # | ||
|  | unless ($hostid) { | ||
|  |     # | ||
|  |     # Get the arg | ||
|  |     # | ||
|  |     $host_name = shift; | ||
|  |     pod2usage( -msg => "Specify the host name\n", -exitval => 1 ) | ||
|  |         unless $host_name; | ||
|  | } | ||
|  | 
 | ||
|  | # | ||
|  | # Sanity check | ||
|  | # | ||
|  | die "Unable to find $cfgfile\n" unless ( -e $cfgfile ); | ||
|  | 
 | ||
|  | # | ||
|  | # Load configuration data | ||
|  | # | ||
|  | my $conf = new Config::General( | ||
|  |     -ConfigFile      => $cfgfile, | ||
|  |     -InterPolateVars => 1, | ||
|  |     -ExtendedAccess  => 1 | ||
|  | ); | ||
|  | my %config = $conf->getall(); | ||
|  | 
 | ||
|  | # | ||
|  | # Connect to the database | ||
|  | # | ||
|  | my $dbhost = $config{database}->{host} // '127.0.0.1'; | ||
|  | my $dbport = $config{database}->{port} // 3306; | ||
|  | my $dbname = $config{database}->{name}; | ||
|  | my $dbuser = $config{database}->{user}; | ||
|  | my $dbpwd  = $config{database}->{password}; | ||
|  | 
 | ||
|  | #$dbh = DBI->connect( "DBI:MariaDB:database=$dbname;host=$dbhost;port=$dbport", | ||
|  | #    $dbuser, $dbpwd, { AutoCommit => 1 } ) | ||
|  | #    or die $DBI::errstr; | ||
|  | 
 | ||
|  | $dbh = DBI->connect( "dbi:mysql:host=$dbhost;port=$dbport;database=$dbname", | ||
|  |     $dbuser, $dbpwd, { AutoCommit => 1 } ) | ||
|  |     or die $DBI::errstr; | ||
|  | 
 | ||
|  | # | ||
|  | # Prepare to read the database either for the hostid or the exact or | ||
|  | # approximate name | ||
|  | # | ||
|  | if ($hostid) { | ||
|  |     # | ||
|  |     # Simple hostid query | ||
|  |     # | ||
|  |     $sth1 = $dbh->prepare(q{SELECT * FROM hosts WHERE hostid = ?}); | ||
|  |     $sth1->execute($hostid); | ||
|  |     if ( $dbh->err ) { | ||
|  |         die $dbh->errstr; | ||
|  |     } | ||
|  | } | ||
|  | else { | ||
|  |     # | ||
|  |     # Host name query | ||
|  |     # | ||
|  |     if ($regexp) { | ||
|  |         # | ||
|  |         # Regexp match requested. Count how many matches there are | ||
|  |         # | ||
|  |         $sth1 = $dbh->prepare( | ||
|  |             q{SELECT count(*) AS count FROM hosts WHERE host REGEXP ?}); | ||
|  |         $sth1->execute($host_name); | ||
|  |         if ( $dbh->err ) { | ||
|  |             warn $dbh->errstr; | ||
|  |         } | ||
|  |         if ( $h1 = $sth1->fetchrow_hashref ) { | ||
|  |             die "Too many matches to regex $host_name\n" | ||
|  |                 unless $h1->{count} == 1; | ||
|  |         } | ||
|  |         else { | ||
|  |             die "Unable to find host matching regex $host_name\n"; | ||
|  |         } | ||
|  | 
 | ||
|  |         $sth1 = $dbh->prepare(q{SELECT * FROM hosts WHERE host REGEXP ?}); | ||
|  |     } | ||
|  |     else { | ||
|  |         $sth1 = $dbh->prepare(q{SELECT * FROM hosts WHERE host = ?}); | ||
|  |     } | ||
|  | 
 | ||
|  |     # | ||
|  |     # Execute the query | ||
|  |     # | ||
|  |     $sth1->execute($host_name); | ||
|  |     if ( $dbh->err ) { | ||
|  |         die $dbh->errstr; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | # | ||
|  | # Did we find it? | ||
|  | # | ||
|  | if ( $h1 = $sth1->fetchrow_hashref ) { | ||
|  |     # | ||
|  |     # Found. Save the hostid to simplify the update if we don't already have | ||
|  |     # it | ||
|  |     # | ||
|  |     $hostid //= $h1->{hostid}; | ||
|  | 
 | ||
|  |     # | ||
|  |     # So what needs changing? | ||
|  |     # | ||
|  |     #<<< [perltidy messes up the following] | ||
|  |     if ($email) { | ||
|  |         $changes{email} = check_field( 'email', | ||
|  |             scalar( run_editor( $h1->{email}, ['+set paste'] ) ), 256, qr{(\n)} ); | ||
|  |     } | ||
|  |     if ($profile) { | ||
|  |         $changes{profile} = run_editor( $h1->{profile}, ['+set paste'] ); | ||
|  |     } | ||
|  |     if ($espeak_name) { | ||
|  |         $changes{espeak_name} = check_field( 'espeak_name', | ||
|  |             scalar( run_editor( $h1->{espeak_name} ) ), 256, qr{(\n)} ); | ||
|  |     } | ||
|  |     #>>> | ||
|  |     print Dumper( \%changes ), "\n" if ( $DEBUG > 2 ); | ||
|  | 
 | ||
|  |     # | ||
|  |     # Are we updating the database then? | ||
|  |     # | ||
|  |     if ($updatedb) { | ||
|  |         # | ||
|  |         # Was anything edited? | ||
|  |         # | ||
|  |         if (%changes) { | ||
|  |             # | ||
|  |             # Did the edits do anything? If not delete the element from the | ||
|  |             # hash since there's no point writing it to the database | ||
|  |             # | ||
|  |             for my $key ( keys(%changes) ) { | ||
|  |                 if ( $changes{$key} eq $h1->{$key} ) { | ||
|  |                     print "No change made to $key, ignored\n"; | ||
|  |                     delete( $changes{$key} ); | ||
|  |                 } | ||
|  |             } | ||
|  |             print Dumper( \%changes ), "\n" if ( $DEBUG > 2 ); | ||
|  |         } | ||
|  | 
 | ||
|  |         # | ||
|  |         # If there's anything left apply the changes | ||
|  |         # | ||
|  |         if (%changes) { | ||
|  |             # | ||
|  |             # Go into transaction mode here so we can fail safely | ||
|  |             # | ||
|  |             $rc = $dbh->begin_work or die $dbh->errstr; | ||
|  | 
 | ||
|  |             my $sql = SQL::Abstract->new; | ||
|  |             my %where = ( hostid => $hostid ); | ||
|  |             my ( $stmt, @bind ) = $sql->update( 'hosts', \%changes, \%where ); | ||
|  |             #print "$stmt\n"; | ||
|  |             #print join( ",", map {"'$_'"} @bind ), "\n"; | ||
|  | 
 | ||
|  |             my $sth = $dbh->prepare($stmt); | ||
|  |             my $rv  = $sth->execute(@bind); | ||
|  | 
 | ||
|  |             # | ||
|  |             # Respond to any error by rolling back | ||
|  |             # | ||
|  |             if ( $dbh->err ) { | ||
|  |                 warn $dbh->errstr; | ||
|  |                 eval { $dbh->rollback }; | ||
|  |                 $rv = 0; | ||
|  |             } | ||
|  |             else { | ||
|  |                 $dbh->commit; | ||
|  |             } | ||
|  |             $rv = 0 if ( $rv eq '0E0' ); | ||
|  | 
 | ||
|  |             # | ||
|  |             # Update the log file | ||
|  |             # | ||
|  |             if ($rv) { | ||
|  |                 print "Updated database\n"; | ||
|  |             } | ||
|  |             else { | ||
|  |                 print "Database not updated due to error\n"; | ||
|  |             } | ||
|  | 
 | ||
|  |         } | ||
|  |         else { | ||
|  |             print "There was nothing to do\n"; | ||
|  |         } | ||
|  |     } | ||
|  |     else { | ||
|  |         print "Database not updated\n"; | ||
|  |     } | ||
|  | } | ||
|  | else { | ||
|  |     if ($hostid) { | ||
|  |         print "Unable to find host number $hostid\n"; | ||
|  |     } | ||
|  |     else { | ||
|  |         print "Unable to find host name $host_name\n"; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | exit; | ||
|  | 
 | ||
|  | #===  FUNCTION  ================================================================ | ||
|  | #         NAME: run_editor | ||
|  | #      PURPOSE: Run an interactive vim editor on a string | ||
|  | #   PARAMETERS: $string         String to edit | ||
|  | #               $options        An arrayref containing options for vim | ||
|  | #                               (optional) Example '+set paste'. Each option | ||
|  | #                               (such as '-c startinsert') needs to be | ||
|  | #                               a separate array element. | ||
|  | #      RETURNS: Edited string | ||
|  | #  DESCRIPTION: Makes a temporary file with File::Temp ensuring that the file | ||
|  | #               is in utf8 mode. Writes the edit string to the file and invokes | ||
|  | #               the 'vim' editor on it. The resulting file is then read back | ||
|  | #               into a string and returned to the caller, again taking care to | ||
|  | #               retain utf8 mode. | ||
|  | #       THROWS: No exceptions | ||
|  | #     COMMENTS: File::Slurp and UTF-8 don't go well together. Moved to | ||
|  | #               File::Slurper instead | ||
|  | #     SEE ALSO: N/A | ||
|  | #=============================================================================== | ||
|  | sub run_editor { | ||
|  |     my ( $string, $options ) = @_; | ||
|  | 
 | ||
|  |     # | ||
|  |     # Build an arguments array for 'system' | ||
|  |     # | ||
|  |     my @args; | ||
|  |     push( @args, @$options ) if $options; | ||
|  | 
 | ||
|  |     # | ||
|  |     # Make a temporary file | ||
|  |     # | ||
|  |     my $tfh = File::Temp->new; | ||
|  |     binmode $tfh, ":encoding(UTF-8)"; | ||
|  |     my $tfn = $tfh->filename; | ||
|  |     print $tfh $string if $string; | ||
|  |     $tfh->close; | ||
|  | 
 | ||
|  |     # | ||
|  |     # Add the filename to the arguments | ||
|  |     # | ||
|  |     push( @args, $tfn ); | ||
|  | 
 | ||
|  |     die "Edit failed\n" | ||
|  |         unless ( system( ( 'vim', @args ) ) == 0 ); | ||
|  | 
 | ||
|  |     return read_text($tfn); | ||
|  | } | ||
|  | 
 | ||
|  | #===  FUNCTION  ================================================================ | ||
|  | #         NAME: check_field | ||
|  | #      PURPOSE: Checks the a field is not too long and doesn't contain certain | ||
|  | #               characters | ||
|  | #   PARAMETERS: $name           name of field | ||
|  | #               $field          string to be checked | ||
|  | #               $maxlen         maximum string length | ||
|  | #               $regex          regex containing illegal characters to be removed | ||
|  | #      RETURNS: The input string truncated and with any illegal characters | ||
|  | #               removed. | ||
|  | #  DESCRIPTION: Runs a substitution on the string then truncates the result if | ||
|  | #               it is too long. | ||
|  | #       THROWS: No exceptions | ||
|  | #     COMMENTS: None | ||
|  | #     SEE ALSO: N/A | ||
|  | #=============================================================================== | ||
|  | sub check_field { | ||
|  |     my ( $name, $field, $maxlen, $regex ) = @_; | ||
|  | 
 | ||
|  |     return unless $field; | ||
|  | 
 | ||
|  |     $field =~ s/$regex//g; | ||
|  |     if ( length($field) > $maxlen ) { | ||
|  |         warn "Field '$name' too long (" | ||
|  |             . length($field) | ||
|  |             . "); truncated to " | ||
|  |             . $maxlen . "\n"; | ||
|  |         $field = substr( $field, 0, $maxlen ); | ||
|  |     } | ||
|  |     return $field; | ||
|  | } | ||
|  | 
 | ||
|  | #===  FUNCTION  ================================================================ | ||
|  | #         NAME: Options | ||
|  | #      PURPOSE: Processes command-line options | ||
|  | #   PARAMETERS: $optref     Hash reference to hold the options | ||
|  | #      RETURNS: Undef | ||
|  | #  DESCRIPTION: | ||
|  | #       THROWS: no exceptions | ||
|  | #     COMMENTS: none | ||
|  | #     SEE ALSO: n/a | ||
|  | #=============================================================================== | ||
|  | sub Options { | ||
|  |     my ($optref) = @_; | ||
|  | 
 | ||
|  |     my @options = ( | ||
|  |         "help",     "debug=i", "updatedb!", "config=s", | ||
|  |         "hostid=i", "regexp",  "email!",    "profile!", | ||
|  |         "espeak_name!", | ||
|  |     ); | ||
|  | 
 | ||
|  |     if ( !GetOptions( $optref, @options ) ) { | ||
|  |         pod2usage( -msg => "Version $VERSION\n", -exitval => 1 ); | ||
|  |     } | ||
|  | 
 | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | __END__ | ||
|  | 
 | ||
|  | 
 | ||
|  | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
|  | #  Application Documentation | ||
|  | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
|  | #{{{ | ||
|  | 
 | ||
|  | =head1 NAME | ||
|  | 
 | ||
|  | edit_host - edit one or more fields in the database for a given host | ||
|  | 
 | ||
|  | =head1 VERSION | ||
|  | 
 | ||
|  | This documentation refers to edit_host version 0.0.7 | ||
|  | 
 | ||
|  | 
 | ||
|  | =head1 USAGE | ||
|  | 
 | ||
|  |     edit_host [-h] [-debug=N] [-[no]updatedb] [-hostid=ID] [-regexp] | ||
|  |     [-[no]email] [-[no]profile] [-[no]espeak_name] [-config=FILE] hostname | ||
|  | 
 | ||
|  |     edit_host -updatedb -espeak_name operat0r | ||
|  |     edit_host -updatedb -espeak_name -regexp oper | ||
|  |     edit_host -updatedb -email -espeak -host=225 | ||
|  | 
 | ||
|  | 
 | ||
|  | =head1 REQUIRED ARGUMENTS | ||
|  | 
 | ||
|  | =over 4 | ||
|  | 
 | ||
|  | =item B<hostname> | ||
|  | 
 | ||
|  | Unless the B<-hostid=ID> option is given (see the OPTIONS section) it is | ||
|  | necessary to provide a host name. | ||
|  | 
 | ||
|  | Unless the B<-regexp> option is provided (see the OPTIONS section) the | ||
|  | hostname must match exactly, otherwise it is regarded as a MySQL regular | ||
|  | expression. | ||
|  | 
 | ||
|  | =back | ||
|  | 
 | ||
|  | =head1 OPTIONS | ||
|  | 
 | ||
|  | =over 4 | ||
|  | 
 | ||
|  | =item B<-[no]updatedb> | ||
|  | 
 | ||
|  | This option is required to make the script apply any changes that are made to | ||
|  | the database. By default no updates are applied (B<-noupdatedb>). | ||
|  | 
 | ||
|  | =item B<-regexp> | ||
|  | 
 | ||
|  | This option causes the B<hostname> argument to be interpreted as a regular | ||
|  | expression for the MySQL database. By default the argument is treated as if it | ||
|  | is an exact match. | ||
|  | 
 | ||
|  | =item B<-hostid=ID> | ||
|  | 
 | ||
|  | The host can be specified by the host ID through this route. If this used then | ||
|  | the B<hostname> argument is not required (and is ignored if given). | ||
|  | 
 | ||
|  | =item B<-[no]email> | ||
|  | 
 | ||
|  | This option, if given (as B<-email>), indicates that the 'email' field is to | ||
|  | be edited.  The Vim editor is invoked to make changes. The default is | ||
|  | B<-noemail> meaning that this field is not to be edited. | ||
|  | 
 | ||
|  | =item B<-[no]profile> | ||
|  | 
 | ||
|  | This option, if given (as B<-profile>), indicates that the 'profile' field is | ||
|  | to be edited.  The Vim editor is invoked to make changes. The default is | ||
|  | B<-noprofile> meaning that this field is not to be edited. | ||
|  | 
 | ||
|  | =item B<-[no]espeak_name> | ||
|  | 
 | ||
|  | This option, if given (as B<-espeak_name>), indicates that the 'espeak_name' | ||
|  | field is to be edited.  The Vim editor is invoked to make changes. The default | ||
|  | is B<-noespeak_name> meaning that this field is not to be edited. | ||
|  | 
 | ||
|  | =item B<-config=FILE> | ||
|  | 
 | ||
|  | This option allows an alternative configuration file to be used. This file | ||
|  | defines the location of the database, its port, its name and the username and | ||
|  | password to be used to access it. This feature was added to allow the script | ||
|  | to access alternative databases or the live database over an SSH tunnel. | ||
|  | 
 | ||
|  | See the CONFIGURATION AND ENVIRONMENT section below for the file format. | ||
|  | 
 | ||
|  | If the option is omitted the default file is used: B<.hpr_db.cfg> | ||
|  | 
 | ||
|  | =back | ||
|  | 
 | ||
|  | =head1 DESCRIPTION | ||
|  | 
 | ||
|  | The script B<edit_host> provides an editor interface to certain fields in | ||
|  | the B<hosts> table of the HPR database. The fields are: | ||
|  | 
 | ||
|  | =over 4 | ||
|  | 
 | ||
|  | =item B<email> | ||
|  | 
 | ||
|  | A single line of up to 256 characters of text. The line is stored in a 'TEXT' | ||
|  | field but it makes no sense to make it too long even though an email address | ||
|  | can be arbitrarily long. The current maximum address length in the database is | ||
|  | 44 characters. | ||
|  | 
 | ||
|  | =item B<profile> | ||
|  | 
 | ||
|  | A multi-line line of text of arbitrary length and content. The contents are | ||
|  | the host's profile in optional HTML format to be displayed on the page which | ||
|  | lists all of their contributions to HPR. | ||
|  | 
 | ||
|  | =item B<espeak_name> | ||
|  | 
 | ||
|  | A single line of up to 256 characters of text. The line is stored in a 'TEXT' | ||
|  | field but it makes no sense to make it too long. Its purpose is to provide the | ||
|  | 'espeak' program with a form of the host name (or alias) which can be spoken | ||
|  | as the host requires. For example the host 'thelovebug' finds his name spoken | ||
|  | as "thel ove bug" and this can be corrected by storing 'TheLoveBug' in this | ||
|  | field. | ||
|  | 
 | ||
|  | =back | ||
|  | 
 | ||
|  | =head1 DIAGNOSTICS | ||
|  | 
 | ||
|  | =over 4 | ||
|  | 
 | ||
|  | =item B<Select one of -email, -profile and -espeak_name> | ||
|  | 
 | ||
|  | At least one of these options is required. This a fatal error. | ||
|  | 
 | ||
|  | =item B<Specify the host name> | ||
|  | 
 | ||
|  | If no host name has been provided, and the B<-hostid=ID> option has not been | ||
|  | used the script is unable to determine the host to edit. This is a fatal | ||
|  | error. | ||
|  | 
 | ||
|  | =item B<Unable to find ...> | ||
|  | 
 | ||
|  | The configuration file containing details of the database cannot be found. | ||
|  | This is a fatal error. | ||
|  | 
 | ||
|  | =item B<DBI connect ... failed: Access denied for user ... > | ||
|  | 
 | ||
|  | The database connection has been denied. Check the configuration details (see | ||
|  | below). This a fatal error. | ||
|  | 
 | ||
|  | =item B<Too many matches to regex ...> | ||
|  | 
 | ||
|  | In B<-regex> mode a hostname has been provided that matches too many hosts in | ||
|  | the database. Try again with a less ambiguous name. This a fatal error. | ||
|  | 
 | ||
|  | =item B<Unable to find host matching regex ...> | ||
|  | 
 | ||
|  | In B<-regex> mode a hostname has been provided that matches no hosts in the | ||
|  | database. Try again. This a fatal error. | ||
|  | 
 | ||
|  | =item B<Edit failed> | ||
|  | 
 | ||
|  | If the Vim edit session fails in some way the script reports it this way. This | ||
|  | a fatal error. | ||
|  | 
 | ||
|  | =item B<Field '...' is too long (...); truncated to ...> | ||
|  | 
 | ||
|  | The string provided for the field is greater than the limit and has been | ||
|  | truncated. This is a warning. | ||
|  | 
 | ||
|  | =back | ||
|  | 
 | ||
|  | =head1 CONFIGURATION AND ENVIRONMENT | ||
|  | 
 | ||
|  | The script obtains the credentials it requires to open the HPR database from | ||
|  | a configuration file. The name of the file it expects is B<.hpr_db.cfg> in the | ||
|  | directory holding the script. To change this will require changing the script. | ||
|  | 
 | ||
|  | The configuration file format is as follows: | ||
|  | 
 | ||
|  |  <database> | ||
|  |      host = 127.0.0.1 | ||
|  |      port = PORT | ||
|  |      name = DATABASE | ||
|  |      user = USERNAME | ||
|  |      password = PASSWORD | ||
|  |  </database> | ||
|  | 
 | ||
|  | =head1 DEPENDENCIES | ||
|  | 
 | ||
|  |  Config::General | ||
|  |  DBI | ||
|  |  Data::Dumper | ||
|  |  File::Slurper | ||
|  |  File::Temp | ||
|  |  Getopt::Long | ||
|  |  Pod::Usage | ||
|  |  SQL::Abstract | ||
|  | 
 | ||
|  | =head1 BUGS AND LIMITATIONS | ||
|  | 
 | ||
|  | There are no known bugs in this module. | ||
|  | Please report problems to Dave Morriss  (Dave.Morriss@gmail.com) | ||
|  | Patches are welcome. | ||
|  | 
 | ||
|  | =head1 AUTHOR | ||
|  | 
 | ||
|  | Dave Morriss (Dave.Morriss@gmail.com) | ||
|  | 
 | ||
|  | =head1 LICENCE AND COPYRIGHT | ||
|  | 
 | ||
|  | Copyright (c) 2018 Dave Morriss (Dave.Morriss@gmail.com). All rights reserved. | ||
|  | 
 | ||
|  | This module is free software; you can redistribute it and/or | ||
|  | modify it under the same terms as Perl itself. See perldoc perlartistic. | ||
|  | 
 | ||
|  | This program is distributed in the hope that it will be useful, | ||
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
|  | 
 | ||
|  | =cut | ||
|  | 
 | ||
|  | #}}} | ||
|  | 
 | ||
|  | # [zo to open fold, zc to close] | ||
|  | 
 | ||
|  | # vim: syntax=perl:ts=8:sw=4:et:ai:tw=78:fo=tcrqn21:fdm=marker | ||
|  | 
 |