Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Location map2 #142

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/ilap_artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
'notificationsXI': ('Notifications', '*PushStore*'),
'notificationsXII': ('Notifications', '*private/var/mobile/Library/UserNotifications*'),
'ooklaSpeedtestData': ('Applications', '**/speedtest.sqlite*'),
'photosMetadata': ('Photos', '**/Photos.sqlite'),
#'photosMetadata': ('Photos', '**/Photos.sqlite'),
'powerlogAll': ('Powerlog', '**/CurrentPowerlog.PLSQL'),
'powerlogGZ': ('Powerlog Backups', '**/Library/BatteryLife/Archives/powerlog_*.PLSQL.gz'),
'queryPredictions': ('SMS & iMessage', '**/query_predictions.db'),
Expand Down
106 changes: 106 additions & 0 deletions scripts/location_map_constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# coding: utf-8
iLEAPP_KMLs = "_KML Exports"

defaultShadowUrl = 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png'

defaultIconUrl = 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-{}.png'

colors = ['red','green','blue','orange','violet','yellow', 'sienna', 'indigo','purple','cyan','darkgray']

legend_tag = "<li><span style='background:{0};opacity:0.7;'></span>{1}</li>"

legend_title_tag = "<div class='legend-title'>{0}</div>"

legend_div = """
<div class='legend-scale'>
<ul class='legend-labels'>
{0}
</ul>
</div>
"""

template_part1 = """
{% macro html(this, kwargs) %}


<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Draggable - Default functionality</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<script>
$( function() {
$( "#maplegend" ).draggable({
start: function (event, ui) {
$(this).css({
right: "auto",
top: "auto",
bottom: "auto"
});
}
});
});

</script>
</head>
<body>


<div id='maplegend' class='maplegend'
style='position: absolute; z-index:9999; border:2px solid grey; background-color:rgba(255, 255, 255, 0.8);
border-radius:6px; padding: 10px; font-size:14px; right: 20px; bottom: 20px;'>
"""
template_part2 = """
</div>

</body>
</html>

<style type='text/css'>
.maplegend .legend-title {
text-align: left;
margin-bottom: 5px;
font-weight: bold;
font-size: 90%;
}
.maplegend .legend-scale ul {
margin: 0;
margin-bottom: 5px;
padding: 0;
float: left;
list-style: none;
}
.maplegend .legend-scale ul li {
font-size: 80%;
list-style: none;
margin-left: 0;
line-height: 18px;
margin-bottom: 2px;
}
.maplegend ul.legend-labels li span {
display: block;
float: left;
height: 16px;
width: 30px;
margin-right: 5px;
margin-left: 0;
border: 1px solid #999;
}
.maplegend .legend-source {
font-size: 80%;
color: #777;
clear: both;
}
.maplegend a {
color: #777;
}
</style>
{% endmacro %}
"""

126 changes: 126 additions & 0 deletions scripts/location_map_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# coding: utf-8
#Import the necessary Python modules
import pandas as pd
import folium
from folium.plugins import TimestampedGeoJson
from shapely.geometry import Point
import os
from datetime import datetime
from branca.element import Template, MacroElement
import html
from scripts.location_map_constants import iLEAPP_KMLs, defaultShadowUrl, defaultIconUrl, colors, legend_tag, legend_title_tag, legend_div, template_part1, template_part2
import sqlite3

from scripts.artifact_report import ArtifactHtmlReport

#Helpers
def htmlencode(string):
return string.encode(encoding='ascii',errors='xmlcharrefreplace').decode('utf-8')

def geodfToFeatures(df, f, props):
coords = []
times = []
for i,row in df[df.Description.str.contains(f)].iterrows():
coords.append(
[row.Point.x,row.Point.y]
)
times.append(datetime.strptime(row.Name,'%Y-%m-%d %H:%M:%S').isoformat())
return {
'type': 'Feature',
'geometry': {
'type': props[f]['fType'],
'coordinates': coords,
},
'properties': {
'times': times,
'style': {'color': props[f]['color']},
'icon': props[f]['icon'],
'iconstyle': {
'iconUrl': props[f]['iconUrl'],
'shadowUrl': props[f]['shadowUrl'],
'iconSize': [25, 41],
'iconAnchor': [12, 41],
'popupAnchor': [1, -34],
'shadowSize': [41, 41],
'radius': 5,
},
},
}


def generate_location_map(reportfolderbase,legend_title):
KML_path = os.path.join(reportfolderbase,iLEAPP_KMLs)
if not os.path.isdir(KML_path) or not os.listdir(KML_path):
return

location_path = os.path.join(reportfolderbase, 'LOCATIONS')
os.makedirs(location_path,exist_ok=True)
db = sqlite3.connect(os.path.join(KML_path,"_latlong.db"))
df = pd.read_sql_query("SELECT key as Name, Activity as Description, latitude, longitude FROM data ;", db)
df["Point"] = df.apply(lambda row: Point(float(row['longitude']),float(row['latitude']),.0), axis=1)

#sorting is needed for correct display
df.sort_values(by=['Name'],inplace=True)

#Parse geo data and add to Folium Map
data_names = df[~df.Description.str.contains('Photos')].Description.unique()
featuresProp = {}

for c,d in zip(colors, data_names):
descFilter = d
if 'ZRT' in d:
fType = 'LineString'
icon = 'marker'
iconUrl = defaultIconUrl.format(c)
shadowUrl = defaultShadowUrl
else:
fType = 'MultiPoint'
icon = 'circle'
iconUrl = ''
shadowUrl = ''

color = c

featuresProp[d] = {
'fType': fType,
'color': c,
'icon': icon,
'iconUrl': iconUrl,
'shadowUrl': defaultShadowUrl,
}

location_map = folium.Map([df.iloc[0].Point.y,df.iloc[0].Point.x], prefer_canvas=True, zoom_start = 6)
bounds = (df[~df.Description.str.contains('Photos')]['longitude'].min(),
df[~df.Description.str.contains('Photos')]['latitude'].min(),
df[~df.Description.str.contains('Photos')]['longitude'].max(),
df[~df.Description.str.contains('Photos')]['latitude'].max(),
)
location_map.fit_bounds([
(bounds[1],bounds[0]),
(bounds[3],bounds[2]),
]
)

tsGeo = TimestampedGeoJson({
'type': 'FeatureCollection',
'features': [
geodfToFeatures(df, f, featuresProp) for f in data_names
]
}, period="PT1M", duration="PT1H", loop=False, transition_time = 50, time_slider_drag_update=True, add_last_point=True, max_speed=200).add_to(location_map)


#legend
legend = '\n'.join([ legend_tag.format(featuresProp[f]['color'], htmlencode(f)) for f in data_names])
template = '\n'.join([template_part1, legend_title_tag.format(htmlencode(legend_title)), legend_div.format(legend), template_part2])

macro = MacroElement()
macro._template = Template(template)

location_map.get_root().add_child(macro)

location_map.save(os.path.join(location_path,"Locations_Map.html"))

report = ArtifactHtmlReport('Locations Map')
report.start_artifact_report(location_path, 'Locations Map', 'Map plotting all locations')
report.write_raw_html(open(os.path.join(location_path,"Locations_Map.html")).read())
report.end_artifact_report()
3 changes: 3 additions & 0 deletions scripts/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from scripts.html_parts import *
from scripts.ilapfuncs import logfunc
from scripts.version_info import aleapp_version, aleapp_contributors
from scripts.location_map_report import generate_location_map


def get_icon_name(category, artifact):
Expand Down Expand Up @@ -227,6 +228,8 @@ def get_icon_name(category, artifact):
icon = 'user'
return icon

#generate loaation map with all KML files
generate_location_map(reportfolderbase, "Legend")

def generate_report(reportfolderbase, time_in_secs, time_HMS, extraction_type, image_input_path):
control = None
Expand Down
50 changes: 25 additions & 25 deletions scripts/version_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,31 @@
# Format = [ Name, Blog-url, Twitter-handle, Github-url]
# Leave blank if not available
aleapp_contributors = [
['Alexis Brignoni', 'https://abrignoni.com', '@AlexisBrignoni', 'https://github.com/abrignoni'],
['Yogesh Khatri', 'https://swiftforensics.com', '@SwiftForensics', 'https://github.com/ydkhatri'],
['Agam Dua', 'https://loopback.dev', '@loopbackdev', 'https://github.com/agamdua'],
['Sarah Edwards', 'https://www.mac4n6.com', '@iamevltwin', 'https://github.com/mac4n6'],
['Heather Mahalik', 'https://smarterforensics.com', '@HeatherMahalik', ''],
['Jessica Hyde', 'https://twitter.com/B1N2H3X', '@B1N2H3X', ''],
['Phill Moore', 'https://thinkdfir.com', '@phillmoore', 'https://github.com/randomaccess3'],
['Mattia Epifani', 'https://blog.digital-forensics.it', '@mattiaep', ''],
['Mike Williamson', 'https://forensicmike1.com', '@forensicmike1', 'https://github.com/forensicmike'],
['Geraldine Blay', 'https://gforce4n6.blogspot.com', '@i_am_the_gia', ''],
['Christopher Vance', 'https://blog.d204n6.com', '@cScottVance', ''],
['Brooke Gottlieb', '', '@xbrookego', ''],
['Jack Farley', 'http://farleyforensics.com', '@JackFarley248', ''],
['Shafik Punja', '', '@qubytelogic', ''],
['Cheeky4N6Monkey', 'https://cheeky4n6monkey.blogspot.com', '@Cheeky4n6Monkey', 'https://github.com/cheeky4n6monkey'],
['Edward Greybeard', '', '', 'https://github.com/edward-greybeard'],
['Douglas Kein', '', '@DouglasKein', ''],
['Claudia Meda', '', '@KlodiaMaida', 'https://github.com/KlodiaMaida'],
['Silvia Spallarossa', '', '@SilviaSpallaro1', 'https://github.com/spatimbs'],
['Francesca Maestri', '', '@franc3sca_m', 'https://github.com/francyM'],
['Christopher Vance', 'https://blog.d204n6.com/', '@cScottVance', 'https://github.com/cScottVance'],
['Jesse Spangenberger', 'https://cyberfenixtech.blogspot.com/', '@AzuleOnyx', 'https://github.com/flamusdiu'],
['Jon Baumann', 'https://ciofecaforensics.com/', '@CiofecaForensic', 'https://github.com/threeplanetssoftware'],
['Scott Koenig', '', '@Scott_Kjr', ''],
['Kevin Pagano', 'https://stark4n6.com/', '@KevinPagano3', 'https://github.com/stark4n6'],
[ 'Alexis Brignoni', 'https://abrignoni.com', '@AlexisBrignoni', 'https://github.com/abrignoni'],
[ 'Yogesh Khatri', 'https://swiftforensics.com', '@SwiftForensics', 'https://github.com/ydkhatri'],
[ 'Agam Dua', 'https://loopback.dev', '@loopbackdev', 'https://github.com/agamdua'],
[ 'Sarah Edwards', 'https://www.mac4n6.com', '@iamevltwin', 'https://github.com/mac4n6'],
[ 'Heather Mahalik', 'https://smarterforensics.com', '@HeatherMahalik', ''],
[ 'Jessica Hyde', 'https://twitter.com/B1N2H3X', '@B1N2H3X', ''],
[ 'Phill Moore', 'https://thinkdfir.com', '@phillmoore', 'https://github.com/randomaccess3'],
[ 'Mattia Epifani', 'https://blog.digital-forensics.it', '@mattiaep', ''],
[ 'Mike Williamson', 'https://forensicmike1.com', '@forensicmike1', 'https://github.com/forensicmike'],
[ 'Geraldine Blay', 'https://gforce4n6.blogspot.com', '@i_am_the_gia', ''],
[ 'Christopher Vance', 'https://blog.d204n6.com', '@cScottVance', ''],
[ 'Brooke Gottlieb', '', '@xbrookego', ''],
[ 'Jack Farley', 'http://farleyforensics.com', '@JackFarley248', ''],
[ 'Shafik Punja', '', '@qubytelogic', ''],
[ 'Cheeky4N6Monkey', 'https://cheeky4n6monkey.blogspot.com', '@Cheeky4n6Monkey', 'https://github.com/cheeky4n6monkey'],
[ 'Edward Greybeard', '', '', 'https://github.com/edward-greybeard'],
[ 'Douglas Kein', '', '@DouglasKein', ''],
[ 'Claudia Meda', '', '@KlodiaMaida', 'https://github.com/KlodiaMaida'],
[ 'Silvia Spallarossa', '', '@SilviaSpallaro1', 'https://github.com/spatimbs'],
[ 'Francesca Maestri', '', '@franc3sca_m', 'https://github.com/francyM'],
[ 'Christopher Vance', 'https://blog.d204n6.com/', '@cScottVance', 'https://github.com/cScottVance'],
[ 'Jesse Spangenberger', 'https://cyberfenixtech.blogspot.com/', '@AzuleOnyx', 'https://github.com/flamusdiu'],
[ 'Jon Baumann', 'https://ciofecaforensics.com/', '@CiofecaForensic', 'https://github.com/threeplanetssoftware'],
[ 'Scott Koenig', '', '@Scott_Kjr', ''],
[ 'Kevin Pagano', 'https://stark4n6.com/', '@KevinPagano3', 'https://github.com/stark4n6'],
['Ed Michael', '', '@EdXlg123', 'https://github.com/edmichael'],
['Anna-Mariya Mateyna', '', '@any333_snickers', 'https://github.com/any333'],
['Tommy Harris', '', '@tobraha', 'https://github.com/tobraha']
Expand Down