Code: Select all
#!/usr/bin/perl
# Data recovery program for OfflineMaps .wpt waypoint files when cellphone is not available.
# Copyright : http://www.fsf.org/copyleft/gpl.html
# Author : Dan Jacobson -- http://jidanni.org/
# Created On : Sun Mar 12 15:11:28 2017
# Last Modified On: Wed Aug 23 22:22:39 2017
# Update Count : 520
# Usage:
# $ wpt2ll *.wpt
# Output:
# $/tmp/Unsorted landmarks/TANK.wpt = {
# 'ACCURACY' => 5,
# 'ELEVATION' => '797',
# 'LATITUDE' => '24.1818142',
# 'LONGETUDE' => '120.8641719',
# 'TIME/FILE' => '2017-06-06 10:55:00',
# 'TIME/WYPT' => '2017-06-06 10:54:24',
# 'VERSION' => 2,
# 'creator' => 'OfflineMaps 2.6b',
# 'creator_url' => 'http://www.offline-maps.net',
# 'icon' => 'Storage tank',
# 'name' => 'TANK'
# };
#
# File format is as specified in http://psyberia.net/res/landmarks/landmarks_file_data_specs.pdf
# Only tested on OfflineMaps file version 2, on Linux.
# Due to spaces in file names, one could also use e.g.,
# ls -t /tmp/Unsorted\ landmarks/*.wpt|xargs --delimiter=\\n ./wpt2ll
use strict;
use warnings FATAL => q!all!;
use POSIX qw(strftime);
use Data::Dumper;
$Data::Dumper::Sortkeys = $Data::Dumper::Indent = 1;
local $/;
while (<>) {
my @k = unpack( 'N2N/((N/a)2)a*', $_ );
my %o = @k[ 2 .. $#k - 1 ];
@o{qw!VERSION HEADER_SIZE TIME/FILE!} =
( @k[ 0, 1 ], strftime( "%F %T", localtime( ( stat($ARGV) )[9] ) ) );
if ( $o{HEADER_SIZE} ) { die "Not ready for HEADER_SIZE != 0" }
else { delete $o{HEADER_SIZE} }
my @t; ##to also work on 32 bit systems (where unpack 'Q' not trusty)
(
@o{qw/JUNK BYTES LONGETUDE LATITUDE ELEVATION/},
@t[ 0, 1 ],
@o{qw/ACCURACY PRESSURE/}
) = my @check = unpack( 'N*', $k[-1] );
$_ /= 1e7 for @o{qw/LONGETUDE LATITUDE/};
if ( $o{ELEVATION} == 2**32 - 10e8 + 1 ) { #but why that number?
delete $o{ELEVATION};
}
else { $o{ELEVATION} /= 1000; }
die "Can't deal with that BYTES value yet."
unless $o{BYTES} / 4 == @check - 2;
die "Can't deal with that JUNK value yet." unless $o{JUNK} == 0xFFFFFFFF;
delete @o{qw/BYTES JUNK/};
$o{'TIME/WYPT'} =
strftime( "%F %T", localtime( ( $t[0] * 2**32 + $t[1] ) / 1000 ) )
if $t[0] + $t[1];
for ( keys %o ) { delete $o{$_} unless defined $o{$_}; }
print Data::Dumper->Dump( [ \%o ], ["File{'$ARGV'}"] );
}