Corrupciones dentro del calendario: duplicados. ¿Cómo analizar su causa y arreglarla?

1

Estoy usando Calendar en una Mac con MacOS X Mountain Lion (10.8.5).

Esta Mac se sincroniza manualmente de forma manual con un iPhone con iOS 7.1.2.

Este Calendar está almacenando 15 años de eventos organizados en 9 "calendarios". Dado que parte de esta información es altamente confidencial, profesional o privada, no los sincronizo en ninguna forma de calendario de tiendas públicas ( iCloud , Google Calendar ...). Por otro lado, tengo muchas copias de seguridad Time Machine y copias de seguridad completas.

Recientemente, descubrí inesperadamente que desde el verano de 2001 he duplicado eventos de día completo dentro de Calendar en mi Mac. He podido ver estos rápidamente porque su naturaleza duplicada es directamente visible. Este no es un caso general: la mayoría de mis eventos de día completo no son duplicado Pero todos mis 9 "calendarios" se ven afectados por esta corrupción . Calculo que tengo unos cientos de eventos en este caso. Veo la misma corrupción en mi iPhone.

Exporté uno de mi calendario y extraje una de las entradas duplicadas. Aquí está la salida de una diferencia en los extractos de 2 .ics :
••My_Mac••$ diff duplicate.[12].ics
2c2
< UID:74FC7CC1-016C-4A74-9E02-7ECDD82C8129
---
> UID:9B6BC4CD-5859-4DC2-8DEA-9158CB8F9B0D
10,11c10,11
< X-WR-ALARMUID:D0FE4A14-981C-4409-84C1-B11107F7EC31
< UID:D0FE4A14-981C-4409-84C1-B11107F7EC31
---
> X-WR-ALARMUID:48141767-C3C6-4131-9984-0DD080833D9F
> UID:48141767-C3C6-4131-9984-0DD080833D9F
••My_Mac••$

Notación: la cadena •• nombre •• significa que "nombre" fue redactado.

Esto es lo que encontré dentro de /var/log/system.log y que podría estar relacionado:

Sep 13 10:08:32 ••My_Mac•• SyncServer[93677]: [0x7fbe60c0bdd0] |SyncServer|Warning| Refreshing watchdog because of a calendar time change alert.
Sep 13 16:09:10 ••My_Mac•• SyncServer[94189]: [0x7fd25a40bdd0] |SyncServer|Warning| Refreshing watchdog because of a calendar time change alert.
Sep 14 03:21:15 ••My_Mac•• SyncServer[94351]: [0x7f9e1ac0bdd0] |SyncServer|Warning| Refreshing watchdog because of a calendar time change alert.
Sep 14 08:56:41 ••My_Mac•• SyncServer[94351]: [0x7f9e1ac0bdd0] |SyncServer|Warning| Refreshing watchdog because of a calendar time change alert.
Sep 15 14:11:39 ••My_Mac•• SyncServer[94351]: [0x7f9e1ac0bdd0] |SyncServer|Warning| Refreshing watchdog because of a calendar time change alert.
Sep 16 00:25:17 ••My_Mac•• SyncServer[95764]: [0x7faf92c0bdd0] |SyncServer|Warning| Refreshing watchdog because of a calendar time change alert.
Sep 16 13:36:27 ••My_Mac•• SyncServer[96213]: [0x7f9470c0bdd0] |SyncServer|Warning| Refreshing watchdog because of a calendar time change alert.
Sep 16 13:51:33 ••My_Mac•• CalendarAgent[90827]: Invalid char _ for PropertyName in line 7
Sep 16 13:51:33 ••My_Mac•• CalendarAgent[90827]: Unexpected EOF, returning last token as fallback

¿Cómo puedo analizar de dónde vienen estos eventos duplicados?

¿Cómo puedo encontrar la fecha y la hora en que un evento podría haber comenzado a corromper tales programas? Sin una fecha del comienzo del daño, mis respaldos son de poca ayuda. Además, implicarán una reconstrucción total de los eventos correctos que ocurrieron después de el daño .

¿Cómo puedo obtener una visión correcta de esta corrupción de todos mis "calendarios"?

Y además, ¿cómo puedo solucionar este enorme y aparentemente aleatorio corrupción de datos ?

    
pregunta daniel Azuelos 16.09.2015 - 16:46

1 respuesta

0

Todavía no tengo una explicación correcta de estas corrupciones, pero al menos escribí una solución para tener una visión clara de la magnitud del daño y para corregirlo.

Aquí hay un script en perl: duplicate.pl :

$ cat <<'eof' >duplicate.pl
#!/usr/bin/perl
use strict ;
use warnings ;

# program reading on its standard input a file under
# ics format exported by iCal or Calendar
# Both only export one calendar at a time

# file = name of created file for a given calendar

my %file = () ;

# filedesc = file descriptor of the created calendar file

my %filedesc = () ;

# hash of all unduplicated events local_event_id
my %events = () ;

# current event storage
my @event = () ;
my $dtstart = '' ;
my $dtend = '' ;

# number of events analysed
my $num_event = 0 ;
my $duplicate = 0 ;
my $calendar = '' ;

# state booleans
my $in_header = 1 ;
my $in_event = 0 ;
my $in_summary = 0 ;
my $line = '' ;
my $summary = '' ;

# local event identifier :      summary;dtstart;dtend
# because ';' is never used within a name
my $local_event_id = '' ;

while (<STDIN>) {
        $line = $_ ;

# header :      BEGIN:VCALENDAR
#               ...
#               BEGIN:VEVENT

        if ( $in_summary ) {

#               continuation line of summary

                if ( $line =~ /^ (.+)\r\n$/ ) {
                        $summary .= $1 ;
                } else {

#                       end of summary continuation lines analysis

                        $in_summary = 0 ;
                }
        }
        if ( $line =~ /^SUMMARY[^:]*:(.+)\r\n$/ ) {
                $summary = $1 ;
                $in_summary = 1 ;
        } elsif ( $line =~ /^BEGIN:VEVENT/) {
                if ( $in_header ) {
                        $in_header = 0 ;

#                       print every lines of event or header

                        foreach $line (@event) {
                                printf {$filedesc{$calendar}} "%s", $line ;
                        }
                }
                $in_event = 1 ;
                @event = () ;
        } elsif ( $line =~ /^X-WR-CALNAME:(.+)\r\n$/) {
                $calendar = $1 ;

#               create .ics file

                if ( ! defined $file{$calendar} ) {
                        $file{$calendar} = $calendar . ".ics" ;
                        if ( -e $file{$calendar} ) {
                                die "$file{$calendar} already exists\n" ;
                        }
                        open ($filedesc{$calendar}, ">", $file{$calendar}) ;

#                       print every lines of header

                        foreach $line (@event) {
                                printf {$filedesc{$calendar}} "%s", $line ;
                        }
                        @event = () ;
                        $in_event = 0 ;
                }
#               printf STDOUT "calendar = %s\n", $calendar ;
#               printf STDOUT "file = %s\n", $file{$calendar} ;
#               printf STDOUT "fh = %d\n", $filedesc{$calendar} ;

        } elsif ( $line =~ /^DTSTART[^:]*:(.*)\r\n$/ ) {
                $dtstart = $1 ;

#               printf STDOUT "DTSTART = %32s\n", $dtstart ;

        } elsif ( $line =~ /^DTEND[^:]*:(.*)\r\n$/ ) {
                $dtend = $1 ;

#               printf STDOUT "DTEND = %32s\n", $dtend ;

        } elsif ( $line =~ /^END:VEVENT/ ) {

# it's only on closing an event definition that we have
# a complete local event identifier

                $local_event_id = "$summary" . ";" . "$dtstart" . ";" . "$dtend" ;


                if ( defined ( $events{"$local_event_id"} )) {

#                       duplicate event

                        printf STDOUT "\n\tduplicate\t%s\n", $local_event_id ;

#                       free event storage

                        @event = () ;
                        $in_event = 0 ;
                        $duplicate++ ;
                } else {

#                       new event
                        $events{$local_event_id} = 1;

                        if ($in_event) {

#                               print every lines of stored event

                                foreach $line (@event) {
                                        printf {$filedesc{$calendar}} "%s", $line ;
                                }
                                @event = () ;
                                $in_event = 0 ;
                                $num_event++ ;
                                $in_header = 1 ;

#                               show progress
                                if (($num_event % 100) == 0) {
                                        printf STDOUT "\n%8d", $num_event ;
                                } else {
                                        print STDOUT "." ;
                                }
                        }
                }
        } elsif ( $in_event == 0 ) {
                $in_header = 1 ;
        }

#       store every line of event or header

        if ($in_event || $in_header) {
                push (@event, $line) ;
        }

}

printf STDOUT "\nevents:%12d\n", $num_event ;
printf STDOUT "duplicates:%8d\n", $duplicate ;

#                       print every lines of ending

                        foreach $line (@event) {
                                printf {$filedesc{$calendar}} "%s", $line ;
                        }

close ($filedesc{$calendar}) ;
exit 0 ;
eof
$ chmod u+x duplicate.pl

Y aquí está la forma en que lo usé:

  1. Desde Calendar , exporta un calendario dado a través de:

    File > Export > Export...

    digamos que es: Documents/Calendar/2015/professionnal.ics

    NB .: esta será una copia de seguridad en caso de problema y mucho más práctica que cualquier manipulación de archivos con la ayuda de Time Machine

  2. Instale el script anterior como:

    ~/Documents/Calendar/src/duplicate.pl
    
  3. Ir al directorio para probar la versión fija, por ejemplo:

    mkdir ~/Documents/Calendar/2015.fixed
    cd ~/Documents/Calendar/2015.fixed
    
  4. Ejecutar duplicate.pl :

    ../src/duplicate.pl <../2015/professionnal.ics
    

    que mostrará el número de eventos leídos y el número de duplicados encontrados y creará aquí una versión fija del calendario:

    ~/Documents/Calendar/2015.fixed/professionnal.ics
    
  5. Compare el resultado con la versión original dañada para verificar que todo esté bien:

     diff ../2015/professionnal.ics .
    
  6. Dentro de Calendar seleccione el calendario professionnal y elimínelo a través de:

    Edit > Delete

  7. Importe el fijo a través de:

    File > Import > Import...

respondido por el daniel Azuelos 22.09.2015 - 02:20

Lea otras preguntas en las etiquetas