diff options
| author | fukachan <fukachan> | 2002-02-13 12:51:48 +0000 |
|---|---|---|
| committer | fukachan <fukachan> | 2002-02-13 12:51:48 +0000 |
| commit | b2ef4925c8507a2f5cfef23e50512de52197a5cb (patch) | |
| tree | 625b085ecc564870bbd195f046cc3df423db57c7 | |
| parent | a1a40616aedc0b2b1d3afb3cfe41cd3670397af6 (diff) | |
| download | fml8-b2ef4925c8507a2f5cfef23e50512de52197a5cb.tar.gz fml8-b2ef4925c8507a2f5cfef23e50512de52197a5cb.tar.bz2 fml8-b2ef4925c8507a2f5cfef23e50512de52197a5cb.zip | |
Initial revision
| -rw-r--r-- | fml/lib/Calendar/Lite.pm | 400 | ||||
| -rw-r--r-- | fml/lib/Calender/Lite.pm | 400 |
2 files changed, 800 insertions, 0 deletions
diff --git a/fml/lib/Calendar/Lite.pm b/fml/lib/Calendar/Lite.pm new file mode 100644 index 00000000..12717c94 --- /dev/null +++ b/fml/lib/Calendar/Lite.pm @@ -0,0 +1,400 @@ +#-*- perl -*- +# +# Copyright (C) 2001,2002 Ken'ichi Fukamachi +# All rights reserved. This program is free software; you can +# redistribute it and/or modify it under the same terms as Perl itself. +# +# $FML: Calender::Lite.pm,v 1.16 2002/02/02 07:55:45 fukachan Exp $ +# + +package Calender::Lite; +use strict; +use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD); +use Carp; + +=head1 NAME + +Calender::Lite - scheduler with minimal functions + +=head1 SYNOPSIS + + use Calender::Lite; + my $schedule = new Calender::Lite; + + $schedule->parse; + + # show table by w3m :-) + my $tmp = $schedule->tmpfile; + my $fh = new FileHandle $tmp, "w"; + $schedule->print($fh); + $fh->close; + + system "w3m -dump $tmp"; + unlink $tmp; + +=head1 DESCRIPTION + +C<TinSchecdule> is a demonstration module to show how to use and build +up modules to couple with CPAN and FML modules. +This routine needs C<HTML::CalendarMonthSimple>. + +It parses files in ~/.schedule/ and output schedule of this month as +HTML TABLE by default. To see it, you need WWW browser e.g. "w3m". + + +=head1 METHODS + +=head2 new($args) + +standard constructor. + +It speculates C<user> by $args->{ user } or $ENV{'user'} or uid +and determine path for ~user/.schedule/. + +$args can take the following variables: + + $args = { + schedule_dir => DIR, + schedule_file => FILE, + mode => MODE, + }; + +C<Caution:> + The string for ~user is restricted to ^[\w\d\.\/]+$. + + PATH is reset in the last of new(). + +=cut + + +# Descriptions: usual constructor. $args is optional, which comes from +# parameters from CGI.pm if fmlsci.cgi uses. +# OR +# libexec/loaders's $args if fmlsch uses. +# Arguments: OBJ($self) HASH_REF($args) +# Side Effects: none +# Return Value: object +sub new +{ + my ($self, $args) = @_; + my ($type) = ref($self) || $self; + my $me = {}; + my $user = defined $args->{ user } ? $args->{ user } : $ENV{'USER'}; + + # default directory to hold schdule file(s): ~/.schedule/ by default + use User::pwent; + unless (defined $user) { + my $p = getpwuid($<); + $user = $p->name; + } + + my $pw = getpwnam($user); + my $home_dir = $pw->dir; + + # XXX FML::Restriction / Taint + # simple check (not enough mature) to avoid -T (taint mode) error ;) + if ($home_dir =~ /^([\w\d\.\/]+)$/) { + $home_dir = $1; + } + else { + croak("invalid home directory string"); + } + + $me->{ _user } = $user; + $me->{ _schedule_dir } = "$home_dir/.schedule"; # ~/.schedule/ by default + $me->{ _schedule_file } = undef; + + for my $key ('schedule_dir', 'schedule_file', 'mode') { + if (defined $args->{ $key }) { + $me->{ "_$key" } = $args->{ $key }; + } + } + + # reset PATH + $ENV{'PATH'} = '/bin/:/usr/bin:/usr/pkg/bin:/usr/local/bin'; + + return bless $me, $type; +} + + +=head2 tmpfile($args) + +return tmpfile path name. +It creates just a file path not file itself. + +=cut + + +# Descriptions: determine template file location +# Arguments: OBJ($self) HASH_REF($args) +# Side Effects: none +# Return Value: STR(filename) +sub tmpfile +{ + my ($self, $args) = @_; + my $user = $self->{ _user }; + my $dir = $self->{ _schedule_dir }; + my $tmpdir; + + if (-w $dir) { + $tmpdir = $dir; + } + else { + croak("$dir not exists\n") unless -d $dir; + croak("$dir is not writable\n") unless -w $dir; + } + + eval q{ + use File::Spec; + $self->{ _tmpfile } = File::Spec->catfile($tmpdir, ".tmp.$$.html"); + }; + croak($@) if $@; + return $self->{ _tmpfile }; +} + + +=head2 parse($args) + +Parse files in ~/.schedule/ or specified schedule file. + +=cut + + +# Descriptions: parse file(s) +# Arguments: OBJ($self) HASH_REF($args) +# Side Effects: update calender entries in $self object +# (actually by _add_entry() calleded here) +# Return Value: none +sub parse +{ + my ($self, $args) = @_; + my ($sec,$min,$hour,$mday,$month,$year,$wday) = localtime(time); + + # get the date to show + $year = defined $args->{ year } ? $args->{ year } : (1900 + $year); + $month = defined $args->{ month } ? $args->{ month } : ($month + 1); + + # schedule file + my $data_dir = $self->{ _schedule_dir }; + my $data_file = $self->{ _schedule_file }; + + # pick up line matched with this pattern + my @pat = ( + sprintf("^%04d%02d(\\d{1,2})\\s+(.*)", $year, $month), + sprintf("^%04d/%02d/(\\d{1,2})\\s+(.*)", $year, $month), + sprintf("^%04d/%d/(\\d{1,2})\\s+(.*)", $year, $month), + sprintf("^%02d(\\d{1,2})\\s+(.*)", $month), + sprintf("^%02d/(\\d{1,2})\\s+(.*)", $month), + ); + + use HTML::CalendarMonthSimple; + my $cal = new HTML::CalendarMonthSimple('year'=> $year, 'month'=> $month); + + if (defined $cal) { + $self->{ _schedule } = $cal; + } + else { + croak("cannot get object"); + } + + $cal->width('70%'); + $cal->border(10); + $cal->header(sprintf("%04d/%02d %s", $year, $month, "schedule")); + $cal->bgcolor('pink'); + + if ($data_file && -f $data_file) { + $self->_analyze($data_file, \@pat); + } + elsif (-d $data_dir) { + use DirHandle; + my $dh = new DirHandle $data_dir; + + if (defined $dh) { + use File::Spec; + + while (defined($_ = $dh->read)) { + next if $_ =~ /~$/; + next if $_ =~ /^\./; + my $schedule_file = File::Spec->catfile($data_dir, $_); + if (-f $schedule_file) { + $self->_analyze($schedule_file, \@pat); + } + } + } + } + else { + croak("invalid data"); + } +} + + +# Descriptions: open, read specified $file +# analyze the line which matches $pattern. +# Arguments: OBJ($self) STR($file) STR($pattern) +# Side Effects: update $self object by _add_entry() +# Return Value: none +sub _analyze +{ + my ($self, $file, $pattern) = @_; + + use FileHandle; + my $fh = new FileHandle $file; + + if (defined $fh) { + FILE: + while (<$fh>) { + for my $pat (@$pattern) { + if (/$pat(.*)/) { + $self->_add_entry($1, $2); + next FILE; + } + } + + # for example, "*/24 something" + if (/^\*\/(\d+)\s+(.*)/) { + $self->_add_entry($1, $2); + } + } + close($fh); + } +} + + +# Descriptions: add calender entry to $self object +# Arguments: OBJ($self) STR($day) STR($buf) +# Side Effects: update $self object +# Return Value: none +sub _add_entry +{ + my ($self, $day, $buf) = @_; + my $cal = $self->{ _schedule }; + $day =~ s/^0//; + + $cal->addcontent($day, "<p>". $buf); +} + + +=head2 C<print($fd)> + +print out the result as HTML. +You can specify the output channel by C<$fd>. + +=cut + + +# Descriptions: print calender by HTML::CalenderMonthSimple::as_HTML() method +# Arguments: OBJ($self) HANDLE($fd) +# Side Effects: none +# Return Value: none +sub print +{ + my ($self, $fd) = @_; + $fd = $fd || \*STDOUT; + print $fd $self->{ _schedule }->as_HTML; +} + + +=head2 C<print_specific_month($fh, $n)> + +print range specified by C<$n>. +C<$n> is number or string among C<this>, C<next> and C<last>. + +=cut + + +# Descriptions: print calender for specific month as HTML +# Arguments: OBJ($self) HANDLE($fd) STR($month) [STR($year)] +# Side Effects: none +# Return Value: none +sub print_specific_month +{ + my ($self, $fh, $month, $year) = @_; + my ($month_now, $year_now) = (localtime(time))[4,5]; + my $default_year = 1900 + $year_now; + my $default_month = $month_now + 1; + my ($thismonth, $thisyear) = ($default_month, $default_year); + + if ($month =~ /^\d+$/) { + $thismonth = $month; + $thisyear = $year if defined $year; + } + else { + if ($default_month == 1) { + $thismonth = 2 if $month eq 'next'; + $thismonth = 12 if $month eq 'last'; + } + elsif ($default_month == 12) { + $thismonth = 1 if $month eq 'next'; + $thismonth = 11 if $month eq 'last'; + } + else { + $thismonth++ if $month eq 'next'; + $thismonth-- if $month eq 'last'; + } + } + + print $fh "<A NAME=\"$month\">\n"; + $self->parse( { month => $thismonth, year => $thisyear } ); + $self->print($fh); +} + + +=head2 get_mode( $mode ) + +show mode (string). + +=head2 set_mode( $mode ) + +override mode. +The mode is either of 'text' or 'html'. + +XXX: The mode is not used in this module itsef. + This is a pragma for other module use.. + +=cut + +# Descriptions: show the current $mode +# Arguments: OBJ($self) +# Side Effects: none +# Return Value: string or undef +sub get_mode +{ + my ($self) = @_; + return (defined $self->{ _mode } ? $self->{ _mode } : undef); +} + + +# Descriptions: overwrite $mode +# Arguments: OBJ($self) STR($mode) +# Side Effects: update $self object +# Return Value: none +sub set_mode +{ + my ($self, $mode) = @_; + $self->{ _mode } = $mode; +} + + +=head1 AUTHOR + +Ken'chi Fukamachi + +=head1 COPYRIGHT + +Copyright (C) 2001,2002 Ken'chi Fukamachi + +All rights reserved. This program is free software; you can +redistribute it and/or modify it under the same terms as Perl itself. + +=head1 HISTORY + +Calender::Lite appeared in fml5 mailing list driver package. +See C<http://www.fml.org/> for more details. + +Firstly this module name is C<TinyScheduler.pm> and renamed to +Calender::Lite later. + +=cut + + +1; diff --git a/fml/lib/Calender/Lite.pm b/fml/lib/Calender/Lite.pm new file mode 100644 index 00000000..12717c94 --- /dev/null +++ b/fml/lib/Calender/Lite.pm @@ -0,0 +1,400 @@ +#-*- perl -*- +# +# Copyright (C) 2001,2002 Ken'ichi Fukamachi +# All rights reserved. This program is free software; you can +# redistribute it and/or modify it under the same terms as Perl itself. +# +# $FML: Calender::Lite.pm,v 1.16 2002/02/02 07:55:45 fukachan Exp $ +# + +package Calender::Lite; +use strict; +use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD); +use Carp; + +=head1 NAME + +Calender::Lite - scheduler with minimal functions + +=head1 SYNOPSIS + + use Calender::Lite; + my $schedule = new Calender::Lite; + + $schedule->parse; + + # show table by w3m :-) + my $tmp = $schedule->tmpfile; + my $fh = new FileHandle $tmp, "w"; + $schedule->print($fh); + $fh->close; + + system "w3m -dump $tmp"; + unlink $tmp; + +=head1 DESCRIPTION + +C<TinSchecdule> is a demonstration module to show how to use and build +up modules to couple with CPAN and FML modules. +This routine needs C<HTML::CalendarMonthSimple>. + +It parses files in ~/.schedule/ and output schedule of this month as +HTML TABLE by default. To see it, you need WWW browser e.g. "w3m". + + +=head1 METHODS + +=head2 new($args) + +standard constructor. + +It speculates C<user> by $args->{ user } or $ENV{'user'} or uid +and determine path for ~user/.schedule/. + +$args can take the following variables: + + $args = { + schedule_dir => DIR, + schedule_file => FILE, + mode => MODE, + }; + +C<Caution:> + The string for ~user is restricted to ^[\w\d\.\/]+$. + + PATH is reset in the last of new(). + +=cut + + +# Descriptions: usual constructor. $args is optional, which comes from +# parameters from CGI.pm if fmlsci.cgi uses. +# OR +# libexec/loaders's $args if fmlsch uses. +# Arguments: OBJ($self) HASH_REF($args) +# Side Effects: none +# Return Value: object +sub new +{ + my ($self, $args) = @_; + my ($type) = ref($self) || $self; + my $me = {}; + my $user = defined $args->{ user } ? $args->{ user } : $ENV{'USER'}; + + # default directory to hold schdule file(s): ~/.schedule/ by default + use User::pwent; + unless (defined $user) { + my $p = getpwuid($<); + $user = $p->name; + } + + my $pw = getpwnam($user); + my $home_dir = $pw->dir; + + # XXX FML::Restriction / Taint + # simple check (not enough mature) to avoid -T (taint mode) error ;) + if ($home_dir =~ /^([\w\d\.\/]+)$/) { + $home_dir = $1; + } + else { + croak("invalid home directory string"); + } + + $me->{ _user } = $user; + $me->{ _schedule_dir } = "$home_dir/.schedule"; # ~/.schedule/ by default + $me->{ _schedule_file } = undef; + + for my $key ('schedule_dir', 'schedule_file', 'mode') { + if (defined $args->{ $key }) { + $me->{ "_$key" } = $args->{ $key }; + } + } + + # reset PATH + $ENV{'PATH'} = '/bin/:/usr/bin:/usr/pkg/bin:/usr/local/bin'; + + return bless $me, $type; +} + + +=head2 tmpfile($args) + +return tmpfile path name. +It creates just a file path not file itself. + +=cut + + +# Descriptions: determine template file location +# Arguments: OBJ($self) HASH_REF($args) +# Side Effects: none +# Return Value: STR(filename) +sub tmpfile +{ + my ($self, $args) = @_; + my $user = $self->{ _user }; + my $dir = $self->{ _schedule_dir }; + my $tmpdir; + + if (-w $dir) { + $tmpdir = $dir; + } + else { + croak("$dir not exists\n") unless -d $dir; + croak("$dir is not writable\n") unless -w $dir; + } + + eval q{ + use File::Spec; + $self->{ _tmpfile } = File::Spec->catfile($tmpdir, ".tmp.$$.html"); + }; + croak($@) if $@; + return $self->{ _tmpfile }; +} + + +=head2 parse($args) + +Parse files in ~/.schedule/ or specified schedule file. + +=cut + + +# Descriptions: parse file(s) +# Arguments: OBJ($self) HASH_REF($args) +# Side Effects: update calender entries in $self object +# (actually by _add_entry() calleded here) +# Return Value: none +sub parse +{ + my ($self, $args) = @_; + my ($sec,$min,$hour,$mday,$month,$year,$wday) = localtime(time); + + # get the date to show + $year = defined $args->{ year } ? $args->{ year } : (1900 + $year); + $month = defined $args->{ month } ? $args->{ month } : ($month + 1); + + # schedule file + my $data_dir = $self->{ _schedule_dir }; + my $data_file = $self->{ _schedule_file }; + + # pick up line matched with this pattern + my @pat = ( + sprintf("^%04d%02d(\\d{1,2})\\s+(.*)", $year, $month), + sprintf("^%04d/%02d/(\\d{1,2})\\s+(.*)", $year, $month), + sprintf("^%04d/%d/(\\d{1,2})\\s+(.*)", $year, $month), + sprintf("^%02d(\\d{1,2})\\s+(.*)", $month), + sprintf("^%02d/(\\d{1,2})\\s+(.*)", $month), + ); + + use HTML::CalendarMonthSimple; + my $cal = new HTML::CalendarMonthSimple('year'=> $year, 'month'=> $month); + + if (defined $cal) { + $self->{ _schedule } = $cal; + } + else { + croak("cannot get object"); + } + + $cal->width('70%'); + $cal->border(10); + $cal->header(sprintf("%04d/%02d %s", $year, $month, "schedule")); + $cal->bgcolor('pink'); + + if ($data_file && -f $data_file) { + $self->_analyze($data_file, \@pat); + } + elsif (-d $data_dir) { + use DirHandle; + my $dh = new DirHandle $data_dir; + + if (defined $dh) { + use File::Spec; + + while (defined($_ = $dh->read)) { + next if $_ =~ /~$/; + next if $_ =~ /^\./; + my $schedule_file = File::Spec->catfile($data_dir, $_); + if (-f $schedule_file) { + $self->_analyze($schedule_file, \@pat); + } + } + } + } + else { + croak("invalid data"); + } +} + + +# Descriptions: open, read specified $file +# analyze the line which matches $pattern. +# Arguments: OBJ($self) STR($file) STR($pattern) +# Side Effects: update $self object by _add_entry() +# Return Value: none +sub _analyze +{ + my ($self, $file, $pattern) = @_; + + use FileHandle; + my $fh = new FileHandle $file; + + if (defined $fh) { + FILE: + while (<$fh>) { + for my $pat (@$pattern) { + if (/$pat(.*)/) { + $self->_add_entry($1, $2); + next FILE; + } + } + + # for example, "*/24 something" + if (/^\*\/(\d+)\s+(.*)/) { + $self->_add_entry($1, $2); + } + } + close($fh); + } +} + + +# Descriptions: add calender entry to $self object +# Arguments: OBJ($self) STR($day) STR($buf) +# Side Effects: update $self object +# Return Value: none +sub _add_entry +{ + my ($self, $day, $buf) = @_; + my $cal = $self->{ _schedule }; + $day =~ s/^0//; + + $cal->addcontent($day, "<p>". $buf); +} + + +=head2 C<print($fd)> + +print out the result as HTML. +You can specify the output channel by C<$fd>. + +=cut + + +# Descriptions: print calender by HTML::CalenderMonthSimple::as_HTML() method +# Arguments: OBJ($self) HANDLE($fd) +# Side Effects: none +# Return Value: none +sub print +{ + my ($self, $fd) = @_; + $fd = $fd || \*STDOUT; + print $fd $self->{ _schedule }->as_HTML; +} + + +=head2 C<print_specific_month($fh, $n)> + +print range specified by C<$n>. +C<$n> is number or string among C<this>, C<next> and C<last>. + +=cut + + +# Descriptions: print calender for specific month as HTML +# Arguments: OBJ($self) HANDLE($fd) STR($month) [STR($year)] +# Side Effects: none +# Return Value: none +sub print_specific_month +{ + my ($self, $fh, $month, $year) = @_; + my ($month_now, $year_now) = (localtime(time))[4,5]; + my $default_year = 1900 + $year_now; + my $default_month = $month_now + 1; + my ($thismonth, $thisyear) = ($default_month, $default_year); + + if ($month =~ /^\d+$/) { + $thismonth = $month; + $thisyear = $year if defined $year; + } + else { + if ($default_month == 1) { + $thismonth = 2 if $month eq 'next'; + $thismonth = 12 if $month eq 'last'; + } + elsif ($default_month == 12) { + $thismonth = 1 if $month eq 'next'; + $thismonth = 11 if $month eq 'last'; + } + else { + $thismonth++ if $month eq 'next'; + $thismonth-- if $month eq 'last'; + } + } + + print $fh "<A NAME=\"$month\">\n"; + $self->parse( { month => $thismonth, year => $thisyear } ); + $self->print($fh); +} + + +=head2 get_mode( $mode ) + +show mode (string). + +=head2 set_mode( $mode ) + +override mode. +The mode is either of 'text' or 'html'. + +XXX: The mode is not used in this module itsef. + This is a pragma for other module use.. + +=cut + +# Descriptions: show the current $mode +# Arguments: OBJ($self) +# Side Effects: none +# Return Value: string or undef +sub get_mode +{ + my ($self) = @_; + return (defined $self->{ _mode } ? $self->{ _mode } : undef); +} + + +# Descriptions: overwrite $mode +# Arguments: OBJ($self) STR($mode) +# Side Effects: update $self object +# Return Value: none +sub set_mode +{ + my ($self, $mode) = @_; + $self->{ _mode } = $mode; +} + + +=head1 AUTHOR + +Ken'chi Fukamachi + +=head1 COPYRIGHT + +Copyright (C) 2001,2002 Ken'chi Fukamachi + +All rights reserved. This program is free software; you can +redistribute it and/or modify it under the same terms as Perl itself. + +=head1 HISTORY + +Calender::Lite appeared in fml5 mailing list driver package. +See C<http://www.fml.org/> for more details. + +Firstly this module name is C<TinyScheduler.pm> and renamed to +Calender::Lite later. + +=cut + + +1; |
