Your IP : 216.73.216.48
if (word(2 $loadinfo()) != [pf]) {
load -pf $word(1 $loadinfo());
return;
};
## Older revisions contain small bug in xform() mechanism, which
## prevent it from proper trimming message after decryption. It
## results in adding of 16 arbitrary chars to your lines, if line
## length is a factor of 16.
if (info(i) < 1702 || J !~ [EPIC5*]) {
xecho -b ERROR: xmsglog: load: EPIC5 (rev. 1702) or newer is required;
return;
};
if (match(*s* $info(o)) == 0) {
xecho -b ERROR: xmsglog: load: client compiled without SSL support: abort loading;
return;
};
package xmsglog;
## Xmsglog script for EPIC5.
## Written by zlonix@efnet, public domain.
##
## Version: 1.0 (November, 2013)
## - Initial roll-out
## This script logs specified types of messages (msg/notice/dcc chats)
## to archive in a form of encrypted lines and provides mechanism to
## search inside this archive.
## Each line is encrypted with AESSHA algorithm and armored with Base64
## encoding. EPIC5 must be compiled with OpenSSL support.
##
## This functionality may be useful if you don't have any special
## "message window" or just don't want to miss private messages in case
## of disconnect, high IRC traffic, power loss or client crash. Also,
## if you want to archive your messages for future references or
## implement automatic log loading whenever you open queries.
##
## !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!!
## This script won't protect you from evil admins, who have
## root account, since they have access to memory of every
## process on the system and hence - to your archive password,
## which must be stored in clear text in EPIC memory.
## Bear this in mind and don't set your password to the same
## thing with which you enter your ibank account.
##
## Quoting Eric Shmidt - "If you have something that you don't
## want anyone to know, maybe you shouldn't be doing it in the
## first place." I may add "at least not on the Internet".
##
## Do not trick yourself with fake feeling of privacy. It's
## like a unicorn - no such thing.
##
## Also, please note that running two clients (e.g. for
## different networks) with the same message log archive
## setting simultaneously may corrupt the archive. It can
## happen due to absense of mandatory file locking in script.
## Consider using different archive files for different
## clients.
## !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!!
##
## Logging is controlled by /set xmsglog. When you set it to ON, script
## will ask you for the password. If you already have message archive script
## will test your password on it. In case of the wrong password, set will
## back to OFF. This is preventive measure from encrypting one archive
## with different keys.
##
## /xmsglog alias allows you to search through your log. You may
## specify different criteria, like nicknames, networks on which messages
## were received/sent, etc.
##
## Few examples:
## /xmsglog -w testnick (http|ftp|https) - search for URLs in your
## conversation with testnick (both: in your msgs and his);
##
## /xmsglog -t testnick (http|ftp|https) - search for URLs which
## you sent to testnick;
##
## /xmsglog -f chanserv -n freenode - search everything ChanServ sent
## to you on freenode network;
##
## /xmsglog (borscht|recipe) -w (nick1|nick2) - search whole archive
## for 'borscht' or 'recipe' within conversations with nick1 or nick2,
## case insensitive;
##
## /xmsglog -w testnick -p 10 - prints no more than last 10 lines from
## conversation with testnick;
##
## Run /xmsglog without flags to see the complete help.
##
## Output is formated with xmsglog.output function, default look was
## taken from BlackJac's Intrepid script, without colors. It's easy to
## re-define this alias after /load'ing, to make it the way you want.
## Comments near the alias explain it in more depth.
##
## Limitation and bugs:
## - there is no way for deletion from the archive, you can pass -l flag
## to the /xmsglog to see line numbers of the messages and delete it
## manually;
## - archive password cannot be changed you must create new archive;
addset xmsglog_file str;
addset xmsglog_log_msg bool;
addset xmsglog_log_notice bool;
addset xmsglog_log_dccchat bool;
addset xmsglog_ignore str;
## controls where message archive is located
## file is created with your current umask
set xmsglog_file ~/.msglog;
## which message types should be logged
set xmsglog_log_msg on;
set xmsglog_log_notice off;
set xmsglog_log_dccchat off;
## nicknames to ignore
## may be useful to ignore services or bots
## case insensitive
set -xmsglog_ignore;
alias xmsglog (args) {
if (!@args) {
xmsglog.help;
return;
};
@ :mode = :subj = :dir = :host = :net = :server = :body = [.*];
@ :print_line = :print_date = :print_raw = :print_last = 0;
while (option = getopt(optopt optarg "m:f:t:w:h:n:s:ldrp:" $args)) {
switch ($option) {
(m) { @ :mode = optarg; };
(f) { @ :subj = optarg; @ :dir = [FROM]; };
(t) { @ :subj = optarg; @ :dir = [TO]; };
(w) { @ :subj = optarg; @ :dir = [(FROM|TO)]; };
(h) { @ :host = optarg; };
(n) { @ :net = optarg; };
(s) { @ :server = optarg; };
(l) { @ :print_line = 1; };
(d) { @ :print_date = 1; };
(r) { @ :print_raw = 1; };
(p) { @ :print_last = optarg; if (!isnumber($optarg) || optarg <= 0) @ :error = 1; };
## XXX: it seems that we can't return from while getopt() loop to abort,
## XXX: otherwise strange things will happen, so I decided to use very simple
## XXX: error handling mechanism, alas!
(!) { @ :error = 1; };
(-) { @ :error = 1; };
};
};
if (@error) {
xmsglog.help;
return;
};
if (@optarg) {
## getopt() returns unused arguments with extra space at the end
## we will use it inside regular expression and it will break it
@ :body = splitw(" " $optarg);
};
if (fexist($xmsglog_file) == 1) {
@ :fd = open($xmsglog_file R);
if (isfilevalid($fd) == 1) {
@ :pattern = [.* $mode $dir $subj $host $net $server .* .* .* .* $body];
@ :rex = regcomp($pattern);
if (regerror($rex)) {
xecho -b ERROR: alias: xmsglog: error compiling regex: $regerror($rex);
return;
};
@ :line_number = 0;
@ :idx = 0;
while (eof($fd) == 0) {
@ :line_number++;
@ :data = read($fd);
@ :text = xform("-B64 -AESSHA" $xmsglog_password $data);
if (regexec($rex $text) == 0) {
if (print_last > 0) {
## we need to remember line itself and its line number
## do it in separate arrays
@ setitem(xmsglog.temp $idx $text);
@ setitem(xmsglog.ln $idx $line_number);
@ :idx++;
} else {
@ xmsglog.output("$print_line $line_number $print_date $print_raw" $text);
};
};
};
@ regfree($rex);
@ close($fd);
## if -p was passed and we have something to display
## figure out where to start and pass those lines to output
if (( :aidx = numitems(xmsglog.temp)) >= 1) {
@ :ridx = (print_last >= aidx) ? 0 : (aidx - print_last);
for i from $ridx to ${numitems(xmsglog.temp) - 1} {
@ xmsglog.output("$print_line $getitem(xmsglog.ln $i) $print_date $print_raw" $getitem(xmsglog.temp $i));
};
@ delarray(xmsglog.temp);
@ delarray(xmsglog.ln);
};
} else {
xecho -b ERROR: alais: xmsglog: $xmsglog_file: fd cannot be used;
};
} else {
xecho -b ERROR: alias: xmsglog: $xmsglog_file: file doesn't exist;
};
};
alias xmsglog.help (void) {
echo;
echo xmsglog - search encrypted message log;
echo;
echo /xmsglog [-m <type>] [-f <nick>] [-t <nick>] [-w <nick>] [-h <hostname>];
echo [-n <net>] [-s <server>] [-l] [-d] [-r] [-p <count>] [body];
# echo [-o <file>] [-z <file>] [body];
echo -m: type of the message to be searched, possible arguments: privmsg, notice,;
echo dccchat;
echo -f: search messages which came from specified <nick>;
echo -t: search messages which were sent by you to specified <nick>;
echo -w: search conversation with specified <nick> (your and his messages);
echo -h: search for messages which have given hostname in their records;
echo -n: search for messages which were sent/received on given <network>;
echo -s: search for messages which were sent/received while you were on <server>;
echo;
echo -l: print corresponding line numbers for the messages in encrypted file;
echo (may be helpful for manual deletion from the archive);
echo -d: print date the messages were sent/received;
echo -r: print raw line from the archive, without formaing;
echo -p: print no more than last <count> matching lines of your query;
echo;
# echo -o: save output to the <file>;
# echo -z: encrypt <file> (password will be asked interactively);
# echo;
echo Everything what won't be processed as flags will be interpreted as a pattern;
echo to search inside the body of the message.;
echo;
echo If you specify several flags, AND logic apply.;
echo;
echo You may use regular expression for option arguments and body search patterns.;
echo;
echo Standard getopt() rules apply: in case of overlapping options last option;
echo wins\; place -- (two dashes) to stop processing of the options.;
echo;
echo -f -t -w flags are mutually exclusive.;
echo;
};
## Default look, taken from BlackJac's Intrepid, color-stripped.
##
## We pass additional arguments from /xmsglog like a 'qword', this
## allows us to specify additional flags without breaking backward
## compatibility with functions people may have been written.
## Inside the function we break this qword to the flags.
##
## This has been done 'just in case' and for better design overall.
##
## Right now following flags are passed:
## word 1 - whether or not print line numbers
## word 2 - line number of the archive
## word 3 - whether or not print timestamps
## word 4 - print lines without formating
##
## Numeric $'s:
## $0 - timestamp of the event, taken with $time()
## $1 - type of the message (PRIVMSG, NOTICE, DCCCHAT)
## $2 - direction, TO (you sent it), FROM (you received it)
## $3 - remote nickname
## $4 - hostname, in case of TO - our's, for FROM - remote's; (NONE for dcc)
## $5 - network name (from 005) (NONE for dcc)
## $6 - servername (NONE for dcc)
## $7 - our own current nickname ($servernick()) (NONE for dcc)
## $8 - $10 - they're dots for now, maybe will be used later
## $11- - the body of the message
alias xmsglog.output (flags qwords 1, ...) {
@ :print_line = word(0 $unsplit(" " $flags));
@ :line_number = word(1 $unsplit(" " $flags));
@ :print_date = word(2 $unsplit(" " $flags));
@ :print_raw = word(3 $unsplit(" " $flags));
# @ :save = word(4 $unsplit(" " $flags));
# @ :file = word(5 $unsplit(" " $flags));
if (print_raw == 1) {
echo ${print_line ? [$line_number ] : []}${print_date ? [[$strftime($0 %H:%M %d-%b %Y)] ] :[]}$*;
return;
};
switch ($1) {
(PRIVMSG) { echo ${print_line ? [$line_number ] : []}${print_date ? [[$strftime($0 %H:%M %d-%b %Y)] ] :[]}[${*2 == [FROM] ? [$3\($4\)] : [msg\($3\)]}] $11-; };
(NOTICE) { echo ${print_line ? [$line_number ] : []}${print_date ? [[$strftime($0 %H:%M %d-%b %Y)] ] :[]}${*2 == [FROM] ? [\-$3\($4\)\-] : [\[notice\($3\)\]]} $11-; };
(DCCCHAT) { echo ${print_line ? [$line_number ] : []}${print_date ? [[$strftime($0 %H:%M %d-%b %Y)] ] :[]}[${*2 == [FROM] ? [$3\(dcc\)] : [chat\($3\)]}] $11-; };
(*) { echo ${print_line ? [$line_number ] : []}${print_date ? [[$strftime($0 %H:%M %d-%b %Y)] ] :[]}[UNKNOWN: $*]; };
};
};
addset xmsglog bool {
if (*0 == [on]) {
alias xmsglog.write (file, text) {
@ :fd = open($file W);
if (isfilevalid($fd) == 1) {
@ :data = xform("+AESSHA +B64" $xmsglog_password $text);
@ write($fd $data);
@ close($fd);
} else {
xecho -b ERROR: alias: xmsglog.write: $file: fd cannot be used;
};
};
# mode type nick . userhost net servername curnick . . . LINE
on #-general_privmsg 300 '% $$servernick() *' {
if (xmsglog_log_msg == [on] && findw($tolower($0) $tolower($xmsglog_ignore)) == -1) {
xmsglog.write $xmsglog_file $time() PRIVMSG FROM $0 $userhost() $serverctl(GET $servernum() 005 NETWORK) $servername() $servernick() . . . $2-;
};
};
on #-send_msg 300 '*' {
if (xmsglog_log_msg == [on] && findw($tolower($0) $tolower($xmsglog_ignore)) == -1) {
xmsglog.write $xmsglog_file $time() PRIVMSG TO $0 $userhost($servernick()) $serverctl(GET $servernum() 005 NETWORK) $servername() $servernick() . . . $1-;
};
};
on #-general_notice 300 '% $$servernick() *' {
if (xmsglog_log_notice == [on] && findw($tolower($0) $tolower($xmsglog_ignore)) == -1) {
xmsglog.write $xmsglog_file $time() NOTICE FROM $0 $userhost() $serverctl(GET $servernum() 005 NETWORK) $servername() $servernick() . . . $2-;
};
};
on #-send_notice 300 '*' {
if (xmsglog_log_notice == [on] && findw($tolower($0) $tolower($xmsglog_ignore)) == -1) {
xmsglog.write $xmsglog_file $time() NOTICE TO $0 $userhost($servernick()) $serverctl(GET $servernum() 005 NETWORK) $servername() $servernick() . . . $1-;
};
};
on #-dcc_chat 300 '*' {
if (xmsglog_log_dccchat == [on] && findw($tolower($0) $tolower($xmsglog_ignore)) == -1) {
xmsglog.write $xmsglog_file $time() DCCCHAT FROM $0 NONE NONE NONE NONE . . . $1-;
};
};
on #-send_dcc_chat 300 '*' {
if (xmsglog_log_dccchat == [on] && findw($tolower($0) $tolower($xmsglog_ignore)) == -1) {
xmsglog.write $xmsglog_file $time() DCCCHAT TO $0 NONE NONE NONE NONE . . . $1-;
};
};
input -noecho "Xmsglog password: " {
if (fsize($xmsglog_file) > 0) {
^assign xmsglog_password $0;
@ :fd = open($xmsglog_file R);
@ :data = read($fd);
@ :text = xform("-B64 -AESSHA" $xmsglog_password $data);
if (isnumber($word(0 $text)) != 1) {
xecho -b ERROR: input: $xmsglog_file: wrong password or archive is corrupted;
^assign -xmsglog_password;
set xmsglog off;
};
} else {
^assign xmsglog_password $0;
};
};
} else {
alias -xmsglog.write;
assign -xmsglog_password;
on #-general_privmsg 300 -'% $$servernick() *';
on #-send_msg 300 -'*';
on #-general_notice 300 -'% $$servernick() *';
on #-send_notice 300 -'*';
on #-dcc_chat 300 -'*';
on #-send_dcc_chat 300 -'*';
};
};