4 use Data::ICal::Entry::Todo;
5 use Data::ICal::Entry::Event;
7 $RT::ICalTicketType ||= "Data::ICal::Entry::Todo";
8 $RT::ICalReminderType ||= "Data::ICal::Entry::Event";
10 my ($UserId, $SearchId, $MagicNumber);
11 my $arg = $m->dhandler_arg;
13 if ($arg =~ m{^(\d+)@(\d+)/(.*)$}) {
17 } elsif ($arg =~ m{^(\d+)/(.*)}) {
21 Abort("Corrupted URL.");
24 my $CurrentUser = new RT::CurrentUser();
25 $CurrentUser->LoadById($UserId);
26 my $user = $CurrentUser->Name;
29 unless ($CurrentUser->Id) {
30 $RT::Logger->error("No such user id $UserId from $ENV{'REMOTE_ADDR'}");
31 $m->out("RT/".$RT::VERSION ." ".404 ."\n\nno such file\n");
35 # verify user has LoadSavedSearch right
36 if ($SearchId and not $CurrentUser->HasRight( Right => 'LoadSavedSearch',
37 Object=> $RT::System )) {
38 $RT::Logger->error("not enough rights for user $user from $ENV{'REMOTE_ADDR'}");
39 $m->out("RT/".$RT::VERSION ." ".404 ."\n\nno such file\n");
44 # if MagicNumber doesn't match the one stored in database, abort
48 $Search = $CurrentUser->Attributes->WithId($SearchId);
49 $ICalAttribute = $Search->FirstAttribute('ICalURL');
51 $ICalAttribute = $CurrentUser->UserObj->FirstAttribute('ICalURL');
54 unless ($ICalAttribute) {
55 $RT::Logger->error("No such ICal feed for $user from $ENV{'REMOTE_ADDR'}");
56 $m->out("RT/".$RT::VERSION ." ".404 ."\n\nno such file\n");
61 if ($MagicNumber ne $ICalAttribute->Content) {
62 $RT::Logger->error("FAILED LOGIN for $user from $ENV{'REMOTE_ADDR'}");
63 $m->out("RT/".$RT::VERSION ." ".404 ."\n\nno such file\n");
67 my $Tickets = RT::Tickets->new($CurrentUser);
69 my $Query = "( Status = 'new' OR Status = 'open' OR Status = 'stalled')
70 AND ( Owner = '" . $CurrentUser->Id ."' OR Owner = 'Nobody' )
71 AND ( Type = 'reminder' OR 'Type' = 'ticket' )";
73 $Query = $Search->SubValue('Query')
76 $Query .= " AND ( Due > '1970-01-01' OR Starts > '1970-01-01' )";
78 $Tickets->FromSQL($Query);
80 $Tickets->OrderBy(FIELD => 'Due', ORDER => 'ASC');
82 my $calendar = Data::ICal->new();
84 my ($uid) = $RT::WebURL =~ m{https?://([^:]+)};
86 while (my $Ticket = $Tickets->Next ) {
89 if ($Ticket->Type eq 'ticket') {
90 $event = add_todo($Ticket, $uid);
92 $event = add_event($Ticket, $uid);
95 $calendar->add_entry($event);
98 my $cal = $calendar->as_string;
100 $r->content_type('text/calendar;charset=utf-8');
106 my ($Reminder, $uid) = @_;
108 return unless defined $Reminder->RefersTo->First;
109 my $Ticket = $Reminder->RefersTo->First->TargetObj;
111 my $now = RT::Date->new( $session{'CurrentUser'} ); $now->SetToNow;
113 summary => $Reminder->Subject ? $Reminder->Subject : '',
114 url => "${RT::WebURL}/Ticket/Display.html?id=" . $Ticket->id,
115 uid => $now->iCal . "-" . $Reminder->Id . "@" . $uid,
116 categories => $Ticket->QueueObj->Name,
117 dtstart => $Reminder->DueObj->iCal,
120 my $event = $RT::ICalReminderType->new();
121 $event->add_properties(%event);
127 my ($Ticket, $uid) = @_;
129 my $now = RT::Date->new( $session{'CurrentUser'} ); $now->SetToNow;
131 summary => $Ticket->Subject ? $Ticket->Subject : '',
132 dtstart => $Ticket->CreatedObj->iCal,
133 url => "${RT::WebURL}/Ticket/Display.html?id=" . $Ticket->id,
134 uid => $now->iCal . "-" . $Ticket->Id . "@" . $uid,
135 categories => $Ticket->QueueObj->Name,
138 $vtodo{due} = $Ticket->DueObj->iCal,
141 if ($Ticket->OwnerObj->Id != $RT::Nobody->Id and $Ticket->OwnerObj->EmailAddress) {
142 $vtodo{organizer} = "MAILTO:" . $Ticket->OwnerObj->EmailAddress;
143 $vtodo{attendee} = "MAILTO:" . $Ticket->OwnerObj->EmailAddress;
144 } elsif ($Ticket->QueueObj->CommentAddress) {
145 $vtodo{organizer} = "MAILTO:" . $Ticket->QueueObj->CommentAddress;
146 $vtodo{attendee} = "MAILTO:" . $Ticket->QueueObj->CommentAddress;
149 $vtodo{priority} = $Ticket->Priority
150 if $Ticket->Priority;
152 my $vtodo = $RT::ICalTicketType->new();
153 $vtodo->add_properties(%vtodo);