Retrouvez cet article dans : Linux Magazine 96
Suppression des doublons d’un agenda au format ICalendar
La RFC 2445 [1] rappelle qu’il y a un vrai besoin de standard pour l’interopérabilité des services d’agendas ou de calendriers. Elle définit en outre le format iCalendar pour permettre d’échanger ou de stocker des informations variées comme les calendriers, des listes de choses à faire ou des évènements. De fait, le format iCalendar est utilisé par de nombreuses applications de gestion d’informations personnelles, qui savent lire et produire des fichiers .ics. Le format reste très libre, et l’interprétation de la sémantique reste à définir pour l’unicité des évènements, en particulier. Justement, notre grand chef, après une migration de son système sur une nouvelle version a essayé de synchroniser son Palm Treo680 avec son calendrier Evolution, mais après plusieurs essais infructueux, le système lui présente désormais ses rendez-vous en double ou en triple. C’est mal ! Heureusement, Perl et CPAN sont là . Une brève recherche (Merci Jérôme) sur CPAN, grâce à l’excellent CPAN Suggest [2] fournit rapidement une réponse et nous aiguille entre autres sur quelques modules excellents et bien documentés de Jesse Vincent (papa entre autres de Request Tracker).Data::Ical [3]
Pour explorer le contenu du calendrier, une ligne comme la suivante suffit (bon, deux, pour préciser le module qui va être utilisé). use Data::ICal;
my $calendar = Data::ICal->new($filename);
iCalendar définit de nombreux composants, rebaptisés entries qui généralement n’ont pas de sous-composants, mais certains peuvent en avoir. Chaque composant peut alors avoir des propriétés, dont certaines sont uniques et d’autres peuvent apparaître plusieurs fois.
Pour filtrer les méchants doublons, il faut commencer par identifier ce qui fait de deux enregistrements similaires des doublons.
Evolution va assez loin dans le respect des standards en utilisant iCalendar comme format de stockage des données. Un export n’est alors même pas nécessaire.
Pour commencer, je ne m’intéresse qu’aux enregistrements de type #!/usr/bin/perl
use strict;
use warnings;
use Data::ICal;
my $input_calendar = Data::ICal->new( filename => shift || ‘calendar.ics’ );
my $output_calendar = Data::ICal->new();
my %component = ();
my %event = ();
open my $output, ‘>’, shift || ‘output_calendar.ics’
or warn "Could not open output file: $!\n";
ENTRY:
foreach my $entry ( @{ $input_calendar->entries } ) {
$component{ $entry->ical_entry_type }++;
if ( $entry->ical_entry_type =~ /VEVENT/ ) {
my $check = ‘’;
if ( $entry->property(‘summary’) ) {
foreach my $property (qw/ summary dtstart dtend /) {
foreach ( @{ $entry->property($property) } ) {
$check .= $_->value;
}
}
$component{‘ Duplicate VEVENT’}++, next ENTRY if exists $event{$check};
$event{$check} = undef;
}
else {
$component{‘ Without summary’}++;
next ENTRY;
}
}
$component{‘ Backed up entry’}++;
$output_calendar->add_entry($entry);
}
END {
print "Saving output calendar... ";
print $output $output_calendar->as_string;
close $output or die "Could not close output file: $!\n";
print "done.\n";
print "Processed entries:\n";
foreach my $key ( reverse sort keys %component ) {
printf "%10s %i\n", $key, $component{$key};
}
}
Au départ, j’avais tenté d’afficher un résumé des événements rencontrés. Le problème, c’est que j’avais une erreur un peu méchante quand j’ai essayé de pointer sur une propriété inexistante (précisément la propriété % time perl remove_duplicates_from_ical
Saving output calendar... done.
Processed entries:
VTIMEZONE 5
VEVENT 8482
Without summary 1518
Duplicate VEVENT 3808
Backed up 3161
perl remove_duplicates_from_ical 23,54s user 0,40s system 99% cpu 24,004 total
Faciliter le déploiement d’un script à l’aide de PAR [4] et PAR::Packer [5]
Comme notre grand chef ne goûte certainement pas aux joies du shell CPAN, il faut trouver un moyen d’empaqueter dans un programme prêt à l’emploi, sans se soucier des dépendances de modules. Ça tombe plutôt bien, % pp -C -x -z 9 -o remdupical remove_duplicates_from_ical
Saving output calendar... done.
Processed entries:
VTIMEZONE 5
VEVENT 8482
Without summary 1518
Duplicate VEVENT 3808
Backed up 3161
% ls -l remdupical remove_duplicates_from_ical
-rwxr-xr-x 1 lg lg 3111695 mai 21 11:37 remdupical
-rw-r--r-- 1 lg lg 1495 mai 21 11:36 remove_duplicates_from_ical
La taille du binaire généré impressionne un peu (enfin, moi surtout), et j’ai eu la mauvaise idée de vouloir lui faire subir une cure d’amaigrissement. Un passage de % strip rempdupical % ll remdupical remove_duplicates_from_ical -rwxr-xr-x 1 lg lg 1316988 mai 21 11:55 remdupical -rw-r--r-- 1 lg lg 1495 mai 21 11:36 remove_duplicates_from_icalSauf que le résultat est le suivant :
% ./remdupical
Usage: ./remdupical [ -Alib.par ] [ -Idir ] [ -Mmodule ] [ src.par ] [ program.pl ]
./remdupical [ -B|-b ] [-Ooutfile] src.par
Le script Perl généré est un peu moins imposant que le binaire.





Donnez votre avis
Vous devez avoir ouvert une session pour écrire un commentaire.