#!/usr/bin/perl -w ###################################################################### # Artemis File Analysis Tool, (C) 2015-2019 Nosey Nick Waterman, # https://noseynick.org/artemis/ # All wrong righted, all rights reserved. Licensed under thev GNU # Affero General Public License v3.0 https://www.gnu.org/licenses/agpl.txt # with Commons Clause https://commonsclause.com/ v1.0 ###################################################################### use strict; my $dir = shift; my $tmpl = shift; $dir && -d $dir && $tmpl && -f $tmpl or die "USAGE: $0 path/to/Artemis/2.7.1 template.html\n"; my %notes = ( 'artemis.exe' => 'The Artemis executable itself!', 'artemis.ini' => 'Configuration for Artemis', 'controls.ini' => 'Key/Joystick bindings', 'changes.txt' => 'Documents changes in each version of Artemis', 'd3dx9_24.dll' => 'Earlier version of D3DX9_43.dll?', 'd3dx9_43.dll' => '3D library used by Artemis.exe', 'd3dcompiler_43.dll' => 'Used by D3DX9_43.dll', 'ftd2xx.dll' => 'DMX library used by Artemis.exe', 'dat/dmxcommands-old.xml' => mktag('Unused?') . ' Old version of...', 'dat/dmxcommands.xml' => 'DMX light sequences', 'mission-file-docs.txt' => 'How to write MISS*.xml', 'uninst.exe' => 'Uninstaller - never needed ;-)', 'uninst.ini' => 'Config for uninst.exe', 'engineeringsettings.dat' => 'Eng presets', 'artemisengineeringpresetmanager.exe' => '' . 'Eng Preset Mgr? May not belong here?', 'dat/missions/miss_hamaksector/teleporter.dxs' => mktag('Unused?') . ' broken ref to MISS_HamakSector_2/teleporter.dxs', '_css' => " .tag { background: #48c; color: #fff; padding: 1px 4px; }\n" . " .unk { background: #c00; color: #fff; padding: 1px 4px; }\n" . " .tab { border-collapse: collapse; }\n" . " .tab tr { border: 1px solid #000; }\n", '_top' => "This is a list of files in the Artemis distribution.\n" . "See also my other Artemis Tools\n" . "

\n", '_bot' => "

\n" . "See also my other Artemis Tools\n" . "

\n" ); print STDERR "# finding files...\n"; open(FIND, "find $dir/ -type f |") or die "Can't find $dir - $!\n"; my (@files, %tags); while () { chomp; s|^$dir/*||; push @files, $_; if (m(^art/sb(\d\d)/skybox_(BK|FR|UP|DN|LF|RT)\.jpg$)) { $tags{lc $_}{Skybox} = "Part of skybox $1 ($2)"; } elsif (m(Thumbs\.db$)) { $tags{lc $_}{'Thumb?'} = 'Windows image thumbnail cache'; } elsif (m(^dat/Asteroid_\d+_(AO|Albedo|Emission).png$)) { $tags{lc $_}{"EXE/UTF16"} = 'UTF16 string appears in Artemis.exe'; $notes{lc $_} = "- kinda (dat/Asteroid_ + _$1.png)"; } elsif (m(^dat/Missions/(MISS_.+)/(MISS_.+)\.xml$)i && lc($1) eq lc ($2)) { $tags{lc $_}{MISS} = 'Mission file'; parse_xml(inMISS => $_, "dat/Missions/$1"); } elsif (m(^dat/Missions/(MISS_.+)/(MISS_.+)_LOG\.txt$)i) { $tags{lc $_}{MISS_LOG} = 'Logfile from a mission'; } elsif (m(^dat/Missions/(MISS_.+)/.+\.txt$)i) { $tags{lc $_}{'MISS_DOC?'} = 'Documentation for this mission?'; } elsif (/~/ || /backup/i) { $tags{lc $_}{'Backup?'} = 'Might be an editor backup file?'; } } close FIND; parse_xml(DAT => "dat/vesselData.xml"); for ( [ UTF16 => '-el' ], [ UTF8 => '' ]) { my ($tag, $arg) = @$_; print STDERR "# tag strings in Artemis.exe...\n"; unless (open(STRINGS, "strings $arg $dir/Artemis.exe |")) { print STDERR "# Can't run: $!\n"; next; } while () { chomp; if (m(dat/.*)) { $tags{lc $&}{"EXE/$tag"} = "$tag string appears in Artemis.exe with forward-slashes"; } elsif (m(dat\\.*)) { my $f = $&; $f =~ s|\\|/|g; $tags{lc $f}{"EXE\\$tag"} = "$tag string appears in Artemis.exe with back-slashes"; } elsif (m(^\w+\.\w\w\w$)i) { $tags{lc $&}{"EXE-$tag"} = "$tag string appears in Artemis.exe with no slashes"; } } close STRINGS; } print STDERR "# Populating HTML template...\n"; my $ver = 'unknown'; if ($dir =~ /(\d+\.\d+\.\d+)/) { $ver = $1; } my %vars = ( title => "Artemis files - version $ver", h1 => "Artemis files - version $ver", description => "Files found in Artemis SBS version $ver", ); open(HTML, $tmpl) or die "Can't open HTML template: $!\n"; while () { if (m(-->)) { print "$notes{_css}\n"; } elsif (/name="(\w+)".*\+\+\+/ || /<(\w+).*\+\+\+/) { my $var = $vars{$1} or die "Dunno how to populate $1 in:\n$_\n"; s/\+\+\+/$var/; } elsif (/^\+\+\+CONTENT\+\+\+/) { print "$notes{_top}\n"; for (sort {lc($a) cmp lc($b)} @files) { my $tag = $tags{lc $_}; print "\n"; } print "
$_", join(' ', $tag || $notes{lc $_} ? ( map { mktag($_, $tag->{$_}) } sort keys %$tag ) : mktag('Unused?'), $notes{lc $_} // '' ), "
\n$notes{_bot}\n"; $_ = ''; } elsif (/\+\+\+/) { die "Dunno how to populate:\n$_\n"; } print $_; } close HTML; sub mktag { my ($tag, $title) = @_; my $class = ($tag =~ /\?$/) ? 'unk' : 'tag'; return "$tag"; } sub parse_xml { my ($tag, $fi, $subdir) = @_; print STDERR "# Parsing $fi ...\n"; unless (open(IN, "$dir/$fi")) { print STDERR "### Failed to open: $!\n"; return; } $fi = "Appears in $fi"; if ($subdir) { $subdir .= '/'; } while () { while (s|="(dat/.+?)"||) { $tags{lc $1}{$tag} ||= $fi; } while (s|filename=".*?(dat\\.+?)"||i) { # fileName="..\..\..\dat\missions\MISS_GMsandbox5a\Voice\dock.ogg" ?!? my $f = $1; $f =~ s|\\|/|g; $tags{lc $f}{$tag} = "$fi with backslashes"; } while (s|filename="(.+?)"||i) { $tags{lc "$subdir$1"}{$tag} ||= $fi; } } close IN; }