/var/www/www.irssi.org-old/scripts/html/nickserv.pl


   1 #!/usr/bin/perl -w
   2 
   3 ## Bugreports and Licence disclaimer.
   4 #
   5 # For bugreports and other improvements contact Geert Hauwaerts <geert@irssi.org>
   6 #
   7 #    This program is free software; you can redistribute it and/or modify
   8 #    it under the terms of the GNU General Public License as published by
   9 #    the Free Software Foundation; either version 2 of the License, or
  10 #    (at your option) any later version.
  11 #
  12 #    This program is distributed in the hope that it will be useful,
  13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 #    GNU General Public License for more details.
  16 #
  17 #    You should have received a copy of the GNU General Public License
  18 #    along with this script; if not, write to the Free Software
  19 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20 #
  21 ##
  22 
  23 use strict;
  24 use Irssi;
  25 use vars qw($VERSION %IRSSI);
  26 
  27 $VERSION = "1.8";
  28 
  29 %IRSSI = (
  30     authors     => 'Geert Hauwaerts',
  31     contact     => 'geert@irssi.org',
  32     name        => 'nickserv.pl',
  33     description => 'This script will authorize you into NickServ.',
  34     license     => 'GNU General Public License',
  35     url         => 'http://irssi.hauwaerts.be/nickserv.pl',
  36     changed     => 'Fri Jun  6 12:03:04 CEST 2008',
  37 );
  38 
  39 my @nickservnet = ();
  40 my $nickservnet_file = "nickserv.networks";
  41 
  42 my @nickservauth = ();
  43 my $nickservauth_file = "nickserv.auth";
  44 
  45 my $irssidir = Irssi::get_irssi_dir();
  46 
  47 my $help = <<EOF;
  48 
  49 Usage: (all on one line)
  50 /NICKSERV [addnet <ircnet> <services\@host>]
  51           [addnick <ircnet> <nickname> <password>]
  52           [delnet <ircnet>]
  53           [delnick <ircnet> <nick>]
  54           [help listnet listnick]
  55 
  56 addnet:     Add a new network into the NickServ list.
  57 addnick:    Add a new nickname into the NickServ list.
  58 delnet:     Delete a network from the NickServ list.
  59 delnick:    Delete a nickname from the NickServ list.
  60 listnet:    Display the contents of the NickServ network list.
  61 listnick:   Display the contents of the NickServ nickname list.
  62 help:       Display this useful little helptext.
  63 
  64 Examples: (all on one line)
  65 /NICKSERV addnet Freenode NickServ\@services.
  66 /NICKSERV addnick Freenode Geert mypass
  67 
  68 /NICKSERV delnet Freenode
  69 /NICKSERV delnick Freenode Geert
  70 
  71 Note: This script doesn't allow wildcards into the NickServ hostname. You must use the full services\@host.
  72       Both /NICKSERV and /NS are valid commands.
  73 EOF
  74 
  75 Irssi::theme_register([
  76     'nickserv_usage_network', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV addnet ircnet services@host%_".',
  77     'nickserv_usage_nickname', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV addnick ircnet nickname password%_".',
  78     'nickserv_delusage', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV delnet ircnet%_".',
  79     'nickserv_delnickusage', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV delnick ircnet nickname%_".',
  80     'nickserv_delled', '%R>>%n %_NickServ:%_ Deleted %_$0%_ and his nicknames from the NickServ ircnet list.',
  81     'nickserv_delled_nick', '%R>>%n %_NickServ:%_ Deleted %_$1%_ from the NickServ list on $0.',
  82     'nickserv_nfound', '%R>>%n %_NickServ:%_ The NickServ ircnet %_$0%_ could not be found.',
  83     'nickserv_nfound_nick', '%R>>%n %_NickServ:%_ The NickServ nickname %_$0%_ could not be found on $1.',
  84     'nickserv_usage', '%R>>%n %_NickServ:%_ Insufficient parameters: Use "%_/NICKSERV help%_" for further instructions.',
  85     'nickserv_no_net', '%R>>%n %_NickServ:%_ Unknown Irssi ircnet %_$0%_.',
  86     'nickserv_wrong_host', '%R>>%n %_NickServ:%_ Malformed services hostname %_$0%_.',
  87     'already_loaded_network', '%R>>%n %_NickServ:%_ The ircnet %_$0%_ already exists in the NickServ ircnet list, please remove it first.',
  88     'nickserv_loaded_nick', '%R>>%n %_NickServ:%_ The nickname %_$0%_ already exists in the NickServ authlist on %_$1%_, please remove it first.',
  89     'nickserv_not_loaded_net', '%R>>%n %_NickServ:%_ The ircnet %_$0%_ doesn\'t exists in the NickServ ircnet list, please add it first.',
  90     'saved_nickname', '%R>>%n %_NickServ:%_ Added nickname %_$1%_ on %_$0%_.',
  91     'network_print', '$[!-2]0 $[20]1 $2',
  92     'password_request', '%R>>%n %_NickServ:%_ Auth Request from NickServ on %_$0%_.',
  93     'password_accepted', '%R>>%n %_NickServ:%_ Password accepted on %_$0%_.',
  94     'password_wrong', '%R>>%n %_NickServ:%_ Password denied on %_$0%_. Please change the password.',
  95     'network_info', '%_ # Ircnet               Services hostname%_',
  96     'network_empty', '%R>>%n %_NickServ:%_ Your NickServ ircnet list is empty.',
  97     'nickname_print', '$[!-2]0 $[20]1 $[18]2 $3',
  98     'nickname_info', '%_ # Ircnet               Nickname           Password%_',
  99     'nickname_empty', '%R>>%n %_NickServ:%_ Your NickServ authlist is empty.',
 100     'nickserv_help', '$0',
 101     'saved_network', '%R>>%n %_NickServ:%_ Added services mask "%_$1%_" on %_$0%_.',
 102     'nickserv_loaded', '%R>>%n %_Scriptinfo:%_ Loaded $0 version $1 by $2.'
 103 ]);
 104 
 105 sub load_nickservnet {
 106 
 107     my ($file) = @_;
 108 
 109     @nickservnet = ();
 110 
 111     if (-e $file) {
 112         local *F;
 113         open(F, "<$file");
 114         local $/ = "\n";
 115 
 116         while (<F>) {
 117             chop;
 118             my $new_nsnet = new_nickserv_network(split("\t"));
 119   
 120             if (($new_nsnet->{name} ne "") && ($new_nsnet->{host} ne "")) {
 121                 push(@nickservnet, $new_nsnet);
 122             }
 123         }
 124         
 125         close(F);
 126     }
 127 }
 128 
 129 sub save_nickservnet {
 130 
 131     my ($file) = @_;
 132 
 133     return unless scalar @nickservnet; # there's nothing to save
 134 
 135     if (-e $file) {
 136         local *F;
 137         open(F, ">$file");
 138 
 139         for (my $n = 0; $n < @nickservnet; ++$n) {
 140             print(F join("\t", $nickservnet[$n]->{name}, $nickservnet[$n]->{host}) . "\n");
 141         }
 142     
 143         close(F);
 144     } else {
 145         create_network_file($file);
 146         save_nickservnet($file);
 147     }
 148 }
 149 
 150 sub create_network_file {
 151     
 152     my ($file) = @_;
 153     
 154     open(F, ">$file") or die "Can't create $file. Reason: $!";
 155 }
 156 
 157 sub new_nickserv_network {
 158 
 159     my $nsnet = {};
 160 
 161     $nsnet->{name} = shift;
 162     $nsnet->{host} = shift;
 163 
 164     return $nsnet;
 165 }
 166 
 167 sub load_nickservnick {
 168 
 169     my ($file) = @_;
 170 
 171     @nickservauth = ();
 172 
 173     if (-e $file) {
 174         local *F;
 175         open(F, "<$file");
 176         local $/ = "\n";
 177 
 178         while (<F>) {
 179             chop;
 180             my $new_nsnick = new_nickserv_nick(split("\t"));
 181   
 182             if (($new_nsnick->{ircnet} ne "") && ($new_nsnick->{nick} ne "") && ($new_nsnick->{pass} ne "")) {
 183                 push(@nickservauth, $new_nsnick);
 184             }
 185         }
 186         
 187         close(F);
 188     }
 189 }
 190 
 191 sub save_nickservnick {
 192 
 193     my ($file) = @_;
 194 
 195     return unless scalar @nickservauth; # there's nothing to save
 196 
 197     if (-e $file) {
 198         local *F;
 199         open(F, ">$file");
 200 
 201         for (my $n = 0; $n < @nickservauth; ++$n) {
 202             print(F join("\t", $nickservauth[$n]->{ircnet}, $nickservauth[$n]->{nick}, $nickservauth[$n]->{pass}) . "\n");
 203         }
 204     
 205         close(F);
 206     } else {
 207         create_nick_file($file);
 208         save_nickservnick($file);
 209     }
 210 }
 211 
 212 sub create_nick_file {
 213     
 214     my ($file) = @_;
 215     
 216     my $umask = umask 0077; # save old umask
 217     open(F, ">$file") or die "Can't create $file. Reason: $!";
 218     umask $umask;
 219 }
 220 
 221 sub new_nickserv_nick {
 222 
 223     my $nsnick = {};
 224 
 225     $nsnick->{ircnet} = shift;
 226     $nsnick->{nick} = shift;
 227     $nsnick->{pass} = shift;
 228 
 229     return $nsnick;
 230 }
 231 
 232 sub add_nickname {
 233     
 234     my ($network, $nickname, $password) = split(" ", @_[0], 3);
 235     my ($correct_network, $correct_nickname, $correct_password);
 236 
 237     if ($network eq "" || $nickname eq "" || $password eq "") {
 238         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_usage_nickname');
 239         return;
 240     }
 241     
 242     if ($network) {
 243         if (!already_loaded_net($network)) {
 244             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_not_loaded_net', $network);
 245             return;
 246         } else {
 247             $correct_network = 1;
 248         }
 249     }
 250     
 251     if ($nickname) {
 252         if (already_loaded_nick($nickname, $network)) {
 253             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_loaded_nick', $nickname, $network);
 254             return;
 255         } else {
 256             $correct_nickname = 1;
 257         }
 258     }
 259     
 260     if ($correct_network && $correct_nickname) {
 261         push(@nickservauth, new_nickserv_nick($network, $nickname, $password));
 262         save_nickservnick("$irssidir/$nickservauth_file");
 263             
 264         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'saved_nickname', $network, $nickname);
 265     }
 266 }
 267 
 268 sub add_network {
 269     
 270     my ($network, $hostname) = split(" ", @_[0], 2);
 271     my ($correct_net, $correct_host);
 272     
 273     if ($network eq "" || $hostname eq "") {
 274         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_usage_network');
 275         return;
 276     }
 277     
 278     if ($network) {
 279         my ($ircnet) = Irssi::chatnet_find($network);
 280         
 281         if (!$ircnet) {
 282             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_no_net', $network);
 283             return;
 284         } elsif (already_loaded_net($network)) {
 285             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'already_loaded_network', $network);
 286             return;
 287         } else {
 288             $correct_net = 1;
 289         }
 290     }
 291  
 292     if ($hostname) {
 293         if ($hostname !~ /^[.+a-zA-Z0-9_-]{1,9}@[.+a-zA-Z0-9_-]{1,}$/) {
 294             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_wrong_host', $hostname);
 295             return;
 296         } else {
 297             $correct_host = 1;
 298         }
 299     }
 300     
 301     if ($correct_net && $correct_host) {
 302         push(@nickservnet, new_nickserv_network($network, $hostname));
 303         save_nickservnet("$irssidir/$nickservnet_file");
 304             
 305         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'saved_network', $network, $hostname);
 306     }
 307 }
 308 
 309 sub already_loaded_net {
 310 
 311     my ($ircnet) = @_;
 312     my $loaded = check_loaded_net($ircnet);
 313 
 314     if ($loaded > -1) {
 315         return 1;
 316     }
 317     
 318     return 0;
 319 }
 320 
 321 sub check_loaded_net {
 322 
 323     my ($ircnet) = @_;
 324 
 325     $ircnet = lc($ircnet);
 326 
 327     for (my $loaded = 0; $loaded < @nickservnet; ++$loaded) {
 328         return $loaded if (lc($nickservnet[$loaded]->{name}) eq $ircnet);
 329     }
 330     
 331     return -1;
 332 }
 333 
 334 sub already_loaded_nick {
 335     
 336     my ($nickname, $network) = @_;
 337     my $loaded = check_loaded_nick($nickname, $network);
 338     
 339     if ($loaded > -1) {
 340         return 1;
 341     }
 342     
 343     return 0
 344 }
 345 
 346 sub check_loaded_nick {
 347     
 348     my ($nickname, $network) = @_;
 349     
 350     $nickname = lc($nickname);
 351     $network = lc($network);
 352     
 353     for (my $loaded = 0; $loaded < @nickservauth; ++$loaded) {
 354         return $loaded if (lc($nickservauth[$loaded]->{nick}) eq $nickname && lc ($nickservauth[$loaded]->{ircnet}) eq $network);
 355     }
 356     
 357     return -1;
 358 }
 359 
 360 sub list_net {
 361     
 362     if (@nickservnet == 0) {
 363         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'network_empty');
 364     } else {
 365         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'network_info');
 366 
 367         for (my $n = 0; $n < @nickservnet ; ++$n) {
 368             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'network_print', $n, $nickservnet[$n]->{name}, $nickservnet[$n]->{host});
 369         }
 370     }
 371 }
 372 
 373 sub list_nick {
 374     
 375     if (@nickservauth == 0) {
 376         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickname_empty');
 377     } else {
 378         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickname_info');
 379 
 380         for (my $n = 0; $n < @nickservauth ; ++$n) {
 381             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickname_print', $n, $nickservauth[$n]->{ircnet}, $nickservauth[$n]->{nick}, "*" x length($nickservauth[$n]->{pass}));
 382         }
 383     }
 384 }
 385 
 386 sub nickserv_notice {
 387     
 388     my ($server, $data, $nick, $address) = @_;
 389     my ($target, $text) = $data =~ /^(\S*)\s:(.*)/;
 390 
 391     if (is_nickserv($server->{tag}, $address)) {
 392         if ($text =~ /^If this is your nickname, type \/msg NickServ/ || $text =~ /^This nickname is registered and protected.  If it is your/ || $text =~ /This nickname is registered\. Please choose a different nickname,/ || $text =~ /^This nickname is registered. Please choose a different nickname/) {
 393             my $password = get_password($server->{tag}, $server->{nick});
 394             
 395             if ($password == -1) {
 396                 Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_request', $server->{tag});
 397                 Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_nfound_nick', $server->{nick}, $server->{tag});
 398                 Irssi::signal_stop();
 399                 return;
 400             }
 401             
 402             Irssi::signal_stop();
 403             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_request', $server->{tag});
 404             $server->command("^MSG NickServ IDENTIFY $password");
 405         } elsif ($text =~ /If this is your nickname, type \/NickServ/) {
 406             my $password = get_password($server->{tag}, $server->{nick});
 407 
 408             if ($password == -1) {
 409                 Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_request', $server->{tag});
 410                 Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_nfound_nick', $server->{nick}, $server->{tag});
 411                 Irssi::signal_stop();
 412                 return;
 413             }
 414 
 415             Irssi::signal_stop();
 416             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_request', $server->{tag});
 417             $server->command("^QUOTE NickServ :IDENTIFY $password");
 418         } elsif ($text =~ /If this is your nickname, type \/msg NS/) {
 419             my $password = get_password($server->{tag}, $server->{nick});
 420 
 421             if ($password == -1) {
 422                 Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_request', $server->{tag});
 423                 Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_nfound_nick', $server->{nick}, $server->{tag});
 424                 Irssi::signal_stop();
 425                 return;
 426             }
 427 
 428             Irssi::signal_stop();
 429             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_request', $server->{tag});
 430             $server->command("^MSG NS IDENTIFY $password");
 431         } elsif ($text =~ /If you do not (.*) within one minute, you will be disconnected/) {
 432             Irssi::signal_stop();
 433         } elsif ($text =~ /^This nickname is owned by someone else/) {
 434             Irssi::signal_stop();
 435         } elsif ($text =~ /^nick, type (.*)  Otherwise,/) {
 436             Irssi::signal_stop();
 437         } elsif ($text =~ /^please choose a different nick./) {
 438             Irssi::signal_stop();
 439         } elsif ($text =~ /^You have already identified/ || $text =~ /^This nick is already identified./) {
 440             Irssi::signal_stop();
 441         } elsif ($text =~ /^Password accepted - you are now recognized/) {
 442             Irssi::signal_stop();
 443             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_accepted', $server->{tag});
 444         } elsif ($text =~ /^Password Incorrect/ || $text =~ /^Password incorrect./) {
 445             Irssi::signal_stop();
 446             Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_wrong', $server->{tag});
 447         }
 448     }
 449 }
 450 
 451 sub is_nickserv {
 452     
 453     my ($net, $host) = @_;
 454 
 455     for (my $loaded = 0; $loaded < @nickservnet; ++$loaded) {
 456         return 1 if (lc($nickservnet[$loaded]->{name}) eq lc($net) && lc($nickservnet[$loaded]->{host}) eq lc($host));
 457     }
 458     return 0;
 459 }
 460 
 461 sub get_password {
 462     
 463     my ($ircnet, $nick) = @_;
 464     
 465     for (my $loaded = 0; $loaded < @nickservauth; ++$loaded) {
 466         return $nickservauth[$loaded]->{pass} if (lc($nickservauth[$loaded]->{ircnet}) eq lc($ircnet) && lc($nickservauth[$loaded]->{nick}) eq lc($nick));
 467     }
 468     
 469     return -1;
 470 }
 471 
 472 sub del_network {
 473 
 474     my ($ircnet) = split(" ", @_[0], 1);
 475     my ($ircnetindex);
 476 
 477     if ($ircnet eq "") {
 478         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_delusage');
 479         return;
 480     }
 481 
 482     for (my $index = 0; $index < @nickservnet; ++$index) {
 483         if (lc($nickservnet[$index]->{name}) eq lc($ircnet)) {
 484             $ircnetindex = 1;
 485         }
 486     }
 487     
 488     if ($ircnetindex) {
 489         @nickservnet = grep {lc($_->{name}) ne lc($ircnet)} @nickservnet;
 490         @nickservauth = grep {lc($_->{ircnet}) ne lc($ircnet)} @nickservauth;
 491         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_delled', $ircnet);
 492         save_nickservnet("$irssidir/$nickservnet_file");
 493         save_nickservnick("$irssidir/$nickservauth_file");
 494     } else {
 495         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_nfound', $ircnet);
 496     }
 497 }
 498 
 499 sub del_nickname {
 500     
 501     my ($ircnet, $nickname) = split(" ", @_[0], 2);
 502     my ($nickindex);
 503     
 504     if ($ircnet eq "" || $nickname eq "") {
 505         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_delnickusage');
 506         return;
 507     }
 508 
 509     for (my $index = 0; $index < @nickservauth; ++$index) {
 510         if (lc($nickservauth[$index]->{ircnet}) eq lc($ircnet) && lc($nickservauth[$index]->{nick}) eq lc($nickname)) {
 511             $nickindex = splice(@nickservauth, $index, 1);
 512         }   
 513     }
 514 
 515     if ($nickindex) {
 516         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_delled_nick', $ircnet, $nickname);
 517         save_nickservnick("$irssidir/$nickservauth_file");
 518     } else {
 519         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_nfound_nick', $ircnet, $nickname);
 520     }
 521 }
 522 
 523 sub nickserv_runsub {
 524     
 525     my ($data, $server, $item) = @_;
 526     $data =~ s/\s+$//g;
 527     
 528     if ($data) {
 529         Irssi::command_runsub('nickserv', $data, $server, $item);
 530     } else {
 531         Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_usage');
 532     }
 533 }
 534 
 535 load_nickservnet("$irssidir/$nickservnet_file");
 536 load_nickservnick("$irssidir/$nickservauth_file");
 537 
 538 Irssi::command_bind('nickserv', 'nickserv_runsub');
 539 Irssi::command_bind('ns', 'nickserv_runsub');
 540 
 541 Irssi::command_bind('nickserv addnet', 'add_network');
 542 Irssi::command_bind('ns addnet', 'add_network');
 543 
 544 Irssi::command_bind('nickserv addnick', 'add_nickname');
 545 Irssi::command_bind('ns addnick', 'add_nickname');
 546 
 547 Irssi::command_bind('nickserv listnet', 'list_net');
 548 Irssi::command_bind('ns listnet', 'list_net');
 549 
 550 Irssi::command_bind('nickserv listnick', 'list_nick');
 551 Irssi::command_bind('ns listnick', 'list_nick');
 552 
 553 Irssi::command_bind('nickserv delnet', 'del_network');
 554 Irssi::command_bind('ns delnet', 'del_network');
 555 
 556 Irssi::command_bind('nickserv delnick', 'del_nickname');
 557 Irssi::command_bind('ns delnick', 'del_nickname');
 558 
 559 Irssi::command_bind('nickserv help' => sub { Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_help', $help) });
 560 Irssi::command_bind('ns help' => sub { Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_help', $help) });
 561 
 562 Irssi::signal_add('event notice', 'nickserv_notice');
 563 Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_loaded', $IRSSI{name}, $VERSION, $IRSSI{authors});