use strict;
use warnings;
+use 5.026;
+
+# For use of the given/when (See https://perlmaven.com/switch-case-statement-in-perl5)
+no warnings 'experimental';
+
use FindBin;
+use Term::ReadKey;
+
use lib "$FindBin::Bin/../lib";
+use lib "$FindBin::Bin/../../lib";
use MAPS;
use MAPSLog;
-
-use Term::ReadLine;
-use Term::ReadLine::Gnu;
-use Term::ReadKey;
-
-my $maps_username;
+use MyDB;
+
+use CmdLine;
+use Utils;
+
+my %cmds = (
+ adduser => {
+ help => 'Add a user to MAPS',
+ description => 'Usage: adduser <userid> <name> <email> <password>',
+ },
+ add2whitelist => {
+ help => 'Add sender to whitelist',
+ description => 'Usage: add2whitelist <sender> <retention>',
+ },
+ cleanlog => {
+ help => 'Cleans out old log entries',
+ description => 'Usage; cleanlog [timestamp]'
+ },
+ log => {
+ help => 'Logs a message',
+ description => 'Usage: log <message>',
+ },
+ loadlist => {
+ help => 'Load a list file',
+ description => 'Usage: loadlist <listfile>',
+ },
+ cleanemail => {
+ help => 'Cleans out old email entries',
+ description => 'Usage: cleanemail [timestamp]',
+ },
+ deliver => {
+ help => 'Delivers a message',
+ description => 'Usage: deliver <message>',
+ },
+ loademail => {
+ help => 'Load an mbox file',
+ description => 'Usage: loademail <mbox>',
+ },
+ dumpemail => {
+ help => 'Dump email from DB to mbox file',
+ description => 'Usage: ',
+ },
+ decrypt => {
+ help => 'Decrypt a password',
+ description => 'Usage: decrypt <password>',
+ },
+ switchuser => {
+ help => 'Switch to user',
+ description => 'Usage: switchuser <userid>',
+ },
+ setpassword => {
+ help => "Set a user's password",
+ description => 'Usage: setpassword',
+ },
+ showuser => {
+ help => 'Show current user',
+ description => 'Usage: showuser',
+ },
+ showusers => {
+ help => 'Shows users in the DB',
+ description => 'Usage: showusers',
+ },
+ showemail => {
+ help => 'Displays email',
+ description => 'Usage: showemail',
+ },
+ showlog => {
+ help => 'Displays <nbr> log entires',
+ description => 'Usage: showlog <nbr>',
+ },
+ space => {
+ help => 'Display space usage',
+ description => 'Usage: space',
+ },
+ showlist => {
+ help => 'Show list by <type>',
+ description => 'Usage: showlist <type>',
+ },
+ encrypt => {
+ help => 'Encrypt a password',
+ description => 'Usage: encrypt <password>',
+ },
+ resequence => {
+ help => 'Resequences a <list>',
+ description => 'Usage: resequence <list>',
+ },
+);
+
+my $userid = GetContext;
sub EncryptPassword($$) {
my ($password, $userid) = @_;
my $encrypted_password = Encrypt $password, $userid;
- print "Password: $password = $encrypted_password\n";
+ say "Encrypted password: '$encrypted_password'";
return;
} # EncryptPassword
my $decrypted_password = Decrypt($password, $userid);
- print "Password: $password = $decrypted_password\n";
+ say "Decrypted password: $decrypted_password";
return;
} # DecryptPassword
sub Resequence($$) {
my ($userid, $type) = @_;
- MAPS::ResequenceList($userid, $type);
+ ResequenceList(
+ userid => $userid,
+ type => $type,
+ );
} # Resequence
-sub GetPassword() {
- print "Password:";
- ReadMode "noecho";
- my $password = ReadLine(0);
- chomp $password;
- print "\n";
- ReadMode "normal";
-
- return $password;
-} # GetPassword
-
sub Login2MAPS($;$) {
my ($username, $password) = @_;
if ($username ne '') {
- $password = GetPassword if !defined $password or $password eq "";
+ $password = GetPassword unless $password;
} # if
while (Login($username, $password) != 0) {
- print "Login failed!\n";
+ say "Login failed!";
+
print "Username:";
+
$username = <>;
- if ($username eq "") {
- print "Login aborted!\n";
+
+ if ($username eq '') {
+ say "Login aborted!";
+
return undef;
} # if
+
chomp $username;
+
$password = GetPassword;
} # if
} elsif ($listfilename eq "null.list") {
$listtype = "null";
} else {
- print "Unknown list file: $listfilename\n";
+ say "Unknown list file: $listfilename";
return;
} # if
my $listfile;
if (!open $listfile, '<', $listfilename) {
- print "Unable to open $listfilename\n";
+ say "Unable to open $listfilename";
return;
} # if
my $sequence = 0;
- Info("Adding $listfilename to $listtype list");
+ Info(
+ userid => $userid,
+ message => "Adding $listfilename to $listtype list",
+ );
while ($listfile) {
chomp;
} # while
if ($sequence == 0) {
- print "No messages found to load ";
+ say "No messages found to load";
} elsif ($sequence == 1) {
- print "Loaded 1 message ";
+ say "Loaded 1 message ";
} else {
- print "Loaded $sequence messages ";
+ say "Loaded $sequence messages";
} # if
- print "from $listfilename\n";
+
+ say "from $listfilename";
close $listfile;
} # LoadListFile
my $file;
- if (!open $file, '<', $filename) {
- print "Unable to open \"$filename\" - $!\n";
- return;
- } # if
+ open $file, '<', $filename
+ or die "Unable to open \"$filename\" - $!\n";
binmode $file;
my $nbr_msgs;
while (!eof $file) {
- my ($sender, $reply_to, $subject, $data) = ReadMsg (*$file);
+ my %msgInfo = ReadMsg *$file;
$nbr_msgs++;
- AddEmail($sender, $subject, $data);
-
- Info("Added message from $sender to email");
+ AddEmail(
+ userid => $userid,
+ sender => $msgInfo{sender},
+ subject => $msgInfo{subject},
+ data => $msgInfo{data},
+ );
+
+ Info(
+ userid => $userid,
+ message => "Added message from $msgInfo{sender} to email"
+ );
} # while
if ($nbr_msgs == 0) {
- print "No messages found to load ";
+ print "No messages found to load";
} elsif ($nbr_msgs == 1) {
- print "Loaded 1 message ";
+ print "Loaded 1 message";
} else {
- print "Loaded $nbr_msgs messages ";
+ print "Loaded $nbr_msgs messages";
} # if
- print "from $file\n";
+
+ say " from $filename";
} # LoadEmail
sub DumpEmail($) {
my $file;
- if (!open $file, '>', $filename) {
- print "Unable to open \"$filename\" - $!\n";
- return;
- } # if
+ open $file, '>', $filename or
+ die "Unable to open \"$filename\" - $!\n";
binmode $file;
- my $i = 0;
- my $handle = FindEmail;
-
- my ($userid, $sender, $subject, $timestamp, $message);
+ my $i = 0;
+
+ my ($err, $msg) = $MAPS::db->find(
+ 'email',
+ "userid = '$userid'",
+ qw(data),
+ );
- while (($userid, $sender, $subject, $timestamp, $message) = GetEmail($handle)) {
- print $file $message;
+ croak $msg if $msg;
+
+ while (my $rec = $MAPS::db->getnext) {
+ say $file $rec->{data};
$i++;
} # while
- print "$i messages dumped to $file\n";
+ say "$i messages dumped to $file";
close $file;
} # DumpEmail
my ($new_user) = @_;
if ($new_user = Login2MAPS($new_user)) {
- print "You are now logged in as $new_user\n";
+ say "You are now logged in as $new_user";
} # if
} # SwitchContext
-sub ShowSpace($) {
- my ($detail) = @_;
+sub SetPassword() {
+ FindUser(userid => $userid);
- my $userid = GetContext;
+ my $rec = GetUser;
- if ($detail) {
- my %msg_space = Space($userid);
+ return unless $rec;
- for (sort (keys (%msg_space))) {
- my $sender = $_;
- my $size = $msg_space{$_};
- format PER_MSG=
-@######### @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-$size,$sender
-.
-$~ = "PER_MSG";
- write ();
- } # foreach
+ my $password = GetPassword('Enter new password');
+ my $repeat = GetPassword('Enter new password again');
+
+ if ($password ne $repeat) {
+ say "Passwords don't match!";
} else {
- my $total_space = Space($userid);
+ $rec->{password} = Encrypt($password, $userid);
- $total_space = $total_space / (1024 * 1024);
+ UpdateUser(%$rec);
- format TOTALSIZE=
+ say "Password updated";
+ } # if
+
+ return;
+} # SetPassword
+
+sub ShowSpace() {
+ my $userid = GetContext;
+
+ my $total_space = Space($userid);
+
+ $total_space = $total_space / (1024 * 1024);
+
+ format TOTALSIZE=
Total size @###.### Meg
$total_space
.
$~ = "TOTALSIZE";
- write ();
- } # if
+
+ write();
} # ShowSpace
sub ShowUser() {
- print "Current userid is " . GetContext() . "\n";
+ say "Current userid is " . GetContext();
} # ShowContext
sub ShowUsers() {
- my ($handle) = FindUser;
+ FindUser(
+ fields => ['userid', 'name', 'email'],
+ );
- my ($userid, $name, $email);
+ my $rec;
format USERLIST =
User ID: @<<<<<<<<< Name: @<<<<<<<<<<<<<<<<<<< Email: @<<<<<<<<<<<<<<<<<<<<<<<
-$userid,$name,$email
+$rec->{userid},$rec->{name},$rec->{email}
.
$~ = "USERLIST";
- while (($userid, $name, $email) = GetUser($handle)) {
- last if ! defined $userid;
- write();
+ while ($rec = GetUser) {
+ last unless $rec->{userid};
+ write;
} # while
-
- $handle->finish;
} # ShowUsers
sub ShowEmail() {
- my ($handle) = FindEmail;
+ my ($err, $msg) = $MAPS::db->find(
+ 'email',
+ "userid='$userid'",
+ qw(userid timestamp sender subject),
+ );
- my ($userid, $sender, $subject, $timestamp, $message);
+my ($timestamp, $sender, $subject);
format EMAIL =
@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$timestamp,$sender,$subject
.
+
$~ = "EMAIL";
- while (($userid, $sender, $subject, $timestamp, $message) = GetEmail($handle)) {
- last unless $userid;
+ while (my $rec = $MAPS::db->getnext) {
+ last unless $rec->{userid};
+
+ $timestamp = $rec->{timestamp};
+ $sender = $rec->{sender};
+ $subject = $rec->{subject};
+
write();
} # while
-
- $handle->finish;
} # ShowEmail
sub ShowLog($) {
$timestamp,$type,$sender,$message
.
$~ = "LOG";
- while (($userid, $timestamp, $sender, $type, $message) = GetLog $handle) {
- last unless $userid;
- write();
+
+ my $count = 0;
+
+ while (my $rec = GetLog) {
+ $timestamp = $rec->{timestamp} || '';
+ $type = $rec->{type} || '';
+ $sender = $rec->{sender} || '';
+ $message = $rec->{message} || '';
+
+ $count++;
+
+ last if $count > $how_many;
+
+ write;
} # while
- $handle->finish;
+ return;
} # ShowLog
sub ShowList($) {
.
$~ = "LIST";
- while (@list = ReturnList($type, $next, $lines)) {
- for (@list) {
- %record = %{$_};
+ # TODO: Why does ReturnList return a one entry array with a many entry array
+ # of hashes. Seems it should just return $list[0], right?
+ while (@list = ReturnList(
+ userid => $userid,
+ type => $type,
+ start_at => $next,
+ lines => $lines)) {
+ for (@{$list[0]}) {
+ %record = %$_;
+
+ # Format blows up if any field is undefined so...
+ $record{pattern} //= '';
+ $record{domain} //= '';
+ $record{comment} //= '';
write();
} # for
- print "Hit any key to continue";
- ReadLine (0);
+
+ print 'Hit any key to continue - q to quit';
+
+ ReadMode 'raw';
+ my $key = ReadKey(0);
+ ReadMode 'normal';
+
+ if ($key eq 'q' or ord $key == 67) {
+ print "\n";
+
+ last;
+ } # if
+
+ print "\r";
+
$next += $lines;
} # while
+
+ return;
} # ShowList
sub ShowStats($) {
$nbr_days ||= 1;
- my %dates = GetStats($nbr_days);
+ my %dates = GetStats(
+ userid => $userid,
+ days => $nbr_days,
+ );
for my $date (keys(%dates)) {
for (keys(%{$dates{$date}})) {
- print "$date $_:";
- print "\t$dates{$date}{$_}\n";
+ say "$date $_:";
+ say "\t$dates{$date}{$_}";
} # for
} # for
} # ShowStats
my $message;
if (!open $message, '<', $filename) {
- print "Unable to open message file $filename\n";
+ say "Unable to open message file $filename";
return;
} # if
return;
} # Deliver
-sub ParseCommand($$$$$){
- my ($cmd, $parm1, $parm2, $parm3,$parm4) = @_;
+sub ExecuteCmd($){
+ my ($line) = @_;
- $_ = $cmd . ' ';
+ my ($cmd, $parm1, $parm2, $parm3, $parm4) = split /\s+/, $line;
- SWITCH: {
- /^$/ && do {
- last SWITCH
- };
+ given ($cmd) {
+ when (!$_) {
+ return;
+ } # when
- /^resequence / && do {
+ when (/^\s*resequence\s*$/) {
Resequence(GetContext(), $parm1);
- last SWITCH
- };
+ } # when
- /^encrypt / && do {
- EncryptPassword($parm1, $parm2);
- last SWITCH
- };
+ when (/^s*encrypt\s*$/) {
+ EncryptPassword($parm1, $userid);
+ } # when
- /^decrypt / && do {
- my $password = UserExists(GetContext());
- DecryptPassword($password, $maps_username);
- last SWITCH
- };
+ when (/^\s*encrypt\s*$/) {
+ EncryptPassword($parm1, $userid);
+ } # when
- /^deliver / && do {
+ when (/^\s*decrypt\s*$/) {
+ DecryptPassword($parm1, $userid);
+ } # when
+
+ when (/^\s*deliver\s*$/) {
Deliver($parm1);
- last SWITCH
- };
+ } # when
+
+ when (/^\s*add2whitelist\s*$/) {
+ if ($parm2) {
+ $parm2 .= ' ' . $parm3
+ } # if
- /^add2whitelist / && do {
- Add2Whitelist($parm1, GetContext(), $parm2);
- last SWITCH
- };
+ Add2Whitelist(
+ userid => GetContext,
+ type => 'white',
+ sender => $parm1,
+ retention => $parm2,
+ );
+ } # when
- /^showusers / && do {
+ when (/^\s*showusers\s*$/) {
ShowUsers;
- last SWITCH
- };
+ } # when
- /^adduser / && do {
- AddUser($parm1, $parm2, $parm3, $parm4);
- last SWITCH;
- };
+ when (/^\s*adduser\s*$/) {
+ AddUser(
+ userid => $parm1,
+ name => $parm2,
+ email => $parm3,
+ password => Encrypt($parm4, $userid),
+ );
+ } # when
- /^cleanemail / && do {
- if ($parm1 eq '') {
- $parm1 = "9999-12-31 23:59:59";
- } # if
- my $nbr_entries = CleanEmail($parm1);
- print "$nbr_entries email entries cleaned\n";
- last SWITCH;
- };
-
- /^deleteemail / && do {
- my $nbr_entries = DeleteEmail($parm1);
- print "$nbr_entries email entries deleted\n";
- last SWITCH;
- };
-
- /^cleanlog / && do {
- if ($parm1 eq '') {
- $parm1 = "9999-12-31 23:59:59";
- } # if
- my $nbr_entries = CleanLog($parm1);
- print "$nbr_entries log entries cleaned\n";
- last SWITCH;
- };
+ when (/^\s*cleanemail\s*$/) {
+ $parm1 = "9999-12-31 23:59:59" unless $parm1;
- /^loadlist / && do {
+ say CleanEmail($parm1);
+ } # when
+
+ when (/^\s*cleanlog\s*$/) {
+ $parm1 = "9999-12-31 23:59:59" unless $parm1;
+
+ say CleanLog($parm1);
+ } # when
+
+ when (/^\s*loadlist\s*$/) {
LoadListFile($parm1);
- last SWITCH;
- };
+ } # when
- /^loademail / && do {
+ when (/^\s*loademail\s*$/) {
LoadEmail($parm1);
- last SWITCH;
- };
+ } # when
- /^dumpemail / && do {
+ when (/^\s*dumpemail\s*$/) {
DumpEmail($parm1);
- last SWITCH;
- };
-
- /^log / && do {
- Logmsg("info", "$parm1 $parm2", $parm3);
- last SWITCH;
- };
-
- /^switchuser / && do {
+ } # when
+
+ when (/^\s*log\s*$/) {
+ Logmsg(
+ userid => $userid,
+ type => $parm1,
+ sender => $parm2,
+ message => $parm3,
+ );
+ } # when
+
+ when (/^\s*switchuser\s*$/) {
SwitchUser($parm1);
- last SWITCH;
- };
+ } # when
- /^showuser / && do {
+ when (/^\s*showuser\s*$/) {
ShowUser;
- last SWITCH;
- };
+ } # when
- /^showemail / && do {
+ when (/^\s*showemail\s*$/) {
ShowEmail;
- last SWITCH
- };
+ } # when
- /^showlog / && do {
+ when (/^\s*showlog\s*$/) {
ShowLog($parm1);
- last SWITCH
- };
+ } # when
- /^showlist / && do {
+ when (/^\s*showlist\s*$/) {
ShowList($parm1);
- last SWITCH
- };
+ } # when
- /^space / && do {
- ShowSpace($parm1);
- last SWITCH
- };
+ when (/^\s*space\s*$/) {
+ ShowSpace;
+ } # when
- /^showstats / && do {
+ when (/^\s*showstats\s*$/) {
ShowStats($parm1);
- last SWITCH
- };
-
- /^help / && do {
- print "Valid commands are:\n\n";
- print "adduser <userid> <realname> <email> <password>\tAdd user to DB\n";
- print "add2whitelist <sender> <name>\t\tAdd sender to whitelist\n";
- print "cleanlog [timestamp]\t\tCleans out old log entries\n";
- print "log <message>\t\t\tLogs a message\n";
- print "loadlist <listfile>\t\t\tLoad a list file\n";
- print "cleanemail [timestamp]\t\tCleans out old email entries\n";
- print "deliver <message>\t\t\tDelivers a message\n";
- print "loademail <mbox>\t\t\tLoad an mbox file\n";
- print "dumpemail <mbox>\t\t\tDump email from DB to an mbox file\n";
- print "deleteemail <sender>\t\t\tDelete email from sender\n";
- print "switchuser <userid>\t\t\tSwitch to user\n";
- print "showuser\t\t\t\tShow current user\n";
- print "showusers\t\t\t\tShows users in the DB\n";
- print "showemail\t\t\t\tDisplays email\n";
- print "showlog <nbr>\t\t\tDisplays <nbr> log entries\n";
- print "space\t <detail>\t\t\tDisplay space usage\n";
- print "showlist <type>\t\t\tShow list by type\n";
- print "showstats <nbr>\t\t\tDisplays <nbr> days of stats\n";
- print "encrypt <password>\t\t\tEncrypt a password\n";
- print "resequence <list>\t\t\tResequences a list\n";
- print "help\t\t\t\t\tThis screen\n";
- print "exit\t\t\t\t\tExit mapsutil\n";
- last SWITCH;
- };
-
- print "Unknown command: $_";
-
- print " ($parm1" if $parm1;
- print ", $parm2" if $parm2;
- print ", $parm3" if $parm3;
- print ", $parm4" if $parm4;
- print ")\n";
- } # SWITCH
-} # ParseCommand
-
-$maps_username = $ENV{MAPS_USERNAME} ? $ENV{MAPS_USERNAME} : $ENV{USER};
-
-my $username = Login2MAPS($maps_username, $ENV{MAPS_PASSWORD});
+ } # when
+
+ when (/^\s*setpassword\s*$/) {
+ SetPassword;
+ } # when
+
+ default {
+ say "Unknown command: $_";
+
+ say "Parm1: $parm1" if $parm1;
+ say "Parm2: $parm2" if $parm2;
+ say "Parm3: $parm3" if $parm3;
+ say "Parm4: $parm4" if $parm4;
+ } # default
+ } # given
+
+ return;
+} # ExecuteCmd
+
+my $username = Login2MAPS($userid, $ENV{MAPS_PASSWORD});
if ($ARGV[0]) {
- ParseCommand($ARGV[0], $ARGV[1], $ARGV[2], $ARGV[3], $ARGV[4]);
+ ExecuteCmd join ' ', @ARGV;
exit;
} # if
-# Use ReadLine
-my $term = new Term::ReadLine 'mapsutil';
-
-while (1) {
- $_ = $term->readline ("MAPSUtil:");
+# Use CommandLine
+$CmdLine::cmdline->set_cmds(%cmds);
+$CmdLine::cmdline->set_eval(\&ExecuteCmd);
- last unless $_;
+while (my ($line, $result) = $CmdLine::cmdline->get) {
+ next unless $line;
- my ($cmd, $parm1, $parm2, $parm3, $parm4) = split;
+ last if $line =~ /^\s*exit\s*$/i or $line =~ /^\s*quit\s*$/i;
- last if ($cmd =~ /exit/i || $cmd =~ /quit/i);
-
- ParseCommand($cmd, $parm1, $parm2, $parm3, $parm4) if defined $cmd;
+ ExecuteCmd $line;
} # while
-print "\n" unless $_;
-
exit;