; IRC8 connection by JD on ^1:LOGON:*:{ raw -q IRCVERS IRC8 MSN-OCX!9.02.0310.2401 raw -q AUTH GateKeeper I : $+ $gk.header(1) haltdef } on 1:PARSELINE:in:*:{ tokenize 32 $parseline if ($1 == AUTH) { if ($2 == GateKeeper || $2 == GateKeeperPassport) { if ($3 == S) { ; Extended (Passport) Authentication. Send %ticket and %passport to server. if ($2- == GateKeeperPassport S :OK) { raw -qn $1-3 $+($base($len(%ticket), 10, 16, 8), %ticket, $base($len(%profile), 10, 16, 8), %profile) } ; Attempt to find GateKeeper v3 Challenge (8 bytes, escaped) elseif ($regex($gettok($parseline,4-,32), /^:GKSSP\\0(?:[^\\]|\\.){2}\x03\\0\\0\\0\x02\\0\\0\\0((?:[^\\]|\\.){8})$/u) > 0) { ; Escaped text can contain characters the client can't handle (eg. 0x00), so convert to &binvar bset -a &challenge 1 $regsubex($regml(1) $+ $servertarget, /([^\\]|\\.)/gu, $gk.asc(\1) $+ $chr(32)) ; GateKeeper authenticaiton is a HMAC-MD5 with fixed key var %result = $hmac(&challenge, SRFMKSJANDRESKKC, md5, 1) .parseline -it .raw -n $1-3 $+(:,$gk.header(3),$regsubex(%result $+ $gk.guid($2), /([0-9a-f]{2})/g, $gk.hex2chr(\1))) } else { echo $color(info2) -t * GateKeeper Authentication Failed } } elseif ($3 == *) { var %oid = $iif($5 != 0, $+($chr(40),OID: $5,$chr(41))) echo $color(info) -t * Logged in as $4 %oid .parseline -it raw -q USER $username * * : $+ $iif($fullname, $ifmatch, ...) raw -q NICK $me } else { echo $color(info2) -t * GateKeeper Authentication Failed } } else { ; This is not GateKeeper. echo $color(info2) -t * ERROR: Unknown Authentication Package $+($chr(40),$2,$chr(41)) } } elseif ($2 == JOIN) { .parseline -it $1-2 $4- .parseline -itq $1 AWAY $iif($gettok($3, 1, 44) == G,:Away) if ($gettok($3, 4, 44) isin +@.) { .parseline -itq $+($1 MODE $right($4, -1) +, $replace($gettok($3, 4, 44), +, v, @, o, ., q) $right($gettok($1, 1, 33), -1)) } } elseif ($2 == PRIVMSG) { if ($regex($4-, /^:\x01S\s([^\\]|\\.)([^\\]|\\.)(.*?);(\d+)\s(.*?)\x01?$/) > 0) { ; Notes: ; Font stored in: $regsubex($regml(3), /([^\\]|\\.)/gu, $chr($gk.asc(\1))) ; Script number stored in: $regml(4) - See also https://learn.microsoft.com/pl-pl/dotnet/api/system.windows.forms.visualstyles.textmetricscharacterset var %msg : var %color $gk.msn2irc($calc($gk.asc($regml(1)) - 1)) if (%color) %msg = $+(%msg, $chr(3), $base(%color, 10, 10, 2)) var %style $calc($gk.asc($regml(2)) - 1) if (%style & 1) %msg = %msg $+ $chr(2) if (%style & 2) %msg = %msg $+ $chr(29) if (%style & 4) %msg = %msg $+ $chr(31) %msg = $+(%msg, $str($chr(2), 2), $regml(5)) .parseline -it $1-3 %msg } } elseif ($2 == 004) { .parseline -itq : $+ $server 005 $me PREFIX=(qov).@+ CHANTYPES=%# } elseif ($2 == 353) { var %original = $right($6-, -1) var %new var %i = 1 while (%i <= $numtok(%original, 32)) { var %user = $gettok(%original, %i, 32) %new = %new $gettok(%user, $numtok(%user, 44), 44) if ($numtok(%user, 44) = 4) { .parseline -itq : $+ $remove($gettok(%user, $numtok(%user, 44), 44), +, @, .) AWAY $iif($gettok(%user, 1, 44) == G,:Away) } inc %i } .parseline -it $1-5 : $+ %new } elseif ($2 == 821) { .parseline -it $1 AWAY } elseif ($2 == 822) { .parseline -it $1 AWAY $3- } } on 1:PARSELINE:out:*:{ tokenize 32 $iif($asc($right($parseline, 1)) == 10, $left($parseline, -1), $parseline) ; JOIN without key/hostkey/ownerkey if ($1 == JOIN && $3 == $null) { if (!$2) return if ($gk.config($2, OWNERKEY)) .parseline -otn $1-2 $ifmatch elseif ($gk.config($2, HOSTKEY)) .parseline -otn $1-2 $ifmatch else .parseline -otn $1-2 $gk.ud } } alias -l gk.msn2irc return $gettok(1 0 5 3 2 7 6 10 15 14 4 9 12 8 13 11, $calc($1 + 1), 32) ; Usage: $gk.header(sequence) - Returns GateKeeper v3 header with specified sequence (1 or 3 for client) alias -l gk.header return $+(GKSSP\0JD,$chr(3),\0\0\0,$chr($$1),\0\0\0) ; Usage: $gk.asc(char) - Returns $asc equivalent for a potentially escaped character (eg. \n) alias -l gk.asc { ; Not escaped if ($left($1, 1) != \) return $asc($1) ; Invalid escape elseif ($mid($1, 2, 1) !isincs 0tnrbc\) return $asc($mid($1, 2, 1)) ; Valid escape (\0 doesn't need replacement) return $replacecs($mid($1, 2, 1), t, 9, n, 10, r, 13, b, 32, c, 44, \, 92) } ; Usage: $gk.hex2chr(hex) - Returns an escaped $chr equivalent from hex alias -l gk.hex2chr { ; Normalise - Remove zero padding var %h = $base($1, 16, 16) ; Chars need escaping if (%h == 0) return \0 elseif (%h == 9) return \t elseif (%h == A) return \n elseif (%h == D) return \r elseif (%h == 20) return \b elseif (%h == 2C) return \c elseif (%h == 5C) return \\ ; Chars don't need escaping else return $chr($base($1, 16, 10)) } alias -l gk.guid { if ($1 == GateKeeperPassport) return $str(00,16) if ($gk.config(settings, GUID)) return $ifmatch var %guid = $md5($time $date $gmt $ctime $ticks) gk.config settings GUID %guid return %guid } alias -l gk.ud { if ($gk.config(settings, UserData1)) return $ifmatch var %ud = $regsubex($str(-, 31), /-/g, $chr($r(33, 126))) gk.config settings UserData1 %ud return %ud } ; Usage: $gk.config(section, key) ; /gk.config
alias gk.config { var %fn $scriptdir $+ gk.settings.ini if ($isid) return $readini(%fn, $1, $2) writeini %fn $1- } ; Adds $username for mIRC (Built-in for AdiIRC) alias -l username { if (@ isin $emailaddr) return $gettok($emailaddr, 1, 46) else return $me }