1package Print;
2
3#
4# Utilities to print information
5#
6# Brian Carrier [carrier@sleuthkit.org]
7# Copyright (c) 2001-2005 by Brian Carrier.  All rights reserved
8#
9# This file is part of the Autopsy Forensic Browser (Autopsy)
10#
11# Autopsy is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
15#
16# Autopsy is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with Autopsy; if not, write to the Free Software
23# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24#
25# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
26# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
27# MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE.
28# IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30# (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR
31# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
36# Escape HTML entities
37# Converts \n to <br>\n
38sub html_encode {
39    my $text = shift;
40    $text =~ s/&/&amp;/gs;
41    $text =~ s/</&lt;/gs;
42    $text =~ s/>/&gt;/gs;
43    $text =~ s/\"/&quot;/gs;
44    $text =~ s/\n/<br>\n/gs;
45
46    # @@@ LEADING SPACES and TABS
47    # while ($text =~ s/^(&nbsp;)*\t/"$1&nbsp;&nbsp;&nbsp;&nbsp;"/eig) {}
48    # while ($text =~ s/^(&nbsp;)* /"$1&nbsp;"/eig) {}
49    return $text;
50}
51
52# remove control chars from printout
53# this does not escape HTML entities, so you can pass this HTML code
54sub print_output {
55    my $out = shift;
56    print "$out";
57
58    while (my $out = shift) {
59        foreach $_ (split(//, $out)) {
60            if (   ($_ eq "\n")
61                || ($_ eq "\r")
62                || ($_ eq "\f")
63                || ($_ eq "\t"))
64            {
65                print "$_";
66            }
67            elsif ((ord($_) < 0x20) && (ord($_) >= 0x00)) {
68                print "^" . ord($_);
69            }
70            else {
71                print "$_";
72            }
73        }
74    }
75}
76
77# Added to provide output in hexdump format
78# function gets called on a per-icat basis,
79# The offset value is the byte offset that this data
80# starts at, since the File.pm code calls it in 1024
81# byte chunks)
82sub print_hexdump {
83    my $out    = shift;    # data to output
84    my $offset = shift;    # starting byte offset in file
85    my $buf    = "";
86
87    foreach $i (split(//, $out)) {
88        my $idx = $offset % 16;
89
90        if ($idx == 0) {
91            printf("%08X:  ", $offset);
92        }
93
94        printf("%02X", ord($i));
95        if (($idx % 2) == 1) {
96            printf(" ");
97        }
98
99        $buf[$idx] = $i;
100
101        if ($idx == 15) {
102            print "   ";
103            for (my $j = 0; $j < 16; $j++) {
104                if ($buf[$j] =~ m/[ -~]/) {
105                    print $buf[$j];
106                }
107                else {
108                    print ".";
109                }
110                $buf[$j] = 0;
111            }
112            print "\n";
113        }
114        $offset++;
115    }
116
117    # print out last line if < 16 bytes long
118    my $l = $offset % 16;
119
120    if ($l) {
121        my $t = (16 - $l) * 2 + (16 - $l) / 2;
122        for (my $j = 0; $j < $t; $j++) {
123            print " ";
124        }
125        print "   ";
126        for (my $j = 0; $j < $l; $j++) {
127            if ($buf[$j] =~ m/[ -~]/) {
128                print $buf[$j];
129            }
130            else {
131                print ".";
132            }
133        }
134        print "\n";
135    }
136}
137
138############################################
139#
140# HTTP/HTML Headers and Footers
141
142# The page that makes the frameset does not have a body statement
143# This routine is used to make the minimum required header statements
144sub print_html_header_frameset {
145    my $text = shift;
146    print "Content-Type: text/html; charset=utf-8$::HTTP_NL$::HTTP_NL";
147
148    my $time = localtime();
149
150    print <<EOF;
151<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
152<html>
153<!-- Autopsy ver. $::VER Forensic Browser -->
154<!-- Page created at: $time -->
155<head>
156  <title>$text</title>
157  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
158  <link rel="stylesheet" href="global.css">
159</head>
160
161EOF
162}
163
164sub print_html_footer_frameset {
165    print "\n</html>\n" . "$::HTTP_NL$::HTTP_NL";
166}
167
168# Create the header information with the body tag
169sub print_html_header {
170    print_html_header_frameset(shift);
171    print "<body bgcolor=\"$::BACK_COLOR\">\n\n";
172    print "<link rel=\"SHORTCUT ICON\" href=\"pict/favicon.ico\">\n";
173}
174
175sub print_html_footer {
176    print "\n</body>\n</html>\n" . "$::HTTP_NL$::HTTP_NL";
177}
178
179# Print the header with the margins set to 0 so that the tab buttons
180# are flush with the edges of the frame
181sub print_html_header_tabs {
182    print_html_header_frameset(shift);
183    print "<body marginheight=0 marginwidth=0 topmargin=0 "
184      . "leftmargin=0 rightmargin=0 botmargin=0 bgcolor=\"$::BACK_COLOR\">\n\n";
185    print "<link rel=\"SHORTCUT ICON\" href=\"pict/favicon.ico\">\n";
186    $is_body = 1;
187}
188
189sub print_html_footer_tabs {
190    print "\n</body>\n</html>\n" . "$::HTTP_NL$::HTTP_NL";
191}
192
193# Header for front page to warn about java script
194sub print_html_header_javascript {
195    my $text = shift;
196    print "Content-Type: text/html; charset=utf-8$::HTTP_NL$::HTTP_NL";
197
198    my $time = localtime();
199
200    # The write line has to stay on one line
201    print <<EOF;
202<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
203<html>
204<!-- Autopsy ver. $::VER Forensic Browser -->
205<!-- Page created at: $time -->
206<head>
207  <title>$text</title>
208  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
209  <link rel="stylesheet" href="global.css">
210  <script language=\"JavaScript\">
211  <!-- hide script from old browsers
212  document.write(\'<center><font color=\"red\"><p>WARNING: Your browser currently has Java Script enabled.</font><p>You do not need Java Script to use Autopsy and it is recommended that it be turned off for security reasons.<hr></center>\');
213  //-->
214  </script>
215</head>
216
217<body bgcolor=\"$::BACK_COLOR\">
218<link rel=\"SHORTCUT ICON\" href=\"pict/favicon.ico\">
219
220EOF
221}
222
223sub print_html_footer_javascript {
224    print "\n</body>\n</html>\n" . "$::HTTP_NL$::HTTP_NL";
225}
226
227# For raw text outputs (Pass the name of a file if it is being saved)
228sub print_text_header {
229    print "Content-Type: text/plain; charset=utf-8$::HTTP_NL";
230    if (scalar @_ > 0) {
231        my $fname = shift();
232        print "Content-Disposition: inline; " . "filename=$fname;$::HTTP_NL";
233    }
234    print "$::HTTP_NL";
235}
236
237sub print_text_footer {
238    print "$::HTTP_NL$::HTTP_NL";
239}
240
241# For forced save outputs
242sub print_oct_header {
243    print "Content-Type: application/octet-stream$::HTTP_NL";
244    if (scalar @_ > 0) {
245        my $fname = shift();
246        print "Content-Disposition: inline; " . "filename=$fname;$::HTTP_NL";
247    }
248    print "$::HTTP_NL";
249}
250
251sub print_oct_footer {
252}
253
254# Error message that is used when an HTTP/HTML header is needed
255# This escapes the characters that chould be HTML entities.
256# it will also replace \n with <br> and other things that html_encode()
257# can do. Do not send arbitrary HTML to this function.
258sub print_check_err {
259    print_html_header("");
260    print html_encode(shift()) . "<br>\n";
261    print_html_footer();
262    sleep(1);
263    exit 1;
264}
265
266# Error message when header already exists
267# This escapes the characters that chould be HTML entities.
268# it will also replace \n with <br> and other things that html_encode()
269# can do. Do not send arbitrary HTML to this function.
270sub print_err {
271    print html_encode(shift()) . "<br>\n";
272    sleep(1);
273    print_html_footer();
274    exit 1;
275}
276
277##################################################################
278#
279# Logging
280#
281#
282
283sub investig_log_fname {
284    return "" unless (defined $::host_dir       && $::host_dir        ne "");
285    return "" unless (exists $Args::args{'inv'} && $Args::args{'inv'} ne "");
286
287    return "$::host_dir" . "$::LOGDIR/$Args::args{'inv'}.log";
288}
289
290sub investig_exec_log_fname {
291    return "" unless (defined $::host_dir       && $::host_dir        ne "");
292    return "" unless (exists $Args::args{'inv'} && $Args::args{'inv'} ne "");
293
294    return "$::host_dir" . "$::LOGDIR/$Args::args{'inv'}.exec.log";
295}
296
297sub host_log_fname {
298    return "" unless (defined $::host_dir && $::host_dir ne "");
299
300    return "$::host_dir" . "$::LOGDIR/host.log";
301}
302
303sub case_log_fname {
304    return "" unless (defined $::case_dir && $::case_dir ne "");
305
306    return "$::case_dir" . "case.log";
307}
308
309# Log data to the investigators specific log file
310sub log_host_inv {
311    return unless ($::USE_LOG == 1);
312
313    my $str = shift;
314    chomp $str;
315
316    my $date  = localtime;
317    my $fname = investig_log_fname();
318    return if ($fname eq "");
319
320    open HOSTLOG, ">>$fname" or die "Can't open log: $fname";
321    print HOSTLOG "$date: $str\n";
322    close(HOSTLOG);
323
324    return;
325}
326
327sub log_host_inv_exec {
328    return unless ($::USE_LOG == 1);
329    my $str = shift;
330    chomp $str;
331
332    my $date  = localtime;
333    my $fname = investig_exec_log_fname();
334    return if ($fname eq "");
335
336    open HOSTLOG, ">>$fname" or die "Can't open log: $fname";
337    print HOSTLOG "$date: $str\n";
338    close(HOSTLOG);
339
340    return;
341}
342
343# log data to the general log file for the host
344sub log_host_info {
345    return unless ($::USE_LOG == 1);
346
347    my $str = shift;
348    chomp $str;
349
350    my $date  = localtime;
351    my $fname = host_log_fname();
352    return if ($fname eq "");
353
354    open HOSTLOG, ">>$fname" or die "Can't open log: $fname";
355    print HOSTLOG "$date: $str\n";
356    close(HOSTLOG);
357
358    return;
359}
360
361sub log_case_info {
362    return unless ($::USE_LOG == 1);
363    my $str = shift;
364    chomp $str;
365    my $date  = localtime;
366    my $fname = case_log_fname();
367    return if ($fname eq "");
368
369    open CASELOG, ">>$fname" or die "Can't open log: $fname";
370    print CASELOG "$date: $str\n";
371    close(CASELOG);
372
373    return;
374}
375
376sub log_session_info {
377    return unless ($::USE_LOG == 1);
378    my $str = shift;
379    chomp $str;
380    my $date = localtime;
381
382    my $lname = "autopsy.log";
383    open AUTLOG, ">>$::LOCKDIR/$lname" or die "Can't open log: $lname";
384    print AUTLOG "$date: $str\n";
385    close(AUTLOG);
386
387    return;
388}
389
3901;
391