diff -urN epona-1.4.14/actions.c anope-1.6.4/actions.c --- epona-1.4.14/actions.c 2002-09-01 02:44:45.000000000 +0200 +++ anope-1.6.4/actions.c 2005-09-08 15:56:07.000000000 +0200 @@ -1,12 +1,14 @@ /* Various routines to perform simple actions. * - * Epona (c) 2000-2002 PegSoft - * Contact us at epona@pegsoft.net + * (C) 2003 Anope Team + * Contact us at info@anope.org * - * This program is free but copyrighted software; see the file COPYING for - * details. + * Please read COPYING and README for furhter details. * - * Based on the original code of Services by Andy Church. + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id: actions.c 420 2004-10-23 23:42:15Z trystan $ * */ @@ -18,45 +20,50 @@ * their limit, toss them off. */ -void bad_password(User *u) +void bad_password(User * u) { time_t now = time(NULL); if (!BadPassLimit) - return; + return; if (BadPassTimeout > 0 && u->invalid_pw_time > 0 - && u->invalid_pw_time < now - BadPassTimeout) - u->invalid_pw_count = 0; + && u->invalid_pw_time < now - BadPassTimeout) + u->invalid_pw_count = 0; u->invalid_pw_count++; u->invalid_pw_time = now; if (u->invalid_pw_count >= BadPassLimit) #ifdef IRC_BAHAMUT - send_cmd(NULL, "SVSKILL %s :%s", u->nick, "Too many invalid passwords"); + send_cmd(NULL, "SVSKILL %s :%s", u->nick, + "Too many invalid passwords"); #else - kill_user(NULL, u->nick, "Too many invalid passwords"); + kill_user(NULL, u->nick, "Too many invalid passwords"); #endif } /*************************************************************************/ -void change_user_mode(User *u, char *modes, char *arg) +void change_user_mode(User * u, char *modes, char *arg) { - int ac = 1; - char *av[2]; - - av[0] = modes; - if (arg) { - av[1] = arg; - ac++; - } - +#ifndef IRC_HYBRID + int ac = 1; + char *av[2]; + + av[0] = modes; + if (arg) { + av[1] = arg; + ac++; + } #ifdef IRC_BAHAMUT - send_cmd(ServerName, "SVSMODE %s %ld %s%s%s", u->nick, u->timestamp, av[0], (ac == 2 ? " " : ""), (ac == 2 ? av[1] : "")); + send_cmd(ServerName, "SVSMODE %s %ld %s%s%s", u->nick, + (long int) u->timestamp, av[0], (ac == 2 ? " " : ""), + (ac == 2 ? av[1] : "")); #else - send_cmd(ServerName, "SVSMODE %s %s%s%s", u->nick, av[0], (ac == 2 ? " " : ""), (ac == 2 ? av[1] : "")); + send_cmd(ServerName, "SVSMODE %s %s%s%s", u->nick, av[0], + (ac == 2 ? " " : ""), (ac == 2 ? av[1] : "")); +#endif + set_umode(u, ac, av); #endif - set_umode(u, ac, av); } /*************************************************************************/ @@ -71,11 +78,11 @@ char buf[BUFSIZE]; if (!user || !*user) - return; + return; if (!source || !*source) - source = ServerName; + source = ServerName; if (!reason) - reason = ""; + reason = ""; snprintf(buf, sizeof(buf), "%s (%s)", source, reason); av[0] = sstrdup(user); av[1] = buf; diff -urN epona-1.4.14/bin/am anope-1.6.4/bin/am --- epona-1.4.14/bin/am 1970-01-01 01:00:00.000000000 +0100 +++ anope-1.6.4/bin/am 2005-09-08 15:56:04.000000000 +0200 @@ -0,0 +1,418 @@ +#!/usr/bin/env perl + +# ==================================================================== +# anomgr: Anope Manager. Used to manage anope revision on SubVersion. +# +# For usage, see the usage subroutine or run the script with no +# command line arguments. +# +# $Id: am 7 2004-03-29 02:17:55Z dane $ +# +# ==================================================================== +require 5.6.0; +use strict; +use Getopt::Std; +use Net::FTP; +use Cwd; + +###################################################################### +# Configuration section. +my $myver="1.0"; +my $svnrev="http://www.zero.org/anosvn.php"; +my $fhint="version.log"; + +# Default values, change or use environment variables instead. +my $copy="anope"; +my $svnpath="/usr/bin"; +my $svnroot="svn://zero.org/repos/$copy"; +my $editor="/usr/bin/vi"; + +# Environment variables SVNBINDIR and SVNROOT override the above +# hardcoded values. +$svnpath="$ENV{SVNBINDIR}" if ($ENV{SVNBINDIR}); +$svnroot="$ENV{SVNROOT}" if ($ENV{SVNROOT}); +$editor="$ENV{EDITOR}" if ($ENV{EDITOR}); + +# Svnlook path. +my $svnlook = "$svnpath/svnlook"; + +# Svn path. +my $svn = "$svnpath/svn"; + +# wget path. Need to change to a perl module instead... +my $wget = "$svnpath/wget"; + +my ( + $rev, + $branch, + $tag, + $ftp, + $dst, + $ver_major, + $ver_minor, + $ver_patch, + $ver_build, + $ver_revision, + $ver_comment, + $svn_comment, + $cver, + $nver, + $ctrlfile, + $tmpfile, + @source, + %opt +); + +{ + my $ok = 1; + foreach my $program ($svnlook, $svn, $editor) + { + if (-e $program) + { + unless (-x $program) + { + warn "$0: required program `$program' is not executable, ", + "edit $0.\n"; + $ok = 0; + } + } + else + { + warn "$0: required program `$program' does not exist, edit $0.\n"; + $ok = 0; + } + } + exit 1 unless $ok; +} + +sub usage() +{ + # More features to add: + # --diff N:M to produce a diff between revisions + # --bugs CLI method to add bug number to the commit message + # --mesg CLI methos to add the commit message + # --create-branch to create a branch + # --create-tag to create a tag + # --switch to switch between branches/tags + print "Usage: $0 <-g | -p | -f> [-r revision | -b branch | -t tag] \n"; + print " Operations:\n"; + print " -g Get Operation\n"; + print " -p Put Operation\n"; + print " -f[tar|diff] FTP Operation, retrieve latest tar or diff\n"; + print " Selector:\n"; + print " -r revision Retrieve by revision number\n"; + print " -b branch Retrieve by branch name\n"; + print " -t tag Retrieve by tag name\n"; + print " Destination:\n"; + print " The working copy to perform the operation in or to. The script will \n"; + print " try to guess where that is, unless you provide a specific path.\n"; + exit; +} + +sub banner() { + + print "Anope Source Managemnt Utility - Version $myver\n\n"; + +} + +sub getans { + my $ans; + while (! (($ans =~ /y/) || ($ans =~ /n/))) { + print "*** Ready to continue? (y/n): "; + $ans = ; + chomp($ans); + $ans = lc($ans); + # $ans = &getans(); + } + + # return $ans; + return ($ans eq "y") ? 1 : 0 +} + +sub find_conflict() { + + my $filename=shift; + my $retval=0; + open (IN2, "$filename") || die "Can't open $filename\n"; + while () { + if (/^<<<<<<new("ftp.zero.org"); + $ftpc->login("ftp","-anonymou@"); + $ftpc->cwd("/incoming"); + + if ( lc($ftp) eq "tar" ) { + print "Retrieving latest tar ball...\n"; + $ftpc->get("anope.tgz"); + } elsif ( lc($ftp) eq "diff" ) { + print "Retrieving latest patch file...\n"; + $ftpc->get("anope.diff"); + } else { + print "Unknown type $ftp, aborting...\n"; + } + $ftpc->quit(); +} + +sub do_get() { + + my $options = "" ; # Options to be passed to the svn command + my $selector = "" ; # Selector to be passed to the svn command + + if ($rev) { + $options .= "-r $rev"; + $selector = "trunk"; + $copy = $copy . "-$rev"; + } elsif ($tag) { + $selector = "tags/$tag"; + $copy = $copy . "-$tag"; + } elsif ($branch) { + $selector = "branches/$branch"; + $copy = $copy . "-$branch"; + } else { + $selector = "trunk"; + } + + if ($dst eq undef) { + my $cwd = &Cwd::cwd(); + if (-f "$cwd/$fhint") { + system("$svn update $options $cwd"); + } elsif (-f "$cwd/$copy/$fhint") { + system("$svn update $options $cwd/$copy"); + } else { + system("$svn checkout $svnroot/$selector $options $cwd/$copy"); + } + } else { + $dst = &Cwd::cwd() if ($dst eq "\.") ; + if (-f "$dst/$fhint") { + system("$svn update $options $dst"); + } else { + system("$svn checkout $svnroot/$selector $options $dst"); + } + } +} + +sub do_put() { + + if ($dst eq undef) { + my $cwd = &Cwd::cwd(); + if (-f "$cwd/$fhint") { + $dst = "$cwd"; + } elsif (-f "$cwd/$copy/$fhint") { + $dst .= "$cwd/$copy"; + } else { + print "Error: Unable to determine your working copy location.\n"; + exit; + } + } else { + $dst = &Cwd::cwd() if ($dst eq "\.") ; + if (! -f "$dst/$fhint") { + print "Error: Unable to determine your working copy location.\n"; + exit; + } + } + + # Check to see if we need to update our working copy first. + my $nupdate; + open (IN, "$svn status --show-updates --verbose $dst|"); + while () { + if (/\*/) { + $nupdate .= "$_"; + } + } + close(IN); + + if ($nupdate ne undef) { + print "*** Warning: There are files modified in the repository that need\n"; + print "*** to be merged back to your working copy before the commit can\n"; + print "*** take place. These files are:\n"; + print $nupdate; + print "Please use: $0 -g $dst\n"; + exit; + } + + # Get a prelim diff of the changes... + my $dcount=0; + my $conflict; + # open (IN, "$svn diff $dst|"); + open (IN, "$svn status $dst|"); + while () { + if (!/^\?/) { + $dcount++; + } + + if (/^C/) { + $_ =~ s/^C\s+//; + chomp($_); + # I don't want to use grep. But my find_conflict sub + # does not seem to work :( Too bad + if (`grep "^<<<<<<<" $_`) { + $conflict .= "$_\n" ; + } else { + system("$svn resolved $_"); + } + } + } + close(IN); + + if ($dcount == 0) { + print "*** Warning: There are no modified files to be commited. Are you\n"; + print "*** sure you are in the right working copy? Verify changes with:\n"; + print "*** $svn diff $dst\n"; + exit; + } + + if ($conflict ne undef) { + print "*** Warning: There are merge conflicts to be resolved! Please take\n"; + print "*** a look at the following files and resolve them manually:\n\n"; + print "$conflict\n"; + exit; + } + + $ctrlfile = "$dst/$fhint"; + # Grab the current revision number. Clunky way, I know! + $ver_revision=`$wget -qO - $svnrev`; + chomp($ver_revision); + + unless ($ver_revision =~ /^\d+/ and $ver_revision > 0) + { + print "*** Error: Got bogus result $ver_revision from $svnrev.\n"; + exit; + } + + $ver_revision++; + open (REV, "$ctrlfile") || die "Can't open $ctrlfile\n"; + while () { + push (@source, $_); + $ver_major = $_ if (/VERSION_MAJOR/); + $ver_minor = $_ if (/VERSION_MINOR/); + $ver_patch = $_ if (/VERSION_PATCH/); + $ver_build = $_ if (/VERSION_BUILD/); + } + close(REV); + + my $junk; + ($junk, $ver_major) = split('"', $ver_major); + ($junk, $ver_minor) = split('"', $ver_minor); + ($junk, $ver_patch) = split('"', $ver_patch); + ($junk, $ver_build) = split('"', $ver_build); + + $cver = "$ver_major.$ver_minor.$ver_patch ($ver_build)"; + $nver = "$ver_major.$ver_minor.$ver_patch ($ver_revision)"; + + # Greet the developer + banner(); + print "*** Repository : $svnroot \n"; + print "*** Working copy : $dst \n" ; + print "*** Current ver. : $cver \n"; + print "*** Updated ver. : $nver \n"; + print "*** Files Changed: $dcount (before indent and version change)\n"; + die ("Aborting...\n") unless &getans(); + + # Need to add a clause for -c "comment" and -b "buglist" + + # Get developers input for commit + $tmpfile=".commit"; + open (OUT, ">$tmpfile") or die ("*** Error! Unable to open $tmpfile file\n"); + print OUT "# Anope commit utility. Please use this template for your commits. +# Add Bugzilla bugs separated by spaces. The note part is free form. +BUILD : $nver +BUGS : +NOTES : "; + close(OUT); + + system("$editor $tmpfile"); + + my $tmp_comment=""; + $ver_comment="#\n"; + $svn_comment=""; + open (IN, "$tmpfile") or die ("*** Error! Unable to open $tmpfile file\n"); + while () { + if ( !/^#/) { + $tmp_comment.="$_"; + chomp($_); + $_ =~ s/\t/ /g; + $ver_comment.="# $_\n"; + $svn_comment.="$_ "; + } + } + close(IN); + + $svn_comment =~ s/\s\s+/ /g; + # Confirm the commit one last time... + print "*** Ready to commit, please verify:\n"; + print "\n$tmp_comment\n"; + + die ("Aborting...\n") unless &getans(); + + print "*** Running Indent...\n"; + system("indent -kr -nut *.c"); + system("rm -f *~"); + + print "*** Bumping the revision number...\n"; + # Re-write the control file + open(OUT, ">$ctrlfile") or die ("*** Error! Unable to open $ctrlfile ... aborting"); + foreach (@source) { + if (/^VERSION_BUILD/) { + $_ =~ s/\"\d+\"/\"$ver_revision\"/; + } elsif (/# \$Log\$/) { + $_ .= "$ver_comment"; + } + print OUT $_; + } + close(OUT); + + print "*** Starting the upload...\n\n"; + my $rval=system("$svn commit $dst --message '$svn_comment'"); + if ( $rval ) { + print "*** Error: Unable to complete commit. Rolling back....\n\n"; + system("$svn revert $ctrlfile"); + } + +} + +{ + usage() if (! @ARGV); + + my $opt = 'hgpf:r:b:t:'; + getopts ("$opt", \%opt) or usage(); + usage() if $opt{h}; + + usage() if ($opt{g} && $opt{p}); + usage() if ($opt{g} && $opt{f}); + usage() if ($opt{p} && $opt{f}); + usage() if ($opt{r} && $opt{b}); + usage() if ($opt{r} && $opt{t}); + usage() if ($opt{b} && $opt{t}); + + $rev = $opt{r} ; + $branch = $opt{b} ; + $tag = $opt{t} ; + $ftp = $opt{f} ; + $dst = shift; + + if ($rev ne undef) { + unless ($rev =~ /^\d+/ and $rev > 0) + { + print "*** Error: Revision number '$rev' must be an integer > 0.\n"; + exit; + } + } + + do_ftp() if $opt{f}; + do_get() if $opt{g}; + do_put() if $opt{p}; + print "*** Done!\n"; + +} + + diff -urN epona-1.4.14/bin/cp-recursive anope-1.6.4/bin/cp-recursive --- epona-1.4.14/bin/cp-recursive 1970-01-01 01:00:00.000000000 +0100 +++ anope-1.6.4/bin/cp-recursive 2005-09-08 15:56:04.000000000 +0200 @@ -0,0 +1,21 @@ +#!/bin/sh + +if [ $1 = "-t" ] ; then + shift +fi +if [ ! "$2" ] ; then + echo >&2 Usage: $0 ' ' + exit 1 +fi +if [ -d "$1" ] ; then + dir="$1" +else + dir="`echo $1 | sed 's#\(.*\)/.*#\1#'`" +fi +while [ "$2" ] ; do + shift +done +if [ ! -d $1 ] ; then + mkdir -p $1 || exit 1 +fi +/bin/tar -Ccf $dir - . | /bin/tar -Cxf $1 - diff -urN epona-1.4.14/bin/langtool anope-1.6.4/bin/langtool --- epona-1.4.14/bin/langtool 1970-01-01 01:00:00.000000000 +0100 +++ anope-1.6.4/bin/langtool 2005-09-08 15:56:04.000000000 +0200 @@ -0,0 +1,239 @@ +#!/usr/bin/perl +# +# Ribosome's all in one language tool +# 1) Compares to check for missing lines +# 2) Compares to check for equal lines +# 3) Fixes (on request) missing lines +# 4) Checks for errors in lines +# 5) Checks for long lines (>60 characters) +# + +# Check to see if we have received arguments +if (!$ARGV[0]) { +print "Usage: $0 [language file]\n"; +exit; +} + +# If yes, set $sourcefile to the language filename +$testagainst = $ARGV[0]; + +# Set $sourcefile to en_us language file +$sourcefile = "en_us.l"; + +# Number of Keys in File, Number of Equal Lines, Number of Missing Lines +# Fixed Lines (optional) and Number of Format Error Lines, Number of Long Lines +my $numberlines = 0; +my $equallines = 0; +my $missinglines = 0; +my $fixedlines = 0; +my $errorline = 0; +my $longlines = 0; + +# Array to hold the lines from the source file and explosion array for long line check + +my @sourcearray; +my @explosion; + +# Create associative arrays which will contain keys and definitions +# One for the control source and one for what is being tested against + +my %sourcehash= (); +my %testhash= (); + +# Check if Files Exist + +if (! -f $sourcefile) { +print "Critical Error: The source file does not exist or is unreadable.\nNote: This tool must be run from the language directory.\n"; +exit; +} + +if (! -f $testagainst) { +print "Critical Error: The language file does not exist or is unreadable\n"; +exit; +} +########################################### +# Function to load sourcefile into memory # +########################################### + +sub load_sourcefile { + + my $_key; # This variable will hold the key + my $_def; # This variable will hold the definition + my $line; # This variable will hold the current line + + open (SOURCEFILE, "< $sourcefile"); # Open the source file + while () { # For each line the source file + $line = $_; # $line is set to the line in the source file + + # Skip comments + if (/^#/) { # This checks for # which indicates comment + next; # If detected, the next line is skipped to + } + + # Start of a key + if (/^[A-Z]/) { # Checks to see if the line is a key + chomp($line); # Removes things that shouldn't be at the end + push (@sourcearray, $line); # Puts the line into the source array + # If a key is defined, load definition into the hash + if ($_key ne undef) { # If the key is defined + $sourcehash{$_key} = $_def; # Add the definition to the associative array + } + $_key=$line; # Set the key to the line + $_def=""; # Reset the definition + next; # Move onto the next line + } + + if ($_key ne undef) { # If the key is set already + $_def.=$line; # The definition is the current line + } + + $sourcehash{$_key} = $_def; # Load the definition into the associative array + } # End of while which reads lines + + close (SOURCEFILE); # Close the source file + +} # End of load_sourcefile function + +################################################# +# Function to load testagainst file into memory # +################################################# + +sub load_testagainst { + + my $_key; # This variable will hold the key + my $_def; # This variable will hold the definition + my $line; # This variable will hold the current line + + open (TESTAGAINSTFILE, "< $testagainst"); # Open the file containing the control lines + while () { # For each line in the file + $line = $_; # $line is set to the lines value + + + # Skip comments + if (/^#/) { # This checks for # which indicates comment + next; # If detected, the next line is skipped to + } + + # Start of a key + if (/^[A-Z]/) { # Checks to see if the line is a key + chomp($line); # Removes things that shouldn't be at the end + + + if ($_key ne undef) { # If the key is defined + $testhash{$_key} = $_def; # Add the definition to the associative array + } + $_key=$line; # Set the key to the line + $_def=""; # Reset the definition + next; # Move onto the next line + } + + if ($_key ne undef) { # If the key is set already + $_def.=$line; # The definition is the current line + } + + $testhash{$_key} = $_def; # Load the definition into the associative array + } # End of while which reads lines + close (TESTAGAINSTFILE); # Close the source file + +} + + +sub get_format { # Function to get the formatting from a string + my $fmt=""; + my $str=shift; # Get the input + + while ($str =~ m/%\w/g) { + $fmt .= $&; + } + + return $fmt; # Return the formatting +} + + +load_sourcefile; # Call function to load the source file +load_testagainst; # Call function to load the test file + +if (!grep(/^LANG_NAME/,%testhash)) { +print "Critical Error: $ARGV[0] is not a valid language file!\n"; +exit; +} + +open (LOG,"> langcheck.log"); # Open logfile for writing + +foreach $sourcearray (@sourcearray) { # For each key stored in the source array + my $_key=$_; # Store key from source array in $_key + + if ((get_format($sourcehash{$sourcearray})) ne (get_format($testhash{$sourcearray}))) { + if ($sourcearray !~ STRFTIME ) { + $errorline++; + print LOG "FORMAT: $sourcearray - (expecting '".get_format($sourcehash{$sourcearray})."' and got '".get_format($testhash{$sourcearray})."')\n"; + } } + + if ($testhash{$sourcearray} eq $sourcehash{$sourcearray} ) { + # If the definitions between the source and the test are equal + $equallines++; # Number of equal lines increases + print LOG "EQUAL: $sourcearray\n"; # Line is written to logfile + } + + if (!grep(/^$sourcearray/,%testhash)) { # If the key is found in the testhash associative array + $missinglines++; # Increase missing lines + print LOG "MISSING: $sourcearray\n"; # Line is written to logfile + } + + @explosion = split(/\n/, $testhash{$sourcearray}); + foreach $explosion (@explosion) { + $explosion =~ s/\002//g; + $explosion =~ s/\037//g; + if (length($explosion) > 61) { + print LOG "LONGLINE: $sourcearray (".substr($explosion,1,30)."...)\n"; + $longlines++; + } + } + +$numberlines++; # Increase the number of lines tested by 1 +} +close (LOG); # Close the logfile + + +######################### +# Show the test results # +######################### + +print "Calculation Results:\n"; +print "----------------------------------\n"; +print "[$numberlines] line(s) were compared\n"; +print "[$equallines] line(s) were found to equal their $sourcefile counterpart(s)\n"; +print "[$missinglines] line(s) were found to be missing\n"; +print "[$longlines] line(s) were found to be long (>60 chars)\n"; +print "[$errorline] line(s) were found to have formatting errors\n"; +print "The specific details of the test have been saved in langcheck.log\n"; + +if ($missinglines) { # If missing lines exist +print "----------------------------------\n"; +print "Missing line(s) have been detected in this test, would you like to fix the file?\n"; +print "This automatically inserts values from the control file ($sourcefile) for the missing values\n"; +print "y/N? (Default: No) "; + +my $input = ; # Ask if the file should be fixed +if ((substr($input,0,1) eq "y") || (substr($input,0,1) eq "Y")) { # If Yes... + +open (FIX, ">> $testagainst"); # Open the file and append changes + +foreach $sourcearray (@sourcearray) { # For each key stored in the source array + my $_key=$_; # Store key from source array in $_key + + if (!grep(/^$sourcearray/,%testhash)) { # If the key is not found in the testhash associative array + print FIX "$sourcearray\n$sourcehash{$sourcearray}"; # Add the line(s) to the language file + $fixedlines++; # Increase the fixed line count + } +} + +close (FIX); # Close file after fixing + +print "Fixing Compete. [$fixedlines] line(s) fixed.\n"; +exit; # And Exit! +} + # Otherwise, quit without fixing +print "Exiting. The language file has NOT been fixed.\n"; + +} diff -urN epona-1.4.14/bin/mydbgen anope-1.6.4/bin/mydbgen --- epona-1.4.14/bin/mydbgen 1970-01-01 01:00:00.000000000 +0100 +++ anope-1.6.4/bin/mydbgen 2005-09-08 15:56:04.000000000 +0200 @@ -0,0 +1,207 @@ +#!/bin/sh +# +# $Id: mydbgen 60 2004-04-18 14:07:35Z dane $ + +# Location of the .sql file with the schema +DBSQL="tables.sql" + +# Schema Version +SVER="1" + +# Local Version, defaults to 0 +LVER="0" + +TFILE="/tmp/.anopedb.$$" + +if [ "`eval echo -n 'a'`" = "-n a" ] ; then + c="\c" +else + n="-n" +fi + +# Fix for bug 10 +for try in HOME/services anope/data ../data data .. . +do + if [ -f "$try/$DBSQL" ]; then + DBFILE="$try/$DBSQL" + fi +done + +if [ ! -f "./$DBFILE" ] ; then + echo "Error: Required file $DBSQL was not found!"; + exit +fi + +echo "" +echo "This script will guide you through the process of configuring your Anope" +echo "installation to make use of MySQL support. This script must be used for both" +echo "new installs as well as for upgrading for users who have a previous version" +echo "of Anope installed" + +while [ -z "$SQLHOST" ] ; do + echo "" + echo "What is the hostname of your MySQL server?" + echo $n "-> $c" + read cc + if [ ! -z "$cc" ] ; then + SQLHOST=$cc + fi +done + +while [ -z "$SQLUSER" ] ; do + echo "" + echo "What is your MySQL username?" + echo $n "-> $c" + read cc + if [ ! -z "$cc" ] ; then + SQLUSER=$cc + fi +done + +OLD_TTY=`stty -g` + +echo "" +echo "What is your MySQL password?" +echo $n "-> $c" +stty -echo echonl +read cc +if [ ! -z "$cc" ] ; then + SQLPASS=$cc +fi +stty $OLD_TTY + +mysqlshow -h$SQLHOST -u$SQLUSER -p$SQLPASS >/dev/null 2>&1 +if test "$?" = "1" ; then + echo "Error: Unable to login, verify your login/password and hostname" + exit +fi + +while [ -z "$SQLDB" ] ; do + echo "" + echo "What is the name of the Anope SQL database?" + echo $n "-> $c" + read cc + if [ ! -z "$cc" ] ; then + SQLDB=$cc + fi +done + +MYSQLDUMP="mysqldump -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB" +MYSQLSHOW="mysqlshow -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB" +MYSQL="mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB" + +echo "" + +$MYSQLSHOW | grep -q $SQLDB +if test "$?" = "1" ; then + echo -n "Unable to find databse, creating... " + mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS -Bs -e "create database $SQLDB" >/dev/null 2>&1 + if test "$?" = "0" ; then + echo "done!" + else + echo "failed!" + FAILED="$FAILED 'database creation'" + fi +fi + +$MYSQL -Bs -e "show tables like 'anope_os_core'" | grep -q anope_os_core +if test "$?" = "1" ; then + echo -n "Unable to find Anope schema, creating... " + $MYSQL < $DBFILE + if test "$?" = "0" ; then + echo "done!" + else + echo "failed!" + FAILED="$FAILED 'schema creation'" + fi +else + # Introduced on Anope 1.6.0 -> Table anope_info + $MYSQL -Bs -e "show tables like 'anope_info'" | grep -q anope_info + if test "$?" = "1" ; then + echo -n "Unable to find Anope info table, creating... " + echo "CREATE TABLE anope_info (version int, date datetime) TYPE=MyISAM" > $TFILE + mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB < $TFILE >/dev/null 2>&1 + if test "$?" = "0" ; then + echo "done!" + + else + echo "failed!" + FAILED="$FAILED 'anope_info table'" + fi + else + LVER="$($MYSQL -sB -e "select version from anope_info")" + if test "x$LVER" = "x" ; then + LVER=0 + fi + fi + + # Introduced on Anope 1.5.14.5 -> anope_cs_info.memomax + $MYSQL -Bs -e "describe anope_cs_info memomax" 2> /dev/null | grep -q memomax + if test "$?" = "1" ; then + echo -n "Unable to find anope_cs_info.memomax, altering... " + echo "ALTER TABLE anope_cs_info ADD memomax smallint unsigned NOT NULL default 0" > $TFILE + mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB < $TFILE >/dev/null 2>&1 + if test "$?" = "0" ; then + echo "done!" + + else + echo "failed!" + FAILED="$FAILED 'anope_cs_info.ttb alter'" + fi + fi + + # Introduced on Anope 1.5.14.5 -> anope_cs_info.ttb + $MYSQL -Bs -e "describe anope_cs_info ttb" 2> /dev/null | grep -q ttb + if test "$?" = "1" ; then + echo -n "Unable to find anope_cs_info.ttb, altering... " + echo "ALTER TABLE anope_cs_info ADD ttb smallint NOT NULL default 0" > $TFILE + mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB < $TFILE >/dev/null 2>&1 + if test "$?" = "0" ; then + echo "done!" + + else + echo "failed!" + FAILED="$FAILED 'anope_cs_info.ttb alter'" + fi + fi + + +fi + +# Insert initial version number. This will have to be redesigned for 1.7 +if [ $LVER -ne $SVER ]; then +echo -n "Inserting initial version number... " +$MYSQL -Bs -e "delete from anope_info" +echo "INSERT INTO anope_info (version, date) VALUES ($SVER, now())" > $TFILE +$MYSQL < $TFILE >/dev/null 2>&1 +if test "$?" = "0" ; then + echo "done!" +else + echo "failed!" + FAILED="$FAILED 'version insert'" +fi +fi + +rm -f $TFILE +if test "x$FAILED" = "x" ; then + # Try to find out more about this installation + SQLSOCK="$(mysql_config --socket 2> /dev/null)" + SQLPORT="$(mysql_config --port 2> /dev/null)" + echo "" + echo "Your MySQL setup is complete and your Anope schema is up to date. Make" + echo "sure you configure MySQL on your services.conf file prior to launching" + echo "Anope with MySQL support. Your configuration values are:" + echo "" + echo "MysqlHost \"$SQLHOST\"" + echo "MysqlUser \"$SQLUSER\"" + echo "MysqlPass \"$SQLPASS\"" + echo "MysqlName \"$SQLDB\"" + echo "MysqlSock \"$SQLSOCK\"" + echo "MysqlPort \"$SQLPORT\"" + echo "" +else + echo "The following operations failed:" + echo "$FAILED" +fi + +exit diff -urN epona-1.4.14/botserv.c anope-1.6.4/botserv.c --- epona-1.4.14/botserv.c 2002-09-01 02:44:45.000000000 +0200 +++ anope-1.6.4/botserv.c 2005-09-08 15:56:07.000000000 +0200 @@ -1,93 +1,100 @@ /* BotServ functions * - * Epona (c) 2000-2002 PegSoft - * Contact us at epona@pegsoft.net + * (C) 2003 Anope Team + * Contact us at info@anope.org * - * This program is free but copyrighted software; see the file COPYING for - * details. + * Please read COPYING and README for furhter details. * - * Based on the original code of Services by Andy Church. + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id: botserv.c 420 2004-10-23 23:42:15Z trystan $ * */ - + /*************************************************************************/ - + #include "services.h" #include "pseudo.h" +/** + * RFC: defination of a valid nick + * nickname = ( letter / special ) *8( letter / digit / special / "-" ) + * letter = %x41-5A / %x61-7A ; A-Z / a-z + * digit = %x30-39 ; 0-9 + * special = %x5B-60 / %x7B-7D ; "[", "]", "\", "`", "_", "^", "{", "|", "}" + **/ +#define isvalidnick(c) ( isalnum(c) || ((c) >='\x5B' && (c) <='\x60') || ((c) >='\x7B' && (c) <='\x7D') || (c)=='-' ) + + /*************************************************************************/ -BotInfo *botlists[256]; /* Hash list of bots */ +BotInfo *botlists[256]; /* Hash list of bots */ int nbots = 0; /*************************************************************************/ static BotInfo *makebot(char *nick); -static UserData *get_user_data(Channel *c, User *u); -static void unassign(User *u, ChannelInfo *ci); +static UserData *get_user_data(Channel * c, User * u); +static void unassign(User * u, ChannelInfo * ci); -static void check_ban(ChannelInfo *ci, User *u, int ttbtype); -static void bot_kick(ChannelInfo *ci, User *u, int message, ...); -static void bot_raw_ban(User *requester, ChannelInfo *ci, char *nick); -static void bot_raw_kick(User *requester, ChannelInfo *ci, char *nick, char *reason); -static void bot_raw_mode(User *requester, ChannelInfo *ci, char *mode, char *nick); -static void bot_raw_unban(ChannelInfo *ci, char *nick); - -static void do_help(User *u); -static void do_bot(User *u); -static void do_botlist(User *u); -static void do_assign(User *u); -static void do_unassign(User *u); -static void do_info(User *u); -static void do_set(User *u); -static void do_kickcmd(User *u); -static void do_badwords(User *u); -static void do_say(User *u); -static void do_act(User *u); +static void check_ban(ChannelInfo * ci, User * u, int ttbtype); +static void bot_kick(ChannelInfo * ci, User * u, int message, ...); +static void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick, + char *reason); +static void bot_raw_kick(User * requester, ChannelInfo * ci, char *nick, + char *reason); +static void bot_raw_mode(User * requester, ChannelInfo * ci, char *mode, + char *nick); +static void bot_raw_unban(ChannelInfo * ci, char *nick); + +static int do_help(User * u); +static int do_bot(User * u); +static int do_botlist(User * u); +static int do_assign(User * u); +static int do_unassign(User * u); +static int do_info(User * u); +static int do_set(User * u); +static int do_kickcmd(User * u); +static int do_badwords(User * u); +static int do_say(User * u); +static int do_act(User * u); +void moduleAddBotServCmds(void); +char *normalizeBuffer(const char *s); +/*************************************************************************/ +/* *INDENT-OFF* */ +void moduleAddBotServCmds(void) { + Command *c; + c = createCommand("HELP",do_help,NULL, -1,-1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("BOTLIST", do_botlist, NULL, BOT_HELP_BOTLIST, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("ASSIGN", do_assign, NULL, BOT_HELP_ASSIGN, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("UNASSIGN", do_unassign, NULL, BOT_HELP_UNASSIGN, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("INFO", do_info, NULL, BOT_HELP_INFO, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("SET", do_set, NULL, BOT_HELP_SET,-1, BOT_SERVADMIN_HELP_SET,BOT_SERVADMIN_HELP_SET, BOT_SERVADMIN_HELP_SET); addCoreCommand(BOTSERV,c); + c = createCommand("SET DONTKICKOPS", NULL, NULL, BOT_HELP_SET_DONTKICKOPS, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("SET DONTKICKVOICES", NULL, NULL, BOT_HELP_SET_DONTKICKVOICES, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("SET FANTASY", NULL, NULL, BOT_HELP_SET_FANTASY, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("SET GREET", NULL, NULL, BOT_HELP_SET_GREET, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("SET SYMBIOSIS", NULL, NULL, BOT_HELP_SET_SYMBIOSIS, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("KICK", do_kickcmd, NULL, BOT_HELP_KICK, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("KICK BADWORDS", NULL, NULL, BOT_HELP_KICK_BADWORDS, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("KICK BOLDS", NULL, NULL, BOT_HELP_KICK_BOLDS, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("KICK CAPS", NULL, NULL, BOT_HELP_KICK_CAPS, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("KICK COLORS", NULL, NULL, BOT_HELP_KICK_COLORS, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("KICK FLOOD", NULL, NULL, BOT_HELP_KICK_FLOOD, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("KICK REPEAT", NULL, NULL, BOT_HELP_KICK_REPEAT, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("KICK REVERSES", NULL, NULL, BOT_HELP_KICK_REVERSES, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("KICK UNDERLINES", NULL, NULL, BOT_HELP_KICK_UNDERLINES, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("BADWORDS", do_badwords, NULL, BOT_HELP_BADWORDS, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("SAY", do_say, NULL, BOT_HELP_SAY, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); + c = createCommand("ACT", do_act, NULL, BOT_HELP_ACT, -1,-1,-1,-1); addCoreCommand(BOTSERV,c); -/*************************************************************************/ - -static Command cmds[] = { - { "HELP", do_help, NULL, -1, -1,-1,-1,-1 }, - { "BOTLIST", do_botlist, NULL, BOT_HELP_BOTLIST, -1,-1,-1,-1 }, - { "ASSIGN", do_assign, NULL, BOT_HELP_ASSIGN, -1,-1,-1,-1 }, - { "UNASSIGN", do_unassign, NULL, BOT_HELP_UNASSIGN, -1,-1,-1,-1 }, - { "INFO", do_info, NULL, BOT_HELP_INFO, -1,-1,-1,-1 }, - { "SET", do_set, NULL, BOT_HELP_SET, - -1, BOT_SERVADMIN_HELP_SET, - BOT_SERVADMIN_HELP_SET, BOT_SERVADMIN_HELP_SET }, - { "SET DONTKICKOPS", NULL, NULL, BOT_HELP_SET_DONTKICKOPS, -1,-1,-1,-1 }, - { "SET DONTKICKVOICES", NULL, NULL, BOT_HELP_SET_DONTKICKVOICES, -1,-1,-1,-1 }, - { "SET FANTASY", NULL, NULL, BOT_HELP_SET_FANTASY, -1,-1,-1,-1 }, - { "SET GREET", NULL, NULL, BOT_HELP_SET_GREET, -1,-1,-1,-1 }, - { "SET SYMBIOSIS", NULL, NULL, BOT_HELP_SET_SYMBIOSIS, -1,-1,-1,-1 }, - { "KICK", do_kickcmd, NULL, BOT_HELP_KICK, -1,-1,-1,-1 }, - { "KICK BADWORDS", NULL, NULL, BOT_HELP_KICK_BADWORDS, -1,-1,-1,-1 }, - { "KICK BOLDS", NULL, NULL, BOT_HELP_KICK_BOLDS, -1,-1,-1,-1 }, - { "KICK CAPS", NULL, NULL, BOT_HELP_KICK_CAPS, -1,-1,-1,-1 }, - { "KICK COLORS", NULL, NULL, BOT_HELP_KICK_COLORS, -1,-1,-1,-1 }, - { "KICK FLOOD", NULL, NULL, BOT_HELP_KICK_FLOOD, -1,-1,-1,-1 }, - { "KICK REPEAT", NULL, NULL, BOT_HELP_KICK_REPEAT, -1,-1,-1,-1 }, - { "KICK REVERSES", NULL, NULL, BOT_HELP_KICK_REVERSES, -1,-1,-1,-1 }, - { "KICK UNDERLINES", NULL, NULL, BOT_HELP_KICK_UNDERLINES, -1,-1,-1,-1 }, - { "BADWORDS", do_badwords, NULL, BOT_HELP_BADWORDS, -1,-1,-1,-1 }, - { "SAY", do_say, NULL, BOT_HELP_SAY, -1,-1,-1,-1 }, - { "ACT", do_act, NULL, BOT_HELP_ACT, -1,-1,-1,-1 }, - /* Services admins commands */ - { "BOT", do_bot, is_services_admin, -1, - -1, BOT_SERVADMIN_HELP_BOT, - BOT_SERVADMIN_HELP_BOT, BOT_SERVADMIN_HELP_BOT }, - { "SET NOBOT", NULL, NULL, -1, - -1, BOT_SERVADMIN_HELP_SET_NOBOT, - BOT_SERVADMIN_HELP_SET_NOBOT, BOT_SERVADMIN_HELP_SET_NOBOT }, - { "SET PRIVATE", NULL, NULL, -1, - -1, BOT_SERVADMIN_HELP_SET_PRIVATE, - BOT_SERVADMIN_HELP_SET_PRIVATE, BOT_SERVADMIN_HELP_SET_PRIVATE }, - - { NULL } -}; - + c = createCommand("BOT", do_bot, is_services_admin, -1,-1, BOT_SERVADMIN_HELP_BOT,BOT_SERVADMIN_HELP_BOT, BOT_SERVADMIN_HELP_BOT); addCoreCommand(BOTSERV,c); + c = createCommand("SET NOBOT", NULL, NULL, -1,-1, BOT_SERVADMIN_HELP_SET_NOBOT,BOT_SERVADMIN_HELP_SET_NOBOT, BOT_SERVADMIN_HELP_SET_NOBOT); addCoreCommand(BOTSERV,c); + c = createCommand("SET PRIVATE", NULL, NULL, -1,-1, BOT_SERVADMIN_HELP_SET_PRIVATE,BOT_SERVADMIN_HELP_SET_PRIVATE, BOT_SERVADMIN_HELP_SET_PRIVATE); addCoreCommand(BOTSERV,c); +} +/* *INDENT-ON* */ /*************************************************************************/ /*************************************************************************/ @@ -99,18 +106,17 @@ int i; BotInfo *bi; - for (i = 0; i < 256; i++) { - for (bi = botlists[i]; bi; bi = bi->next) - { - count++; - mem += sizeof(*bi); - mem += strlen(bi->nick)+1; - mem += strlen(bi->user)+1; - mem += strlen(bi->host)+1; - mem += strlen(bi->real)+1; + for (i = 0; i < 256; i++) { + for (bi = botlists[i]; bi; bi = bi->next) { + count++; + mem += sizeof(*bi); + mem += strlen(bi->nick) + 1; + mem += strlen(bi->user) + 1; + mem += strlen(bi->host) + 1; + mem += strlen(bi->real) + 1; + } } - } - + *nrec = count; *memuse = mem; } @@ -122,33 +128,33 @@ void bs_init(void) { - Command *cmd; - - cmd = lookup_cmd(cmds, "SET SYMBIOSIS"); + Command *cmd; + moduleAddBotServCmds(); + cmd = findCommand(BOTSERV, "SET SYMBIOSIS"); if (cmd) - cmd->help_param1 = s_ChanServ; + cmd->help_param1 = s_ChanServ; } /*************************************************************************/ /* Main BotServ routine. */ -void botserv(User *u, char *buf) +void botserv(User * u, char *buf) { char *cmd, *s; cmd = strtok(buf, " "); if (!cmd) { - return; + return; } else if (stricmp(cmd, "\1PING") == 0) { - if (!(s = strtok(NULL, ""))) - s = "\1"; - notice(s_BotServ, u->nick, "\1PING %s", s); + if (!(s = strtok(NULL, ""))) + s = "\1"; + notice(s_BotServ, u->nick, "\1PING %s", s); } else if (skeleton) { - notice_lang(s_BotServ, u, SERVICE_OFFLINE, s_BotServ); + notice_lang(s_BotServ, u, SERVICE_OFFLINE, s_BotServ); } else { - run_cmd(s_BotServ, u, cmds, cmd); + mod_run_cmd(s_BotServ, u, BOTSERV, cmd); } } @@ -157,374 +163,417 @@ /* Handles all messages sent to bots. (Currently only answers to pings ;) */ -void botmsgs(User *u, BotInfo *bi, char *buf) +void botmsgs(User * u, BotInfo * bi, char *buf) { - char *cmd = strtok(buf, " "); - char *s; - - if (!cmd || !u) return; - - if (!stricmp(cmd, "\1PING")) { - if (!(s = strtok(NULL, ""))) - s = "\1"; - notice(bi->nick, u->nick, "\1PING %s", s); - } + char *cmd = strtok(buf, " "); + char *s; + + if (!cmd || !u) + return; + + if (!stricmp(cmd, "\1PING")) { + if (!(s = strtok(NULL, ""))) + s = "\1"; + notice(bi->nick, u->nick, "\1PING %s", s); + } } /*************************************************************************/ -/* Handles all messages that are sent to registered channels where a +/* Handles all messages that are sent to registered channels where a * bot is on. * */ -void botchanmsgs(User *u, ChannelInfo *ci, char *buf) +void botchanmsgs(User * u, ChannelInfo * ci, char *buf) { - int c; - int16 cstatus = 0; - char *cmd; - UserData *ud; - - if (!u) return; - - /* Answer to ping if needed, without breaking the buffer. */ - if (!strnicmp(buf, "\1PING", 5)) - notice(ci->bi->nick, u->nick, buf); - - /* If it's a /me, cut the CTCP part at the beginning (not - * at the end, because one character just doesn't matter, - * but the ACTION may create strange behaviours with the - * caps or badwords kickers */ - if (!strnicmp(buf, "\1ACTION ", 8)) - buf += 8; - - /* Now we can make kicker stuff. We try to order the checks - * from the fastest one to the slowest one, since there's - * no need to process other kickers if an user is kicked before - * the last kicker check. - * - * But FIRST we check whether the user is protected in any - * way. - */ - - /* We first retrieve the user status on the channel if needed */ - if (ci->botflags & (BS_DONTKICKOPS | BS_DONTKICKVOICES)) - cstatus = chan_get_user_status(ci->c, u); - - if (buf && !check_access(u, ci, CA_NOKICK) && + int c; + int16 cstatus = 0; + char *cmd; + UserData *ud; + + if (!u) + return; + + /* Answer to ping if needed, without breaking the buffer. */ + if (!strnicmp(buf, "\1PING", 5)) + notice(ci->bi->nick, u->nick, buf); + + /* If it's a /me, cut the CTCP part at the beginning (not + * at the end, because one character just doesn't matter, + * but the ACTION may create strange behaviours with the + * caps or badwords kickers */ + if (!strnicmp(buf, "\1ACTION ", 8)) + buf += 8; + + /* Now we can make kicker stuff. We try to order the checks + * from the fastest one to the slowest one, since there's + * no need to process other kickers if an user is kicked before + * the last kicker check. + * + * But FIRST we check whether the user is protected in any + * way. + */ + + /* We first retrieve the user status on the channel if needed */ + if (ci->botflags & (BS_DONTKICKOPS | BS_DONTKICKVOICES)) + cstatus = chan_get_user_status(ci->c, u); + + if (buf && !check_access(u, ci, CA_NOKICK) && #ifdef HAS_HALFOP -# ifdef IRC_UNREAL - (!(ci->botflags & BS_DONTKICKOPS) || !(cstatus & (CUS_HALFOP | CUS_OP | CUS_OWNER | CUS_PROTECT))) +#if defined(IRC_UNREAL) || defined (IRC_VIAGRA) + (!(ci->botflags & BS_DONTKICKOPS) + || !(cstatus & (CUS_HALFOP | CUS_OP | CUS_OWNER | CUS_PROTECT))) +# elif defined (IRC_ULTIMATE3) + (!(ci->botflags & BS_DONTKICKOPS) + || !(cstatus & (CUS_HALFOP | CUS_OP | CUS_PROTECT))) # else - (!(ci->botflags & BS_DONTKICKOPS) || !(cstatus & (CUS_HALFOP | CUS_OP))) + (!(ci->botflags & BS_DONTKICKOPS) + || !(cstatus & (CUS_HALFOP | CUS_OP))) # endif #else - (!(ci->botflags & BS_DONTKICKOPS) || !(cstatus & CUS_OP)) + (!(ci->botflags & BS_DONTKICKOPS) || !(cstatus & CUS_OP)) #endif - && (!(ci->botflags & BS_DONTKICKVOICES) || !(cstatus & CUS_VOICE))) - { - /* Bolds kicker */ - if ((ci->botflags & BS_KICK_BOLDS) && strchr(buf, 2)) - { - check_ban(ci, u, TTB_BOLDS); - bot_kick(ci, u, BOT_REASON_BOLD); - return; - } - - /* Color kicker */ - if ((ci->botflags & BS_KICK_COLORS) && strchr(buf, 3)) - { - check_ban(ci, u, TTB_COLORS); - bot_kick(ci, u, BOT_REASON_COLOR); - return; - } - - /* Reverses kicker */ - if ((ci->botflags & BS_KICK_REVERSES) && strchr(buf, 22)) - { - check_ban(ci, u, TTB_REVERSES); - bot_kick(ci, u, BOT_REASON_REVERSE); - return; - } - - /* Underlines kicker */ - if ((ci->botflags & BS_KICK_UNDERLINES) && strchr(buf, 31)) - { - check_ban(ci, u, TTB_UNDERLINES); - bot_kick(ci, u, BOT_REASON_UNDERLINE); - return; - } - - /* Caps kicker */ - if ((ci->botflags & BS_KICK_CAPS) && ((c = strlen(buf)) >= ci->capsmin)) - { - int i = 0; - char *s = buf; - - do { - if (isupper(*s)) - i++; - } while (*s++); - - if (i >= ci->capsmin && i*100/c>=ci->capspercent) - { - check_ban(ci, u, TTB_CAPS); - bot_kick(ci, u, BOT_REASON_CAPS); - return; - } - } - - /* Bad words kicker */ - if (ci->botflags & BS_KICK_BADWORDS) - { - int i; - int mustkick = 0; - BadWord *bw; - - for (i = 0, bw = ci->badwords; i < ci->bwcount; i++, bw++) - { - if (!bw->in_use) - continue; - - if (bw->type == BW_ANY && stristr(buf, bw->word)) { - mustkick = 1; - } else if (bw->type == BW_SINGLE) { - int len = strlen(bw->word); - - if (!stricmp(buf, bw->word)) { - mustkick = 1; - /* two next if are quite odd isn't it? =) */ - } else if ((strchr(buf, ' ') == buf+len) && (stristr(buf, bw->word) == buf)) { - mustkick = 1; - } else if ((strrchr(buf, ' ') == buf+strlen(buf)-len-1) && (stristr(buf, bw->word) == buf+strlen(buf)-len)) { - mustkick = 1; - } else { - char *wordbuf = scalloc(len+3, 1); - - wordbuf[0] = ' '; - wordbuf[len+1] = ' '; - wordbuf[len+2] = '\0'; - memcpy(wordbuf+1, bw->word, len); - - if (stristr(buf, wordbuf)) mustkick = 1; - } - } else if (bw->type == BW_START) { - int len = strlen(bw->word); - - if (!strnicmp(buf, bw->word, len)) { - mustkick = 1; - } else { - char *wordbuf = scalloc(len+2, 1); - - memcpy(wordbuf+1, bw->word, len); - wordbuf[0] = ' '; - wordbuf[len+1] = '\0'; - - if (stristr(buf, wordbuf)) mustkick = 1; - - free(wordbuf); - } - } else if (bw->type == BW_END) { - int len = strlen(bw->word); - - if (!strnicmp(buf+strlen(buf)-len, bw->word, len)) { - mustkick = 1; - } else { - char *wordbuf = scalloc(len+2, 1); - - memcpy(wordbuf, bw->word, len); - wordbuf[len] = ' '; - wordbuf[len+1] = '\0'; - - if (stristr(buf, wordbuf)) mustkick = 1; - - free(wordbuf); - } - } - - if (mustkick) - { - check_ban(ci, u, TTB_BADWORDS); - if (BSGentleBWReason) - bot_kick(ci, u, BOT_REASON_BADWORD_GENTLE); - else - bot_kick(ci, u, BOT_REASON_BADWORD, bw->word); - return; - } - } - } - - /* Flood kicker */ - if (ci->botflags & BS_KICK_FLOOD) - { - time_t now = time(NULL); - - ud = get_user_data(ci->c, u); - if (!ud) return; - - if (now - ud->last_start > ci->floodsecs) - { - ud->last_start = time(NULL); - ud->lines = 0; - } - - ud->lines++; - if (ud->lines >= ci->floodlines) - { - check_ban(ci, u, TTB_FLOOD); - bot_kick(ci, u, BOT_REASON_FLOOD); - return; - } - } - - /* Repeat kicker */ - if (ci->botflags & BS_KICK_REPEAT) - { - ud = get_user_data(ci->c, u); - if (!ud) return; - - if (ud->lastline && stricmp(ud->lastline, buf)) { - free(ud->lastline); - ud->lastline = sstrdup(buf); - ud->times = 0; - } else { - if (!ud->lastline) - ud->lastline = sstrdup(buf); - ud->times++; - } - - if (ud->times >= ci->repeattimes) - { - check_ban(ci, u, TTB_REPEAT); - bot_kick(ci, u, BOT_REASON_REPEAT); - return; - } - } - } - - /* Fantaisist commands */ - - if (buf && (ci->botflags & BS_FANTASY) && *buf == '!' && check_access(u, ci, CA_FANTASIA)) { - cmd = strtok(buf, " "); - - if (cmd) { -#ifdef IRC_UNREAL - if (!stricmp(cmd, "!deowner")) { - if (is_founder(u, ci)) - bot_raw_mode(u, ci, "-q", u->nick); - } else + && (!(ci->botflags & BS_DONTKICKVOICES) || !(cstatus & CUS_VOICE))) { + /* Bolds kicker */ + if ((ci->botflags & BS_KICK_BOLDS) && strchr(buf, 2)) { + check_ban(ci, u, TTB_BOLDS); + bot_kick(ci, u, BOT_REASON_BOLD); + return; + } + + /* Color kicker */ + if ((ci->botflags & BS_KICK_COLORS) && strchr(buf, 3)) { + check_ban(ci, u, TTB_COLORS); + bot_kick(ci, u, BOT_REASON_COLOR); + return; + } + + /* Reverses kicker */ + if ((ci->botflags & BS_KICK_REVERSES) && strchr(buf, 22)) { + check_ban(ci, u, TTB_REVERSES); + bot_kick(ci, u, BOT_REASON_REVERSE); + return; + } + + /* Underlines kicker */ + if ((ci->botflags & BS_KICK_UNDERLINES) && strchr(buf, 31)) { + check_ban(ci, u, TTB_UNDERLINES); + bot_kick(ci, u, BOT_REASON_UNDERLINE); + return; + } + + /* Caps kicker */ + if ((ci->botflags & BS_KICK_CAPS) + && ((c = strlen(buf)) >= ci->capsmin)) { + int i = 0; + char *s = buf; + + do { + if (isupper(*s)) + i++; + } while (*s++); + + if (i >= ci->capsmin && i * 100 / c >= ci->capspercent) { + check_ban(ci, u, TTB_CAPS); + bot_kick(ci, u, BOT_REASON_CAPS); + return; + } + } + + /* Bad words kicker */ + if (ci->botflags & BS_KICK_BADWORDS) { + int i; + int mustkick = 0; + char *nbuf = NULL; + BadWord *bw; + + /* Normalize the buffer */ + nbuf = normalizeBuffer(buf); + if (nbuf) { + for (i = 0, bw = ci->badwords; i < ci->bwcount; i++, bw++) { + if (!bw->in_use) + continue; + + if (bw->type == BW_ANY && stristr(nbuf, bw->word)) { + mustkick = 1; + } else if (bw->type == BW_SINGLE) { + int len = strlen(bw->word); + + if (!stricmp(nbuf, bw->word)) { + mustkick = 1; + /* two next if are quite odd isn't it? =) */ + } else if ((strchr(nbuf, ' ') == nbuf + len) + && (stristr(nbuf, bw->word) == nbuf)) { + mustkick = 1; + } else + if ((strrchr(nbuf, ' ') == + nbuf + strlen(nbuf) - len - 1) + && (stristr(nbuf, bw->word) == + nbuf + strlen(nbuf) - len)) { + mustkick = 1; + } else { + char *wordbuf = scalloc(len + 3, 1); + + wordbuf[0] = ' '; + wordbuf[len + 1] = ' '; + wordbuf[len + 2] = '\0'; + memcpy(wordbuf + 1, bw->word, len); + + if (stristr(nbuf, wordbuf)) + mustkick = 1; + } + } else if (bw->type == BW_START) { + int len = strlen(bw->word); + + if (!strnicmp(nbuf, bw->word, len)) { + mustkick = 1; + } else { + char *wordbuf = scalloc(len + 2, 1); + + memcpy(wordbuf + 1, bw->word, len); + wordbuf[0] = ' '; + wordbuf[len + 1] = '\0'; + + if (stristr(nbuf, wordbuf)) + mustkick = 1; + + free(wordbuf); + } + } else if (bw->type == BW_END) { + int len = strlen(bw->word); + + if (!strnicmp + (nbuf + strlen(nbuf) - len, bw->word, len)) { + mustkick = 1; + } else { + char *wordbuf = scalloc(len + 2, 1); + + memcpy(wordbuf, bw->word, len); + wordbuf[len] = ' '; + wordbuf[len + 1] = '\0'; + + if (stristr(nbuf, wordbuf)) + mustkick = 1; + + free(wordbuf); + } + } + + if (mustkick) { + check_ban(ci, u, TTB_BADWORDS); + if (BSGentleBWReason) + bot_kick(ci, u, BOT_REASON_BADWORD_GENTLE); + else + bot_kick(ci, u, BOT_REASON_BADWORD, bw->word); + if (nbuf) + free(nbuf); + return; + } + } + /* Free the normalized buffer */ + if (nbuf) + free(nbuf); + } + } + + /* Flood kicker */ + if (ci->botflags & BS_KICK_FLOOD) { + time_t now = time(NULL); + + ud = get_user_data(ci->c, u); + if (!ud) + return; + + if (now - ud->last_start > ci->floodsecs) { + ud->last_start = time(NULL); + ud->lines = 0; + } + + ud->lines++; + if (ud->lines >= ci->floodlines) { + check_ban(ci, u, TTB_FLOOD); + bot_kick(ci, u, BOT_REASON_FLOOD); + return; + } + } + + /* Repeat kicker */ + if (ci->botflags & BS_KICK_REPEAT) { + ud = get_user_data(ci->c, u); + if (!ud) + return; + + if (ud->lastline && stricmp(ud->lastline, buf)) { + free(ud->lastline); + ud->lastline = sstrdup(buf); + ud->times = 0; + } else { + if (!ud->lastline) + ud->lastline = sstrdup(buf); + ud->times++; + } + + if (ud->times >= ci->repeattimes) { + check_ban(ci, u, TTB_REPEAT); + bot_kick(ci, u, BOT_REASON_REPEAT); + return; + } + } + } + + + /* return if the user is on the ignore list */ + if (get_ignore(u->nick) != NULL) { + return; + } + + /* Fantaisist commands */ + + if (buf && (ci->botflags & BS_FANTASY) && *buf == '!' + && check_access(u, ci, CA_FANTASIA)) { + cmd = strtok(buf, " "); + + if (cmd) { +#if defined(IRC_UNREAL) || defined (IRC_VIAGRA) + if (!stricmp(cmd, "!deowner")) { + if (is_founder(u, ci)) + bot_raw_mode(u, ci, "-q", u->nick); + } else #endif - if (!stricmp(cmd, "!kb")) { - char *target = strtok(NULL, " "); - char *reason = strtok(NULL, ""); - - if (!target && check_access(u, ci, CA_BANME)) { - bot_raw_ban(u, ci, u->nick); - bot_raw_kick(u, ci, u->nick, "Requested"); - } else if (target && check_access(u, ci, CA_BAN)) { - if (!stricmp(target, ci->bi->nick)) { - bot_raw_ban(u, ci, u->nick); - bot_raw_kick(u, ci, u->nick, "Oops!"); - } else { - bot_raw_ban(u, ci, target); - if (!reason) - bot_raw_kick(u, ci, target, "Requested"); - else - bot_raw_kick(u, ci, target, reason); - } - } - } else if (!stricmp(cmd, "!kick")) { - char *target = strtok(NULL, " "); - char *reason = strtok(NULL, ""); - - if (!target && check_access(u, ci, CA_KICKME)) { - bot_raw_kick(u, ci, u->nick, "Requested"); - } else if (target && check_access(u, ci, CA_KICK)) { - if (!stricmp(target, ci->bi->nick)) - bot_raw_kick(u, ci, u->nick, "Oops!"); - else if (!reason) - bot_raw_kick(u, ci, target, "Requested"); - else - bot_raw_kick(u, ci, target, reason); - } -#ifdef IRC_UNREAL - } else if (!stricmp(cmd, "!owner")) { - if (is_founder(u, ci)) - bot_raw_mode(u, ci, "+q", u->nick); + if (!stricmp(cmd, "!kb")) { + char *target = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + + if (!target && check_access(u, ci, CA_BANME)) { + bot_raw_ban(u, ci, u->nick, "Requested"); + } else if (target && check_access(u, ci, CA_BAN)) { + if (!stricmp(target, ci->bi->nick)) { + bot_raw_ban(u, ci, u->nick, "Oops!"); + } else { + if (!reason) + bot_raw_ban(u, ci, target, "Requested"); + else + bot_raw_ban(u, ci, target, reason); + } + } + } else if ((!stricmp(cmd, "!kick")) || (!stricmp(cmd, "!k"))) { + char *target = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + + if (!target && check_access(u, ci, CA_KICKME)) { + bot_raw_kick(u, ci, u->nick, "Requested"); + } else if (target && check_access(u, ci, CA_KICK)) { + if (!stricmp(target, ci->bi->nick)) + bot_raw_kick(u, ci, u->nick, "Oops!"); + else if (!reason) + bot_raw_kick(u, ci, target, "Requested"); + else + bot_raw_kick(u, ci, target, reason); + } +#if defined(IRC_UNREAL) || defined (IRC_VIAGRA) + } else if (!stricmp(cmd, "!owner")) { + if (is_founder(u, ci)) + bot_raw_mode(u, ci, "+q", u->nick); #endif - } else if (!stricmp(cmd, "!seen")) { - char *target = strtok(NULL, " "); - char buf[BUFSIZE]; - - if (target) { - User *u2; - NickAlias *na; - ChanAccess *access; - - if (!stricmp(ci->bi->nick, target)) - { - /* If we look for the bot */ - snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_BOT), u->nick); - send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, buf); - } else if (!(na = findnick(target)) || (na->status & NS_VERBOTEN)) { - /* If the nick is not registered or forbidden */ - snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_UNKNOWN), target); - send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, buf); - } else if ((u2 = nc_on_chan(ci->c, na->nc))) { - /* If the nick we're looking for is on the channel, - * there are three possibilities: it's yourself, - * it's the nick we look for, it's an alias of the - * nick we look for. - */ - if (u == u2 || (u->na && u->na->nc == na->nc)) - snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_YOU), u->nick); - else if (!stricmp(u2->nick, target)) - snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_ON_CHANNEL), u2->nick); - else - snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_ON_CHANNEL_AS), target, u2->nick); - send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, buf); - } else if ((access = get_access_entry(na->nc, ci))) { - /* User is on the access list but not present actually. - Special case: if access->last_seen is 0 it's that we - never seen the user. - */ - if (access->last_seen) { - char durastr[192]; - duration(u->na, durastr, sizeof(durastr), time(NULL) - access->last_seen); - snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_ON), target, durastr); - } else { - snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_NEVER), target); - } - send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, buf); - } else { - /* All other cases */ - snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_UNKNOWN), target); - send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, buf); - } - } - } else if (!stricmp(cmd, "!unban") && check_access(u, ci, CA_OPDEOP)) { - char *target = strtok(NULL, " "); - - if (!target) - bot_raw_unban(ci, u->nick); - else - bot_raw_unban(ci, target); - } else { - CSModeUtil *util = csmodeutils; - - do { - if (!stricmp(cmd, util->bsname)) { - char *target = strtok(NULL, " "); - - if (!target && check_access(u, ci, util->levelself)) - bot_raw_mode(u, ci, util->mode, u->nick); - else if (target && check_access(u, ci, util->level)) - bot_raw_mode(u, ci, util->mode, target); - } - } while ((++util)->name != NULL); - } - } - } + } else if (!stricmp(cmd, "!seen")) { + char *target = strtok(NULL, " "); + char buf[BUFSIZE]; + + if (target) { + User *u2; + NickAlias *na; + ChanAccess *access; + + if (!stricmp(ci->bi->nick, target)) { + /* If we look for the bot */ + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_BOT), u->nick); + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, + buf); + } else if (!(na = findnick(target)) + || (na->status & NS_VERBOTEN)) { + /* If the nick is not registered or forbidden */ + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_UNKNOWN), + target); + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, + buf); + } else if ((u2 = nc_on_chan(ci->c, na->nc))) { + /* If the nick we're looking for is on the channel, + * there are three possibilities: it's yourself, + * it's the nick we look for, it's an alias of the + * nick we look for. + */ + if (u == u2 || (u->na && u->na->nc == na->nc)) + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_YOU), + u->nick); + else if (!stricmp(u2->nick, target)) + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_ON_CHANNEL), + u2->nick); + else + snprintf(buf, sizeof(buf), + getstring(u->na, + BOT_SEEN_ON_CHANNEL_AS), + target, u2->nick); + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, + buf); + } else if ((access = get_access_entry(na->nc, ci))) { + /* User is on the access list but not present actually. + Special case: if access->last_seen is 0 it's that we + never seen the user. + */ + if (access->last_seen) { + char durastr[192]; + duration(u->na, durastr, sizeof(durastr), + time(NULL) - access->last_seen); + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_ON), target, + durastr); + } else { + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_NEVER), + target); + } + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, + buf); + } else { + /* All other cases */ + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_UNKNOWN), + target); + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, + buf); + } + } + } else if (!stricmp(cmd, "!unban") + && check_access(u, ci, CA_UNBAN)) { + char *target = strtok(NULL, " "); + + if (!target) + bot_raw_unban(ci, u->nick); + else + bot_raw_unban(ci, target); + } else { + CSModeUtil *util = csmodeutils; + + do { + if (!stricmp(cmd, util->bsname)) { + char *target = strtok(NULL, " "); + + if (!target + && check_access(u, ci, util->levelself)) + bot_raw_mode(u, ci, util->mode, u->nick); + else if (target + && check_access(u, ci, util->level)) + bot_raw_mode(u, ci, util->mode, target); + } + } while ((++util)->name != NULL); + } + } + } } /*************************************************************************/ @@ -551,31 +600,31 @@ int failed = 0; if (!(f = open_db(s_BotServ, BotDBName, "r", BOT_VERSION))) - return; + return; ver = get_file_version(f); - while (!failed && (c = getc_db(f)) != 0) { - char *s; - - if (c != 1) - fatal("Invalid format in %s %d", BotDBName, c); - - SAFE(read_string(&s, f)); - bi = makebot(s); - free(s); - SAFE(read_string(&bi->user, f)); - SAFE(read_string(&bi->host, f)); - SAFE(read_string(&bi->real, f)); - if (ver >= 10) { - SAFE(read_int16(&tmp16, f)); - bi->flags = tmp16; - } - SAFE(read_int32(&tmp32, f)); - bi->created = tmp32; - SAFE(read_int16(&tmp16, f)); - bi->chancount = tmp16; - } + while (!failed && (c = getc_db(f)) != 0) { + char *s; + + if (c != 1) + fatal("Invalid format in %s %d", BotDBName, c); + + SAFE(read_string(&s, f)); + bi = makebot(s); + free(s); + SAFE(read_string(&bi->user, f)); + SAFE(read_string(&bi->host, f)); + SAFE(read_string(&bi->real, f)); + if (ver >= 10) { + SAFE(read_int16(&tmp16, f)); + bi->flags = tmp16; + } + SAFE(read_int32(&tmp32, f)); + bi->created = tmp32; + SAFE(read_int16(&tmp16, f)); + bi->chancount = tmp16; + } close_db(f); } @@ -605,48 +654,69 @@ int i; if (!(f = open_db(s_BotServ, BotDBName, "w", BOT_VERSION))) - return; + return; - for (i = 0; i < 256; i++) { - for (bi = botlists[i]; bi; bi = bi->next) - { - SAFE(write_int8(1, f)); - SAFE(write_string(bi->nick, f)); - SAFE(write_string(bi->user, f)); - SAFE(write_string(bi->host, f)); - SAFE(write_string(bi->real, f)); - SAFE(write_int16(bi->flags, f)); - SAFE(write_int32(bi->created, f)); - SAFE(write_int16(bi->chancount, f)); - } - } + for (i = 0; i < 256; i++) { + for (bi = botlists[i]; bi; bi = bi->next) { + SAFE(write_int8(1, f)); + SAFE(write_string(bi->nick, f)); + SAFE(write_string(bi->user, f)); + SAFE(write_string(bi->host, f)); + SAFE(write_string(bi->real, f)); + SAFE(write_int16(bi->flags, f)); + SAFE(write_int32(bi->created, f)); + SAFE(write_int16(bi->chancount, f)); + } + } SAFE(write_int8(0, f)); - + close_db(f); + } #undef SAFE /*************************************************************************/ -/* Inserts a bot in the bot list. I can't be much explicit mh? */ +void save_bs_rdb_dbase(void) +{ +#ifdef USE_RDB + int i; + BotInfo *bi; + + if (!rdb_open()) + return; + + rdb_clear_table("anope_bs_core"); + + for (i = 0; i < 256; i++) { + for (bi = botlists[i]; bi; bi = bi->next) { + rdb_save_bs_core(bi); + } + } + rdb_close(); +#endif +} -static void insert_bot(BotInfo *bi) -{ +/*************************************************************************/ + +/* Inserts a bot in the bot list. I can't be much explicit mh? */ + +static void insert_bot(BotInfo * bi) +{ BotInfo *ptr, *prev; - + for (prev = NULL, ptr = botlists[tolower(*bi->nick)]; - ptr != NULL && stricmp(ptr->nick, bi->nick) < 0; - prev = ptr, ptr = ptr->next) - ; - bi->prev = prev; + ptr != NULL && stricmp(ptr->nick, bi->nick) < 0; + prev = ptr, ptr = ptr->next); + bi->prev = prev; bi->next = ptr; if (!prev) - botlists[tolower(*bi->nick)] = bi; + botlists[tolower(*bi->nick)] = bi; else - prev->next = bi; + prev->next = bi; if (ptr) - ptr->prev = bi; + ptr->prev = bi; } /*************************************************************************/ @@ -665,43 +735,44 @@ /*************************************************************************/ -static void change_bot_nick(BotInfo *bi, char *newnick) +static void change_bot_nick(BotInfo * bi, char *newnick) { - if (bi->next) - bi->next->prev = bi->prev; + if (bi->next) + bi->next->prev = bi->prev; if (bi->prev) - bi->prev->next = bi->next; + bi->prev->next = bi->next; else - botlists[tolower(*bi->nick)] = bi->next; - - if (bi->nick) free(bi->nick); - bi->nick = sstrdup(newnick); - - insert_bot(bi); + botlists[tolower(*bi->nick)] = bi->next; + + if (bi->nick) + free(bi->nick); + bi->nick = sstrdup(newnick); + + insert_bot(bi); } /*************************************************************************/ -static int delbot(BotInfo *bi) +static int delbot(BotInfo * bi) { cs_remove_bot(bi); - + if (bi->next) - bi->next->prev = bi->prev; + bi->next->prev = bi->prev; if (bi->prev) - bi->prev->next = bi->next; + bi->prev->next = bi->next; else - botlists[tolower(*bi->nick)] = bi->next; - + botlists[tolower(*bi->nick)] = bi->next; + nbots--; - + free(bi->nick); free(bi->user); free(bi->host); free(bi->real); - + free(bi); - + return 1; } @@ -710,12 +781,14 @@ BotInfo *findbot(char *nick) { BotInfo *bi; - - if (!nick || !*nick) return NULL; - + + if (!nick || !*nick) + return NULL; + for (bi = botlists[tolower(*nick)]; bi; bi = bi->next) - if (!stricmp(nick, bi->nick)) return bi; - + if (!stricmp(nick, bi->nick)) + return bi; + return NULL; } @@ -723,16 +796,14 @@ /* Unassign a bot from a channel. Assumes u, ci and ci->bi are not NULL */ -static void unassign(User *u, ChannelInfo *ci) +static void unassign(User * u, ChannelInfo * ci) { - if (ci->c && ci->c->usercount >= BSMinUsers) { -#ifdef DEBUG_JOPA - log("THALES: %s parts %s (unassign from %s)", ci->bi->nick, ci->name, u->nick); -#endif - send_cmd(ci->bi->nick, "PART %s :UNASSIGN from %s", ci->name, u->nick); - } - ci->bi->chancount--; - ci->bi = NULL; + if (ci->c && ci->c->usercount >= BSMinUsers) { + send_cmd(ci->bi->nick, "PART %s :UNASSIGN from %s", ci->name, + u->nick); + } + ci->bi->chancount--; + ci->bi = NULL; } /*************************************************************************/ @@ -740,145 +811,155 @@ /* Returns ban data associated with an user if it exists, allocates it otherwise. */ -static BanData *get_ban_data(Channel *c, User *u) +static BanData *get_ban_data(Channel * c, User * u) { - char mask[BUFSIZE]; - BanData *bd, *next; - time_t now = time(NULL); - - if (!c || !u) return NULL; - - snprintf(mask, sizeof(mask), "%s@%s", u->username, GetHost(u)); - - for (bd = c->bd; bd; bd = next) { - if (now - bd->last_use > BSKeepData) - { - if (bd->next) - bd->next->prev = bd->prev; - if (bd->prev) - bd->prev->next = bd->next; - else - c->bd = bd->next; - if (bd->mask) free(bd->mask); - next = bd->next; - free(bd); - continue; - } - if (!stricmp(bd->mask, mask)) - { - bd->last_use = now; - return bd; - } - next = bd->next; - } - - /* If we fall here it is that we haven't found the record */ - bd = scalloc(sizeof(BanData), 1); - bd->mask = sstrdup(mask); - bd->last_use = now; - - bd->prev = NULL; - bd->next = c->bd; - if (bd->next) bd->next->prev = bd; - c->bd = bd; - - return bd; + char mask[BUFSIZE]; + BanData *bd, *next; + time_t now = time(NULL); + + if (!c || !u) + return NULL; + + snprintf(mask, sizeof(mask), "%s@%s", u->username, GetHost(u)); + + for (bd = c->bd; bd; bd = next) { + if (now - bd->last_use > BSKeepData) { + if (bd->next) + bd->next->prev = bd->prev; + if (bd->prev) + bd->prev->next = bd->next; + else + c->bd = bd->next; + if (bd->mask) + free(bd->mask); + next = bd->next; + free(bd); + continue; + } + if (!stricmp(bd->mask, mask)) { + bd->last_use = now; + return bd; + } + next = bd->next; + } + + /* If we fall here it is that we haven't found the record */ + bd = scalloc(sizeof(BanData), 1); + bd->mask = sstrdup(mask); + bd->last_use = now; + + bd->prev = NULL; + bd->next = c->bd; + if (bd->next) + bd->next->prev = bd; + c->bd = bd; + + return bd; } /*************************************************************************/ -/* Returns BotServ data associated with an user on a given channel. +/* Returns BotServ data associated with an user on a given channel. * Allocates it if necessary. */ -static UserData *get_user_data(Channel *c, User *u) +static UserData *get_user_data(Channel * c, User * u) { - struct c_userlist *user; - - if (!c || !u) return NULL; - - for (user = c->users; user; user = user->next) { - if (user->user == u) { - if (user->ud) - { - time_t now = time(NULL); - - /* Checks whether data is obsolete */ - if (now - user->ud->last_use > BSKeepData) - { - if (user->ud->lastline) free(user->ud->lastline); - /* We should not free and realloc, but reset to 0 - instead. */ - memset(user->ud, 0, sizeof(UserData)); - user->ud->last_use = now; - } - - return user->ud; - } else { - user->ud = scalloc(sizeof(UserData), 1); - user->ud->last_use = time(NULL); - return user->ud; - } - } - } - - return NULL; + struct c_userlist *user; + + if (!c || !u) + return NULL; + + for (user = c->users; user; user = user->next) { + if (user->user == u) { + if (user->ud) { + time_t now = time(NULL); + + /* Checks whether data is obsolete */ + if (now - user->ud->last_use > BSKeepData) { + if (user->ud->lastline) + free(user->ud->lastline); + /* We should not free and realloc, but reset to 0 + instead. */ + memset(user->ud, 0, sizeof(UserData)); + user->ud->last_use = now; + } + + return user->ud; + } else { + user->ud = scalloc(sizeof(UserData), 1); + user->ud->last_use = time(NULL); + return user->ud; + } + } + } + + return NULL; } /*************************************************************************/ /* Makes the bot join a channel and op himself. */ -void bot_join(ChannelInfo *ci) -{ - int i; - - if (!ci || !ci->c || !ci->bi) return; - - if (BSSmartJoin) - { - /* We check for bans */ - int count = ci->c->bancount; - if (count) { - char botmask[BUFSIZE]; - char **bans = scalloc(sizeof(char *) * count, 1); - char *av[3]; - - memcpy(bans, ci->c->bans, sizeof(char *) * count); - snprintf(botmask, sizeof(botmask), "%s!%s@%s", ci->bi->nick, ci->bi->user, ci->bi->host); - - av[0] = ci->c->name; - av[1] = sstrdup("-b"); - for (i = 0; i < count; i++) { - if (match_wild_nocase(ci->c->bans[i], botmask)) { - send_cmd(ci->bi->nick, "MODE %s -b %s", ci->name, bans[i]); - av[2] = sstrdup(bans[i]); - do_cmode(ci->bi->nick, 3, av); - free(av[2]); - } - } - free(av[1]); - free(bans); - } - - /* Should we be invited? */ - if ((ci->c->mode & CMODE_i) || (ci->c->limit && ci->c->usercount >= ci->c->limit)) - send_cmd(NULL, "NOTICE @%s :%s invited %s into the channel.", ci->c->name, ci->bi->nick, ci->bi->nick); - } - +void bot_join(ChannelInfo * ci) +{ + int i; + + if (!ci || !ci->c || !ci->bi) + return; + + if (BSSmartJoin) { + /* We check for bans */ + int count = ci->c->bancount; + if (count) { + char botmask[BUFSIZE]; + char **bans = scalloc(sizeof(char *) * count, 1); + char *av[3]; + + memcpy(bans, ci->c->bans, sizeof(char *) * count); + snprintf(botmask, sizeof(botmask), "%s!%s@%s", ci->bi->nick, + ci->bi->user, ci->bi->host); + + av[0] = ci->c->name; + av[1] = sstrdup("-b"); + for (i = 0; i < count; i++) { + if (match_wild_nocase(ci->c->bans[i], botmask)) { + send_cmd(ci->bi->nick, "MODE %s -b %s", ci->name, + bans[i]); + av[2] = sstrdup(bans[i]); + do_cmode(ci->bi->nick, 3, av); + free(av[2]); + } + } + free(av[1]); + free(bans); + } + + /* Should we be invited? */ + if ((ci->c->mode & CMODE_i) + || (ci->c->limit && ci->c->usercount >= ci->c->limit)) + send_cmd(NULL, "NOTICE @%s :%s invited %s into the channel.", + ci->c->name, ci->bi->nick, ci->bi->nick); + } #ifdef IRC_BAHAMUT -# ifdef DEBUG_JOPA - log("THALES: %s joins %s (usercount = %d)", ci->bi->nick, ci->c->name, ci->c->usercount); -# endif - send_cmd(ci->bi->nick, "SJOIN %ld %s", ci->c->creation_time, ci->c->name); + send_cmd(ci->bi->nick, "SJOIN %ld %s", (long int) ci->c->creation_time, + ci->c->name); +#elif defined(IRC_HYBRID) + send_cmd(NULL, "SJOIN %ld %s + :%s", (long int) time(NULL), + ci->c->name, ci->bi->nick); #else - send_cmd(ci->bi->nick, "JOIN %s", ci->c->name); + send_cmd(ci->bi->nick, "JOIN %s", ci->c->name); #endif -#ifdef IRC_UNREAL - send_cmd(ci->bi->nick, "MODE %s +ao %s %s", ci->c->name, ci->bi->nick, ci->bi->nick); +#if defined(IRC_UNREAL) || defined (IRC_VIAGRA) + send_cmd(ci->bi->nick, "MODE %s +ao %s %s", ci->c->name, ci->bi->nick, + ci->bi->nick); +#elif defined(IRC_PTLINK) + /* PTLinks requieres an IRCop to u-line changes, so use ChanServ */ + send_cmd(s_ChanServ, "MODE %s +ao %s %s", ci->c->name, ci->bi->nick, + ci->bi->nick); #else - send_cmd(ci->bi->nick, "MODE %s +o %s", ci->c->name, ci->bi->nick); + send_cmd(ci->bi->nick, "MODE %s +o %s", ci->c->name, ci->bi->nick); #endif } @@ -887,16 +968,16 @@ /* This makes the bot rejoin all channel he is on when he gets killed * or changed. */ - -void bot_rejoin_all(BotInfo *bi) + +void bot_rejoin_all(BotInfo * bi) { - int i; - ChannelInfo *ci; - - for (i = 0; i < 256; i++) - for (ci = chanlists[i]; ci; ci = ci->next) - if (ci->bi == bi && ci->c && (ci->c->usercount >= BSMinUsers)) - bot_join(ci); + int i; + ChannelInfo *ci; + + for (i = 0; i < 256; i++) + for (ci = chanlists[i]; ci; ci = ci->next) + if (ci->bi == bi && ci->c && (ci->c->usercount >= BSMinUsers)) + bot_join(ci); } /*************************************************************************/ @@ -904,48 +985,50 @@ /* This makes a ban if the user has to have one. In every cases it increments the kick count for the user. */ -static void check_ban(ChannelInfo *ci, User *u, int ttbtype) +static void check_ban(ChannelInfo * ci, User * u, int ttbtype) { - BanData *bd = get_ban_data(ci->c, u); - - if (!bd) return; - - bd->ttb[ttbtype]++; - if (bd->ttb[ttbtype] == ci->ttb[ttbtype]) - { - char *av[3]; - char mask[BUFSIZE]; - - bd->ttb[ttbtype] = 0; - - av[0] = ci->name; - av[1] = sstrdup("+b"); - get_idealban(ci, u, mask, sizeof(mask)); - av[2] = mask; - send_cmd(ci->bi->nick, "MODE %s +b %s", av[0], av[2]); - do_cmode(ci->bi->nick, 3, av); - free(av[1]); - } + BanData *bd = get_ban_data(ci->c, u); + + if (!bd) + return; + + bd->ttb[ttbtype]++; + if (bd->ttb[ttbtype] == ci->ttb[ttbtype]) { + char *av[3]; + char mask[BUFSIZE]; + + bd->ttb[ttbtype] = 0; + + av[0] = ci->name; + av[1] = sstrdup("+b"); + get_idealban(ci, u, mask, sizeof(mask)); + av[2] = mask; + send_cmd(ci->bi->nick, "MODE %s +b %s", av[0], av[2]); + do_cmode(ci->bi->nick, 3, av); + free(av[1]); + } } /*************************************************************************/ /* This makes a bot kick an user. Works somewhat like notice_lang in fact ;) */ -static void bot_kick(ChannelInfo *ci, User *u, int message, ...) +static void bot_kick(ChannelInfo * ci, User * u, int message, ...) { va_list args; char buf[1024]; const char *fmt; char *av[3]; - if (!ci || !ci->bi || !ci->c || !u) return; - + if (!ci || !ci->bi || !ci->c || !u) + return; + va_start(args, message); fmt = getstring(u->na, message); - if (!fmt) return; + if (!fmt) + return; vsnprintf(buf, sizeof(buf), fmt, args); - + av[0] = ci->name; av[1] = u->nick; av[2] = buf; @@ -955,55 +1038,97 @@ /*************************************************************************/ -/* Makes a simple ban. */ +/* Makes a simple ban and kicks the target */ -static void bot_raw_ban(User *requester, ChannelInfo *ci, char *nick) +static void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick, + char *reason) { - char *av[3]; - char mask[BUFSIZE]; - User *u = finduser(nick); - - if (!u) - return; - - if ((ci->flags & CI_PEACE) && stricmp(requester->nick, nick) && (get_access(u, ci) >= get_access(requester, ci))) - return; - - av[0] = ci->name; - av[1] = sstrdup("+b"); - get_idealban(ci, u, mask, sizeof(mask)); - av[2] = mask; - send_cmd(ci->bi->nick, "MODE %s +b %s", av[0], av[2]); - do_cmode(ci->bi->nick, 3, av); - free(av[1]); + char *av[3]; + char mask[BUFSIZE]; + User *u = finduser(nick); + + if (!u) + return; + +#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3) + if (is_protected(u) && (requester != u)) { + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, + getstring2(NULL, PERMISSION_DENIED)); + return; + } +#endif + + if ((ci->flags & CI_PEACE) && stricmp(requester->nick, nick) + && (get_access(u, ci) >= get_access(requester, ci))) + return; + +#if defined (IRC_ULTIMATE) || defined(IRC_ULTIMATE3) || defined(IRC_UNREAL) || defined(IRC_VIAGRA) || defined(IRC_HYBRID) + if (is_excepted(ci, u) == 1) { + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, + getstring2(NULL, BOT_EXCEPT)); + return; + } +#endif + + av[0] = ci->name; + av[1] = sstrdup("+b"); + get_idealban(ci, u, mask, sizeof(mask)); + av[2] = mask; + send_cmd(ci->bi->nick, "MODE %s +b %s", av[0], av[2]); + do_cmode(ci->bi->nick, 3, av); + free(av[1]); + + av[0] = ci->name; + av[1] = nick; + + if (!reason) { + av[2] = ci->bi->nick; + } else { + if (strlen(reason) > 200) + reason[200] = '\0'; + av[2] = reason; + } + + send_cmd(ci->bi->nick, "KICK %s %s :%s", av[0], av[1], av[2]); + do_kick(ci->bi->nick, 3, av); } /*************************************************************************/ /* Makes a kick with a "dynamic" reason ;) */ -static void bot_raw_kick(User *requester, ChannelInfo *ci, char *nick, char *reason) +static void bot_raw_kick(User * requester, ChannelInfo * ci, char *nick, + char *reason) { char *av[3]; - User *u = finduser(nick); - - if (!u || !is_on_chan(ci->c, u)) - return; + User *u = finduser(nick); + + if (!u || !is_on_chan(ci->c, u)) + return; - if ((ci->flags & CI_PEACE) && stricmp(requester->nick, nick) && (get_access(u, ci) >= get_access(requester, ci))) - return; +#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3) + if (is_protected(u) && (requester != u)) { + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, + getstring2(NULL, PERMISSION_DENIED)); + return; + } +#endif + + if ((ci->flags & CI_PEACE) && stricmp(requester->nick, nick) + && (get_access(u, ci) >= get_access(requester, ci))) + return; av[0] = ci->name; av[1] = nick; - - if (!reason) { - av[2] = ci->bi->nick; - } else { - if (strlen(reason) > 200) - reason[200] = '\0'; - av[2] = reason; - } - + + if (!reason) { + av[2] = ci->bi->nick; + } else { + if (strlen(reason) > 200) + reason[200] = '\0'; + av[2] = reason; + } + send_cmd(ci->bi->nick, "KICK %s %s :%s", av[0], av[1], av[2]); do_kick(ci->bi->nick, 3, av); } @@ -1012,1064 +1137,1438 @@ /* Makes a mode operation on a channel for a nick */ -static void bot_raw_mode(User *requester, ChannelInfo *ci, char *mode, char *nick) +static void bot_raw_mode(User * requester, ChannelInfo * ci, char *mode, + char *nick) { - char *av[3]; - User *u = finduser(nick); - - if (!u || !is_on_chan(ci->c, u)) - return; - - if (*mode == '-' && (ci->flags & CI_PEACE) && stricmp(requester->nick, nick) && (get_access(u, ci) >= get_access(requester, ci))) - return; - - av[0] = ci->name; - av[1] = mode; - av[2] = nick; - - send_cmd(ci->bi->nick, "MODE %s %s %s", av[0], av[1], av[2]); - do_cmode(ci->bi->nick, 3, av); + char *av[3]; + User *u = finduser(nick); + + if (!u || !is_on_chan(ci->c, u)) + return; + +#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3) + if (is_protected(u) && *mode == '-' && (requester != u)) { + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, + getstring2(NULL, PERMISSION_DENIED)); + return; + } +#endif + + if (*mode == '-' && (ci->flags & CI_PEACE) + && stricmp(requester->nick, nick) + && (get_access(u, ci) >= get_access(requester, ci))) + return; + + av[0] = ci->name; + av[1] = mode; + av[2] = nick; + + send_cmd(ci->bi->nick, "MODE %s %s %s", av[0], av[1], av[2]); + do_cmode(ci->bi->nick, 3, av); } /*************************************************************************/ /* Removes all bans for a nick on a channel */ -static void bot_raw_unban(ChannelInfo *ci, char *nick) +static void bot_raw_unban(ChannelInfo * ci, char *nick) { #ifndef IRC_BAHAMUT - int count, i; - char *av[3], **bans; - User *u; + int count, i; + char *av[3], **bans; + User *u; #endif - - if (!ci || !ci->c || !ci->bi || !nick) return; + + if (!ci || !ci->c || !ci->bi || !nick) + return; #ifndef IRC_BAHAMUT - if (!(u = finduser(nick))) - return; + if (!(u = finduser(nick))) + return; #else - if (!finduser(nick)) - return; + if (!finduser(nick)) + return; #endif - + #ifndef IRC_BAHAMUT - av[0] = ci->name; - av[1] = sstrdup("-b"); - - count = ci->c->bancount; - bans =scalloc(sizeof(char *) * count, 1); - memcpy(bans, ci->c->bans, sizeof(char *) * count); - - for (i = 0; i < count; i++) { - if (match_usermask(bans[i], u)) { - send_cmd(ci->bi->nick, "MODE %s -b %s", ci->name, bans[i]); - av[2] = bans[i]; - do_cmode(ci->bi->nick, 3, av); - } - } - free(bans); - free(av[1]); + av[0] = ci->name; + av[1] = sstrdup("-b"); + + count = ci->c->bancount; + bans = scalloc(sizeof(char *) * count, 1); + memcpy(bans, ci->c->bans, sizeof(char *) * count); + + for (i = 0; i < count; i++) { + if (match_usermask(bans[i], u)) { + send_cmd(ci->bi->nick, "MODE %s -b %s", ci->name, bans[i]); + av[2] = bans[i]; + do_cmode(ci->bi->nick, 3, av); + } + } + free(bans); + free(av[1]); #else - send_cmd(ServerName, "SVSMODE %s -b %s", ci->name, nick); + send_cmd(ServerName, "SVSMODE %s -b %s", ci->name, nick); #endif } /*************************************************************************/ /*************************************************************************/ -static void do_help(User *u) +static int do_help(User * u) { char *cmd = strtok(NULL, ""); if (!cmd) { - notice_help(s_BotServ, u, BOT_HELP, BSMinUsers); - if (is_services_oper(u)) - notice_help(s_BotServ, u, BOT_SERVADMIN_HELP); + notice_help(s_BotServ, u, BOT_HELP, BSMinUsers); + if (is_services_oper(u)) + notice_help(s_BotServ, u, BOT_SERVADMIN_HELP); + moduleDisplayHelp(4, u); } else { - help_cmd(s_BotServ, u, cmds, cmd); + mod_help_cmd(s_BotServ, u, BOTSERV, cmd); } + return MOD_CONT; } /*************************************************************************/ -static void do_bot(User *u) +static int do_bot(User * u) { BotInfo *bi; char *cmd = strtok(NULL, " "); - + char *ch = NULL; + if (!cmd) - syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); - else if (!stricmp(cmd, "ADD")) - { - char *nick = strtok(NULL, " "); - char *user = strtok(NULL, " "); - char *host = strtok(NULL, " "); - char *real = strtok(NULL, ""); - - if (!nick || !user || !host || !real) - syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); - else if (readonly) - notice_lang(s_BotServ, u, BOT_BOT_READONLY); - else if (findbot(nick)) - notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); - else { - User *u2; - NickAlias *na; - - /* We check whether the nick is registered, and drop it if so. */ - if ((na = findnick(nick))) { - if (NSSecureAdmins && nick_is_services_admin(na->nc) && !is_services_root(u)) { - notice_lang(s_BotServ, u, PERMISSION_DENIED); - return; - } - delnick(na); - } - - bi = makebot(nick); - if (!bi) { - notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); - return; - } - - bi->user = sstrdup(user); - bi->host = sstrdup(host); - bi->real = sstrdup(real); - bi->created = time(NULL); - bi->chancount = 0; - - /* We check whether user with this nick is online, and kill it if so */ - if ((u2 = finduser(nick))) - kill_user(s_BotServ, u2->nick, "This nick is now used by Services"); - - /* We make the bot online, ready to serve */ -#if defined(IRC_UNREAL) - NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+qS", 1); -#elif defined(IRC_ULTIMATE) - NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+pS", 1); + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + else if (!stricmp(cmd, "ADD")) { + char *nick = strtok(NULL, " "); + char *user = strtok(NULL, " "); + char *host = strtok(NULL, " "); + char *real = strtok(NULL, ""); + + if (!nick || !user || !host || !real) + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + else if (readonly) + notice_lang(s_BotServ, u, BOT_BOT_READONLY); + else if (findbot(nick)) + notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); + else { + User *u2; + NickAlias *na; + + /** + * Check the nick is valid re RFC 2812 + **/ + if (isdigit(nick[0]) || nick[0] == '-') { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + for (ch = nick; *ch && (ch - nick) < NICKMAX; ch++) { + if (!isvalidnick(*ch)) { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + } + if (!isValidHost(host, 3)) { + notice_lang(s_BotServ, u, BOT_BAD_HOST); + return MOD_CONT; + } + for (ch = user; *ch && (ch - user) < USERMAX; ch++) { + if (!isalnum(*ch)) { + notice_lang(s_BotServ, u, BOT_BAD_IDENT); + return MOD_CONT; + } + } + + /** + * Check the host is valid re RFC 2812 + **/ + + /* Check whether it's a services client's nick and return if so - Certus */ + + if ((s_NickServ && (stricmp(nick, s_NickServ) == 0)) + || (s_NickServAlias && !stricmp(nick, s_NickServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_ChanServ && (stricmp(nick, s_ChanServ) == 0)) + || (s_ChanServAlias + && !stricmp(nick, s_ChanServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_MemoServ && (stricmp(nick, s_MemoServ) == 0)) + || (s_MemoServAlias + && !stricmp(nick, s_MemoServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_BotServ && (stricmp(nick, s_BotServ) == 0)) + || (s_BotServAlias + && !stricmp(nick, s_BotServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_HelpServ && (stricmp(nick, s_HelpServ) == 0)) + || (s_HelpServAlias + && !stricmp(nick, s_HelpServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_OperServ && (stricmp(nick, s_OperServ) == 0)) + || (s_OperServAlias + && !stricmp(nick, s_OperServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else + if ((s_GlobalNoticer + && (stricmp(nick, s_GlobalNoticer) == 0)) + || (s_GlobalNoticerAlias + && !stricmp(nick, s_GlobalNoticerAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_HostServ && (stricmp(nick, s_HostServ) == 0)) + || (s_HostServAlias + && !stricmp(nick, s_HostServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } + + /* We check whether the nick is registered, and drop it if so. */ + if ((na = findnick(nick))) { + if (NSSecureAdmins && nick_is_services_admin(na->nc) + && !is_services_root(u)) { + notice_lang(s_BotServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + delnick(na); + } + + bi = makebot(nick); + if (!bi) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } + + bi->user = sstrdup(user); + bi->host = sstrdup(host); + bi->real = sstrdup(real); + bi->created = time(NULL); + bi->chancount = 0; + + /* We check whether user with this nick is online, and kill it if so */ + if ((u2 = finduser(nick))) + kill_user(s_BotServ, u2->nick, + "This nick is now used by Services"); + + /* We make the bot online, ready to serve */ +#if defined(IRC_UNREAL) || defined (IRC_VIAGRA) + NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+qS", 1); +#elif defined(IRC_ULTIMATE) || defined (IRC_ULTIMATE3) + NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+pS", 1); #else - NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+", 1); + NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+", 1); #endif - - notice_lang(s_BotServ, u, BOT_BOT_ADDED, bi->nick, bi->user, bi->host, bi->real); - } - } - else if (!stricmp(cmd, "CHANGE")) - { - char *oldnick = strtok(NULL, " "); - char *nick = strtok(NULL, " "); - char *user = strtok(NULL, " "); - char *host = strtok(NULL, " "); - char *real = strtok(NULL, ""); - - if (!oldnick || !nick) - syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); - else if (readonly) - notice_lang(s_BotServ, u, BOT_BOT_READONLY); - else if (!(bi = findbot(oldnick))) - notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick); - else - { - User *u2; - NickAlias *na; - - /* Checks whether there *are* changes. - * Case sensitive because we may want to change just the case. - * And we must finally check that the nick is not already - * taken by another bot. - */ - if (!strcmp(bi->nick, nick) - && ((user) ? !strcmp(bi->user, user) : 1) - && ((host) ? !strcmp(bi->host, host) : 1) - && ((real) ? !strcmp(bi->real, real) : 1)) - { - notice_lang(s_BotServ, u, BOT_BOT_ANY_CHANGES); - return; - } - - if (stricmp(bi->nick, nick) && findbot(nick)) - { - notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); - return; - } - - if (stricmp(bi->nick, nick)) - { - /* The new nick is really different, so we remove the Q line for - the old nick. */ - send_cmd(NULL, "UNSQLINE %s", bi->nick); - - /* We check whether the nick is registered, and drop it if so */ - if ((na = findnick(nick))) - delnick(na); - - /* We check whether user with this nick is online, and kill it if so */ - if ((u2 = finduser(nick))) - kill_user(s_BotServ, u2->nick, "This nick is now used by Services"); - } - - if (strcmp(nick, bi->nick)) - change_bot_nick(bi, nick); - - if (user && strcmp(user, bi->user)) - { - free(bi->user); - bi->user = sstrdup(user); - } - if (host && strcmp(host, bi->host)) - { - free(bi->host); - bi->host = sstrdup(host); - } - if (real && strcmp(real, bi->real)) - { - free(bi->real); - bi->real = sstrdup(real); - } - - /* If only the nick changes, we just make the bot change his nick, - else we must make it quit and rejoin. */ - if (!user) - send_cmd(oldnick, "NICK %s", bi->nick); - else { - send_cmd(oldnick, "QUIT :Quit: Be right back"); + + notice_lang(s_BotServ, u, BOT_BOT_ADDED, bi->nick, bi->user, + bi->host, bi->real); + } + } else if (!stricmp(cmd, "CHANGE")) { + char *oldnick = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + char *user = strtok(NULL, " "); + char *host = strtok(NULL, " "); + char *real = strtok(NULL, ""); + + if (!oldnick || !nick) + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + else if (readonly) + notice_lang(s_BotServ, u, BOT_BOT_READONLY); + else if (!(bi = findbot(oldnick))) + notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick); + else { + User *u2; + NickAlias *na; + + /* Checks whether there *are* changes. + * Case sensitive because we may want to change just the case. + * And we must finally check that the nick is not already + * taken by another bot. + */ + if (!strcmp(bi->nick, nick) + && ((user) ? !strcmp(bi->user, user) : 1) + && ((host) ? !strcmp(bi->host, host) : 1) + && ((real) ? !strcmp(bi->real, real) : 1)) { + notice_lang(s_BotServ, u, BOT_BOT_ANY_CHANGES); + return MOD_CONT; + } + + /* Check whether it's a services client's nick and return if so - Certus */ + if ((s_NickServ && !stricmp(nick, s_NickServ)) + || (s_NickServAlias && !stricmp(nick, s_NickServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_ChanServ && !stricmp(nick, s_ChanServ)) + || (s_ChanServAlias + && !stricmp(nick, s_ChanServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_MemoServ && !stricmp(nick, s_MemoServ)) + || (s_MemoServAlias + && !stricmp(nick, s_MemoServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_BotServ && !stricmp(nick, s_BotServ)) + || (s_BotServAlias + && !stricmp(nick, s_BotServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_HelpServ && !stricmp(nick, s_HelpServ)) + || (s_HelpServAlias + && !stricmp(nick, s_HelpServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_OperServ && !stricmp(nick, s_OperServ)) + || (s_OperServAlias + && !stricmp(nick, s_OperServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_GlobalNoticer && !stricmp(nick, s_GlobalNoticer)) + || (s_GlobalNoticerAlias + && !stricmp(nick, s_GlobalNoticerAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } else if ((s_HostServ && !stricmp(nick, s_HostServ)) + || (s_HostServAlias + && !stricmp(nick, s_HostServAlias))) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } + + /** + * Check the nick is valid re RFC 2812 + **/ + if (isdigit(nick[0]) || nick[0] == '-') { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + for (ch = nick; *ch && (ch - nick) < NICKMAX; ch++) { + if (!isvalidnick(*ch)) { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + } + if (!isValidHost(host, 3)) { + notice_lang(s_BotServ, u, BOT_BAD_HOST); + return MOD_CONT; + } + + for (ch = user; *ch && (ch - user) < USERMAX; ch++) { + if (!isalnum(*ch)) { + notice_lang(s_BotServ, u, BOT_BAD_IDENT); + return MOD_CONT; + } + } + + if (stricmp(bi->nick, nick) && findbot(nick)) { + notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); + return MOD_CONT; + } + + if (stricmp(bi->nick, nick)) { + /* The new nick is really different, so we remove the Q line for + the old nick. */ +#ifndef IRC_HYBRID + send_cmd(NULL, "UNSQLINE %s", bi->nick); +#endif + + /* We check whether the nick is registered, and drop it if so */ + if ((na = findnick(nick))) + delnick(na); + + /* We check whether user with this nick is online, and kill it if so */ + if ((u2 = finduser(nick))) + kill_user(s_BotServ, u2->nick, + "This nick is now used by Services"); + } + + if (strcmp(nick, bi->nick)) + change_bot_nick(bi, nick); + + if (user && strcmp(user, bi->user)) { + free(bi->user); + bi->user = sstrdup(user); + } + if (host && strcmp(host, bi->host)) { + free(bi->host); + bi->host = sstrdup(host); + } + if (real && strcmp(real, bi->real)) { + free(bi->real); + bi->real = sstrdup(real); + } + + /* If only the nick changes, we just make the bot change his nick, + else we must make it quit and rejoin. */ + if (!user) + send_cmd(oldnick, "NICK %s", bi->nick); + else { + send_cmd(oldnick, "QUIT :Quit: Be right back"); #if defined(IRC_UNREAL) - NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+qS", 1); + NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+qS", 1); #elif defined(IRC_ULTIMATE) - NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+pS", 1); + NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+pS", 1); #else - NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+", 1); + NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+", 1); #endif - bot_rejoin_all(bi); - } - - notice_lang(s_BotServ, u, BOT_BOT_CHANGED, oldnick, bi->nick, bi->user, bi->host, bi->real); - } - } - else if (!stricmp(cmd, "DEL")) - { - char *nick = strtok(NULL, " "); - - if (!nick) - syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); - else if (readonly) - notice_lang(s_BotServ, u, BOT_BOT_READONLY); - else if (!(bi = findbot(nick))) - notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); - else - { - send_cmd(bi->nick, "QUIT :Quit: Help! I'm being deleted by %s!", u->nick); - send_cmd(NULL, "UNSQLINE %s", bi->nick); - delbot(bi); - - notice_lang(s_BotServ, u, BOT_BOT_DELETED, nick); - } - } - else if (!stricmp(cmd, "LIST")) do_botlist(u); - else syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); -} - -/*************************************************************************/ - -static void do_botlist(User *u) -{ - int i, count = 0; - BotInfo *bi; - - if (!nbots) { - notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY); - return; - } - - for (i = 0; i < 256; i++) { - for (bi = botlists[i]; bi; bi = bi->next) { - if (!(bi->flags & BI_PRIVATE)) { - if (!count) - notice_lang(s_BotServ, u, BOT_BOTLIST_HEADER); - count++; - notice_user(s_BotServ, u, " %-15s (%s@%s)", bi->nick, bi->user, bi->host); - } - } - } - - if (is_oper(u) && count < nbots) { - notice_lang(s_BotServ, u, BOT_BOTLIST_PRIVATE_HEADER); - - for (i = 0; i < 256; i++) { - for (bi = botlists[i]; bi; bi = bi->next) { - if (bi->flags & BI_PRIVATE) { - notice_user(s_BotServ, u, " %-15s (%s@%s)", bi->nick, bi->user, bi->host); - count++; - } - } - } - } - - if (!count) - notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY); - else - notice_lang(s_BotServ, u, BOT_BOTLIST_FOOTER, count); -} - -/*************************************************************************/ - -static void do_assign(User *u) -{ - char *chan = strtok(NULL, " "); - char *nick = strtok(NULL, " "); - BotInfo *bi; - ChannelInfo *ci; - - if (readonly) - notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); - else if (!chan || !nick) - syntax_error(s_BotServ, u, "ASSIGN", BOT_ASSIGN_SYNTAX); - else if (!(bi = findbot(nick))) - notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); - else if (bi->flags & BI_PRIVATE && !is_oper(u)) - notice_lang(s_BotServ, u, PERMISSION_DENIED); - else if (!(ci = cs_findchan(chan))) - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); - else if (ci->flags & CI_VERBOTEN) - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); - else if (ci->bi) - notice_lang(s_BotServ, u, BOT_ASSIGN_ALREADY, chan); - else if ((ci->botflags & BS_NOBOT) || (!check_access(u, ci, CA_ASSIGN) && !is_services_admin(u))) - notice_lang(s_BotServ, u, PERMISSION_DENIED); - else - { - ci->bi = bi; - bi->chancount++; - if (ci->c && ci->c->usercount >= BSMinUsers) { -#ifdef DEBUG_JOPA - log("THALES: %s has been assigned to %s", bi->nick, ci->name); + bot_rejoin_all(bi); + } + + notice_lang(s_BotServ, u, BOT_BOT_CHANGED, oldnick, bi->nick, + bi->user, bi->host, bi->real); + } + } else if (!stricmp(cmd, "DEL")) { + char *nick = strtok(NULL, " "); + + if (!nick) + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + else if (readonly) + notice_lang(s_BotServ, u, BOT_BOT_READONLY); + else if (!(bi = findbot(nick))) + notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); + else { + send_cmd(bi->nick, + "QUIT :Quit: Help! I'm being deleted by %s!", + u->nick); +#ifndef IRC_HYBRID + send_cmd(NULL, "UNSQLINE %s", bi->nick); #endif - bot_join(ci); - } - notice_lang(s_BotServ, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name); - } + delbot(bi); + + notice_lang(s_BotServ, u, BOT_BOT_DELETED, nick); + } + } else if (!stricmp(cmd, "LIST")) + do_botlist(u); + else + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + + return MOD_CONT; +} + +/*************************************************************************/ + +static int do_botlist(User * u) +{ + int i, count = 0; + BotInfo *bi; + + if (!nbots) { + notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY); + return MOD_CONT; + } + + for (i = 0; i < 256; i++) { + for (bi = botlists[i]; bi; bi = bi->next) { + if (!(bi->flags & BI_PRIVATE)) { + if (!count) + notice_lang(s_BotServ, u, BOT_BOTLIST_HEADER); + count++; + notice_user(s_BotServ, u, " %-15s (%s@%s)", bi->nick, + bi->user, bi->host); + } + } + } + + if (is_oper(u) && count < nbots) { + notice_lang(s_BotServ, u, BOT_BOTLIST_PRIVATE_HEADER); + + for (i = 0; i < 256; i++) { + for (bi = botlists[i]; bi; bi = bi->next) { + if (bi->flags & BI_PRIVATE) { + notice_user(s_BotServ, u, " %-15s (%s@%s)", + bi->nick, bi->user, bi->host); + count++; + } + } + } + } + + if (!count) + notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY); + else + notice_lang(s_BotServ, u, BOT_BOTLIST_FOOTER, count); + return MOD_CONT; +} + +/*************************************************************************/ + +static int do_assign(User * u) +{ + char *chan = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + BotInfo *bi; + ChannelInfo *ci; + + if (readonly) + notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); + else if (!chan || !nick) + syntax_error(s_BotServ, u, "ASSIGN", BOT_ASSIGN_SYNTAX); + else if (!(bi = findbot(nick))) + notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); + else if (bi->flags & BI_PRIVATE && !is_oper(u)) + notice_lang(s_BotServ, u, PERMISSION_DENIED); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + else if (ci->flags & CI_VERBOTEN) + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if ((ci->bi) && (stricmp(ci->bi->nick, nick) == 0)) + notice_lang(s_BotServ, u, BOT_ASSIGN_ALREADY, ci->bi->nick, chan); + else if ((ci->botflags & BS_NOBOT) + || (!check_access(u, ci, CA_ASSIGN) && !is_services_admin(u))) + notice_lang(s_BotServ, u, PERMISSION_DENIED); + else { + if (ci->bi) + unassign(u, ci); + ci->bi = bi; + bi->chancount++; + if (ci->c && ci->c->usercount >= BSMinUsers) { + bot_join(ci); + } + notice_lang(s_BotServ, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name); + } + return MOD_CONT; } /*************************************************************************/ -static void do_unassign(User *u) +static int do_unassign(User * u) { - char *chan = strtok(NULL, " "); - ChannelInfo *ci; - - if (readonly) - notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); - else if (!chan) - syntax_error(s_BotServ, u, "UNASSIGN", BOT_UNASSIGN_SYNTAX); - else if (!(ci = cs_findchan(chan))) - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + char *chan = strtok(NULL, " "); + ChannelInfo *ci; + + if (readonly) + notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); + else if (!chan) + syntax_error(s_BotServ, u, "UNASSIGN", BOT_UNASSIGN_SYNTAX); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); else if (ci->flags & CI_VERBOTEN) - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); - else if (!is_services_admin(u) && !check_access(u, ci, CA_ASSIGN)) - notice_lang(s_BotServ, u, ACCESS_DENIED); - else - { - if (ci->bi) - unassign(u, ci); - notice_lang(s_BotServ, u, BOT_UNASSIGN_UNASSIGNED, ci->name); - } -} - -/*************************************************************************/ - -static void send_bot_channels(User *u, BotInfo *bi) -{ - int i; - ChannelInfo *ci; - char buf[307], *end; - - *buf = 0; - end = buf; - - for (i = 0; i < 256; i++) { - for (ci = chanlists[i]; ci; ci = ci->next) { - if (ci->bi == bi) { - if (strlen(buf) + strlen(ci->name) > 300) { - notice_user(s_BotServ, u, buf); - *buf = 0; - end = buf; - } - end += snprintf(end, sizeof(buf)-(end-buf), " %s ", ci->name); - } - } - } - - if (*buf) - notice_user(s_BotServ, u, buf); -} - -static void do_info(User *u) -{ - BotInfo *bi; - ChannelInfo *ci; - char *query = strtok(NULL, " "); - - int need_comma = 0, is_servadmin = is_services_admin(u); - char buf[BUFSIZE], *end; - const char *commastr = getstring(u->na, COMMA_SPACE); - - if (!query) - syntax_error(s_BotServ, u, "INFO", BOT_INFO_SYNTAX); - else if ((bi = findbot(query))) { - char buf[BUFSIZE]; - struct tm *tm; - - notice_lang(s_BotServ, u, BOT_INFO_BOT_HEADER, bi->nick); - notice_lang(s_BotServ, u, BOT_INFO_BOT_MASK, bi->user, bi->host); - notice_lang(s_BotServ, u, BOT_INFO_BOT_REALNAME, bi->real); - tm = localtime(&bi->created); - strftime_lang(buf, sizeof(buf), u, STRFTIME_DATE_TIME_FORMAT, tm); - notice_lang(s_BotServ, u, BOT_INFO_BOT_CREATED, buf); - notice_lang(s_BotServ, u, BOT_INFO_BOT_OPTIONS, getstring(u->na, (bi->flags & BI_PRIVATE) ? BOT_INFO_OPT_PRIVATE : BOT_INFO_OPT_NONE)); - notice_lang(s_BotServ, u, BOT_INFO_BOT_USAGE, bi->chancount); - - if (is_services_admin(u)) - send_bot_channels(u, bi); - } else if ((ci = cs_findchan(query))) { - if (!is_servadmin && !is_founder(u, ci)) { - notice_lang(s_BotServ, u, PERMISSION_DENIED); - return; - } - - notice_lang(s_BotServ, u, BOT_INFO_CHAN_HEADER, ci->name); - if (ci->bi) notice_lang(s_BotServ, u, BOT_INFO_CHAN_BOT, ci->bi->nick); - else notice_lang(s_BotServ, u, BOT_INFO_CHAN_BOT_NONE); - - if (ci->botflags & BS_KICK_BADWORDS) - { - if (ci->ttb[TTB_BADWORDS]) notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BADWORDS_BAN, getstring(u->na, BOT_INFO_ACTIVE), ci->ttb[TTB_BADWORDS]); - else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BADWORDS, getstring(u->na, BOT_INFO_ACTIVE)); - } else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BADWORDS, getstring(u->na, BOT_INFO_INACTIVE)); - if (ci->botflags & BS_KICK_BOLDS) - { - if (ci->ttb[TTB_BOLDS]) notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BOLDS_BAN, getstring(u->na, BOT_INFO_ACTIVE), ci->ttb[TTB_BOLDS]); - else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BOLDS, getstring(u->na, BOT_INFO_ACTIVE)); - } else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BOLDS, getstring(u->na, BOT_INFO_INACTIVE)); - if (ci->botflags & BS_KICK_CAPS) - { - if (ci->ttb[TTB_CAPS]) notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_CAPS_BAN, getstring(u->na, BOT_INFO_ACTIVE), ci->ttb[TTB_CAPS], ci->capsmin, ci->capspercent); - else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_CAPS_ON, getstring(u->na, BOT_INFO_ACTIVE), ci->capsmin, ci->capspercent); - } else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_CAPS_OFF, getstring(u->na, BOT_INFO_INACTIVE)); - if (ci->botflags & BS_KICK_COLORS) - { - if (ci->ttb[TTB_COLORS]) notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_COLORS_BAN, getstring(u->na, BOT_INFO_ACTIVE), ci->ttb[TTB_COLORS]); - else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_COLORS, getstring(u->na, BOT_INFO_ACTIVE)); - } else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_COLORS, getstring(u->na, BOT_INFO_INACTIVE)); - if (ci->botflags & BS_KICK_FLOOD) - { - if (ci->ttb[TTB_FLOOD]) notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_FLOOD_BAN, getstring(u->na, BOT_INFO_ACTIVE), ci->ttb[TTB_FLOOD], ci->floodlines, ci->floodsecs); - else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_FLOOD_ON, getstring(u->na, BOT_INFO_ACTIVE), ci->floodlines, ci->floodsecs); - } else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_FLOOD_OFF, getstring(u->na, BOT_INFO_INACTIVE)); - if (ci->botflags & BS_KICK_REPEAT) - { - if (ci->ttb[TTB_REPEAT]) notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REPEAT_BAN, getstring(u->na, BOT_INFO_ACTIVE), ci->ttb[TTB_REPEAT], ci->repeattimes); - else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REPEAT_ON, getstring(u->na, BOT_INFO_ACTIVE), ci->repeattimes); - } else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REPEAT_OFF, getstring(u->na, BOT_INFO_INACTIVE)); - if (ci->botflags & BS_KICK_REVERSES) - { - if (ci->ttb[TTB_REVERSES]) notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REVERSES_BAN, getstring(u->na, BOT_INFO_ACTIVE), ci->ttb[TTB_REVERSES]); - else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REVERSES, getstring(u->na, BOT_INFO_ACTIVE)); - } else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REVERSES, getstring(u->na, BOT_INFO_INACTIVE)); - if (ci->botflags & BS_KICK_UNDERLINES) - { - if (ci->ttb[TTB_UNDERLINES]) notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_UNDERLINES_BAN, getstring(u->na, BOT_INFO_ACTIVE), ci->ttb[TTB_UNDERLINES]); - else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_UNDERLINES, getstring(u->na, BOT_INFO_ACTIVE)); - } else notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_UNDERLINES, getstring(u->na, BOT_INFO_INACTIVE)); - - end = buf; - *end = 0; - if (ci->botflags & BS_DONTKICKOPS) { - end += snprintf(end, sizeof(buf)-(end-buf), "%s", - getstring(u->na, BOT_INFO_OPT_DONTKICKOPS)); - need_comma = 1; - } - if (ci->botflags & BS_DONTKICKVOICES) { - end += snprintf(end, sizeof(buf)-(end-buf), "%s%s", - need_comma ? commastr : "", - getstring(u->na, BOT_INFO_OPT_DONTKICKVOICES)); - need_comma = 1; - } - if (ci->botflags & BS_FANTASY) { - end += snprintf(end, sizeof(buf)-(end-buf), "%s%s", - need_comma ? commastr : "", - getstring(u->na, BOT_INFO_OPT_FANTASY)); - need_comma = 1; - } - if (ci->botflags & BS_GREET) { - end += snprintf(end, sizeof(buf)-(end-buf), "%s%s", - need_comma ? commastr : "", - getstring(u->na, BOT_INFO_OPT_GREET)); - need_comma = 1; - } - if (ci->botflags & BS_NOBOT) { - end += snprintf(end, sizeof(buf)-(end-buf), "%s%s", - need_comma ? commastr : "", - getstring(u->na, BOT_INFO_OPT_NOBOT)); - need_comma = 1; - } - if (ci->botflags & BS_SYMBIOSIS) { - end += snprintf(end, sizeof(buf)-(end-buf), "%s%s", - need_comma ? commastr : "", - getstring(u->na, BOT_INFO_OPT_SYMBIOSIS)); - need_comma = 1; - } - notice_lang(s_BotServ, u, BOT_INFO_CHAN_OPTIONS, - *buf ? buf : getstring(u->na, BOT_INFO_OPT_NONE)); - - } else notice_lang(s_BotServ, u, BOT_INFO_NOT_FOUND, query); -} - -/*************************************************************************/ - -static void do_set(User *u) -{ - char *chan = strtok(NULL, " "); - char *option = strtok(NULL, " "); - char *value = strtok(NULL, " "); - int is_servadmin = is_services_admin(u); - - ChannelInfo *ci; - - if (readonly) - notice_lang(s_BotServ, u, BOT_SET_DISABLED); - else if (!chan || !option || !value) - syntax_error(s_BotServ, u, "SET", BOT_SET_SYNTAX); - else if (is_servadmin && !stricmp(option, "PRIVATE")) { - BotInfo *bi; - - if ((bi = findbot(chan))) { - if (!stricmp(value, "ON")) { - bi->flags |= BI_PRIVATE; - notice_lang(s_BotServ, u, BOT_SET_PRIVATE_ON, bi->nick); - } else if (!stricmp(value, "OFF")) { - bi->flags &= ~BI_PRIVATE; - notice_lang(s_BotServ, u, BOT_SET_PRIVATE_OFF, bi->nick); - } else { - syntax_error(s_BotServ, u, "SET PRIVATE", BOT_SET_PRIVATE_SYNTAX); - } - } else { - notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, chan); - } - return; - } else if (!(ci = cs_findchan(chan))) - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if (!is_services_admin(u) && !check_access(u, ci, CA_ASSIGN)) + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + if (ci->bi) + unassign(u, ci); + notice_lang(s_BotServ, u, BOT_UNASSIGN_UNASSIGNED, ci->name); + } + return MOD_CONT; +} + +/*************************************************************************/ + +static void send_bot_channels(User * u, BotInfo * bi) +{ + int i; + ChannelInfo *ci; + char buf[307], *end; + + *buf = 0; + end = buf; + + for (i = 0; i < 256; i++) { + for (ci = chanlists[i]; ci; ci = ci->next) { + if (ci->bi == bi) { + if (strlen(buf) + strlen(ci->name) > 300) { + notice_user(s_BotServ, u, buf); + *buf = 0; + end = buf; + } + end += + snprintf(end, sizeof(buf) - (end - buf), " %s ", + ci->name); + } + } + } + + if (*buf) + notice_user(s_BotServ, u, buf); + return; +} + +static int do_info(User * u) +{ + BotInfo *bi; + ChannelInfo *ci; + char *query = strtok(NULL, " "); + + int need_comma = 0, is_servadmin = is_services_admin(u); + char buf[BUFSIZE], *end; + const char *commastr = getstring(u->na, COMMA_SPACE); + + if (!query) + syntax_error(s_BotServ, u, "INFO", BOT_INFO_SYNTAX); + else if ((bi = findbot(query))) { + char buf[BUFSIZE]; + struct tm *tm; + + notice_lang(s_BotServ, u, BOT_INFO_BOT_HEADER, bi->nick); + notice_lang(s_BotServ, u, BOT_INFO_BOT_MASK, bi->user, bi->host); + notice_lang(s_BotServ, u, BOT_INFO_BOT_REALNAME, bi->real); + tm = localtime(&bi->created); + strftime_lang(buf, sizeof(buf), u, STRFTIME_DATE_TIME_FORMAT, tm); + notice_lang(s_BotServ, u, BOT_INFO_BOT_CREATED, buf); + notice_lang(s_BotServ, u, BOT_INFO_BOT_OPTIONS, + getstring(u->na, + (bi-> + flags & BI_PRIVATE) ? BOT_INFO_OPT_PRIVATE : + BOT_INFO_OPT_NONE)); + notice_lang(s_BotServ, u, BOT_INFO_BOT_USAGE, bi->chancount); + + if (is_services_admin(u)) + send_bot_channels(u, bi); + } else if ((ci = cs_findchan(query))) { + if (!is_servadmin && !is_founder(u, ci)) { + notice_lang(s_BotServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + notice_lang(s_BotServ, u, BOT_INFO_CHAN_HEADER, ci->name); + if (ci->bi) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_BOT, ci->bi->nick); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_BOT_NONE); + + if (ci->botflags & BS_KICK_BADWORDS) { + if (ci->ttb[TTB_BADWORDS]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BADWORDS_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_BADWORDS]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BADWORDS, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BADWORDS, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_BOLDS) { + if (ci->ttb[TTB_BOLDS]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BOLDS_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_BOLDS]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BOLDS, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BOLDS, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_CAPS) { + if (ci->ttb[TTB_CAPS]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_CAPS_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_CAPS], ci->capsmin, + ci->capspercent); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_CAPS_ON, + getstring(u->na, BOT_INFO_ACTIVE), ci->capsmin, + ci->capspercent); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_CAPS_OFF, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_COLORS) { + if (ci->ttb[TTB_COLORS]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_COLORS_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_COLORS]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_COLORS, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_COLORS, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_FLOOD) { + if (ci->ttb[TTB_FLOOD]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_FLOOD_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_FLOOD], ci->floodlines, + ci->floodsecs); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_FLOOD_ON, + getstring(u->na, BOT_INFO_ACTIVE), + ci->floodlines, ci->floodsecs); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_FLOOD_OFF, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_REPEAT) { + if (ci->ttb[TTB_REPEAT]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REPEAT_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_REPEAT], ci->repeattimes); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REPEAT_ON, + getstring(u->na, BOT_INFO_ACTIVE), + ci->repeattimes); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REPEAT_OFF, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_REVERSES) { + if (ci->ttb[TTB_REVERSES]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REVERSES_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_REVERSES]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REVERSES, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REVERSES, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_UNDERLINES) { + if (ci->ttb[TTB_UNDERLINES]) + notice_lang(s_BotServ, u, + BOT_INFO_CHAN_KICK_UNDERLINES_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_UNDERLINES]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_UNDERLINES, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_UNDERLINES, + getstring(u->na, BOT_INFO_INACTIVE)); + + end = buf; + *end = 0; + if (ci->botflags & BS_DONTKICKOPS) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s", + getstring(u->na, BOT_INFO_OPT_DONTKICKOPS)); + need_comma = 1; + } + if (ci->botflags & BS_DONTKICKVOICES) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_DONTKICKVOICES)); + need_comma = 1; + } + if (ci->botflags & BS_FANTASY) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_FANTASY)); + need_comma = 1; + } + if (ci->botflags & BS_GREET) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_GREET)); + need_comma = 1; + } + if (ci->botflags & BS_NOBOT) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_NOBOT)); + need_comma = 1; + } + if (ci->botflags & BS_SYMBIOSIS) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_SYMBIOSIS)); + need_comma = 1; + } + notice_lang(s_BotServ, u, BOT_INFO_CHAN_OPTIONS, + *buf ? buf : getstring(u->na, BOT_INFO_OPT_NONE)); + + } else + notice_lang(s_BotServ, u, BOT_INFO_NOT_FOUND, query); + return MOD_CONT; +} + +/*************************************************************************/ + +static int do_set(User * u) +{ + char *chan = strtok(NULL, " "); + char *option = strtok(NULL, " "); + char *value = strtok(NULL, " "); + int is_servadmin = is_services_admin(u); + + ChannelInfo *ci; + + if (readonly) + notice_lang(s_BotServ, u, BOT_SET_DISABLED); + else if (!chan || !option || !value) + syntax_error(s_BotServ, u, "SET", BOT_SET_SYNTAX); + else if (is_servadmin && !stricmp(option, "PRIVATE")) { + BotInfo *bi; + + if ((bi = findbot(chan))) { + if (!stricmp(value, "ON")) { + bi->flags |= BI_PRIVATE; + notice_lang(s_BotServ, u, BOT_SET_PRIVATE_ON, bi->nick); + } else if (!stricmp(value, "OFF")) { + bi->flags &= ~BI_PRIVATE; + notice_lang(s_BotServ, u, BOT_SET_PRIVATE_OFF, bi->nick); + } else { + syntax_error(s_BotServ, u, "SET PRIVATE", + BOT_SET_PRIVATE_SYNTAX); + } + } else { + notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, chan); + } + return MOD_CONT; + } else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); else if (ci->flags & CI_VERBOTEN) - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); else if (!is_servadmin && !check_access(u, ci, CA_SET)) - notice_lang(s_BotServ, u, ACCESS_DENIED); - else - { - if (!stricmp(option, "DONTKICKOPS")) { - if (!stricmp(value, "ON")) { - ci->botflags |= BS_DONTKICKOPS; - notice_lang(s_BotServ, u, BOT_SET_DONTKICKOPS_ON, ci->name); - } else if (!stricmp(value, "OFF")) { - ci->botflags &= ~BS_DONTKICKOPS; - notice_lang(s_BotServ, u, BOT_SET_DONTKICKOPS_OFF, ci->name); - } else { - syntax_error(s_BotServ, u, "SET DONTKICKOPS", BOT_SET_DONTKICKOPS_SYNTAX); - } - } else if (!stricmp(option, "DONTKICKVOICES")) { - if (!stricmp(value, "ON")) { - ci->botflags |= BS_DONTKICKVOICES; - notice_lang(s_BotServ, u, BOT_SET_DONTKICKVOICES_ON, ci->name); - } else if (!stricmp(value, "OFF")) { - ci->botflags &= ~BS_DONTKICKVOICES; - notice_lang(s_BotServ, u, BOT_SET_DONTKICKVOICES_OFF, ci->name); - } else { - syntax_error(s_BotServ, u, "SET DONTKICKVOICES", BOT_SET_DONTKICKVOICES_SYNTAX); - } - } else if (!stricmp(option, "FANTASY")) { - if (!stricmp(value, "ON")) { - ci->botflags |= BS_FANTASY; - notice_lang(s_BotServ, u, BOT_SET_FANTASY_ON, ci->name); - } else if (!stricmp(value, "OFF")) { - ci->botflags &= ~BS_FANTASY; - notice_lang(s_BotServ, u, BOT_SET_FANTASY_OFF, ci->name); - } else { - syntax_error(s_BotServ, u, "SET FANTASY", BOT_SET_FANTASY_SYNTAX); - } - } else if (!stricmp(option, "GREET")) { - if (!stricmp(value, "ON")) { - ci->botflags |= BS_GREET; - notice_lang(s_BotServ, u, BOT_SET_GREET_ON, ci->name); - } else if (!stricmp(value, "OFF")) { - ci->botflags &= ~BS_GREET; - notice_lang(s_BotServ, u, BOT_SET_GREET_OFF, ci->name); - } else { - syntax_error(s_BotServ, u, "SET GREET", BOT_SET_GREET_SYNTAX); - } - } else if (is_servadmin && !stricmp(option, "NOBOT")) { - if (!stricmp(value, "ON")) { - ci->botflags |= BS_NOBOT; - if (ci->bi) unassign(u, ci); - notice_lang(s_BotServ, u, BOT_SET_NOBOT_ON, ci->name); - } else if (!stricmp(value, "OFF")) { - ci->botflags &= ~BS_NOBOT; - notice_lang(s_BotServ, u, BOT_SET_NOBOT_OFF, ci->name); - } else { - syntax_error(s_BotServ, u, "SET NOBOT", BOT_SET_NOBOT_SYNTAX); - } - } else if (!stricmp(option, "SYMBIOSIS")) { - if (!stricmp(value, "ON")) { - ci->botflags |= BS_SYMBIOSIS; - notice_lang(s_BotServ, u, BOT_SET_SYMBIOSIS_ON, ci->name); - } else if (!stricmp(value, "OFF")) { - ci->botflags &= ~BS_SYMBIOSIS; - notice_lang(s_BotServ, u, BOT_SET_SYMBIOSIS_OFF, ci->name); - } else { - syntax_error(s_BotServ, u, "SET SYMBIOSIS", BOT_SET_SYMBIOSIS_SYNTAX); - } - } else { - notice_help(s_BotServ, u, BOT_SET_UNKNOWN, option); - } - } -} - -/*************************************************************************/ - -static void do_kickcmd(User *u) -{ - char *chan = strtok(NULL, " "); - char *option = strtok(NULL, " "); - char *value = strtok(NULL, " "); - char *ttb = strtok(NULL, " "); - - ChannelInfo *ci; - - if (readonly) - notice_lang(s_BotServ, u, BOT_KICK_DISABLED); - else if (!chan || !option || !value) - syntax_error(s_BotServ, u, "KICK", BOT_KICK_SYNTAX); - else if (stricmp(value, "ON") && stricmp(value, "OFF")) - syntax_error(s_BotServ, u, "KICK", BOT_KICK_SYNTAX); - else if (!(ci = cs_findchan(chan))) - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); - else if (ci->flags & CI_VERBOTEN) - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); - else if (!is_services_admin(u) && !check_access(u, ci, CA_SET)) - notice_lang(s_BotServ, u, ACCESS_DENIED); - else - { - if (!stricmp(option, "BADWORDS")) { - if (!stricmp(value, "ON")) { - if (ttb) { - ci->ttb[TTB_BADWORDS] = atol(ttb); - if (ci->ttb[TTB_BADWORDS] < 0) { - notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); - return; - } - } else ci->ttb[TTB_BADWORDS] = 0; - ci->botflags |= BS_KICK_BADWORDS; - if (ci->ttb[TTB_BADWORDS]) notice_lang(s_BotServ, u, BOT_KICK_BADWORDS_ON_BAN, ci->ttb[TTB_BADWORDS]); - else notice_lang(s_BotServ, u, BOT_KICK_BADWORDS_ON); - } else { - ci->botflags &= ~BS_KICK_BADWORDS; - notice_lang(s_BotServ, u, BOT_KICK_BADWORDS_OFF); - } - } else if (!stricmp(option, "BOLDS")) { - if (!stricmp(value, "ON")) { - if (ttb) { - ci->ttb[TTB_BOLDS] = atol(ttb); - if (ci->ttb[TTB_BOLDS] < 0) { - notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); - return; - } - } else ci->ttb[TTB_BOLDS] = 0; - ci->botflags |= BS_KICK_BOLDS; - if (ci->ttb[TTB_BOLDS]) notice_lang(s_BotServ, u, BOT_KICK_BOLDS_ON_BAN, ci->ttb[TTB_BOLDS]); - else notice_lang(s_BotServ, u, BOT_KICK_BOLDS_ON); - } else { - ci->botflags &= ~BS_KICK_BOLDS; - notice_lang(s_BotServ, u, BOT_KICK_BOLDS_OFF); - } - } else if (!stricmp(option, "CAPS")) { - if (!stricmp(value, "ON")) { - char *min = strtok(NULL, " "); - char *percent = strtok(NULL, " "); - - if (ttb) { - ci->ttb[TTB_CAPS] = atol(ttb); - if (ci->ttb[TTB_CAPS] < 0) { - notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); - return; - } - } else ci->ttb[TTB_CAPS] = 0; - - if (!min) ci->capsmin = 10; - else ci->capsmin = atol(min); - if (ci->capsmin < 1) ci->capsmin = 10; - - if (!percent) ci->capspercent = 25; - else ci->capspercent = atol(percent); - if (ci->capspercent < 1 || ci->capspercent > 100) ci->capspercent = 25; - - ci->botflags |= BS_KICK_CAPS; - if (ci->ttb[TTB_CAPS]) notice_lang(s_BotServ, u, BOT_KICK_CAPS_ON_BAN, ci->capsmin, ci->capspercent, ci->ttb[TTB_CAPS]); - else notice_lang(s_BotServ, u, BOT_KICK_CAPS_ON, ci->capsmin, ci->capspercent); - } else { - ci->botflags &= ~BS_KICK_CAPS; - notice_lang(s_BotServ, u, BOT_KICK_CAPS_OFF); - } - } else if (!stricmp(option, "COLORS")) { - if (!stricmp(value, "ON")) { - if (ttb) { - ci->ttb[TTB_COLORS] = atol(ttb); - if (ci->ttb[TTB_COLORS] < 0) { - notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); - return; - } - } else ci->ttb[TTB_COLORS] = 0; - ci->botflags |= BS_KICK_COLORS; - if (ci->ttb[TTB_COLORS]) notice_lang(s_BotServ, u, BOT_KICK_COLORS_ON_BAN, ci->ttb[TTB_COLORS]); - else notice_lang(s_BotServ, u, BOT_KICK_COLORS_ON); - } else { - ci->botflags &= ~BS_KICK_COLORS; - notice_lang(s_BotServ, u, BOT_KICK_COLORS_OFF); - } - } else if (!stricmp(option, "FLOOD")) { - if (!stricmp(value, "ON")) { - char *lines = strtok(NULL, " "); - char *secs = strtok(NULL, " "); - - if (ttb) { - ci->ttb[TTB_FLOOD] = atol(ttb); - if (ci->ttb[TTB_FLOOD] < 0) { - notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); - return; - } - } else ci->ttb[TTB_FLOOD] = 0; - - if (!lines) ci->floodlines = 6; - else ci->floodlines = atol(lines); - if (ci->floodlines < 2) ci->floodlines = 6; - - if (!secs) ci->floodsecs = 10; - else ci->floodsecs = atol(secs); - if (ci->floodsecs < 1 || ci->floodsecs > BSKeepData) ci->floodsecs = 10; - - ci->botflags |= BS_KICK_FLOOD; - if (ci->ttb[TTB_FLOOD]) notice_lang(s_BotServ, u, BOT_KICK_FLOOD_ON_BAN, ci->floodlines, ci->floodsecs, ci->ttb[TTB_FLOOD]); - else notice_lang(s_BotServ, u, BOT_KICK_FLOOD_ON, ci->floodlines, ci->floodsecs); - } else { - ci->botflags &= ~BS_KICK_FLOOD; - notice_lang(s_BotServ, u, BOT_KICK_FLOOD_OFF); - } - } else if (!stricmp(option, "REPEAT")) { - if (!stricmp(value, "ON")) { - char *times = strtok(NULL, " "); - - if (ttb) { - ci->ttb[TTB_REPEAT] = atol(ttb); - if (ci->ttb[TTB_REPEAT] < 0) { - notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); - return; - } - } else ci->ttb[TTB_REPEAT] = 0; - - if (!times) ci->repeattimes = 3; - else ci->repeattimes = atol(times); - if (ci->repeattimes < 2) ci->repeattimes = 3; - - ci->botflags |= BS_KICK_REPEAT; - if (ci->ttb[TTB_REPEAT]) notice_lang(s_BotServ, u, BOT_KICK_REPEAT_ON_BAN, ci->repeattimes, ci->ttb[TTB_REPEAT]); - else notice_lang(s_BotServ, u, BOT_KICK_REPEAT_ON, ci->repeattimes); - } else { - ci->botflags &= ~BS_KICK_REPEAT; - notice_lang(s_BotServ, u, BOT_KICK_REPEAT_OFF); - } - } else if (!stricmp(option, "REVERSES")) { - if (!stricmp(value, "ON")) { - if (ttb) { - ci->ttb[TTB_REVERSES] = atol(ttb); - if (ci->ttb[TTB_REVERSES] < 0) { - notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); - return; - } - } else ci->ttb[TTB_REVERSES] = 0; - ci->botflags |= BS_KICK_REVERSES; - if (ci->ttb[TTB_REVERSES]) notice_lang(s_BotServ, u, BOT_KICK_REVERSES_ON_BAN, ci->ttb[TTB_REVERSES]); - else notice_lang(s_BotServ, u, BOT_KICK_REVERSES_ON); - } else { - ci->botflags &= ~BS_KICK_REVERSES; - notice_lang(s_BotServ, u, BOT_KICK_REVERSES_OFF); - } - } else if (!stricmp(option, "UNDERLINES")) { - if (!stricmp(value, "ON")) { - if (ttb) { - ci->ttb[TTB_UNDERLINES] = atol(ttb); - if (ci->ttb[TTB_UNDERLINES] < 0) { - notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); - return; - } - } else ci->ttb[TTB_UNDERLINES] = 0; - ci->botflags |= BS_KICK_UNDERLINES; - if (ci->ttb[TTB_UNDERLINES]) notice_lang(s_BotServ, u, BOT_KICK_UNDERLINES_ON_BAN, ci->ttb[TTB_UNDERLINES]); - else notice_lang(s_BotServ, u, BOT_KICK_UNDERLINES_ON); - } else { - ci->botflags &= ~BS_KICK_UNDERLINES; - notice_lang(s_BotServ, u, BOT_KICK_UNDERLINES_OFF); - } - } else notice_help(s_BotServ, u, BOT_KICK_UNKNOWN, option); - } + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + if (!stricmp(option, "DONTKICKOPS")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_DONTKICKOPS; + notice_lang(s_BotServ, u, BOT_SET_DONTKICKOPS_ON, + ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_DONTKICKOPS; + notice_lang(s_BotServ, u, BOT_SET_DONTKICKOPS_OFF, + ci->name); + } else { + syntax_error(s_BotServ, u, "SET DONTKICKOPS", + BOT_SET_DONTKICKOPS_SYNTAX); + } + } else if (!stricmp(option, "DONTKICKVOICES")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_DONTKICKVOICES; + notice_lang(s_BotServ, u, BOT_SET_DONTKICKVOICES_ON, + ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_DONTKICKVOICES; + notice_lang(s_BotServ, u, BOT_SET_DONTKICKVOICES_OFF, + ci->name); + } else { + syntax_error(s_BotServ, u, "SET DONTKICKVOICES", + BOT_SET_DONTKICKVOICES_SYNTAX); + } + } else if (!stricmp(option, "FANTASY")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_FANTASY; + notice_lang(s_BotServ, u, BOT_SET_FANTASY_ON, ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_FANTASY; + notice_lang(s_BotServ, u, BOT_SET_FANTASY_OFF, ci->name); + } else { + syntax_error(s_BotServ, u, "SET FANTASY", + BOT_SET_FANTASY_SYNTAX); + } + } else if (!stricmp(option, "GREET")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_GREET; + notice_lang(s_BotServ, u, BOT_SET_GREET_ON, ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_GREET; + notice_lang(s_BotServ, u, BOT_SET_GREET_OFF, ci->name); + } else { + syntax_error(s_BotServ, u, "SET GREET", + BOT_SET_GREET_SYNTAX); + } + } else if (is_servadmin && !stricmp(option, "NOBOT")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_NOBOT; + if (ci->bi) + unassign(u, ci); + notice_lang(s_BotServ, u, BOT_SET_NOBOT_ON, ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_NOBOT; + notice_lang(s_BotServ, u, BOT_SET_NOBOT_OFF, ci->name); + } else { + syntax_error(s_BotServ, u, "SET NOBOT", + BOT_SET_NOBOT_SYNTAX); + } + } else if (!stricmp(option, "SYMBIOSIS")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_SYMBIOSIS; + notice_lang(s_BotServ, u, BOT_SET_SYMBIOSIS_ON, ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_SYMBIOSIS; + notice_lang(s_BotServ, u, BOT_SET_SYMBIOSIS_OFF, ci->name); + } else { + syntax_error(s_BotServ, u, "SET SYMBIOSIS", + BOT_SET_SYMBIOSIS_SYNTAX); + } + } else { + notice_help(s_BotServ, u, BOT_SET_UNKNOWN, option); + } + } + return MOD_CONT; +} + +/*************************************************************************/ + +static int do_kickcmd(User * u) +{ + char *chan = strtok(NULL, " "); + char *option = strtok(NULL, " "); + char *value = strtok(NULL, " "); + char *ttb = strtok(NULL, " "); + + ChannelInfo *ci; + + if (readonly) + notice_lang(s_BotServ, u, BOT_KICK_DISABLED); + else if (!chan || !option || !value) + syntax_error(s_BotServ, u, "KICK", BOT_KICK_SYNTAX); + else if (stricmp(value, "ON") && stricmp(value, "OFF")) + syntax_error(s_BotServ, u, "KICK", BOT_KICK_SYNTAX); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + else if (ci->flags & CI_VERBOTEN) + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if (!is_services_admin(u) && !check_access(u, ci, CA_SET)) + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + if (!stricmp(option, "BADWORDS")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_BADWORDS] = atol(ttb); + if (ci->ttb[TTB_BADWORDS] < 0) { + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_BADWORDS] = 0; + ci->botflags |= BS_KICK_BADWORDS; + if (ci->ttb[TTB_BADWORDS]) + notice_lang(s_BotServ, u, BOT_KICK_BADWORDS_ON_BAN, + ci->ttb[TTB_BADWORDS]); + else + notice_lang(s_BotServ, u, BOT_KICK_BADWORDS_ON); + } else { + ci->botflags &= ~BS_KICK_BADWORDS; + notice_lang(s_BotServ, u, BOT_KICK_BADWORDS_OFF); + } + } else if (!stricmp(option, "BOLDS")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_BOLDS] = atol(ttb); + if (ci->ttb[TTB_BOLDS] < 0) { + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_BOLDS] = 0; + ci->botflags |= BS_KICK_BOLDS; + if (ci->ttb[TTB_BOLDS]) + notice_lang(s_BotServ, u, BOT_KICK_BOLDS_ON_BAN, + ci->ttb[TTB_BOLDS]); + else + notice_lang(s_BotServ, u, BOT_KICK_BOLDS_ON); + } else { + ci->botflags &= ~BS_KICK_BOLDS; + notice_lang(s_BotServ, u, BOT_KICK_BOLDS_OFF); + } + } else if (!stricmp(option, "CAPS")) { + if (!stricmp(value, "ON")) { + char *min = strtok(NULL, " "); + char *percent = strtok(NULL, " "); + + if (ttb) { + ci->ttb[TTB_CAPS] = atol(ttb); + if (ci->ttb[TTB_CAPS] < 0) { + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_CAPS] = 0; + + if (!min) + ci->capsmin = 10; + else + ci->capsmin = atol(min); + if (ci->capsmin < 1) + ci->capsmin = 10; + + if (!percent) + ci->capspercent = 25; + else + ci->capspercent = atol(percent); + if (ci->capspercent < 1 || ci->capspercent > 100) + ci->capspercent = 25; + + ci->botflags |= BS_KICK_CAPS; + if (ci->ttb[TTB_CAPS]) + notice_lang(s_BotServ, u, BOT_KICK_CAPS_ON_BAN, + ci->capsmin, ci->capspercent, + ci->ttb[TTB_CAPS]); + else + notice_lang(s_BotServ, u, BOT_KICK_CAPS_ON, + ci->capsmin, ci->capspercent); + } else { + ci->botflags &= ~BS_KICK_CAPS; + notice_lang(s_BotServ, u, BOT_KICK_CAPS_OFF); + } + } else if (!stricmp(option, "COLORS")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_COLORS] = atol(ttb); + if (ci->ttb[TTB_COLORS] < 0) { + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_COLORS] = 0; + ci->botflags |= BS_KICK_COLORS; + if (ci->ttb[TTB_COLORS]) + notice_lang(s_BotServ, u, BOT_KICK_COLORS_ON_BAN, + ci->ttb[TTB_COLORS]); + else + notice_lang(s_BotServ, u, BOT_KICK_COLORS_ON); + } else { + ci->botflags &= ~BS_KICK_COLORS; + notice_lang(s_BotServ, u, BOT_KICK_COLORS_OFF); + } + } else if (!stricmp(option, "FLOOD")) { + if (!stricmp(value, "ON")) { + char *lines = strtok(NULL, " "); + char *secs = strtok(NULL, " "); + + if (ttb) { + ci->ttb[TTB_FLOOD] = atol(ttb); + if (ci->ttb[TTB_FLOOD] < 0) { + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_FLOOD] = 0; + + if (!lines) + ci->floodlines = 6; + else + ci->floodlines = atol(lines); + if (ci->floodlines < 2) + ci->floodlines = 6; + + if (!secs) + ci->floodsecs = 10; + else + ci->floodsecs = atol(secs); + if (ci->floodsecs < 1 || ci->floodsecs > BSKeepData) + ci->floodsecs = 10; + + ci->botflags |= BS_KICK_FLOOD; + if (ci->ttb[TTB_FLOOD]) + notice_lang(s_BotServ, u, BOT_KICK_FLOOD_ON_BAN, + ci->floodlines, ci->floodsecs, + ci->ttb[TTB_FLOOD]); + else + notice_lang(s_BotServ, u, BOT_KICK_FLOOD_ON, + ci->floodlines, ci->floodsecs); + } else { + ci->botflags &= ~BS_KICK_FLOOD; + notice_lang(s_BotServ, u, BOT_KICK_FLOOD_OFF); + } + } else if (!stricmp(option, "REPEAT")) { + if (!stricmp(value, "ON")) { + char *times = strtok(NULL, " "); + + if (ttb) { + ci->ttb[TTB_REPEAT] = atol(ttb); + if (ci->ttb[TTB_REPEAT] < 0) { + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_REPEAT] = 0; + + if (!times) + ci->repeattimes = 3; + else + ci->repeattimes = atol(times); + if (ci->repeattimes < 2) + ci->repeattimes = 3; + + ci->botflags |= BS_KICK_REPEAT; + if (ci->ttb[TTB_REPEAT]) + notice_lang(s_BotServ, u, BOT_KICK_REPEAT_ON_BAN, + ci->repeattimes, ci->ttb[TTB_REPEAT]); + else + notice_lang(s_BotServ, u, BOT_KICK_REPEAT_ON, + ci->repeattimes); + } else { + ci->botflags &= ~BS_KICK_REPEAT; + notice_lang(s_BotServ, u, BOT_KICK_REPEAT_OFF); + } + } else if (!stricmp(option, "REVERSES")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_REVERSES] = atol(ttb); + if (ci->ttb[TTB_REVERSES] < 0) { + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_REVERSES] = 0; + ci->botflags |= BS_KICK_REVERSES; + if (ci->ttb[TTB_REVERSES]) + notice_lang(s_BotServ, u, BOT_KICK_REVERSES_ON_BAN, + ci->ttb[TTB_REVERSES]); + else + notice_lang(s_BotServ, u, BOT_KICK_REVERSES_ON); + } else { + ci->botflags &= ~BS_KICK_REVERSES; + notice_lang(s_BotServ, u, BOT_KICK_REVERSES_OFF); + } + } else if (!stricmp(option, "UNDERLINES")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_UNDERLINES] = atol(ttb); + if (ci->ttb[TTB_UNDERLINES] < 0) { + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_UNDERLINES] = 0; + ci->botflags |= BS_KICK_UNDERLINES; + if (ci->ttb[TTB_UNDERLINES]) + notice_lang(s_BotServ, u, BOT_KICK_UNDERLINES_ON_BAN, + ci->ttb[TTB_UNDERLINES]); + else + notice_lang(s_BotServ, u, BOT_KICK_UNDERLINES_ON); + } else { + ci->botflags &= ~BS_KICK_UNDERLINES; + notice_lang(s_BotServ, u, BOT_KICK_UNDERLINES_OFF); + } + } else + notice_help(s_BotServ, u, BOT_KICK_UNKNOWN, option); + } + return MOD_CONT; } /*************************************************************************/ -static int badwords_del_callback(User *u, int num, va_list args) +static int badwords_del_callback(User * u, int num, va_list args) { BadWord *bw; ChannelInfo *ci = va_arg(args, ChannelInfo *); int *last = va_arg(args, int *); if (num < 1 || num > ci->bwcount) - return 0; + return 0; *last = num; - - bw = &ci->badwords[num-1]; - if (bw->word) - free(bw->word); + + bw = &ci->badwords[num - 1]; + if (bw->word) + free(bw->word); bw->word = NULL; bw->in_use = 0; - + return 1; } -static int badwords_list(User *u, int index, ChannelInfo *ci, int *sent_header) +static int badwords_list(User * u, int index, ChannelInfo * ci, + int *sent_header) { BadWord *bw = &ci->badwords[index]; - + if (!bw->in_use) - return 0; + return 0; if (!*sent_header) { - notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_HEADER, ci->name); - *sent_header = 1; + notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_HEADER, ci->name); + *sent_header = 1; } - - notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_FORMAT, index+1, bw->word, - ((bw->type == BW_SINGLE) ? "(SINGLE)" : - ((bw->type == BW_START) ? "(START)" : - ((bw->type == BW_END) ? "(END)" : ""))) - ); + + notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_FORMAT, index + 1, + bw->word, + ((bw->type == + BW_SINGLE) ? "(SINGLE)" : ((bw->type == + BW_START) ? "(START)" + : ((bw->type == + BW_END) ? "(END)" : ""))) + ); return 1; } -static int badwords_list_callback(User *u, int num, va_list args) +static int badwords_list_callback(User * u, int num, va_list args) { ChannelInfo *ci = va_arg(args, ChannelInfo *); int *sent_header = va_arg(args, int *); if (num < 1 || num > ci->bwcount) - return 0; - return badwords_list(u, num-1, ci, sent_header); + return 0; + return badwords_list(u, num - 1, ci, sent_header); } -static void do_badwords(User *u) +static int do_badwords(User * u) { char *chan = strtok(NULL, " "); - char *cmd = strtok(NULL, " "); + char *cmd = strtok(NULL, " "); char *word = strtok(NULL, ""); ChannelInfo *ci; BadWord *bw; - + int i; - int need_args = (cmd && (!stricmp(cmd, "LIST") || !stricmp(cmd, "CLEAR"))); + int need_args = (cmd + && (!stricmp(cmd, "LIST") || !stricmp(cmd, "CLEAR"))); if (!cmd || (need_args ? 0 : !word)) { - syntax_error(s_BotServ, u, "BADWORDS", BOT_BADWORDS_SYNTAX); + syntax_error(s_BotServ, u, "BADWORDS", BOT_BADWORDS_SYNTAX); } else if (!(ci = cs_findchan(chan))) { - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); } else if (ci->flags & CI_VERBOTEN) { - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); - } else if (!check_access(u, ci, CA_BADWORDS) && (!need_args || !is_services_admin(u))) { - notice_lang(s_BotServ, u, ACCESS_DENIED); + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!check_access(u, ci, CA_BADWORDS) + && (!need_args || !is_services_admin(u))) { + notice_lang(s_BotServ, u, ACCESS_DENIED); } else if (stricmp(cmd, "ADD") == 0) { - - char *opt, *pos; - int type = BW_ANY; - - if (readonly) { - notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); - return; - } - - pos = strrchr(word, ' '); - if (pos) { - opt = pos+1; - if (*opt) { - if (!stricmp(opt, "SINGLE")) type = BW_SINGLE; - else if (!stricmp(opt, "START")) type = BW_START; - else if (!stricmp(opt, "END")) type = BW_END; - if (type != BW_ANY) *pos = 0; - } - } - - for (bw = ci->badwords, i = 0; i < ci->bwcount; bw++, i++) { - if (bw->word && !stricmp(bw->word, word)) { - notice_lang(s_BotServ, u, BOT_BADWORDS_ALREADY_EXISTS, bw->word, ci->name); - return; - } - } - - for (i = 0; i < ci->bwcount; i++) { - if (!ci->badwords[i].in_use) - break; - } - if (i == ci->bwcount) { - if (i < BSBadWordsMax) { - ci->bwcount++; - ci->badwords = srealloc(ci->badwords, sizeof(BadWord) * ci->bwcount); - } else { - notice_lang(s_BotServ, u, BOT_BADWORDS_REACHED_LIMIT, BSBadWordsMax); - return; - } - } - bw = &ci->badwords[i]; - bw->in_use = 1; - bw->word = sstrdup(word); - bw->type = type; - - notice_lang(s_BotServ, u, BOT_BADWORDS_ADDED, bw->word, ci->name); + + char *opt, *pos; + int type = BW_ANY; + + if (readonly) { + notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); + return MOD_CONT; + } + + pos = strrchr(word, ' '); + if (pos) { + opt = pos + 1; + if (*opt) { + if (!stricmp(opt, "SINGLE")) + type = BW_SINGLE; + else if (!stricmp(opt, "START")) + type = BW_START; + else if (!stricmp(opt, "END")) + type = BW_END; + if (type != BW_ANY) + *pos = 0; + } + } + + for (bw = ci->badwords, i = 0; i < ci->bwcount; bw++, i++) { + if (bw->word && !stricmp(bw->word, word)) { + notice_lang(s_BotServ, u, BOT_BADWORDS_ALREADY_EXISTS, + bw->word, ci->name); + return MOD_CONT; + } + } + + for (i = 0; i < ci->bwcount; i++) { + if (!ci->badwords[i].in_use) + break; + } + if (i == ci->bwcount) { + if (i < BSBadWordsMax) { + ci->bwcount++; + ci->badwords = + srealloc(ci->badwords, sizeof(BadWord) * ci->bwcount); + } else { + notice_lang(s_BotServ, u, BOT_BADWORDS_REACHED_LIMIT, + BSBadWordsMax); + return MOD_CONT; + } + } + bw = &ci->badwords[i]; + bw->in_use = 1; + bw->word = sstrdup(word); + bw->type = type; + + notice_lang(s_BotServ, u, BOT_BADWORDS_ADDED, bw->word, ci->name); } else if (stricmp(cmd, "DEL") == 0) { - if (readonly) { - notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); - return; - } - - /* Special case: is it a number/list? Only do search if it isn't. */ - if (isdigit(*word) && strspn(word, "1234567890,-") == strlen(word)) { - int count, deleted, last = -1; - deleted = process_numlist(word, &count, badwords_del_callback, u, - ci, &last); - if (!deleted) { - if (count == 1) { - notice_lang(s_BotServ, u, BOT_BADWORDS_NO_SUCH_ENTRY, - last, ci->name); - } else { - notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, ci->name); - } - } else if (deleted == 1) { - notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_ONE, ci->name); - } else { - notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_SEVERAL, - deleted, ci->name); - } - } else { - for (i = 0; i < ci->bwcount; i++) { - if (ci->badwords[i].in_use && !stricmp(ci->badwords[i].word, word)) - break; - } - if (i == ci->bwcount) { - notice_lang(s_BotServ, u, BOT_BADWORDS_NOT_FOUND, word, chan); - return; - } - bw = &ci->badwords[i]; - notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED, bw->word, ci->name); - if (bw->word) - free(bw->word); - bw->word = NULL; - bw->in_use = 0; - } + if (readonly) { + notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); + return MOD_CONT; + } + + /* Special case: is it a number/list? Only do search if it isn't. */ + if (isdigit(*word) && strspn(word, "1234567890,-") == strlen(word)) { + int count, deleted, last = -1; + deleted = + process_numlist(word, &count, badwords_del_callback, u, ci, + &last); + if (!deleted) { + if (count == 1) { + notice_lang(s_BotServ, u, BOT_BADWORDS_NO_SUCH_ENTRY, + last, ci->name); + } else { + notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, + ci->name); + } + } else if (deleted == 1) { + notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_ONE, + ci->name); + } else { + notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_SEVERAL, + deleted, ci->name); + } + } else { + for (i = 0; i < ci->bwcount; i++) { + if (ci->badwords[i].in_use + && !stricmp(ci->badwords[i].word, word)) + break; + } + if (i == ci->bwcount) { + notice_lang(s_BotServ, u, BOT_BADWORDS_NOT_FOUND, word, + chan); + return MOD_CONT; + } + bw = &ci->badwords[i]; + notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED, bw->word, + ci->name); + if (bw->word) + free(bw->word); + bw->word = NULL; + bw->in_use = 0; + } } else if (stricmp(cmd, "LIST") == 0) { - int sent_header = 0; + int sent_header = 0; - if (ci->bwcount == 0) { - notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_EMPTY, chan); - return; - } - if (word && strspn(word, "1234567890,-") == strlen(word)) { - process_numlist(word, NULL, badwords_list_callback, u, ci, - &sent_header); - } else { - for (i = 0; i < ci->bwcount; i++) { - if (!(ci->badwords[i].in_use)) continue; - if (word && ci->badwords[i].word - && !match_wild_nocase(word, ci->badwords[i].word)) - continue; - badwords_list(u, i, ci, &sent_header); - } - } - if (!sent_header) - notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, chan); - - } else if (stricmp(cmd, "CLEAR") == 0) { - - if (readonly) { - notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); - return; - } - - for (i = 0; i < ci->bwcount; i++) - if (ci->badwords[i].word) free(ci->badwords[i].word); - - free(ci->badwords); - ci->badwords = NULL; - ci->bwcount = 0; + if (ci->bwcount == 0) { + notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_EMPTY, chan); + return MOD_CONT; + } + if (word && strspn(word, "1234567890,-") == strlen(word)) { + process_numlist(word, NULL, badwords_list_callback, u, ci, + &sent_header); + } else { + for (i = 0; i < ci->bwcount; i++) { + if (!(ci->badwords[i].in_use)) + continue; + if (word && ci->badwords[i].word + && !match_wild_nocase(word, ci->badwords[i].word)) + continue; + badwords_list(u, i, ci, &sent_header); + } + } + if (!sent_header) + notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, chan); + + } else if (stricmp(cmd, "CLEAR") == 0) { + + if (readonly) { + notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); + return MOD_CONT; + } + + for (i = 0; i < ci->bwcount; i++) + if (ci->badwords[i].word) + free(ci->badwords[i].word); + + free(ci->badwords); + ci->badwords = NULL; + ci->bwcount = 0; - notice_lang(s_BotServ, u, BOT_BADWORDS_CLEAR); + notice_lang(s_BotServ, u, BOT_BADWORDS_CLEAR); } else { - syntax_error(s_BotServ, u, "BADWORDS", BOT_BADWORDS_SYNTAX); + syntax_error(s_BotServ, u, "BADWORDS", BOT_BADWORDS_SYNTAX); } + return MOD_CONT; } /*************************************************************************/ -static void do_say(User *u) +static int do_say(User * u) { - ChannelInfo *ci; - - char *chan = strtok(NULL, " "); - char *text = strtok(NULL, ""); - - if (!chan || !text) - syntax_error(s_BotServ, u, "SAY", BOT_SAY_SYNTAX); - else if (!(ci = cs_findchan(chan))) - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + ChannelInfo *ci; + + char *chan = strtok(NULL, " "); + char *text = strtok(NULL, ""); + + if (!chan || !text) + syntax_error(s_BotServ, u, "SAY", BOT_SAY_SYNTAX); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); else if (ci->flags & CI_VERBOTEN) - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); - else if (!ci->bi) - notice_help(s_BotServ, u, BOT_NOT_ASSIGNED); - else if (!ci->c || ci->c->usercount < BSMinUsers) - notice_lang(s_BotServ, u, BOT_NOT_ON_CHANNEL, ci->name); + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if (!ci->bi) + notice_help(s_BotServ, u, BOT_NOT_ASSIGNED); + else if (!ci->c || ci->c->usercount < BSMinUsers) + notice_lang(s_BotServ, u, BOT_NOT_ON_CHANNEL, ci->name); else if (!check_access(u, ci, CA_SAY)) - notice_lang(s_BotServ, u, ACCESS_DENIED); - else { - send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, text); - ci->bi->lastmsg = time(NULL); - } + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + if (text[0] != '\001') { + send_cmd(ci->bi->nick, "PRIVMSG %s :%s", ci->name, text); + ci->bi->lastmsg = time(NULL); + if (logchan && LogBot) + send_cmd(ci->bi->nick, "PRIVMSG %s :SAY %s %s %s", + LogChannel, u->nick, ci->name, text); + } else { + syntax_error(s_BotServ, u, "SAY", BOT_SAY_SYNTAX); + } + } + return MOD_CONT; } /*************************************************************************/ -static void do_act(User *u) -{ - ChannelInfo *ci; - - char *chan = strtok(NULL, " "); - char *text = strtok(NULL, ""); - - if (!chan || !text) - syntax_error(s_BotServ, u, "ACT", BOT_ACT_SYNTAX); - else if (!(ci = cs_findchan(chan))) - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); +static int do_act(User * u) +{ + ChannelInfo *ci; + + char *chan = strtok(NULL, " "); + char *text = strtok(NULL, ""); + + if (!chan || !text) + syntax_error(s_BotServ, u, "ACT", BOT_ACT_SYNTAX); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); else if (ci->flags & CI_VERBOTEN) - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); - else if (!ci->bi) - notice_help(s_BotServ, u, BOT_NOT_ASSIGNED); - else if (!ci->c || ci->c->usercount < BSMinUsers) - notice_lang(s_BotServ, u, BOT_NOT_ON_CHANNEL, ci->name); + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if (!ci->bi) + notice_help(s_BotServ, u, BOT_NOT_ASSIGNED); + else if (!ci->c || ci->c->usercount < BSMinUsers) + notice_lang(s_BotServ, u, BOT_NOT_ON_CHANNEL, ci->name); else if (!check_access(u, ci, CA_SAY)) - notice_lang(s_BotServ, u, ACCESS_DENIED); - else { - send_cmd(ci->bi->nick, "PRIVMSG %s :%cACTION %s%c", ci->name, 1, text, 1); - ci->bi->lastmsg = time(NULL); - } + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + send_cmd(ci->bi->nick, "PRIVMSG %s :%cACTION %s%c", ci->name, 1, + text, 1); + ci->bi->lastmsg = time(NULL); + if (logchan && LogBot) + send_cmd(ci->bi->nick, "PRIVMSG %s :ACT %s %s %s", LogChannel, + u->nick, ci->name, text); + } + return MOD_CONT; } /*************************************************************************/ +char *normalizeBuffer(const char *buf) +{ + char *newbuf = NULL; + int i, len, j = 0; + + len = strlen(buf); + newbuf = (char *) malloc(sizeof(char) * len + 1); + + for (i = 0; i < len; i++) { + switch (buf[i]) { + /* Bold ctrl char */ + case 2: + break; + /* Color ctrl char */ + case 3: + /* If the next character is a digit, its also removed */ + if (isdigit(buf[i + 1])) { + i++; + + /* Check for background color code + * and remove it as well + */ + if (buf[i + 1] == ',') { + i++; + + if (isdigit(buf[i + 1])) + i++; + } + } + + break; + + /* Reverse ctrl char */ + case 22: + break; + /* Underline ctrl char */ + case 31: + break; + /* A valid char gets copied into the new buffer */ + default: + newbuf[j] = buf[i]; + j++; + } + } + + /* Terminate the string */ + newbuf[j] = 0; + + return (newbuf); +} diff -urN epona-1.4.14/BUGS anope-1.6.4/BUGS --- epona-1.4.14/BUGS 2002-09-01 02:44:45.000000000 +0200 +++ anope-1.6.4/BUGS 1970-01-01 01:00:00.000000000 +0100 @@ -1,13 +0,0 @@ -Clone detection can give false warnings if a user connects and then signs -off several times in rapid succession. - -Clone detection also goes off wrongly if a server links and has a number of -clients from the same hostname. - -/msg OperServ RESTART / kill -HUP don't work sometimes. SHUTDOWN / -kill -TERM (or just kill) still work in this case. [Happens after -netsplits?] - -If there is absolutely no activity on your network, Services may delay -timed events (nick kills, database saving, etc.) until the next message -comes in from Services' uplink server. diff -urN epona-1.4.14/Changes anope-1.6.4/Changes --- epona-1.4.14/Changes 2002-09-01 02:44:45.000000000 +0200 +++ anope-1.6.4/Changes 2005-09-08 15:56:07.000000000 +0200 @@ -1,3 +1,473 @@ +Anope Version 1.6.4 +------------------- +Provided by Anope Dev. - 2005 +08/29 F Various compiler warnings when compiling with gcc4. [ #00] +08/29 F Memory leak when using mysql to save data. [ #00] +05/25 F Wrong option output with listnicks. [#380] +03/02 F /ns alist output. [#288] + +Anope Version 1.6.3 +------------------- +Provided by Anope Dev. - 2004 +10/10 F Corrected a large number of spelling and typing errors in docs. [ #87] +10/10 F Fixed typo in example.conf. [ #70] +10/10 F Fixed a bug with globals containing format characters [ #52] +10/10 F Fixed missing RANDOMNEWS entry on /OS HELP [ #40] +10/10 F Badwords now cannot be evaded by using ctrl chars or color codes [ #22] +10/09 F Bug in LogChannel possibly causing segfaults. [#176] +10/09 F NOOP bug with wildcards. [#115] +10/09 F Removed RESTRICTED from incorrectly labeled lang file entry. [#111] +10/09 F Added SQLINE to NICK() on PTlink. [ #96] +10/09 F HostServ functions no longer called for non VHOST capable ircds. [ #77] +06/07 F Fixed xOP management inconsistency. [ #38] +06/07 F ALIST bug when being invoked by systems admins. [ #20] +05/17 F Typo in HostServ help. [ #51] +05/17 F HostServ admin help display. [ #7] + +Provided by DrStein - 2004 +10/10 F NEWS reordering issue [ #00] +10/10 F NS GLIST allows the owner of the nick to use the nickname param. [ #00] +10/10 F Fixed MySQL error, whereby checks are only done if mysql is on. [ #00] + +Provided by Trystan - 2004 +10/24 F Fixed OPNOTICE when doing /CS OP [#198] +10/23 F Compiler warnings with new FreeBSD systems. [ #00] +10/11 F Hybrid halfop support on SJOIN [#164] +10/11 F CSDefBantype in the config can be set to 0 [#177] +10/11 F Resolved longstanding NICKIP issue on AKILLs. [ #17] +10/10 F Improved on DrStein typo fix to init.c [ #00] + +Anope Version 1.6.2 +-------------------- +Provided by Anope Dev. +2004/04/12 Fixed bug on quoted MD5 password fix for MySQL use (#11) +2004/04/11 Fixed mydbgen table schema detection and creation. (#10) + +Anope Version 1.6.1 +-------------------- +Provided by Anope Dev. +2004/04/12 Fixed quoted MD5 password for MySQL use (#11) +2004/04/11 Fixed table.sql detection on mydbgen script (#10) +2004/04/04 Fixed moduleAddCommand for a non-existant service (#3) +2004/04/01 Fixed in-ability to add module commands outside AnopeInit +2004/03/31 Fixed MySQL double encryption if using MD5. +2004/03/31 Fixed a tiny memleak in the moduleAddCommand call +2004/03/31 Fixed a bug with modules doing recursive callback calls (#5) + +Anope Version 1.6.0 +-------------------- +Provided by Anope Dev. +2004/03/22 Added and updated several documents on "docs" folder. +2004/03/22 Added bin/dbgen to help MySQL db schema. +2004/03/21 Fixed module makefile to use -Wall for new modules +2004/03/21 Fixed config check startup warnings (0000467) +2004/03/21 Fixed bug where mkdir should be mkdir -p to create parent (0000468) +2004/03/22 Fixed Crash on channel memo (0000347) + +Anope Version 1.5.15 +-------------------- +Provided by Anope Dev. +2004/03/14 Fixed LogBot and LogChan issue (0000437) +2004/03/14 Fixed tiny bug in french lang file (0000465) +2004/03/14 Fixed chanmode +r not being removed. (0000462) +2004/03/12 Fixed MySQL limited data fields (0000434) +2004/03/12 Fixed a cosmetic typo (0000440) +2004/03/14 Fixed mysql (null) values (0000450) +2004/03/06 Fixed module duplicate functions (0000431) +2004/03/06 Fixed module unload issue (0000432) +2004/03/13 Fixed missing channel fields on MySQL schema +2004/03/13 Fixed MySQL calls even when disabled. +2004/03/07 Fixed a malformed mode crash for some ircd's +2004/03/13 Added db save on startup + +Anope Version 1.5.14 +-------------------- +Provided by Anope Dev. +2004/02/17 Disabled modules on OpenBSD for the time being (0000408) +2004/02/15 Added Viagra's VS command to handle vHosts properly (0000404) +2004/02/15 Fixed HostSetters to cover all aliases in the group (0000412) +2004/02/07 Fixed channel '#' may not be registered anymore (0000030) +2004/02/07 Fixed opers can't /OS MODE on +A chans anymore (0000403) +2004/02/07 Fixed registration via group on nicknames preconfirmation (0000400) +2004/02/14 Fixed hardcoded references to "OperServ" (0000411) +2004/02/19 Fixed nickserv list problem with unconfirmed nicknames (0000406) +2004/02/14 Fixed DefCon to cover more cases properly (0000407) +2004/02/02 Fixed bug where non-id'ed nicks could do /cs identify +2004/02/07 Fixed bug where you could /cs identify infinite times +2004/02/09 Fixed incorrect help files Changed ServicesAdmin->SuperAdmin +2004/02/14 Fixed typos in en_us.l language file + +Anope Version 1.5.13 +-------------------- +Provided by Anope Dev. +2004/01/30 Fixed malformed buffer bug (0000398) +2004/01/31 Fixed OperServ news system reordering. (0000396) +2004/01/19 Fixed minor typos on en_us.l (0000380) (0000381) +2004/01/31 Fixed ALL option for ChanServ info (0000395) +2004/01/18 Fixed HostServ Set message for non-registered nicks + +Anope Version 1.5.12 +-------------------- +Provided by Anope Dev. +2004/01/12 Added optimized language parser +2004/01/11 Added moduleSetHelpHelp to modules.h +2004/01/11 Added updated documentation +2004/01/12 Added language tool (langtool.pl) +2004/01/13 Added line length check (>60 char) to langtool.pl +2004/01/17 Added better MySQL detection on configure script +2004/01/17 Removed ExtSock experimental code +2004/01/07 Fixed broken CHANKILL expire (0000333) +2004/01/03 Fixed bot creation issue (0000348) +2004/01/11 Fixed /OS STAFF output (0000346) +2004/01/11 Fixed bot change/creation error (0000348) +2004/01/03 Fixed /MS STAFF output (0000356) +2004/01/07 Fixed modunload crash with disabled services (0000370) +2004/01/17 Fixed missing HostServ on HelpServ help list (0000377) + +Provided by GeniusDex +2004/01/04 Updated nl.l (Dutch language File) +2004/01/11 Updated documentation + +Anope Version 1.5.11 +-------------------- +Provided by Anope Dev. +2003/12/12 Fixed all printf parameters on all language files +2003/12/08 Fixed HOST_HELP string for all languages (0000340) +2003/12/08 ChanServ and NickServ LIST's now accept #X-Y for seaching +2003/12/09 Nickname enforcer will now kill instead of svsnick on hybridircd + +Provided by Oleg Nikolaev aka Isot +2003/12/12 New ru.l (Russian lang file) + +Provided by DrStein +2003/12/12 Updated es.l (Spanish language File). + +Provided by GeniusDex +2003/12/12 Updated nl.l (Dutch language File). + +Provided by Stuff +2003/12/09 Updated de.l (German lang file) + +Anope Version 1.5.10 +-------------------- +Provided by Anope Dev. +2003/11/24 New version of putanope to make more robust +2003/11/24 New #defines for version tokens (see built version.h) +2003/11/24 New version schema: major.minor.patch.build +2003/11/16 Fixed mlock +c on Ultimate3 (0000320) +2003/11/16 Fixed BotServ +ao on PTLink (0000313) +2003/11/16 All channel modes now supported on PTLink (0000311) +2003/11/16 Absolute mode cleaning for /CS CLEAR #chan MODES +2003/11/16 Services will now kill users on hybrid instead of svsnick (0000240) +2003/11/15 Fixed a bug with module message's +2003/11/15 Added a generic footer to list's without (0000222) +2003/11/15 Adding a ./configure script to modules folder +2003/11/15 Removed Experimental status from Module and Viagra +2003/11/15 Fixed /ms staff on memo notifucation (0000221) +2003/11/09 Fixed compile.sh for bsd based systems +2003/11/09 Fixed bug in moduleDelCallback routine + +Anope Version 1.5.9 +-------------------- +Provided by Anope Dev. +2003/11/03 Added optional MysqlSecure password security directive +2003/11/03 Fixed case insensitive password fields on MySQL (0000196) +2003/11/03 Fixed /OS STAFF bug not showing online aliases (0000124) +2003/11/03 Fixed wrong /CS HELP output on Ultimate2/3 (0000189) +2003/11/02 Fixed empty fields on the cs_access table (0000197) +2003/11/02 Fixed SA's unable to /NS LOGOUT themselves (0000288) +2003/11/02 Fixed SQLINE help syntax (0000291) +2003/11/01 Added moduleDelCallback for module coders +2003/11/01 Modified module AnopeInit call, fixed bug (0000289) +2003/11/01 Fixed error in pt.l file and memoserv help +2003/10/29 Fixed -h bug for valid halfop's when joining a empty chan (0000245) +2003/10/29 Fixed forbidden chan spammy log file bug (0000284) + +Provided by GeniusDex +2003/11/01 Converted HelpServ into a "real" services, modules now work for it + +Anope Version 1.5.8 +-------------------- +Provided by Anope Dev. +2003/10/08 Fixed compile errors on PTLink and Ultimate3 as nither have vIdents +2003/10/17 Fixed double TAB on language files (0000283) +2003/10/14 Added a check on nicksserv logout so you can't logout services admins +2003/10/17 Added new configuration directive AnonymousGlobal (0000116) + +Provided by ShadowMaster +2003/10/08 Added NickIP Akill matching + +Anope Version 1.5.7 +-------------------- +Provided by Anope Dev. +2003/10/05 Added /ns update to replace further identifies, /ns identify will now only work once +2003/10/03 Added check_unload function to modules. (like on-error unloading) +2003/10/03 Added directive MysqlPort +2003/09/22 Added moduleHelp framework for module coders, see hs_moo.c +2003/09/21 Added moduleGetLastBuffer() and a module cmdTable bug fixed +2003/08/16 Added moduleAddCallback command for module coders +2003/10/06 Fixed bug with botserv bot creation when using services-aliases. (thanks to Killerchen) +2003/10/05 Fixed vident on ban issue (bug 0000268) +2003/10/05 Fixed memo order reset on deletion (bug 0000270) +2003/09/07 Fixed clearmodes issue (bug 0000121) +2003/09/07 Fixed ServicesRoot reload issue (bug 0000194) +2003/09/07 Fixed empty ip proxy crash (bug 0000217) +2003/09/04 Fixed bug ref: 0000170 - optional ""'s in mail sending +2003/07/28 Fixed Channel DROP then FORBID crash on MySQL (0000199) +2003/07/28 Fixed HostServ launch on Viagra and PTlink (0000190) +2003/07/27 Fixed BotServ bots now unkickable on Ultimate3 (0000159) +2003/07/27 Fixed Hybrid NICK_IS_REGISTERED dupe (0000184) +2003/07/27 Fixed PTlink /newmask issue (0000188) +2003/07/20 Fixed MySQL compile errors on Ultimate +2003/07/20 Fixed PTlink sbuf compile error +2003/07/20 Fixed chanserv badword MySQL issue +2003/08/30 Allow for E/F lines when handling akilled host's joining the network +2003/07/25 Added External socket support (*VERY* EXPERIMENTAL) +2003/07/20 Made MySQL ns_id, na_id and ci_id useful by preserving it's value across updates +2003/07/20 Some MySQL Optimizations (MySQL 3.23.32+ required) + +Provided by DrStein +2003/10/05 Updated es.l (Spanish language File). + +Anope Version 1.5.6 +-------------------- +Provided by Anope Dev. +2003/07/16 Reimplemented +oa and +oq on net-joins and ModeOnId (less intrusive) +2003/07/16 Added bin directory with misc tools +2003/07/12 Fixed chankill no expire +2003/07/13 Fixed BotServ bug when trying to add a bot with a services client's name. +2003/07/10 Changed mlock_key from int to a String in mysql.c (Thanks goto Trystan) +2003/07/09 Added request Syntax. Changed version to show the actual compiled Ircd's name. +2003/06/29 Added services/modules/runtime for tmp storage of .so files +2003/06/29 Fixed a small bug in nickserv load. +2003/06/29 Fixed multiple chan modes at once Ulitmate issue + +Anope Version 1.5.5 +-------------------- +Provided by Anope Dev. +2003/06/24 Added the ability to autoload modules at services startup +2003/06/23 Now MySQL functionality is optional even when compiled with MySQL support +2003/06/23 Combined +oq +oa +ha +va on net-joins. +2003/06/22 Prevent botserv say sending a ctcp to a channel +2003/06/22 Fixed nickserv setting +d on users using group +2003/06/22 Fixed non services admins able to drop nick's still awaiting a email code +2003/06/17 Added EXPERIMENTAL module support. + +Provided by GeniusDex +2003/06/23 Dutch language file. + +Anope Version 1.5.4 +-------------------- +Provided by Anope Dev. +2003/06/11 Added RemoteServer2 and RemoteServer3 to the conf. If one server is down, the services will try the next one. +2003/06/06 Added /MS SENDALL to send a massmemo to all registered users +2003/06/03 Renamed function log() to alog() to prevent gcc3.3 warnings +2003/06/03 Services now WALLOPS about db saves on /os shutdown +2003/06/03 Modified NetworkDomain directive to allow multiple domains +2003/06/03 Added NSRestrictGetPass and CSRestrictGetPass directives to restrict access to getpass command. +2003/06/03 Added a directive in the conf that makes ChanServ opers only. +2003/06/02 Added phase 1 of MySQL Support + +Anope Version 1.5.3 +-------------------- +Provided by Anope Dev. +2003/05/31 Removed TitanIRCd support. Difference willnot allow joint support +2003/05/25 Custom GlobalOnCycle message +2003/05/25 Defcon reject all new connections Kill message. +2003/05/25 CHANKILL will not akill opers in the channel +2003/05/25 Add command for MemoServ to send memo to all Admins/Opers +2003/05/24 Fixed /os restart bug +2003/05/24 Updated lang files - various errors/bug fixs +2003/05/23 Fixed NSModeOnID it will only set unset modes (as far as possible) + +Provided by Popcorn +2003/05/26 Added ViagraIRCd 1.3.x / TitanIRCd 2.0.3 support (experimental) + +Provided by James +2003/05/30 Fixed deleting ban exceptions. +2003/05/29 Added a much improved services ignore that can use wildcards. +2003/05/24 Added Hybrid 7 support - james your the daddy! :-) + +Provided by openglx +2003/05/26 Added PTlink 6.15.0 or later support (experimental) + +Anope Version 1.5.2 +-------------------- +Provided by Anope Dev. +2003/05/20 Added GlobalOnDefcon to global current Defcon Level when set +2003/05/20 Added GlobalOnDefconMore to allow admin to attach a msg to users +2003/05/15 Added No New Memos to Defcon +2003/05/15 Edit lanuage file to allow the user to know services are in Defcon +2003/05/15 Added /NS GETEMAIL to allow matches of nick to email (0000013) +2003/04/28 Added /OS SVSNICK to forcefully change a user's nickname + +Anope Version 1.5.1 +-------------------- +Provided by Anope Dev. :) +2003/04/27 Added Forbid/Suspend reason on akick if defined (0000023) +2003/04/27 Added /OS CHANKILL command to deal with botnet channels (0000066) +2003/04/26 Added DEFCON framework, along with basic settings +2003/04/23 Removed Sequana IRCd support as well as conversion from IRCservices v4.4 +2003/04/19 Added HostSetters directive to allow NON-OPERS to use HostServ +2003/04/19 Added Operserv Staff command feature request: 0000018 +2003/04/18 Added a pattern matching + range specifying to /HostServ LIST +2003/04/18 Added DELALL command to HostServ to compliment SETALL +2003/04/14 Services Root Admins are no longer affected by MailDelay +2003/04/10 Added user's ident and host to WallBadOS +2003/04/02 The old chanbot will now part on a /bs assign (smarter assign) +2003/04/02 Added name tag for globalmsgs (shows the name of the sender) + +Anope Version 1.4.23 +-------------------- +Provided by Anope Dev. +2003/05/18 Fixed /ns list display error with no-expire +2003/05/15 Fixed Exception move bug +2003/05/15 Fixed /msg Operserv noop issue +2003/05/05 Fixed Invalid nick/host/ident when using /bs bot CHANGE + +Anope Version 1.4.22 +-------------------- +Provided by Anope Dev. +2003/04/27 Fixed unsuspend crash when the # sign was left out +2003/04/27 Fixed JOIN modes not set correctly internaly (e.g. for /cs clear ops) +2003/04/26 Fixed OperServ jupe will only attempt to Jupe valid server masks +2003/04/26 Fixed SETHOST for nonexistent user nickname in log files +2003/04/26 Fixed Nonrelevant compiler warning (eof on botserv.c) +2003/04/26 Fixed vIdent support for Ultimate2.x + +Provided by James +2003/04/26 Fixed No valid tld and logchan issue on Ultimate3 + +Anope Version 1.4.21 +-------------------- +Provided by Anope Dev. (thanks goto PopCorn) +2003/04/20 Fixed BotServ nick/host/ident checking +2003/04/20 Fixed HostServ valid host/ident checking + +Anope Version 1.4.20 +-------------------- +Provided by PopCorn +2003/04/18 Fixed xOP permission problem + +Anope Version 1.4.19 +-------------------- +Provided by Anope Dev. :) +2003/04/12 Fixed MSNofityAll bug that crashed Services. +2003/04/12 Fixed MD5 compilation error. + +Anope Version 1.4.18 +-------------------- +Provided by Anope Dev. :) +2003/03/27 SUSPENDed Channels can't be DROPed by Founder anymore +2003/03/27 Fixed a couple of log'ing errors to tidy logfiels up a bit +2003/03/20 Fixed a minor epona bug with !unban (BotServ will now + check the UNBAN level instead of the OPDEOP level) +2003/03/14 On Ultimate3 you can now MLOCK +NSA. + Please note that MLOCK'ing +A and +O will only work on + Ultimate3.a31 and later. +2003/03/11 Fixed buffer bug with long akill reasons and AddAkiller +2003/03/08 MemoServ notification for Channel memos, upon join and send. +2003/03/07 SuperAdmin can now be turned ON/OFF on a per-admin basis + logging of use is also added. +2003/03/07 Added OperServ ignore function +2003/03/07 Added optional globalmsg on startup and shutdown/restart +2003/03/07 Added config option to hide Services stats o from non-opers +2003/03/05 Fixed a bug with clearmodes +2003/03/03 Added OperServ umode function to change usermodes (SuperAdmin only) +2003/03/03 Added OperServ oline function to give operflags to users (SuperAdmin only) +2003/03/03 Fixed several issues with +p users and ChanServ/Botserv + kick and negative mode changes. +2003/03/02 Added Optional Channel ModeOnID +2003/02/22 Added email verification when registering a nick +2003/02/22 Added HostServ GROUP command, to allow users to sync + all vHost's in a nick group. +2003/02/22 Added /MS DEL LAST +2003/03/21 Updated it.l (Italian language File). +2003/03/21 Updated es.l (Spanish language File). +2003/03/21 Updated de.l (German language File). + +Provided by Kevin +2003/03/21 Updated fr.l (French language File). + +Anope Version 1.4.17 +-------------------- +Provided by Anope Dev. :) +2003/03/02 Fixed HostServ bug on non VHOST ircds. +2003/02/20 Fixed the -logchan -debug bug, now they are mutualy exclusive +2003/02/19 Added the #define HAS_VIDENT to signify an ircd able to + dynamicaly change a user's ident +2003/02/19 HostServ updated to allow ident@host's for compatiable + ircds +2003/02/19 NickServ ALIST command added which deprecates ChanServ + CLIST/ALIST +2003/02/19 Complain to the oper about long vhosts +2003/02/19 Added sanity check on vHost on HostServ SET/SETALL +2003/02/19 Fixed HostServ support for UltimateIRCd 3.0.0 +2003/02/18 NS INFO ALL shows the vHost if it was set with hostserv +2003/02/18 NS ID is an alias for NS IDENTIFY +2003/02/18 Updated it.l (Italian language File). +2003/02/18 Updated es.l (Spanish language File). +2003/02/17 Fixed KILL (Alias Recovery) bug. +2003/02/17 Fixed CHAN_CLIST_FORMAT on all languages. +2003/02/17 Removed "scalloc" warnings. + +Provided by Seb +2003/02/18 Updated fr.l (French language File). + +Provided by Certus +2003/03/01 Updated de.l (German language File). + +Anope Version 1.4.16 +-------------------- +Provided by Anope Dev. +2003/02/16 Fixed all language files to conform to latest index +2003/02/15 Fix for Bahamut/Ultimate3 AKILL command. +2003/02/14 CS XOP ADD moves an existing xop nick between lists +2003/02/14 CS ACCESS LIST shows xop properly instead of levels +2003/02/14 CS ALIST implemented +2003/02/14 CS CLIST modified for users +2003/02/13 HostServ Support + Alias +2003/02/13 CS SUSPEND/UNSUSPEND implemented +2003/02/13 Kill recovery for Aliases +2003/02/13 Exception checking banning mechanism + +Anope Version 1.4.15 +-------------------- +Provided by Daniel Engel +2003/02/03 Interim name change for the project to Anope. +2003/02/03 Created Changes.conf for services.conf changes. +2003/02/03 Portuguese Language File up to date. +2003/02/03 Spanish Language File up to date. +2003/02/03 RAW messages now logged. +2003/02/03 Access list DELETE and CLEAR now logged. +2003/02/03 Added Super Admin founder of all (view new example.conf). +2003/02/03 Prepend nick to AKILL reason (view new example.conf). +2003/02/03 Added AKILL reason to WallOSAkill notifier. +2003/02/03 Added BotServ !k alias of !kick. +2003/02/03 Logging BotServ ACT and SAY to a channel (view new example.conf). +2003/02/03 Added a more informative error on disabled RAW command. +2003/02/03 Fixed most compile warnings. + +Provided by Lucas Nussbaum +2003/02/03 Access Denied Logging. +2003/02/03 Services Alias (view new example.conf). +2003/02/03 Split Buffer exploit fix. + +Provided by David Narayan +2003/02/03 Logging to a channel + CLI flag (view new example.conf). + +Provided by David +2003/02/03 OperServ corruption notification. + +Provided by JH +2003/02/03 ChanServ end of ACCESS list notification. + +Provided by Thomas Juberg +2003/02/03 UltimateIRCd version 3.0.0.1 (mod-1.2) support. + +Provided by Daniele Nicolucci +2003/02/03 Italian language file. + Epona Version 1.4.14 -------------------- 2002/09/01 Nickname SQLINEs are now also enforced on nick change. diff -urN epona-1.4.14/Changes.conf anope-1.6.4/Changes.conf --- epona-1.4.14/Changes.conf 1970-01-01 01:00:00.000000000 +0100 +++ anope-1.6.4/Changes.conf 2005-09-08 15:56:07.000000000 +0200 @@ -0,0 +1,444 @@ +Anope Version 1.6.4 +-------------------- +No Changes. + +Anope Version 1.6.3 +-------------------- +No Changes. + +Anope Version 1.6.2 +-------------------- +No Changes. + +Anope Version 1.6.1 +-------------------- +No Changes. + +Anope Version 1.6.0 +-------------------- +** ADDED CONFIGURATION DIRECTIVES ** + +########################################################################### +# +# DefCon configuration +# +########################################################################### +# DefConLevel [OPTIONAL] +# Default defcon level (1-5) to use when starting services up, level 5 +# instructs services to run as normal. + +#DefConLevel 5 + +# DefCon1-4 [REQUIRED if Defcon is activated] +# These numercics determine which of the following operations take place +# at each level, the correct numeric can be found by adding together the +# number for each restriction you wish to place at a level. +# No new channel registrations 1 +# No New Nick Registrations 2 +# No MLOCK changes 4 +# Force Chan Mode 8 +# Use Reduced Session Limit 16 +# KILL any new clients trying to connect 32 +# Services will ignore everyone but opers 64 +# Services will silently ignore everyone but opers 128 +# AKILL all new clients trying to connect 256 +# No new memos sent to block memoserv attacks 512 + +#DefCon4 23 +# No channel reg + No Nick Reg + No MLOCK changes + Use Reduced Session Limit +# 1 + 2 + 4 + 16 + +#DefCon3 31 +# As DefCon4 + Services will Force Chan Mode's on channels +# 23 + 8 + +#DefCon2 159 +# As DefCon3 + Services will silently ignore everyone but opers +# 32 + 128 + +#DefCon1 415 +# As DefCon2 + AKILL all new clients trying to connect +# 159 + 256 + +# DefConSessionLimit [REQUIRED if DefCon is activated] +# New session limit to use when a defcon level is using "reduced" +# session limiting. +# NOTE: When using DefCon this value needs to be defined +#DefConSessionLimit 2 + +# DefConAkillExpire