/usr/share/usermin/schedule
NameSizeModeActions
images/-0755rm
ulang/-0755rm
atmode.pl6640755editdlrm
CHANGELOG6100644editdlrm
clear.cgi2730755editdlrm
config180644editdlrm
config.info960644editdlrm
config.info.ca1160755editdlrm
config.info.el1970644editdlrm
config.info.nl1250644editdlrm
config.info.no970644editdlrm
defaultuconfig120644editdlrm
delete.cgi6280755editdlrm
edit.cgi44170755editdlrm
email.pl3310755editdlrm
index.cgi21900755editdlrm
module.info1950644editdlrm
module.info.ar00644editdlrm
module.info.ar.auto2420644editdlrm
module.info.bg00644editdlrm
module.info.bg.auto2290644editdlrm
module.info.ca280644editdlrm
module.info.ca.auto1430644editdlrm
module.info.cs290644editdlrm
module.info.cs.auto1340644editdlrm
module.info.da00644editdlrm
module.info.da.auto1400644editdlrm
module.info.de1340644editdlrm
module.info.el00644editdlrm
module.info.el.auto3850644editdlrm
module.info.es00644editdlrm
module.info.es.auto1710644editdlrm
module.info.eu00644editdlrm
module.info.eu.auto1540644editdlrm
module.info.fa00644editdlrm
module.info.fa.auto2250644editdlrm
module.info.fi00644editdlrm
module.info.fi.auto1680644editdlrm
module.info.fr00644editdlrm
module.info.fr.auto1330644editdlrm
module.info.hr00644editdlrm
module.info.hr.auto1430644editdlrm
module.info.hu270644editdlrm
module.info.hu.auto1250644editdlrm
module.info.it00644editdlrm
module.info.it.auto1450644editdlrm
module.info.ja00644editdlrm
module.info.ja.auto1960644editdlrm
module.info.ko00644editdlrm
module.info.ko.auto1330644editdlrm
module.info.ms00644editdlrm
module.info.ms.auto1420644editdlrm
module.info.nl00644editdlrm
module.info.nl.auto1390644editdlrm
module.info.no310644editdlrm
module.info.no.auto1170644editdlrm
module.info.pl1630644editdlrm
module.info.pl.auto1630644editdlrm
module.info.pt00644editdlrm
module.info.pt.auto1440644editdlrm
module.info.pt_BR320644editdlrm
module.info.pt_BR.auto1190644editdlrm
module.info.ru500644editdlrm
module.info.ru.auto2360644editdlrm
module.info.sk00644editdlrm
module.info.sk.auto1660644editdlrm
module.info.sv00644editdlrm
module.info.sv.auto1700644editdlrm
module.info.tr00644editdlrm
module.info.tr.auto1600644editdlrm
module.info.uk00644editdlrm
module.info.uk.auto2720644editdlrm
module.info.zh00644editdlrm
module.info.zh.auto1060644editdlrm
module.info.zh_TW00644editdlrm
module.info.zh_TW.auto1120644editdlrm
save.cgi35450755editdlrm
schedule-lib.pl90800755editdlrm
uconfig.info770644editdlrm
uconfig.info.ca990755editdlrm
uconfig.info.cs930644editdlrm
uconfig.info.de910644editdlrm
uconfig.info.el1670644editdlrm
uconfig.info.nl990644editdlrm
uconfig.info.no870644editdlrm
uconfig.info.pt_BR00644editdlrm
view.cgi5690755editdlrm
Edit: /usr/share/usermin/schedule/schedule-lib.pl (9080B)
# Functions for scheduled email notification BEGIN { push(@INC, ".."); }; use WebminCore; use Time::Local; &init_config(); $cron_cmd = "$module_config_directory/email.pl"; $atmode_cmd = "$module_config_directory/atmode.pl"; if (!-x $cron_cmd && $< == 0) { &create_wrapper($cron_cmd, $module_name, "email.pl"); } if (!-x $atmode_cmd && $< == 0) { &create_wrapper($atmode_cmd, $module_name, "atmode.pl"); } &switch_to_remote_user(); &create_user_config_dirs(); &foreign_require("cron", "cron-lib.pl"); &foreign_require("mailbox", "mailbox-lib.pl"); $schedules_dir = "$user_module_config_directory/schedules"; $messages_dir = "$user_module_config_directory/messages"; $files_dir = "$user_module_config_directory/files"; $old_cron_cmd = "$user_module_config_directory/email.pl"; $old_atmode_cmd = "$user_module_config_directory/atmode.pl"; # list_schedules() # Returns a list of all scheduled messages sub list_schedules { local @rv; opendir(DIR, $schedules_dir); foreach $f (readdir(DIR)) { next if ($f eq "." || $f eq ".."); local $sched = &get_schedule($f); push(@rv, $sched) if ($sched); } closedir(DIR); return @rv; } # get_schedule(id) sub get_schedule { local $file = "$schedules_dir/$_[0]"; local %sched; &read_file($file, \%sched); $sched{'id'} = $_[0]; $sched{'file'} = $file; $sched{'mfile'} = "$messages_dir/$_[0]"; open(MAIL, $sched{'mfile'}); while() { $sched{'mail'} .= $_; } close(MAIL); return \%sched; } # save_schedule(&sched) sub save_schedule { mkdir($schedules_dir, 0700) if (!-d $schedules_dir); mkdir($messages_dir, 0700) if (!-d $messages_dir); $_[0]->{'id'} ||= time().$$; local $file = $_[0]->{'file'} || "$schedules_dir/$_[0]->{'id'}"; local %copy = %{$_[0]}; delete($copy{'mail'}); &write_file($file, \%copy); local $mfile = $_[0]->{'mfile'} || "$messages_dir/$_[0]->{'id'}"; &open_tempfile(MAIL, ">$mfile"); &print_tempfile(MAIL, $_[0]->{'mail'}); &close_tempfile(MAIL); } # delete_schedule(&sched) sub delete_schedule { unlink($_[0]->{'file'}); unlink($_[0]->{'mfile'}); system("rm -rf ".quotemeta("$files_dir/$_[0]->{'id'}")); } # list_schedule_files(&sched) # Returns a list of files attached to a scheduled email sub list_schedule_files { local ($sched) = @_; return ( ) if (!$sched->{'id'}); local @rv; opendir(DIR, "$files_dir/$sched->{'id'}"); foreach my $f (readdir(DIR)) { next if ($f eq "." || $f eq ".."); local $path = "$files_dir/$sched->{'id'}/$f"; if (-l $path) { # A server-side file push(@rv, { 'file' => readlink($path), 'id' => $f, 'type' => 0, 'size' => nice_size(recursive_disk_usage(resolve_links($path))) }); } else { # An uploaded file push(@rv, { 'file' => $path, 'id' => $f, 'type' => 1, 'size' => nice_size(recursive_disk_usage($path)) }); } } closedir(DIR); return sort { lc($a->{'id'}) cmp lc($b->{'id'}) } @rv; } # create_schedule_file(&sched, path|data, uploaded-filename) # Adds a file to a scheduled email sub create_schedule_file { local ($sched, $path, $uploaded) = @_; mkdir($files_dir, 0700) if (!-d $files_dir); mkdir("$files_dir/$sched->{'id'}", 0700) if (!-d "$files_dir/$sched->{'id'}"); if ($uploaded) { $uploaded =~ s/^(.*)[\/\\]//; &open_tempfile(FILE, ">$files_dir/$sched->{'id'}/$uploaded"); &print_tempfile(FILE, $path); &close_tempfile(FILE); } else { local $short = $path; $short =~ s/^(.*)[\/\\]//; symlink($path, "$files_dir/$sched->{'id'}/$short"); } } # delete_schedule_file(&sched, &file) sub delete_schedule_file { local ($sched, $file) = @_; unlink("$files_dir/$sched->{'id'}/$file->{'id'}"); } # find_cron_job(&sched) # Finds the cron job for some scheduled email sub find_cron_job { local @jobs = &cron::list_cron_jobs(); local ($job) = grep { $_->{'user'} eq $remote_user && ($_->{'command'} eq "$cron_cmd $_[0]->{'id'}" || $_->{'command'} eq "$old_cron_cmd $_[0]->{'id'}") } @jobs; return $job; } # my_email_address([with-name]) sub my_email_address { local ($froms, $doms) = &mailbox::list_from_addresses(); if (@$froms) { local ($fp) = &mailbox::split_addresses($froms->[0]); if ($fp) { return $_[0] ? $fp->[2] : $fp->[0]; } } return $remote_user.'@'.&get_system_hostname(); } # create_atmode_job() # If any jobs exist that are scheduled at a specific time, create a cron job # to check for them once per minute sub create_atmode_job { local @ats = grep { $_->{'at'} } &list_schedules(); if (@ats) { local @jobs = &cron::list_cron_jobs(); local ($badjob) = grep { $_->{'user'} eq $remote_user && $_->{'command'} eq $old_atmode_cmd } @jobs; if ($badjob) { &cron::delete_cron_job($badjob); } local ($job) = grep { $_->{'user'} eq $remote_user && $_->{'command'} eq $atmode_cmd } @jobs; if (!$job) { local @mins = map { $_*5 } (0 .. 11); $job = { 'command' => $atmode_cmd, 'user' => $remote_user, 'active' => 1, 'mins' => join(",", @mins), 'hours' => '*', 'days' => '*', 'months' => '*', 'weekdays' => '*' }; &cron::create_cron_job($job); } } } # make_email(&schedule) sub make_email { local ($sched) = @_; local $myaddr = &my_email_address(1); local $data = $sched->{'mail'}; if ($config{'attach'} && $sched->{'mailfile'}) { open(FILE, $sched->{'mailfile'}); while() { $data .= $_; } close(FILE); } local @attach; foreach my $file (&list_schedule_files($sched)) { local $type = &guess_mime_type($file->{'id'}, "application/octet-stream"). "; name=\"$file->{'id'}\""; local $disp = "inline; filename=\"$file->{'id'}\""; push(@attach, { 'headers' => [ [ 'Content-type', $type ], [ 'Content-Disposition', $disp ], [ 'Content-Transfer-Encoding', 'base64' ] ], 'data' => &read_file_contents($file->{'file'}) }); } return { 'headers' => [ [ 'From' => $sched->{'from'} || $myaddr ], [ 'To' => &mailbox::expand_to($sched->{'to'}) || $myaddr ], [ 'Cc' => &mailbox::expand_to($sched->{'cc'}) ], [ 'Bcc' => &mailbox::expand_to($sched->{'bcc'}) ], [ 'Subject' => $sched->{'subject'} ] ], 'attach' => [ { 'headers' => [ [ 'Content-type', ($sched->{'is_html'} ? 'text/html' : 'text/plain') ] ], 'data' => $data }, @attach ] }; } # create_wrapper(wrapper-path, module, script) # Creates a wrapper script which calls a script in some module's directory # with the proper webmin environment variables set. Copied from the cron module, # so that it can be called before requireing cron-lib.pl sub create_wrapper { local $perl_path = &get_perl_path(); &open_tempfile(CMD, ">$_[0]"); &print_tempfile(CMD, <) { \$root = \$1 if (/^root=(.*)/); } close(CONF); \$ENV{'WEBMIN_CONFIG'} = "$ENV{'WEBMIN_CONFIG'}"; \$ENV{'WEBMIN_VAR'} = "$ENV{'WEBMIN_VAR'}"; chdir("\$root/$_[1]"); exec("\$root/$_[1]/$_[2]", \@ARGV) || die "Failed to run \$root/$_[1]/$_[2] : \$!"; EOF ); &close_tempfile(CMD); chmod(0755, $_[0]); } # next_run(&sched) # Returns the unix time at which the given scheduled email will next be sent sub next_run { local ($sched) = @_; if ($sched->{'at'}) { return $sched->{'at'}; } else { local $now = time(); local @tm = localtime($now); local @mins = &cron_all_ranges($sched->{'mins'}, 0, 59); local @hours = &cron_all_ranges($sched->{'hours'}, 0, 23); local @days = &cron_all_ranges($sched->{'days'}, 1, 31); local @months = &cron_all_ranges($sched->{'months'}, 1, 12); local @weekdays = &cron_all_ranges($sched->{'weekdays'}, 0, 6); local ($min, $hour, $day, $month, $year); local @possible; foreach $min (@mins) { foreach $hour (@hours) { foreach $day (@days) { foreach $month (@months) { foreach $year ($tm[5] .. $tm[5]+7) { local $tt; eval { $tt = timelocal(0, $min, $hour, $day, $month-1, $year) }; next if ($tt < $now); local @ttm = localtime($tt); next if (&indexof($ttm[6], @weekdays) < 0); push(@possible, $tt); last; } } } } } @possible = sort { $a <=> $b } @possible; return $possible[0]; } } # cron_first(list, min, max, current) # Returns the lowest value from expanding a cron range >= current sub cron_first { local @r = &cron_range($_[0], $_[1], $_[2]); local $r; foreach $r (sort { $a <=> $b } @r) { if ($r >= $_[3]) { return $r; } } return undef; } # cron_range(range, min, max) sub cron_range { local ($w, $min, $max) = @_; local $j; local %inuse; if ($w eq "*") { # all values for($j=$min; $j<=$max; $j++) { $inuse{$j}++; } } elsif ($w =~ /^\*\/(\d+)$/) { # only every Nth for($j=$min; $j<=$max; $j+=$1) { $inuse{$j}++; } } elsif ($w =~ /^(\d+)-(\d+)\/(\d+)$/) { # only every Nth of some range for($j=$1; $j<=$2; $j+=$3) { $inuse{int($j)}++; } } elsif ($w =~ /^(\d+)-(\d+)$/) { # all of some range for($j=$1; $j<=$2; $j++) { $inuse{int($j)}++; } } else { # One value $inuse{int($w)}++; } return sort { $a <=> $b } (keys %inuse); } # cron_all_ranges(comma-list, min, max) sub cron_all_ranges { local @rv; foreach $r (split(/,/, $_[0])) { push(@rv, &cron_range($r, $_[1], $_[2])); } return sort { $a <=> $b } @rv; } 1;