kluzz

xonsolidated.pl

Apr 22nd, 2011
285
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/perl -w
  2.  
  3. # xonsolidated.pl - Copyright 2011 by Jan Fredrik Leversund <kluzz@radical.org> (Twitter: @KluZz)
  4.  
  5. # This script reads the CellLocation data from a consolidated.db file (extracted from your
  6. # iPhone 4 backup or whatever) and spits out a KML file suitable for loading into
  7. # Google Earth or similar.
  8.  
  9. # NB! This script is provided AS-IS, and I make no claims that it is accurate, safe or
  10. # otherwise useful to anyone but myself.
  11.  
  12. # This script requires the DBI and DBD::SQLite modules.
  13.  
  14. use DBI;
  15.  
  16. die "Usage: $0 <db file>\n" unless scalar @ARGV == 1 and -f $ARGV[0];
  17. my $dbfile = $ARGV[0];
  18. my $dbh = DBI->connect("dbi:SQLite:dbname=" . $dbfile, "", "");
  19. die "Unable to open database file $dbfile: $!\n" unless $dbh;
  20.  
  21. my $data  = $dbh->selectall_arrayref("select rowid, Timestamp, Longitude, Latitude from CellLocation where Confidence > 0 order by rowid");
  22.  
  23. die "No data found! Possibly not an SQLite file?\n" unless $data;
  24.  
  25. # Parse stuff into time segments
  26. my %segments = ();
  27. foreach $p (@{$data})
  28. {
  29.     push @{$segments{$p->[1]}}, {lon => $p->[2], lat => $p->[3]};
  30. }
  31.  
  32. # Convert the segment hash into an array (it'll make sense later, honestly)
  33. my @segments = ();
  34. foreach $s (sort keys %segments)
  35. {
  36.     push @segments, [$s, $segments{$s}];
  37. }
  38.  
  39. # Start outputting the XML file
  40. open KML, ">$dbfile.kml" or die "Unable to create $dbfile.kml file: $!\n";
  41.  
  42. print KML "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document>\n";
  43. print KML "<name>$dbfile.kml</name>\n";
  44.  
  45. # Define line and icon styles for each segment
  46. foreach $s (@segments)
  47. {
  48.     my ($ts, $points) = @{$s};
  49.     my $col = sprintf("ff%06x", int(rand(0x1000000)));
  50.     print KML "<Style id=\"_$ts\">\n<LineStyle>\n<color>$col</color>\n<width>2</width>\n</LineStyle>\n";
  51.     print KML "<IconStyle>\n<color>$col</color>\n</IconStyle>\n</Style>\n";
  52. }
  53.  
  54. for ($i = 0; $i < scalar @segments; $i++)
  55. {
  56.     my ($ts, $points) = @{$segments[$i]};
  57.    
  58.     # Include the first point of the next segment, for continuity.
  59.     if (defined $segments[$i + 1])
  60.     {
  61.         push @{$points}, $segments[$i + 1][1][0];
  62.     }
  63.  
  64.     my $newdate = scalar localtime ($ts + 978307200);
  65.  
  66.     # Define the first coordinate of the segment as a point placemark
  67.     print KML "<Placemark>\n<name>$newdate</name>\n<description></description>\n<styleUrl>_$ts</styleUrl>\n";
  68.     printf KML "<Point>\n<coordinates>%s,%s</coordinates>\n</Point>\n</Placemark>\n", $points->[0]{lon}, $points->[0]{lat};
  69.  
  70.     # Define the entire segment as a line string
  71.     print KML "<Placemark>\n<name>$newdate</name>\n<description></description>\n<styleUrl>_$ts</styleUrl>\n";
  72.     print KML "<LineString>\n<extrude>1</extrude>\n<tessellate>1</tessellate>\n<altitudeMode>clampedToGround</altitudeMode>\n<coordinates>\n";
  73.  
  74.     foreach $c (@{$points})
  75.     {
  76.         print KML $c->{lon} . "," . $c->{lat} . "\n";
  77.     }
  78.  
  79.     print KML "</coordinates>\n</LineString>\n</Placemark>\n";
  80. }
  81.  
  82. print KML "</Document>\n</kml>\n";
  83.  
  84. # Finito.
RAW Paste Data