Skip to content

Commit

Permalink
Merge pull request #362 from hollie/calendar_fixes_hplato
Browse files Browse the repository at this point in the history
Various fixes for the calendar interface by @hplato
  • Loading branch information
hollie committed Mar 15, 2014
2 parents 005a06e + ca54602 commit 7f253fb
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 39 deletions.
49 changes: 33 additions & 16 deletions bin/ical2vsdb
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@ use strict;
##
## Date::Calc
## DateTime::TimeZone
## Crypt::SSLeay is required if using https
##
## All other libs should exist w/i the core mh lib/site dir structure
##

## Changelog 3.4 10-04-06: for some reason ical parser is adding an 'ical' level in the
## ical parse hash from a Darwin Calendar Server. Added a dcsfix option

##
## v4.0 01-2014: Date bugfix, added https method, added control calendar, and made sync_dtstamp
## and dcsfix defaults. Added in nosync_dtstamp and nodcsfix option to override.
## NOTE: v4 requires the update 2014 vsdb calendar schema (adding a control attribute).
## Common module organizer 2014 and vsdb calendar.pl 1.6.0-3 required.
##

use lib '../lib', '../lib/site';
use iCal::Parser;
Expand All @@ -33,12 +39,11 @@ use vsLock;
# verify todos (uninitialized string message?)
# verify locking works as expected


my $progname = "ical2vsdb";
my $progver = "v3.4 10-04-06";
my $progver = "v4 01-2014";
my $DB = 0;

my $days_before = 180; # defaults to avoid large vsdb databases, can be overriden
my $days_before = -180; # defaults to avoid large vsdb databases, can be overriden
my $days_after = 180; #

my $config_file= "";
Expand All @@ -55,6 +60,7 @@ $config_file = $ARGV[0] if $ARGV[0];
&help if ((lc $config_file eq "-h") or (lc $config_file eq "--h") or ($config_file eq ""));

print "iCal to vsDB Misterhouse import ($progname $progver) starting...\n";
print "Debug Level $DB\n" if ($DB);

&purge_icals if ($config_file eq "--purge-ical-info");

Expand Down Expand Up @@ -120,10 +126,12 @@ while (1) {
print "done\n";
$process = 1;

} elsif ((lc $ical_data[$loop]->{method} eq "http") or (lc $ical_data[$loop]->{method} eq "webcal")) {
print "Fetching via LWP...";
} elsif ((lc $ical_data[$loop]->{method} eq "http") or (lc $ical_data[$loop]->{method} eq "https") or (lc $ical_data[$loop]->{method} eq "webcal")) {
my $ua = new LWP::UserAgent;
my $req = new HTTP::Request GET => "http://" . $calendar_loc;
my $method = "http";
$method .= "s" if (lc $ical_data[$loop]->{method} eq "https");
print "Fetching via LWP:$method...";
my $req = new HTTP::Request GET => $method . "://" . $calendar_loc;
if ($ical_data[$loop]->{username}) {
$req->authorization_basic($ical_data[$loop]->{username},$ical_data[$loop]->{password});
}
Expand Down Expand Up @@ -162,7 +170,7 @@ while (1) {

if ($process) {

if ($ical_data[$loop]->{options}->{sync_dtstamp}) {
unless ($ical_data[$loop]->{options}->{nosync_dtstamp}) {
print "Syncing DTSTAMP attributes from CREATED...\n";
$data =~ s/DTSTAMP:(.*)\n//g;
$data =~ s/CREATED:(.*)\n/CREATED:$1\nDTSTAMP:$1\n/g;
Expand All @@ -178,7 +186,7 @@ while (1) {
# print "Debug: Hash=$ical_data[$loop]->{hash}\n" if (defined $ical_data[$loop]->{hash});

if (!(defined $ical_data[$loop]->{hash}) or ($ical_data[$loop]->{hash} ne $digest)) {
print "New Calendar entries. Processing iCal...";
print "New Calendar entries. Processing iCal.";
if ($ical_data[$loop]->{method} ne "dir") {
eval {$parser->parse_strings($data); };
}
Expand Down Expand Up @@ -299,14 +307,16 @@ sub parse_cal {
my $opt_speak_todo = 0;
my $opt_holiday = 0;
my $opt_vacation = 0;
my $opt_control = 0;

$opt_speak_cal = 1 if (exists $options->{speak_cal});
$opt_speak_todo = 1 if (exists $options->{speak_todo});
$opt_holiday = 1 if (exists $options->{holiday});
$opt_vacation = 1 if (exists $options->{vacation});
$opt_control = 1 if (exists $options->{control});

my ($opt_sourcename) = $options->{name} if (defined $options->{name});
$cal = $cal->{ical} if (exists $options->{dcsfix});
print "Fixing Darwin Calendar Server Settings...\n" if ($DB and (exists $options->{dcsfix}));
$cal = $cal->{ical} unless (exists $options->{nodcsfix});
my $calname = $cal->{cals}->[0]->{'X-WR-CALNAME'};
$calname = $opt_sourcename if $opt_sourcename;

Expand Down Expand Up @@ -334,16 +344,17 @@ sub parse_cal {
print "."; #give some progress
while (my $uid = each %{$cal->{events}->{$year}->{$month}->{$day}}) {
my $delta;

#is this event in range?
if ($days_before or $days_after) {
$delta = Delta_Days($lyear,$lmon,$lday, $year,$month,$day);
}
print "EventID:$uid, before=$days_before after=$days_after delta=$delta\n" if ($DB>2);

#if not then skip the item
next if ((($days_before) and ($days_before > $delta)) or
(($days_after) and ($days_after < $delta)));

(($days_after) and ($days_after < $delta)));

print "Processing EventID:$uid\n" if ($DB >2);
my $event_ref = $cal->{events}->{$year}->{$month}->{$day}->{$uid};
my $starttime = "12:00 am"; # starttime and endtime are initialized the same if all day
my $endtime = "12:00 am";
Expand Down Expand Up @@ -380,6 +391,8 @@ sub parse_cal {
$holiday = "on" if $opt_holiday;
my $vacation = "off";
$vacation = "on" if $opt_vacation;
my $control = "off";
$control = "on" if $opt_control;

my $description = $event_ref->{DESCRIPTION} || '';
if ($description) {
Expand All @@ -399,6 +412,7 @@ sub parse_cal {
$out_cals[$count]->{DETAILS} = $description;
$out_cals[$count]->{HOLIDAY} = $holiday;
$out_cals[$count]->{VACATION} = $vacation;
$out_cals[$count]->{CONTROL} = $control;
$out_cals[$count]->{SOURCE} = $source;
$out_cals[$count]->{REMINDER} = $reminder;
$out_cals[$count]->{ENDTIME} = $endtime;
Expand Down Expand Up @@ -542,7 +556,8 @@ sub init {
$ical_data[$count]->{options}->{$key} = $value;
}
$ical_data[$count]->{hash} = "none";

print "Applying second level ical parsing (set nodscfix if this breaks anything) ...\n" unless (exists $ical_data[$count]->{options}->{nodcsfix});

my ($method, $loc) = split(/:\/\//,$url);
if ($loc) {
my ($username, $password, $uri) = $loc =~ /^(\S+):(\S+)@(\S+)/i;
Expand Down Expand Up @@ -593,12 +608,14 @@ sub help {

print "usage\t$progname CONFIGURATION_FILE OUTPUT_DIR\n";
print " or\t$progname --purge-ical-info OUTPUT_DIR\n";
print "version $progver\n";
print "\n\n";
print " -- CONFIG FILE SYNTAX -- \n";
print "TYPE<tab>VALUE<tab>option\n\n";
print "TYPE = cfg_version|ical|days_before|days_after|sleep\n";
print "VALUE = parameter value or ical location (http://, file://, dir://)\n";
print "OPTION = comma delimited values (holiday,name=Joe User,speak_todos,vacation,sync_dtstamp)\n";
print "OPTION = comma delimited values (holiday,name=Joe User,speak_todos,vacation,\n";
print " control, nodcsfix, nosync_dtstamp)\n";
print "\n";

die;
Expand Down
55 changes: 46 additions & 9 deletions code/common/organizer.pl
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
# Category = Time

#@ This module is a significant update from 2.103, and has a few functions;
#@ This module is a significant update from MH v2, and has a few functions;
#@<br>
#@ <ul>
#@ <li> iCal2vsDB syncronization control. Imports iCal files (Apple iCal,
#@ Mozilla Sunbird) into MH as standard calendars, or holiday/vacation
#@ calendars.
#@ <li> New in v3.1 now can control objects using a control calendar
#@ <li> Monitors the vsDB calendar and todo files and creates required events
#@ to process these items (creates organizer_*.pl files in the code dir)
#@ <li> Implements an Organizer_Events class for manipulating events, holidays
#@ and vacations.
#@ <li> Automatically updates vsDB 'databases' with the new required fields
#@<br>
#@ Minimum Requirements: calendar.pl 1.5.7-4 and tasks.pl 1.4.8-4 (Misterhouse v2.104)
#@ Minimum Requirements: calendar.pl 1.6.0-3 and tasks.pl 1.4.8-4 (Misterhouse v2.104)

=begin comment
Expand All @@ -37,22 +38,29 @@
url examples:
http://server/path/to/icalfile.ics
https://server/path/to/icalfile.ics
file://path/to/icalfile.ics
http://user@pass:server/file.ics
ical2vsdb_<name>_options = comma delimited list of ical processing options
Options available:
sync_dtstamp some calendars (ie google) update the dtstamp field each time the calendar
is downloaded, such that it is processed each time. Setting this option
syncs the dtstamp field with created, ensuring that ical2vsdb only runs when
the calendar has changed.
speak_cal to speak calendar entries
speak_todo to speak task entries
holiday calendar entries should be treated as holiday time
vacation calendar entries should be treated as vacation time
name=XXXX set source name to XXX rather than parse it from inside the ical
dcsfix might be needed to parse calendars using the Darwin Calendar Server
Changed in ical2vsdb 4
nodcsfix most calendar servers (ie google) need a second level parse. Set this if the ical
isn't being processed
nosync_dtstamp some calendars (ie google) update the dtstamp field each time the calendar
is downloaded, such that it is processed each time. ical2vsdb syncs these fields
ensuring that ical2vsdb only runs when the calendar has changed. Set this if there is
too much processing not if non-google calendars aren't being processed
control For dedicated item control calendars. MH objects with the same name as the
event will be turned on during the event duration
ie
ical2vsdb_account1 = http://house/holical.ics
Expand All @@ -67,6 +75,8 @@
iCal2vsDB uses iCal::Parser, which has several significant dependancies to operate correctly,
these have been included in lib/site
for https access Crypt::SSLeay needs to be installed manually as well
=cut


Expand Down Expand Up @@ -198,7 +208,7 @@ package main;
if defined $main::config_parms{organizer_announce_priorday_times};

#Check to see if calendar and organizer databases need upgrade
my @_upd_cal = ( 'DATE','TIME','EVENT','CATEGORY','DETAILS','HOLIDAY','VACATION','SOURCE','REMINDER','ENDTIME' );
my @_upd_cal = ( 'DATE','TIME','EVENT','CATEGORY','DETAILS','HOLIDAY','VACATION','SOURCE','REMINDER','ENDTIME','CONTROL' );
$calOk = &update_vsdb('Calendar',$_organizer_cal->name,@_upd_cal);

my @_upd_todo = ( 'Complete','Description','DueDate','AssignedTo','Notes','SPEAK','SOURCE','REMINDER','STARTDATE','CATEGORY' );
Expand Down Expand Up @@ -309,12 +319,14 @@ package main;
$data{reminder} = $objDB->FieldValue('REMINDER');
$data{category} = $objDB->FieldValue('CATEGORY');
$data{endtime} = $objDB->FieldValue('ENDTIME');
$data{control} = $objDB->FieldValue('CONTROL');
$data{endtime} = (!($data{endtime}) && $data{time}) ? $data{time} : $data{endtime};
$data{allday} = ($data{time} eq $data{endtime}) ? 'Yes' : 'No';
$data{notes} = $objDB->FieldValue('DETAILS');
$data{startdt} = $data{date} . ' ' . (($data{time}) ? $data{time} : "12:00 am");
$data{enddt} = $data{date} . ' '
. (($data{endtime} && $data{endtime} !~ /12:00 am/i) ? $data{time} : "11:59 pm");
. (($data{endtime} && $data{endtime} !~ /12:00 am/i) ? $data{endtime} : "11:59 pm");


#changed to notify an array of email addresses
$data{name_count} = 0;
Expand Down Expand Up @@ -474,6 +486,9 @@ sub generate_code {
my $default_reminder = $main::config_parms{organizer_reminder};
$default_reminder = '15m' unless $default_reminder;
$data{reminder} = $default_reminder unless $data{reminder} or $data{allday} =~ /^y/i;

#print_log "organizerDB: data{type}=$data{type} data{control}=$data{control} data{desc}=$data{description}";

my $task_flag = $main::config_parms{organizer_vc_category};
if (($task_flag) && ($data{type} eq 'task') &&
(($data{category} and ($data{category} =~ /^$task_flag/i)) or ($data{description} =~ /^$task_flag/i))) {
Expand All @@ -494,6 +509,28 @@ sub generate_code {
}
return;
}

# control calendars turn item on and off. Note that this only tests if an object exists. A better way
# might be to check if on & off are valid states...
if (($data{type} eq 'event') and ($data{control} eq 'on')) {
my $obj = $data{description};
#&main::print_log("organizerDB: found control event $obj starting $data{startdt} ending $data{enddt}");
my $obj_test = '';
my $obj_state = '';
eval { $obj_test = &main::get_object_by_name($obj); $obj_state = state $obj_test };
if ($obj_state) {
if (($data{startdt}) and ($data{enddt})) {
print MYCODE "if (time_now '$data{startdt}') { set \$$obj ON; }; #Control Event\n";
print MYCODE "if (time_now '$data{enddt}') { set \$$obj OFF; }; #Control Event\n";
} else {
&main::print_log("Organizer: Warning, invalid times for event object $obj. Ignoring Event on $data{startdt}");
}
} else {
&main::print_log("Organizer: Warning, cannot determing state of event object $obj. This item might not exist. Ignoring Event on $data{startdt}");
}
return;
}

if ($data{reminder} and !(time_greater_than($data{time_date}) or $data{reminder} eq 'none')) {
my @reminders = split(/,/,$data{reminder});
for my $reminder_info (@reminders) {
Expand Down
32 changes: 18 additions & 14 deletions web/organizer/calendar.pl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# or indirectly caused by this software.
#
# Version History
# 1.6.0-3 - 01/04/14 - added support for control calendars (hide them)
# 1.6.0-2 - 11/02/07 - minor bugfix to in icalsync name
# 1.6.0-1 - 09/24/07 - Updated to organizer release 2.5.2 without admin login and ical customization
# (1.6.0 added admin login & changed navigation)
Expand All @@ -30,7 +31,7 @@
# 1.5.2 - 08/22/01 - added file locking
# ----------------------------------------------------------------------------

my $VERSION = "1.6.0-2";
my $VERSION = "1.6.0-3";

BEGIN {
# $SIG{__WARN__} = \&FatalError;
Expand Down Expand Up @@ -338,18 +339,19 @@ sub PrintDay {
}

while (!$objMyDb->EOF) {
my $custcolor = "";
$custcolor = " bgcolor='$dataHolidayColor' " if ($objMyDb->FieldValue("HOLIDAY") eq "on");
$custcolor = " bgcolor='$dataVacationColor' " if ($objMyDb->FieldValue("VACATION") eq "on");
$custcolor = " bgcolor='$dataMultipleColor' " if (($objMyDb->FieldValue("VACATION") eq "on") and ($objMyDb->FieldValue("HOLIDAY") eq "on")); # if a day is both vacation and holiday

my $icon = $detailIcon;
my $source = $objMyDb->FieldValue("SOURCE");
$icon = "images/ical_1.jpg" if ($source =~ /^ical=/);
my $link = "<a href='$scriptName?vsSD=$showDayDetails&vsMA=$showforAudrey&vsCOM=EDIT&vsMonth=$month&vsYear=$year&vsDay=$day&vsID=" . $objMyDb->FieldValue("ID") . "'>";
print "<tr $custcolor><td>" . $link . "<img src='$icon' border='0'></a></td>";
print "<td><font size='2' face='arial,helvetica'>" . $objMyDb->FieldValue("TIME") . "&nbsp;</font></td>";
print "<td>" . $link . "<font size='2' face='arial,helvetica'>" . $objMyDb->FieldValue("EVENT") . "&nbsp;</font></td></a></tr>\n";
unless ($objMyDb->FieldValue("CONTROL") eq "on") { #Don't display CONTROL calendars
my $custcolor = "";
$custcolor = " bgcolor='$dataHolidayColor' " if ($objMyDb->FieldValue("HOLIDAY") eq "on");
$custcolor = " bgcolor='$dataVacationColor' " if ($objMyDb->FieldValue("VACATION") eq "on");
$custcolor = " bgcolor='$dataMultipleColor' " if (($objMyDb->FieldValue("VACATION") eq "on") and ($objMyDb->FieldValue("HOLIDAY") eq "on")); # if a day is both vacation and holiday
my $icon = $detailIcon;
my $source = $objMyDb->FieldValue("SOURCE");
$icon = "images/ical_1.jpg" if ($source =~ /^ical=/);
my $link = "<a href='$scriptName?vsSD=$showDayDetails&vsMA=$showforAudrey&vsCOM=EDIT&vsMonth=$month&vsYear=$year&vsDay=$day&vsID=" . $objMyDb->FieldValue("ID") . "'>";
print "<tr $custcolor><td>" . $link . "<img src='$icon' border='0'></a></td>";
print "<td><font size='2' face='arial,helvetica'>" . $objMyDb->FieldValue("TIME") . "&nbsp;</font></td>";
print "<td>" . $link . "<font size='2' face='arial,helvetica'>" . $objMyDb->FieldValue("EVENT") . "&nbsp;</font></td></a></tr>\n";
}
$objMyDb->MoveNext;
}

Expand Down Expand Up @@ -460,7 +462,7 @@ sub PrintMonth {
if ($showDayDetails) {
print "<font size='1'>";
while (!$objMyDb->EOF) {
print "<a href='$scriptName?vsSD=$showDayDetails&vsMA=$showforAudrey&vsCOM=EDIT&vsMonth=$month&vsYear=$year&vsDay=$weekDayCount&vsID=" . $objMyDb->FieldValue("ID") . "'>" .$objMyDb->FieldValue("EVENT") . "</a><br>";
print "<a href='$scriptName?vsSD=$showDayDetails&vsMA=$showforAudrey&vsCOM=EDIT&vsMonth=$month&vsYear=$year&vsDay=$weekDayCount&vsID=" . $objMyDb->FieldValue("ID") . "'>" .$objMyDb->FieldValue("EVENT") . "</a><br>" unless ($objMyDb->FieldValue("CONTROL") eq "on"); #Don't display CONTROL calendars;
$objMyDb->MoveNext;
}
print "</font>";
Expand Down Expand Up @@ -573,6 +575,8 @@ sub PrintCurrentRecord {
} elsif ($fieldName eq "ENDTIME") {
$endtime_entry = $objMyDB->FieldValue($fieldName);

} elsif ($fieldName eq "CONTROL") {
#Don't display CONTROL field. Do nothing
} else {
print "<tr valign='top' bgcolor='#DDDDDD'>\n";
print "<td><font face='arial' size='2'>" . $fieldName . "</font></td>\n";
Expand Down

0 comments on commit 7f253fb

Please sign in to comment.