[ Index ] |
|
Code source de WebCalendar 1.0.5 |
1 #!/usr/bin/perl 2 3 =head1 NAME 4 palm_datebook.pl 5 6 =head1 SYNOPSIS 7 Reads the events from a Palm Desktop DateBook.dat 8 9 =head1 DESCRIPTION 10 This file reads a Palm Desktop DateBook file (datebook.dat) and prints 11 all the non-expired entries (can return all, see below) to STDOUT. It prints a pipe 12 separated value list by default. 13 14 =head1 USAGE 15 The script is set up to be used with the webcalendar and doesn't need to be 16 altered. If you want to use it some other way, then change the variables in 17 the config section to suit your needs and edit the main program (bottom of script). 18 You can uncomment the $outfile config to print to a file. The default program 19 will not include expired events and takes 2 arguments: 20 21 1. $DateBookFileName - The name/location of the datebook.dat 22 2. $exc_private - If a 1 is passed private records will be skipped 23 24 The following data is available in $Entry: 25 26 $Entry->{RecordID} = Record ID in the Palm 27 $Entry->{Status} = Identifies new and deleted records (status in datebook) 28 $Entry->{Position} = Position in list? 29 $Entry->{StartTime} = In seconds since 1970 30 $Entry->{EndTime} = In seconds since 1970 31 $Entry->{Description} = Description of event (string) 32 $Entry->{Duration} = How long the event lasts (in minutes) 33 $Entry->{Note} = Note (string) 34 $Entry->{Untimed} = 1 = true 0 = false 35 $Entry->{Private} = 1 = true 0 = false 36 $Entry->{Category} = useless for Palm 37 $Entry->{AlarmSet} = 1 = true 0 = false 38 $Entry->{AlarmAdvanceAmount} = How many units in AlarmAdvanceType (-1 means not set) 39 $Entry->{AlarmAdvanceType} = Units: (0=minutes, 1=hours, 2=days) 40 $Entry->{Repeat} = Array containing repeat information (if repeat) 41 $Entry->{Repeat}->{Interval} = 1=daily,2=weekly,3=MonthlyByDay,4=MonthlyByDate,5=Yearly 42 $Entry->{Repeat}->{Frequency} = How often event occurs. (1=every, 2=every other,etc.) 43 $Entry->{Repeat}->{EndTime} = When the repeat ends (In seconds since 1970) 44 $Entry->{Repeat}->{Exceptions} = An exception to the repeat (In seconds since 1970) 45 $Entry->{Repeat}->{RepeatDays} = For Weekly: What days to repeat on (7 characters...y or n for each day) 46 $Entry->{Repeat}->{DayNum} = For MonthlyByDay: Day of week (1=sun,2=mon,3=tue,4=wed,5=thu,6=fri,7=sat) 47 $Entry->{Repeat}->{WeekNum} = For MonthlyByDay: Week number (1=first,2=second,3=third,4=fourth,5=last) 48 49 =head1 CONTRIBUTERS 50 Eduard Martinescu - Provided patch to parse category list. 51 52 =cut 53 54 use CGI qw (:standard); 55 my $q = new CGI; 56 my ($Year, $Month, $Day); 57 my $DATA; 58 59 # ----------------------- Config if necessary ---------------------------- 60 my $DateBookFileName = $ARGV[0]; # The name of the file 61 my $exc_private = $ARGV[1]; # Do we want private entries? (1 = skip private) 62 my $inc_expired = 0; # Do we want expired entries? (1 = include expired) 63 my $sep = "|"; # what to separate the output with 64 #my $outfile = "/tmp/datebook_dump.txt"; # uncomment to print to file 65 #--------------------------------------------------------------------------- 66 67 #================= 68 sub ReadDateBook { 69 #================= 70 # ReadDateBook opens the file we passed (datebook.dat) and reads the entries. 71 72 my ($FileName, $Filter) = @_; 73 my (@Fields, @Entries, $FieldCount, $NumberOfEntries); 74 my ($Entry, $i, $Header, $Tag); 75 my ($NextFree, $CategoryCount, $Category, @Categories, $ResourceID); 76 my ($FieldsPerRow, $RecordIdPos, $RecordStatusPos, $RecordPlacementPos); 77 78 open DATEBOOK, "<".$FileName; 79 binmode DATEBOOK; 80 81 local $/ = undef; 82 $_ = <DATEBOOK>; 83 $GlobalPos = 0; 84 close DATEBOOK; 85 86 # First, check the initial 4 byte "tag" field. 87 $Tag = ReadByteString(4); 88 89 # Next, read the header information. 90 $FileName = ReadPilotString(); 91 $Header = ReadPilotString(); 92 $NextFree = ReadLong(); 93 94 # Read the category information 95 $CategoryCount = ReadLong(); 96 for ($i=0; $i<$CategoryCount; $i++) { 97 $Category = ReadCategory(); 98 push (@Categories,$Category) if ($Category ne 0); 99 } 100 101 $ResourceID = ReadLong(); 102 $FieldsPerRow = ReadLong(); 103 $RecordIdPos = ReadLong(); 104 $RecordStatusPos = ReadLong(); 105 $RecordPlacementPos = ReadLong(); 106 107 # Read the field list. 108 $FieldCount = ReadShort(); 109 for ($i=0; $i<$FieldCount; $i++) 110 {push @Fields, ReadShort();} 111 112 # Figure out how many entries to read 113 $NumberOfEntries = ReadLong() / $FieldCount; 114 115 # Read the entries. 116 for ($i=0; $i<$NumberOfEntries; $i++) { 117 $Entry = ReadEntry(); 118 if ($Entry ne 0){ 119 if (!$Filter or &$Filter($Entry)){push @Entries, $Entry;} 120 } 121 } 122 123 return @Entries; 124 } 125 126 #============== 127 sub ReadEntry { 128 #============== 129 # ReadPalmEntry reads a single entry from the datebook, stores it in a local 130 # hash, and returns a reference to that hash. The reference can safely 131 # be stored in an array for later use. 132 133 my (%Entry); 134 135 $Entry{RecordID} = ReadPilotField(); 136 $Entry{Status} = ReadPilotField(); 137 $Entry{Position} = ReadPilotField(); 138 $Entry{StartTime} = ReadPilotField(); 139 $Entry{EndTime} = ReadPilotField(); 140 $Entry{Description} = ReadPilotField(); 141 $Entry{Duration} = ReadPilotField(); 142 $Entry{Note} = ReadPilotField(); 143 $Entry{Untimed} = ReadPilotField(); 144 $Entry{Private} = ReadPilotField(); 145 $Entry{Category} = ReadPilotField(); 146 $Entry{AlarmSet} = ReadPilotField(); 147 $Entry{AlarmAdvanceAmount} = ReadPilotField(); 148 $Entry{AlarmAdvanceType} = ReadPilotField(); 149 $Entry{Repeat} = ReadPilotField(); 150 151 #Should return as -1 if not set, but is returning as 4294967295 152 $Entry{AlarmAdvanceAmount} = "-1" if ($Entry{AlarmAdvanceAmount} eq '4294967295'); 153 154 # Remove Crap from the DateBook5 Application 155 $Entry{Note} = '' if ($Entry{Note} =~ /^\#\#[fcdxX\@]/); 156 157 # Filter single quotes, \n\r 158 $Entry{Description} = &filter_quotes($Entry{Description}); 159 $Entry{Note} = &filter_quotes($Entry{Note}); 160 161 # Calculate duration in minutes 162 $Entry{Duration} = ($Entry{EndTime} - $Entry{StartTime}) / 60; 163 164 # Skip private records if $exc_private 165 if (($exc_private) && ($Entry{Private} == 1)) { 166 return 0; 167 # Skip Record if not in Palm (no RecordID) or marked for deletion 168 } elsif (($Entry{RecordID} == 0) || ($Entry{Status} == 129) || ($Entry{Status} == 4)){ 169 return 0; 170 # Skip events that are past endtime (except repeats that aren't expired) unless $inc_expired 171 } elsif (($Entry{EndTime} < time()) && (!$Entry{Repeat}) && (!$inc_expired)){ 172 return 0; 173 } elsif (($Entry{Repeat}) && ($Entry{Repeat}{EndTime} < time())&& ($Entry{Repeat}{EndTime} != 0) && (!$inc_expired)){ 174 return 0; 175 } else { 176 #print $Entry{RecordID} . "\n"; 177 return \%Entry; 178 } 179 } 180 181 #=================== 182 sub ReadPilotField { 183 #=================== 184 # ReadPilotField returns a single field from the datebook file. 185 my ($Type, $N, $sun, $mon, $tue, $wed, $thu, $fri, $sat); 186 my ($i, $DatesToSkip, $Repeat, $Interval, $Frequency, $Duration, $Position, $EndTime, $exceptions, @E); 187 my (%RA); 188 189 $Type = ReadLong(); 190 191 if ($Type == 1 or $Type == 3 or $Type == 6) { 192 return ReadLong(); 193 } elsif ($Type == 5) { 194 ReadLong(); # Skip the long of all zeroes 195 return ReadPilotString(); 196 } elsif ($Type == 8) { 197 $DatesToSkip = ReadShort(); 198 for ($i=1; $i<=$DatesToSkip; $i++) 199 {$exceptions .= ReadLong().":";} 200 chop $exceptions; 201 $Repeat = ReadShort(); 202 if ($Repeat == 0xFFFF) { 203 ReadShort(); 204 $Skip = ReadShort(); 205 SkipBytes($Skip); 206 } elsif ($Repeat and $Repeat != 0x8001) { #($Repeat == 0x1a40 or $Repeat == 0xb3c0 or $Repeat == 0xe750) 207 # print " DEBUG: Repeat is $Repeat\n"; 208 # ReadLong(); 209 } 210 if ($Repeat) { 211 $Interval = ReadLong(); 212 $Frequency = ReadLong(); 213 $EndTime = ReadLong(); 214 if ($EndTime eq 1956542399) { # No EndTime 215 $EndTime = ''; 216 } 217 218 ReadLong(); 219 $DayNum = ReadLong(); 220 if ($Interval == 2) { 221 $Position = ReadByte(); 222 } elsif ($Interval == 3) { 223 $Position = ReadLong(); 224 } elsif ($Interval == 5) { 225 $Position = ReadLong(); 226 } else { 227 $Position == 0; 228 } 229 230 # Build the Repeat array to return 231 $RA{Interval} = $Interval; 232 $RA{Frequency} = $Frequency; 233 $RA{EndTime} = $EndTime; 234 if ($exceptions){ $RA{Exceptions} = $exceptions;} 235 236 if ($Interval == 2) { # Weekly repeat 237 # $Position is an integer that tells what days of the week 238 # to repeat on. (sun=1,mon=2,tue=4,wed=8,thu=16,fri=32,sat=64) 239 # The numbers are added together to give a unique integer. 240 # We will break it down since the WebCalendar doesn't use this format. 241 $N = $Position; 242 243 # Check for Saturday 244 if ($N - 64 >= 0) { 245 $sat = 'y'; 246 $N -= 64; 247 } else { 248 $sat = 'n'; 249 } 250 251 # Check for Friday 252 if ($N - 32 >= 0) { 253 $fri = 'y'; 254 $N -= 32; 255 } else { 256 $fri = 'n'; 257 } 258 259 # Check for Thursday 260 if ($N - 16 >= 0) { 261 $thu = 'y'; 262 $N -= 16; 263 } else { 264 $thu = 'n'; 265 } 266 267 # Check for Wednesday 268 if ($N - 8 >= 0) { 269 $wed = 'y'; 270 $N -= 8; 271 } else { 272 $wed = 'n'; 273 } 274 275 # Check for Tuesday 276 if ($N - 4 >= 0) { 277 $tue = 'y'; 278 $N -= 4; 279 } else { 280 $tue = 'n'; 281 } 282 283 # Check for Monday 284 if ($N - 2 >= 0) { 285 $mon = 'y'; 286 $N -= 2; 287 } else { 288 $mon = 'n'; 289 } 290 291 # Check for Sunday 292 if ($N - 1 >= 0) { 293 $sun = 'y'; 294 $N -= 1; 295 } else { 296 $sun = 'n'; 297 } 298 $RA{RepeatDays} = $sun.$mon.$tue.$wed.$thu.$fri.$sat; 299 } elsif ($Interval == 3) { # Monthlybyday repeat 300 $RA{DayNum} = $DayNum + 1; # Day of week (1=sun,2=mon,3=tue,4=wed,5=thu,6=fri,7=sat) 301 $RA{WeekNum} = $Position + 1; # Week number (1=first,2=second,3=third,4=fourth,5=last) 302 } 303 return \%RA; 304 } else { 305 return 0; # No repeat 306 } 307 } else { 308 # print STDERR "There's a problem with this pilot field of type $Type\n"; 309 return undef; 310 } 311 } 312 313 314 #=================== 315 sub ReadByteString { 316 #=================== 317 # ReadByteString reads the number of bytes passed to it as a parameter 318 # and returns it as a character string. 319 320 my ($Count) = @_; 321 $GlobalPos += $Count; 322 return substr ($_, $GlobalPos-$Count, $Count); 323 } 324 325 #==================== 326 sub ReadPilotString { 327 #==================== 328 # ReadPilotString reads a pilot formatted string, which is a size (one 329 # byte, unless the byte is 0xFF, then it's the two bytes after the 0xFF), 330 # followed by that many bytes, and returns a Perl string. 331 332 my ($String) = ""; 333 my ($Length, $i); 334 335 $Length = unpack ('C', substr ($_, $GlobalPos, 1)); 336 $GlobalPos++; 337 if ($Length == 255) { 338 $Length = ReadShort(); 339 } 340 341 $GlobalPos += $Length; 342 return substr ($_, $GlobalPos-$Length, $Length); 343 } 344 345 #============== 346 sub SkipBytes { 347 #============== 348 # SkipBytes is just like ReadByteString, except it throws away the data, 349 # rather than returning it. 350 351 my ($Count) = @_; 352 $GlobalPos += $Count; 353 } 354 355 #============= 356 sub ReadByte { 357 #============= 358 # ReadByte reads a single byte, and returns it as an integer. 359 360 $GlobalPos++; 361 return unpack ('C', substr($_, $GlobalPos-1, 1)); 362 } 363 364 #============== 365 sub ReadShort { 366 #============== 367 # ReadShort reads two bytes, and returns them as an integer (low order 368 # byte is the first one read). 369 370 $GlobalPos+=2; 371 return unpack ('S', substr($_, $GlobalPos-2, 2)); 372 } 373 374 #============= 375 sub ReadLong { 376 #============= 377 # ReadLong reads four bytes, and returns them as an integer (low order 378 # byte is the first one read). 379 380 $GlobalPos+=4; 381 return unpack ('L', substr($_, $GlobalPos-4, 4)); 382 } 383 384 #==================== 385 sub ByDateAscending { 386 #==================== 387 # Sort records by StartTime 388 389 return $a->{StartTime} <=> $b->{StartTime}; 390 } 391 392 #================== 393 sub filter_quotes { 394 #================== 395 # Filter newline/return 396 397 my $temp = $_[0]; 398 # $temp =~ s/'/\\'/g; 399 $temp =~ s/\n|\r/ /g; # Remove newline 400 return ($temp); 401 } 402 403 #================= 404 sub ReadCategory { 405 #================= 406 # ReadCategory reads a single category entry from the datebook, 407 # stores it in a local hash, and returns a reference to that hash. 408 # The reference can safely be stored in an array for later use. 409 410 my (%Entry); 411 412 $Entry{Index} = ReadLong(); 413 $Entry{CategoryID} = ReadLong(); 414 $Entry{DirtyFlag} = ReadLong(); 415 $Entry{LongName} = ReadPilotString(); 416 $Entry{ShortName} = ReadPilotString(); 417 return \%Entry; 418 } 419 420 #----------------------------- Main Program ------------------------------- 421 422 foreach $Entry (sort ByDateAscending ReadDateBook($DateBookFileName)) { 423 $DATA .= $Entry->{RecordID}. $sep; 424 $DATA .= $Entry->{StartTime}. $sep; 425 $DATA .= $Entry->{EndTime}. $sep; 426 $DATA .= $Entry->{Description}. $sep; 427 $DATA .= $Entry->{Duration}. $sep; 428 $DATA .= $Entry->{Note}. $sep; 429 $DATA .= $Entry->{Untimed}. $sep; 430 $DATA .= $Entry->{Private}. $sep; 431 $DATA .= $Entry->{Category}. $sep; 432 $DATA .= $Entry->{AlarmSet}. $sep; 433 $DATA .= $Entry->{AlarmAdvanceAmount}. $sep; 434 $DATA .= $Entry->{AlarmAdvanceType}. $sep; 435 $DATA .= $Entry->{Repeat}->{Interval}. $sep; 436 $DATA .= $Entry->{Repeat}->{Frequency}. $sep; 437 $DATA .= $Entry->{Repeat}->{EndTime}. $sep; 438 $DATA .= $Entry->{Repeat}->{Exceptions}. $sep; 439 $DATA .= $Entry->{Repeat}->{RepeatDays}. $sep; 440 # $DATA .= $Entry->{Repeat}->{DayNum}. $sep; 441 $DATA .= $Entry->{Repeat}->{WeekNum}. $sep; 442 $DATA .= "\n"; 443 } 444 445 if ($outfile) { 446 die "Couldn't open $outfile: $!" if ((open OUT, ">$outfile") eq undef); 447 flock (OUT, 2);print OUT $DATA;flock (OUT, 8);close OUT; 448 } else { 449 print STDOUT $DATA; 450 } 451 exit;
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Nov 30 19:09:19 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |