commit: 6a7d8fab58c70a80175dc107178ee5dcac733adc
Author: Robin H. Johnson <robbat2 <AT> gentoo <DOT> org>
AuthorDate: Sun Jul 3 15:01:33 2016 +0000
Commit: Robin H. Johnson <robbat2 <AT> gentoo <DOT> org>
CommitDate: Sun Jul 3 15:01:33 2016 +0000
URL: https://gitweb.gentoo.org/proj/elections.git/commit/?id=6a7d8fab
Votify: improve election base validation, and code documentation.
Signed-off-by: Robin H. Johnson <robbat2 <AT> gentoo.org>
Votify.pm | 81 +++++++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 55 insertions(+), 26 deletions(-)
diff --git a/Votify.pm b/Votify.pm
index ed5b519..8e0fe1a 100644
--- a/Votify.pm
+++ b/Votify.pm
@@ -13,7 +13,10 @@ use Cwd qw(abs_path);
use File::Basename;
use File::Spec::Functions;
use List::Util;
+use Data::Dumper;
+use Carp::Always;
use strict;
+use warnings;
our $datefmt = '%Y-%m-%d %H:%M:%S UTC';
our ($basedir) = List::Util::first { -d $_ } ('/etc/elections',
dirname(__FILE__));
@@ -27,42 +30,61 @@ sub import {
my @REQUIRED_FILES = qw(ballot officials start stop voters);
-sub get_datadir {
- my $election_name = shift;
+# Takes the name of an election and ensure it's validate under the basedir,
+# returning the full path to the election if valid, and undef if not valid.
+# Where valid is:
+# A directory containing ALL of the files in @REQUIRED_FILES, either either
+# their direct names, or the name of the election on the end of the files.
+# Eg 'ballot' or 'ballot-election1234'.
+sub validate_election_dir {
+ my $election_rawdir = shift;
+ return 0 unless defined $election_rawdir;
+ return 0 if substr($election_rawdir,0,1) eq ".";
+
+ my $election_name = $election_rawdir;
+ $election_name =~ s/.*\///;
my $election_dir = abs_path(catfile($Votify::basedir, $election_name));
- if(!validate_election_dir()) {
- die "$election_name is not a valid election!"
- }
- return $election_dir;
-}
-sub validate_election_dir {
- return 0 unless $_;
- my $election_dir = $_;
- my $election_name = $election_dir;
- $election_name =~ /.*\//;
- return 0 unless -d "$basedir/$election_dir";
+ # Fail if it's not a directory in the basedir
+ return 0 unless -d $election_dir;
+
+ # Do not try to validate hidden directories.
return 0 if substr($election_name,0,1) eq ".";
- my $valid = List::Util::reduce {
- $a or $b ? 1 : 0;
- } map {
+
+ # Validate that the required files exist in the dir
+ # Part 1, convert the array to a map
+ my %REQUIRED_FILES_valid = map {
my $file_valid = 0;
# Legacy naming:
- $file_valid = 1 if -f sprintf("%s/%s-%s", "$basedir/$election_name",
$_, $election_name);
+ $file_valid = 1 if -f sprintf("%s/%s-%s", $election_dir, $_,
$election_name);
# New naming:
- $file_valid = 1 if -f sprintf("%s/%s", "$basedir/$election_name", $_);
+ $file_valid = 1 if -f sprintf("%s/%s", $election_dir, $_);
#printf "File %s valid=%d\n", $_, $file_valid;
- $file_valid;
+ ($_, $file_valid);
} @REQUIRED_FILES;
- return $valid;
+
+ # Part 2, ensure all of the map is true
+ my $valid = List::Util::reduce {
+ $a or $b ? 1 : 0;
+ } values(%REQUIRED_FILES_valid);
+
+ # Now return.
+ return $election_dir if $valid;
+ return undef;
}
sub get_elections_list {
my @elections;
opendir(D, $Votify::basedir) or die;
@elections = sort grep {
- my $valid = validate_election_dir(catfile($Votify::basedir, $_));
- $valid;
+ -d $_ and
+ $_ ne "." and
+ $_ ne ".." and
+ $_ ne "" and
+ substr($_, 0, 1) ne ".";
+ } grep {
+ my $valid_election_dir = validate_election_dir($_);
+ defined $valid_election_dir;
} readdir D;
closedir D;
return @elections;
@@ -84,7 +106,8 @@ sub grabfile_int {
sub get_single_election_hashref {
my $election_name = shift;
- my $election_dir = catfile($Votify::basedir, $election_name);
+ my $election_dir = validate_election_dir($election_name);
+ return undef unless defined $election_dir;
my %election;
foreach my $fn (@REQUIRED_FILES){
#print "Scan $fn\n";
@@ -101,7 +124,9 @@ sub get_single_election_hashref {
sub get_elections_hash {
my %elections;
- %elections = map { $_ => get_single_election_hashref($_) }
get_elections_list();
+ my @elections_list = get_elections_list();
+ #print Dumper(\@elections_list);
+ %elections = map { $_ => get_single_election_hashref($_) } @elections_list;
return %elections;
}
@@ -151,11 +176,13 @@ sub officials {
######################################################################
package VoterList;
+use File::Spec::Functions;
sub new {
my ($class, $election_name) = @_;
my (@voterlist, $r);
- my $datadir = Votify::get_datadir($election_name);
+ my $datadir = Votify::validate_election_dir($election_name);
+ die "Unable to get election dir for name $election_name" unless defined
$datadir;
my ($self) = {
election => $election_name,
default_filename => catfile($datadir, "confs-$election_name"),
@@ -230,10 +257,12 @@ sub write {
package MasterBallot;
use Data::Dumper;
+use File::Spec::Functions;
sub new {
my ($class, $election_name, $vl) = @_;
- my $datadir = Votify::get_datadir($election_name);
+ my $datadir = Votify::validate_election_dir($election_name);
+ die "Unable to get election dir for name $election_name" unless defined
$datadir;
my ($self) = {
election => $election_name,
default_filename => catfile($datadir, "master-$election_name"),