#!/usr/bin/perl -w
# Luis Mondesi < lemsx1@gmail.com >
# $Revision: 1.15 $
# $Date: 2005-12-16 08:27:16 $
#
# DESCRIPTION:
# This script takes your tasks.ics file from Evolution
# and parses some fields and present that in a nicely format
# HTML file
#
# USAGE: etodo.pl -u "Name of User"
# Run this from a cronjob every X number of hours/minutes
# or whatever pleases you :-)
# This could've been written as a CGI, but, just to make it
# globally available to all users without compromising security
# it's done as a per-user basis...
#
# ex:
# etodo.pl -u "Name of User"
# etodo.pl -hc -t -u "Name of User" -d SECONDS
#
# BUGS:
# * tasks cannot have the Time set because the file is splitted in
# more than one lines and it's harder to match with a regex. will
# find work-around later...
# * doesn't run in CGI mode. This would imply passing the user
# or something that identifies the user in the URL and that's
# consider a security problem... a way to do it would be to have
# a symlink to the task.ics file somewhere and pass the file as an
# argument, or have numbers mapped to usernames somehow and pass
# those numbers instead... there are a million ways to accomplished
# this... for now it's just better to have e/a user run their own
# etodo.pl script.
# TODO:
# * add switch to hide completed tasks ( -hc or --hide-completed )
# * add the date and a optional switch to put the date in the title
# of the HTML file ( -t or --time )
# * add switch to run in daemon mode for with number of second sleep
# ( -d SECONDS or --daemon=SECONDS ). Daemon mode should detach
# from the terminal and become a background process. Thus there
# would be no need to run it from a cron job
# * add a switch for displaying the help ( --help or -h )
#
# * add -o for output .html file
#
# CHANGELOG:
# - initial relase
# LICENSE: GPL
use strict;
$|++;
# Modules to load
#
# uses CGI module for all our HTML needs...
use CGI qw(:standard);
# Configuration:
# Variables
#
my $debugging = 0;
# path of file in evolution 2
my $vtask = $ENV{'HOME'}."/.evolution/tasks/local/system/tasks.ics";
# output to this HTML file
my $ohtml = $ENV{'HOME'}."/public_html/tasks.html";
# End configuration... no need to edit below this comment
#************************************************************
my $HIDE_COMPLETED = 0;
my $SHOW_TIME = 0;
my $USER_NAME = "none";
my $EMAIL = "none\@none.com";
my $SECONDS_TO_RUN = 0;
my $date = "";
my $HELP=0;
use Getopt::Long;
Getopt::Long::Configure('bundling');
# * add switch to hide completed tasks ( -hc or --hide-completed )
# * add the date and a optional switch to put the date in the title
# of the HTML file ( -t or --time )
# * add switch to run in daemon mode for with number of second sleep
# ( -d SECONDS or --daemon=SECONDS ). Daemon mode should detach
# from the terminal and become a background process. Thus there
# would be no need to run it from a cron job
# * add a switch for displaying the help ( --help or -h )
#
GetOptions(
'H|hide-completed' => \$HIDE_COMPLETED,
't|show-time' => \$SHOW_TIME,
'u|user=s' => \$USER_NAME,
'e|email=s' => \$EMAIL,
'd|daemon=i' => \$SECONDS_TO_RUN,
'o|output=s' => \$ohtml,
'h|help' => \$HELP
) and $ohtml = shift;
print STDOUT "USAGE: etodo.pl [options] [output_filename]
-u,--user \"user\" \t display this for the title
\t -t,--show-time \t show time (title)
\t -d,--daemon SECONDS \t non interactive ( TODO: implement )
\t -H,--hide-completed \t hide completed tasks
\t -o,--output \"filename\" \t output file to output to. Unless passed from command line as last argument
" if ($HELP);
my @ary;
my $i = 0; # counter
my $k = 0; # counter
my $records = 0;
# get_fields() gets relevant fields from .ics file:
# PERCENT-COMPLETE
# DTSTAMP
# PRIORITY
# SUMMARY
#
# ...
#
sub get_fields(){
open (VFILE,$vtask) || die ("Could not open $vtask");
while (<VFILE>) {
if ( $_ =~ m/^BEGIN:VTODO/) {
#skip all values until starting of VTODO
#analyze the tasks.ics to see why...
$i++;
}
# we need to find the beginning first....
next if ( $i < 1 );
# we are sure we don't want this line...
next if ( $_ =~ m/^END:VTODO/ );
if ( $i > 0 ) {
if ($_ =~ m/^DUE;/ ){
# there are two types of Due dates
# without time
$_ =~ s/^DUE;.*VALUE=DATE:([0-9]{1,8}).*/$1/;
# with time
# this doesn't work because there is a new line character
# and we need the next line. Only solution
# is to remove the due time until a better solution
# is achieved
#$_ =~ s/^DUE;.*:.*[\s]*([0-9]*)T.*/$i/;
# time is in the form YYYYMMDD
$_ =~ s/(\d{1,4})(\d{1,2})(\d{1,2})/$1-$2-$3/;
$ary[$i]->{dtdue}=$_;
}
if ($_ =~ m/^DTSTART/ ){
$_ =~ s/^DTSTART;.*VALUE=DATE:([0-9]{1,8}).*/$1/;
$_ =~ s/(\d{1,4})(\d{1,2})(\d{1,2})/$1-$2-$3/;
$ary[$i]->{dtstart}=$_;
}
if ($_ =~ m/^SUMMARY:/ ) {
$_ =~ s/^SUMMARY://;
$ary[$i]->{summary}=$_;
}
if ($_ =~ m/^PERCENT-COMPLETE:/ ) {
$_ =~ s/^PERCENT-COMPLETE://;
$ary[$i]->{progress}=$_;
}
if ($_ =~ m/^PRIORITY:/ ) {
$_ =~ s/^PRIORITY://;
$ary[$i]->{priority}=$_;
}
if ($_ =~ m/^DESCRIPTION:/ ) {
$_ =~ s/^DESCRIPTION://;
$ary[$i]->{description}=$_;
}
#if ($_ =~ m/^COMPLETED:/ && $STARTED == 1){
# $_ =~ s/^COMPLETED:(.*)T.*/$1/;
# push(@completed, $_);
#}
#if ($_ =~ m/^DTSTAMP:/ && $STARTED == 1) {
# $_ =~ s/^DTSTAMP://;
# push(@dstamp, $_);
#}
}
} # end while
close VFILE;
# hold number of records.
#return $i;
$records = $i;
}
# print_fileds() prints content for arrays:
# @dtstart;
# @summary;
# @progress;
# @dtstamp;
# @priority;
# @completed;
# @dtdue;
sub print_fields
{
# yep, perl can be made to look weird...
# this means:
# if the user passed a file name from the command line,
# then create a handle for it,
# else print a warning to STDERR and use STDOUT as our file handle
( defined($ohtml) and open (OFILE,"> $ohtml") )
or ( print STDERR ("Could not open output file: $!
Printing to STDOUT instead
")
and *OFILE = *STDOUT );
if ( $SHOW_TIME == 1 ) {
$date = localtime;
}
print OFILE start_html(
-title=>"Evolution Tasks [$USER_NAME] $date",
-author=>"$USER_NAME <$EMAIL>",
-dtd=>"html",
-lang=>"en_US",
-encoding=>"iso-8859-1",
-head=>[
meta({-http_equiv => 'Cache-Control',-content => 'no-cache'}),
meta({-http_equiv => 'Expires',-content => '0'}),
meta({-http_equiv => 'Pragma',-content => 'no-cache'}),
meta({-http_equiv => 'refresh',-content => '300;URL=tasks.html'})
],
-BGCOLOR=>'white'
);
print OFILE "<table width='100%'>
";
print OFILE Tr(
{
-align=>"CENTER",
-valign=>"TOP",
-bgcolor=>"#e5e5e5"},
td("NUMBER"),
td("START DATE"),
td("DUE DATE"),
td("SUMMARY"),
td("PROGRESS"),
td("PRIORITY"
));
if ( $debugging == 1 ) { print "**** RECORDS: ".$records."
" };
for ($i = 1;$i <= $records;$i++) {
print OFILE "<tr>
";
#number
print OFILE td($i);
#date start
my $d_start = ( exists($ary[$i]->{dtstart}) ) ? $ary[$i]->{dtstart} : 0;
print OFILE td($d_start);
#date due
my $d_due = ( exists($ary[$i]->{dtdue}) ) ? $ary[$i]->{dtdue} : 0;
print OFILE td($d_due);
#summary
{
# this is a block for which we do not need
# to see warnings!
# this line temporarily turns off warnings
no warnings;
if ( exists($ary[$i]->{description}) ) {
# should we clean the strings first?
# we should at least remove " (quotes)
# from the description...
print OFILE td("<a href=\"#\" title=\"$ary[$i]->{description}\">$ary[$i]->{summary}</a>");
} else {
print OFILE td("$ary[$i]->{summary}");
}
}
#progress
if ( $ary[$i]->{progress} == 100 ) {
print OFILE td("COMPLETED");
} else {
# print 50 hashes...
my $hash_tmp = "";
my $limit = $ary[$i]->{progress}/2;
for ($k=0; $k <= $limit ; $k++) {
$hash_tmp .= "#";
} # end for k
$ary[$i]->{progress}=~s/(
|
)//;
print OFILE td("$hash_tmp ($ary[$i]->{progress}/100)");
}
#priority
if ( $ary[$i]->{priority} <= 3 && $ary[$i]->{priority} != 0) {
print OFILE td("HIGH");
} elsif ($ary[$i]->{priority} >= 4 && $ary[$i]->{priority}<6) {
print OFILE td("NORMAL");
} elsif ($ary[$i]->{priority} >= 6 ) {
print OFILE td("LOW");
} else {
print OFILE td("UNDEF");
}
#end table row
print OFILE "</tr>
";
} # end for i
print OFILE "</table>
",end_html;
close OFILE;
}
get_fields();
print_fields();
Advertisement